Annotation of researchv10no/cmd/map/libmap/tetra.c, revision 1.1.1.1

1.1       root        1: #include "map.h"
                      2: 
                      3: /*
                      4:  *     conformal map of earth onto tetrahedron
                      5:  *     the stages of mapping are
                      6:  *     (a) stereo projection of tetrahedral face onto
                      7:  *         isosceles curvilinear triangle with 3 120-degree
                      8:  *         angles and one straight side
                      9:  *     (b) map of this triangle onto half plane cut along
                     10:  *         3 rays from the roots of unity to infinity
                     11:  *             formula (z^4+2*3^.5*z^2-1)/(z^4-2*3^.5*z^2-1)
                     12:  *     (c) do 3 times for  each sector of plane:
                     13:  *         map of |arg z|<=pi/6, cut along z>1 into
                     14:  *         triangle |arg z|<=pi/6, Re z<=const,
                     15:  *         with upper side of cut going into upper half of
                     16:  *         of vertical side of triangle and lowere into lower
                     17:  *             formula int from 0 to z dz/sqrt(1-z^3)
                     18:  *
                     19:  *     int from u to 1 3^.25*du/sqrt(1-u^3) =
                     20:                F(acos((rt3-1+u)/(rt3+1-u)),sqrt(1/2+rt3/4))
                     21:  *     int from 1 to u 3^.25*du/sqrt(u^3-1) =
                     22:  *             F(acos((rt3+1-u)/(rt3-1+u)),sqrt(1/2-rt3/4))
                     23:  *     this latter formula extends analytically down to
                     24:  *     u=0 and is the basis of this routine, with the
                     25:  *     argument of complex elliptic integral elco2
                     26:  *     being tan(acos...)
                     27:  *     the formula F(pi-x,k) = 2*F(pi/2,k)-F(x,k) is
                     28:  *     used to cross over into the region where Re(acos...)>pi/2
                     29:  *             f0 and fpi are suitably scaled complete integrals
                     30: */
                     31: 
                     32: #define TFUZZ 0.00001
                     33: 
                     34: static struct place tpole[4];  /* point of tangency of tetrahedron face*/
                     35: static double tpoleinit[4][2] = {
                     36:        1.,     0.,
                     37:        1.,     180.,
                     38:        -1.,    90.,
                     39:        -1.,    -90.
                     40: };
                     41: static struct tproj {
                     42:        double tlat,tlon;       /* center of stereo projection*/
                     43:        double ttwist;          /* rotatn before stereo*/
                     44:        double trot;            /*rotate after projection*/
                     45:        struct place projpl;    /*same as tlat,tlon*/
                     46:        struct coord projtw;    /*same as ttwist*/
                     47:        struct coord postrot;   /*same as trot*/
                     48: } tproj[4][4] = {
                     49: {/*00*/        {0.},
                     50:  /*01*/        {90.,   0.,     90.,    -90.},
                     51:  /*02*/        {0.,    45.,    -45.,   150.},
                     52:  /*03*/        {0.,    -45.,   -135.,  30.}
                     53: },
                     54: {/*10*/        {90.,   0.,     -90.,   90.},
                     55:  /*11*/ {0.},
                     56:  /*12*/ {0.,   135.,   -135.,  -150.},
                     57:  /*13*/        {0.,    -135.,  -45.,   -30.}
                     58: },
                     59: {/*20*/        {0.,    45.,    135.,   -30.},
                     60:  /*21*/        {0.,    135.,   45.,    -150.},
                     61:  /*22*/        {0.},
                     62:  /*23*/        {-90.,  0.,     180.,   90.}
                     63: },
                     64: {/*30*/        {0.,    -45.,   45.,    -150.},
                     65:  /*31*/ {0.,   -135.,  135.,   -30.},
                     66:  /*32*/        {-90.,  0.,     0.,     90.},
                     67:  /*33*/ {0.} 
                     68: }};
                     69: static double tx[4] = {        /*where to move facet after final rotation*/
                     70:        0.,     0.,     -1.,    1.      /*-1,1 to be sqrt(3)*/
                     71: };
                     72: static double ty[4] = {
                     73:        0.,     2.,     -1.,    -1.
                     74: };
                     75: static double root3;
                     76: static double rt3inv;
                     77: static double two_rt3;
                     78: static double tkc,tk,tcon;
                     79: static double f0r,f0i,fpir,fpii;
                     80: 
                     81: static void
                     82: twhichp(struct place *g, int *p, int *q)
                     83: {
                     84:        int i,j,k;
                     85:        double cosdist[4];
                     86:        struct place *tp;
                     87:        for(i=0;i<4;i++) {
                     88:                tp = &tpole[i];
                     89:                cosdist[i] = g->nlat.s*tp->nlat.s +
                     90:                          g->nlat.c*tp->nlat.c*(
                     91:                          g->wlon.s*tp->wlon.s +
                     92:                          g->wlon.c*tp->wlon.c);
                     93:        }
                     94:        j = 0;
                     95:        for(i=1;i<4;i++)
                     96:                if(cosdist[i] > cosdist[j])
                     97:                        j = i;
                     98:        *p = j;
                     99:        k = j==0?1:0;
                    100:        for(i=0;i<4;i++)
                    101:                if(i!=j&&cosdist[i]>cosdist[k])
                    102:                        k = i;
                    103:        *q = k;
                    104: }
                    105: 
                    106: int
                    107: Xtetra(struct place *place, double *x, double *y)
                    108: {
                    109:        int i,j;
                    110:        struct place pl;
                    111:        register struct tproj *tpp;
                    112:        double vr, vi;
                    113:        double br, bi;
                    114:        double zr,zi,z2r,z2i,z4r,z4i,sr,si,tr,ti;
                    115:        twhichp(place,&i,&j);
                    116:        copyplace(place,&pl);
                    117:        norm(&pl,&tproj[i][j].projpl,&tproj[i][j].projtw);
                    118:        Xstereographic(&pl,&vr,&vi);
                    119:        zr = vr/2;
                    120:        zi = vi/2;
                    121:        if(zr<=TFUZZ)
                    122:                zr = TFUZZ;
                    123:        csq(zr,zi,&z2r,&z2i);
                    124:        csq(z2r,z2i,&z4r,&z4i);
                    125:        z2r *= two_rt3;
                    126:        z2i *= two_rt3;
                    127:        cdiv(z4r+z2r-1,z4i+z2i,z4r-z2r-1,z4i-z2i,&sr,&si);
                    128:        csqrt(sr-1,si,&tr,&ti);
                    129:        cdiv(tcon*tr,tcon*ti,root3+1-sr,-si,&br,&bi);
                    130:        if(br<0) {
                    131:                br = -br;
                    132:                bi = -bi;
                    133:                if(!elco2(br,bi,tk,1.,1.,&vr,&vi))
                    134:                        return 0;
                    135:                vr = fpir - vr;
                    136:                vi = fpii - vi;
                    137:        } else 
                    138:                if(!elco2(br,bi,tk,1.,1.,&vr,&vi))
                    139:                        return 0;
                    140:        if(si>=0) {
                    141:                tr = f0r - vi;
                    142:                ti = f0i + vr;
                    143:        } else {
                    144:                tr = f0r + vi;
                    145:                ti = f0i - vr;
                    146:        }
                    147:        tpp = &tproj[i][j];
                    148:        *x = tr*tpp->postrot.c +
                    149:             ti*tpp->postrot.s + tx[i];
                    150:        *y = ti*tpp->postrot.c -
                    151:             tr*tpp->postrot.s + ty[i];
                    152:        return(1);
                    153: }
                    154: 
                    155: int
                    156: tetracut(struct place *g, struct place *og, double *cutlon)
                    157: {
                    158:        int i,j,k;
                    159:        if((g->nlat.s<=-rt3inv&&og->nlat.s<=-rt3inv) && 
                    160:           (ckcut(g,og,*cutlon=0.)==2||ckcut(g,og,*cutlon=PI)==2))
                    161:                return(2);
                    162:        twhichp(g,&i,&k);
                    163:        twhichp(og,&j,&k);
                    164:        if(i==j||i==0||j==0)
                    165:                return(1);
                    166:        return(0);
                    167: }
                    168: 
                    169: proj
                    170: tetra(void)
                    171: {
                    172:        register i;
                    173:        int j;
                    174:        register struct place *tp;
                    175:        register struct tproj *tpp;
                    176:        double t;
                    177:        root3 = sqrt(3.);
                    178:        rt3inv = 1/root3;
                    179:        two_rt3 = 2*root3;
                    180:        tkc = sqrt(.5-.25*root3);
                    181:        tk = sqrt(.5+.25*root3);
                    182:        tcon = 2*sqrt(root3);
                    183:        elco2(tcon/(root3-1),0.,tkc,1.,1.,&f0r,&f0i);
                    184:        elco2(1.e15,0.,tk,1.,1.,&fpir,&fpii);
                    185:        fpir *= 2;
                    186:        fpii *= 2;
                    187:        for(i=0;i<4;i++) {
                    188:                tx[i] *= f0r*root3;
                    189:                ty[i] *= f0r;
                    190:                tp = &tpole[i];
                    191:                t = tp->nlat.s = tpoleinit[i][0]/root3;
                    192:                tp->nlat.c = sqrt(1 - t*t);
                    193:                tp->nlat.l = atan2(tp->nlat.s,tp->nlat.c);
                    194:                deg2rad(tpoleinit[i][1],&tp->wlon);
                    195:                for(j=0;j<4;j++) {
                    196:                        tpp = &tproj[i][j];
                    197:                        latlon(tpp->tlat,tpp->tlon,&tpp->projpl);
                    198:                        deg2rad(tpp->ttwist,&tpp->projtw);
                    199:                        deg2rad(tpp->trot,&tpp->postrot);
                    200:                }
                    201:        }
                    202:        return(Xtetra);
                    203: }
                    204: 

unix.superglobalmegacorp.com

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