Annotation of researchv10no/cmd/map/lox/loxodromic.c, revision 1.1.1.1

1.1       root        1: #include "map.h"
                      2: #include <stdio.h>
                      3: 
                      4: /* development of a loxodrome from a unit sphere onto a plane
                      5:    the loxodrome passes through 0,0 on the sphere,
                      6:    inclined a (alpha) from the equator
                      7: 
                      8:    latitude p (phi) positive north
                      9:    longitude t (theta) positive east - opposite to "map"
                     10:    all angles in radians
                     11: 
                     12:    x,y are coords of developed curve
                     13:    c (chi) is angle of inclination of developed curve from x axis
                     14: 
                     15:    dx/dp = cos(c)/sin(a)
                     16:    dy/dp = sin(c)/sin(a)
                     17:    dc/dp = tan(p)/tan(a)
                     18:    dt/dp = 1/(cos(p)*tan(a))
                     19: 
                     20:    cc lox.c -lport -lF77 -lI77
                     21:    a.out alpha         here alpha is in degrees
                     22: */
                     23: extern char *realloc();
                     24: static double renorm();
                     25: static bsearch(), getxy(), calcf(), solve();
                     26: #define DEG (180/PI)
                     27: #define MAX 85
                     28: 
                     29: /* curlicue is an ordered sequence of points
                     30: along the midline of the spiral, in both geographic
                     31: and developed coordinates */
                     32: struct curl {
                     33:        double phi,x,y,theta,chi;
                     34: } *curlicue;   /* the midline */
                     35: int nc;                /* number of points on the midline */
                     36: 
                     37: struct coord a;        /* alpha, angle from equator */
                     38: static signa = 1;
                     39: static double z[4];            /* x==z[0],y==z[1],t=z[2],c==z[3] */
                     40: 
                     41: /* inputs to dodes, port library integration routine */
                     42: 
                     43: static int n = 4;
                     44: static double z0[4];           /* initial values = 0,0,0,a */
                     45: static double p0;              /* initial value of p = 0 */
                     46: static double p1 = 86*PI/180;  /* final value, 89.99+ degrees */
                     47: static double dt;              /* current time step */
                     48: static double deg = PI/180;    /* 1 degree */
                     49: static float errpar[2] = {1.e-7,1.e-7};
                     50: 
                     51: static
                     52: f(p,z,n,r)
                     53: double *p, *z, *r;
                     54: int *n;
                     55: {
                     56:        r[0] = cos(z[3])/a.s;
                     57:        r[1] = sin(z[3])/a.s;
                     58:        r[2] = a.c/(cos(*p)*a.s);
                     59:        r[3] = sin(*p)*r[2];
                     60: }
                     61: static
                     62: handle(t0,z0,t1,z1,n,dt,ts,e)
                     63: double *t0,*z0,*t1,*z1,*dt,*ts;
                     64: float *e;
                     65: int *n;
                     66: {
                     67:        if(*dt > deg) *dt = deg;
                     68:        if(fabs(z1[3]-z0[3])>.1 && *dt >.00001)
                     69:                *dt *= .1/fabs(z1[3]-z0[3]);
                     70:        if(*t1 + *dt >= PI/2)
                     71:                *dt = (PI/2 - *t1)/2;
                     72:        if(*t1 + *dt > *ts)
                     73:                *dt = *ts - *t1 + .00001;
                     74:        curlicue = (struct curl*)realloc((char*)curlicue,
                     75:                        (nc+1)*sizeof(*curlicue));
                     76:        curlicue[nc].phi = *t1;
                     77:        curlicue[nc].x = z1[0];
                     78:        curlicue[nc].y = z1[1];
                     79:        curlicue[nc].theta = z1[2];
                     80:        curlicue[nc].chi = z1[3];
                     81:        nc++;
                     82:        /*printf("%f %f %f %f %f\n",*t1*DEG,
                     83:                z1[0]*DEG,z1[1]*DEG,z1[2]*DEG,z1[3]*DEG);
                     84:        fflush(stdout);*/
                     85:        if(*t0==*t1) abort();
                     86: }
                     87: static
                     88: struct place negplace(place)
                     89: struct place *place;
                     90: {
                     91:        struct place iplace;
                     92:        iplace = *place;
                     93:        iplace.nlat.l = -place->nlat.l;
                     94:        iplace.nlat.s = -place->nlat.s;
                     95:        iplace.wlon.l = -place->wlon.l;
                     96:        iplace.wlon.s = -place->wlon.s;
                     97:        return iplace;
                     98: }
                     99: static
                    100: Xloxodromic(place, x, y)
                    101: struct place *place;
                    102: float *x, *y;
                    103: {
                    104:        double u1 = place->nlat.l;
                    105:        double v1 = -place->wlon.l;
                    106:        double d,p,t;
                    107:        if(fabs(u1) > MAX*RAD) return 0;
                    108:        if(u1 < 0) {
                    109:                struct place iplace;
                    110:                int ret;
                    111:                iplace = negplace(place);
                    112:                ret = Xloxodromic(&iplace,x,y);
                    113:                *x = -*x;
                    114:                *y = -*y;
                    115:                return ret;
                    116:        }
                    117:        v1 = renorm(u1,bsearch(u1,0),v1);
                    118:        solve(u1,v1,&d,&p,&t);
                    119:        /*printf("%f %f %f %f %f %f\n",
                    120:                u,v,v1*DEG,d*DEG,p*DEG,t*DEG);
                    121:        fflush(stdout);*/
                    122:        getxy(d,p,x,y);
                    123:        /*printf("%f %f\n",x*DEG,y*DEG);
                    124:        fflush(stdout);*/
                    125:        return 1;
                    126: }
                    127: int (*loxodromic(par))()
                    128: float par;
                    129: {
                    130:        deg2rad(par, &a);
                    131:        if(par < 0)
                    132:                signa = -1;
                    133:        z0[3] = a.l;
                    134:        dt = deg;
                    135:        handle(&deg,z0,&p0,z0,&n,&deg,&p1,errpar);
                    136:        dodes_(f,z0,&n,&p0,&p1,&dt,errpar,handle);
                    137:        return Xloxodromic;
                    138: }
                    139: 
                    140: /* find the index for latitude (i=0) or longitude (i=1)
                    141: in array curlicue.  In case of longitude, u must have
                    142: been normalized by renorm() */
                    143: static
                    144: bsearch(u,i)
                    145: double u;
                    146: {
                    147:        int top = nc;
                    148:        int bot = 0;
                    149:        int mid;
                    150:        while(bot<top-1) {
                    151:                mid = (bot+top)/2;
                    152:                if(i==0&&curlicue[mid].phi<=u||
                    153:                   i==1&&(signa>0&&curlicue[mid].theta<=u||
                    154:                          signa<0&&curlicue[mid].theta>=u))
                    155:                        bot = mid;
                    156:                else
                    157:                        top = mid;
                    158:        }
                    159:        return bot;
                    160: }
                    161: /* wind v thru multiples of 2*PI until it lies within PI
                    162: of the (linearly interpolated) midline */
                    163: static double
                    164: renorm(u,n,v)
                    165: double u,v;
                    166: {
                    167:        double t,fract;
                    168:        fract = (u-curlicue[n].phi)/
                    169:                (curlicue[n+1].phi-curlicue[n].phi);
                    170:        t = curlicue[n].theta*(1-fract) +
                    171:                curlicue[n+1].theta*fract;
                    172:        if(signa > 0) while(v<t-PI)
                    173:                v += 2*PI;
                    174:        else while(v>t+PI)
                    175:                v -= 2*PI;
                    176:        return v;
                    177: }
                    178: /* given the height (d) and foot (p,t) of the perpendicular projection
                    179: of a point onto the midline, return the x-y coordinates of the point*/
                    180: static
                    181: getxy(d,p,xp,yp)
                    182: float d,p,*xp,*yp;
                    183: {
                    184:        int n, sign = 1;
                    185:        double fract, x0, y0, c0;
                    186:        if(p < 0) {
                    187:                p = -p;
                    188:                sign = -1;
                    189:        }
                    190:        n = bsearch(p,0);
                    191:        fract = (p-curlicue[n].phi)/
                    192:                (curlicue[n+1].phi-curlicue[n].phi);
                    193:        x0 = sign*(curlicue[n].x*(1-fract) +
                    194:                curlicue[n+1].x*fract);
                    195:        y0 = sign*(curlicue[n].y*(1-fract) +
                    196:                curlicue[n+1].y*fract);
                    197:        c0 = curlicue[n].chi*(1-fract) +
                    198:                curlicue[n+1].chi*fract;
                    199:        *xp = x0 - d*sin(c0);
                    200:        *yp = y0 + d*cos(c0);
                    201: }      
                    202: 
                    203: /*
                    204:        solve simultaneously for d,p,t (dist to midline,
                    205:                                        phi lat on midline,
                    206:                                        theta lon on midline)
                    207:        given a, u, v (rhumb angle from parallels, lat, east lon)
                    208: 
                    209:        sin d sin a = cos u sin(t-v)            law of sines
                    210:        sin u = cos d sin p + sin d cos p cos a law of cosines
                    211:        t tan a = log tan (p/2 + PI/4)          eqn of rhumb line
                    212: 
                    213:        initial guess: d=u-p, t=v, p from table lookup in curlicue
                    214: */
                    215: static double su,cu,v0;
                    216: static int n3 = 3, jmax = 50;
                    217: static double acc = 1e-6;
                    218: static
                    219: calcf(n,x,nf,g)
                    220: int *n, *nf;
                    221: double *x,*g;
                    222: {
                    223:        double f[3], sd;
                    224:        if(x[1]>=PI/2) {
                    225:                *nf = 0;
                    226:                return;
                    227:        }
                    228:        sd = sin(x[0]);
                    229:        f[0] = sd*a.s-cu*sin(x[2]-v0);
                    230:        f[1] = su - cos(x[0])*sin(x[1]) - sd*cos(x[1])*a.c;
                    231:        f[2] = x[2]*a.s/a.c - log(tan(x[1]/2+PI/4));
                    232:        /*printf("calcf: d p t %g %f %f",
                    233:                x[0]*DEG,x[1]*DEG,x[2]*DEG);
                    234:        printf(" resid %f %f %f\n",f[0],f[1],f[2]);
                    235:        fflush(stdout);*/
                    236:        *g = f[0]*f[0]+f[1]*f[1]+f[2]*f[2];
                    237: }
                    238: /* given renormed lat-lon (u,v) find the height (*dp) and foot
                    239: (*pp,*tp) of a perpendicular to the midline. precondition: u>=0 */
                    240: static
                    241: solve(u,v,dp,pp,tp)
                    242: double u,v,*dp,*pp,*tp;
                    243: {
                    244:        double z[3];    /* d, p, t */
                    245:        int n;
                    246:        if(u < 0) {
                    247:                abort();
                    248:                solve(-u,-v,dp,pp,tp);
                    249:                *dp = -*dp;
                    250:                *pp = -*pp;
                    251:                *tp = -*tp;
                    252:                return;
                    253:        }
                    254:        n = bsearch(signa*fabs(v),1);
                    255:        su = sin(u);
                    256:        cu = cos(u);
                    257:        z[1] = curlicue[n].phi; /* initial guess */
                    258:        if(signa*v < 0) z[1] = -z[1];
                    259:        z[0] = u - z[1];
                    260:        z[2] = v0 = v;
                    261:        /*printf("inputs (deg) %f %f\n",u*DEG,v*DEG);
                    262:        printf("interval %d guess (deg) %f %f %f\n",n,
                    263:                z[0]*DEG,z[1]*DEG,z[2]*DEG);
                    264:        fflush(stdout);*/
                    265:        dsmnf_(&n3,z,calcf,&jmax,&acc);
                    266:        *dp = z[0];
                    267:        *pp = z[1];
                    268:        *tp = z[2];
                    269: }
                    270: loxcut(g,og,cutlon)
                    271: struct place *g, *og;
                    272: 
                    273: {
                    274:        double glon, oglon;
                    275:        double sign = g->nlat.l>=0? 1: -1;
                    276:        double nlat = sign*g->nlat.l;
                    277:        if(nlat > MAX*RAD)
                    278:                return 0;
                    279:        glon = sign*renorm(nlat, bsearch(nlat,0),
                    280:                                -sign*g->wlon.l);
                    281:        sign = og->nlat.l>=0? 1: -1;
                    282:        nlat = sign*og->nlat.l;
                    283:        if(nlat > MAX*RAD)
                    284:                return 0;
                    285:        oglon = sign*renorm(nlat, bsearch(nlat,0),
                    286:                                -sign*og->wlon.l);
                    287:        return fabs(glon-oglon) < PI;
                    288: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.