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

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

unix.superglobalmegacorp.com

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