1*59cc4ca5SDavid du Colombier #include <u.h>
2*59cc4ca5SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include "map.h"
43e12c5d1SDavid du Colombier
53e12c5d1SDavid du Colombier /*
63e12c5d1SDavid du Colombier * conformal map of earth onto tetrahedron
73e12c5d1SDavid du Colombier * the stages of mapping are
83e12c5d1SDavid du Colombier * (a) stereo projection of tetrahedral face onto
93e12c5d1SDavid du Colombier * isosceles curvilinear triangle with 3 120-degree
103e12c5d1SDavid du Colombier * angles and one straight side
113e12c5d1SDavid du Colombier * (b) map of this triangle onto half plane cut along
123e12c5d1SDavid du Colombier * 3 rays from the roots of unity to infinity
133e12c5d1SDavid du Colombier * formula (z^4+2*3^.5*z^2-1)/(z^4-2*3^.5*z^2-1)
143e12c5d1SDavid du Colombier * (c) do 3 times for each sector of plane:
153e12c5d1SDavid du Colombier * map of |arg z|<=pi/6, cut along z>1 into
163e12c5d1SDavid du Colombier * triangle |arg z|<=pi/6, Re z<=const,
173e12c5d1SDavid du Colombier * with upper side of cut going into upper half of
183e12c5d1SDavid du Colombier * of vertical side of triangle and lowere into lower
193e12c5d1SDavid du Colombier * formula int from 0 to z dz/sqrt(1-z^3)
203e12c5d1SDavid du Colombier *
213e12c5d1SDavid du Colombier * int from u to 1 3^.25*du/sqrt(1-u^3) =
223e12c5d1SDavid du Colombier F(acos((rt3-1+u)/(rt3+1-u)),sqrt(1/2+rt3/4))
233e12c5d1SDavid du Colombier * int from 1 to u 3^.25*du/sqrt(u^3-1) =
243e12c5d1SDavid du Colombier * F(acos((rt3+1-u)/(rt3-1+u)),sqrt(1/2-rt3/4))
253e12c5d1SDavid du Colombier * this latter formula extends analytically down to
263e12c5d1SDavid du Colombier * u=0 and is the basis of this routine, with the
273e12c5d1SDavid du Colombier * argument of complex elliptic integral elco2
283e12c5d1SDavid du Colombier * being tan(acos...)
293e12c5d1SDavid du Colombier * the formula F(pi-x,k) = 2*F(pi/2,k)-F(x,k) is
303e12c5d1SDavid du Colombier * used to cross over into the region where Re(acos...)>pi/2
313e12c5d1SDavid du Colombier * f0 and fpi are suitably scaled complete integrals
323e12c5d1SDavid du Colombier */
333e12c5d1SDavid du Colombier
343e12c5d1SDavid du Colombier #define TFUZZ 0.00001
353e12c5d1SDavid du Colombier
363e12c5d1SDavid du Colombier static struct place tpole[4]; /* point of tangency of tetrahedron face*/
37219b2ee8SDavid du Colombier static double tpoleinit[4][2] = {
383e12c5d1SDavid du Colombier 1., 0.,
393e12c5d1SDavid du Colombier 1., 180.,
403e12c5d1SDavid du Colombier -1., 90.,
413e12c5d1SDavid du Colombier -1., -90.
423e12c5d1SDavid du Colombier };
433e12c5d1SDavid du Colombier static struct tproj {
44219b2ee8SDavid du Colombier double tlat,tlon; /* center of stereo projection*/
45219b2ee8SDavid du Colombier double ttwist; /* rotatn before stereo*/
46219b2ee8SDavid du Colombier double trot; /*rotate after projection*/
473e12c5d1SDavid du Colombier struct place projpl; /*same as tlat,tlon*/
483e12c5d1SDavid du Colombier struct coord projtw; /*same as ttwist*/
493e12c5d1SDavid du Colombier struct coord postrot; /*same as trot*/
503e12c5d1SDavid du Colombier } tproj[4][4] = {
513e12c5d1SDavid du Colombier {/*00*/ {0.},
523e12c5d1SDavid du Colombier /*01*/ {90., 0., 90., -90.},
533e12c5d1SDavid du Colombier /*02*/ {0., 45., -45., 150.},
543e12c5d1SDavid du Colombier /*03*/ {0., -45., -135., 30.}
553e12c5d1SDavid du Colombier },
563e12c5d1SDavid du Colombier {/*10*/ {90., 0., -90., 90.},
573e12c5d1SDavid du Colombier /*11*/ {0.},
583e12c5d1SDavid du Colombier /*12*/ {0., 135., -135., -150.},
593e12c5d1SDavid du Colombier /*13*/ {0., -135., -45., -30.}
603e12c5d1SDavid du Colombier },
613e12c5d1SDavid du Colombier {/*20*/ {0., 45., 135., -30.},
623e12c5d1SDavid du Colombier /*21*/ {0., 135., 45., -150.},
633e12c5d1SDavid du Colombier /*22*/ {0.},
643e12c5d1SDavid du Colombier /*23*/ {-90., 0., 180., 90.}
653e12c5d1SDavid du Colombier },
663e12c5d1SDavid du Colombier {/*30*/ {0., -45., 45., -150.},
673e12c5d1SDavid du Colombier /*31*/ {0., -135., 135., -30.},
683e12c5d1SDavid du Colombier /*32*/ {-90., 0., 0., 90.},
693e12c5d1SDavid du Colombier /*33*/ {0.}
703e12c5d1SDavid du Colombier }};
71219b2ee8SDavid du Colombier static double tx[4] = { /*where to move facet after final rotation*/
723e12c5d1SDavid du Colombier 0., 0., -1., 1. /*-1,1 to be sqrt(3)*/
733e12c5d1SDavid du Colombier };
74219b2ee8SDavid du Colombier static double ty[4] = {
753e12c5d1SDavid du Colombier 0., 2., -1., -1.
763e12c5d1SDavid du Colombier };
773e12c5d1SDavid du Colombier static double root3;
78219b2ee8SDavid du Colombier static double rt3inv;
793e12c5d1SDavid du Colombier static double two_rt3;
803e12c5d1SDavid du Colombier static double tkc,tk,tcon;
81219b2ee8SDavid du Colombier static double f0r,f0i,fpir,fpii;
823e12c5d1SDavid du Colombier
833e12c5d1SDavid du Colombier static void
twhichp(struct place * g,int * p,int * q)843e12c5d1SDavid du Colombier twhichp(struct place *g, int *p, int *q)
853e12c5d1SDavid du Colombier {
863e12c5d1SDavid du Colombier int i,j,k;
87219b2ee8SDavid du Colombier double cosdist[4];
883e12c5d1SDavid du Colombier struct place *tp;
893e12c5d1SDavid du Colombier for(i=0;i<4;i++) {
903e12c5d1SDavid du Colombier tp = &tpole[i];
913e12c5d1SDavid du Colombier cosdist[i] = g->nlat.s*tp->nlat.s +
923e12c5d1SDavid du Colombier g->nlat.c*tp->nlat.c*(
933e12c5d1SDavid du Colombier g->wlon.s*tp->wlon.s +
943e12c5d1SDavid du Colombier g->wlon.c*tp->wlon.c);
953e12c5d1SDavid du Colombier }
963e12c5d1SDavid du Colombier j = 0;
973e12c5d1SDavid du Colombier for(i=1;i<4;i++)
983e12c5d1SDavid du Colombier if(cosdist[i] > cosdist[j])
993e12c5d1SDavid du Colombier j = i;
1003e12c5d1SDavid du Colombier *p = j;
1013e12c5d1SDavid du Colombier k = j==0?1:0;
1023e12c5d1SDavid du Colombier for(i=0;i<4;i++)
1033e12c5d1SDavid du Colombier if(i!=j&&cosdist[i]>cosdist[k])
1043e12c5d1SDavid du Colombier k = i;
1053e12c5d1SDavid du Colombier *q = k;
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier
1083e12c5d1SDavid du Colombier int
Xtetra(struct place * place,double * x,double * y)109219b2ee8SDavid du Colombier Xtetra(struct place *place, double *x, double *y)
1103e12c5d1SDavid du Colombier {
1113e12c5d1SDavid du Colombier int i,j;
1123e12c5d1SDavid du Colombier struct place pl;
1133e12c5d1SDavid du Colombier register struct tproj *tpp;
114219b2ee8SDavid du Colombier double vr, vi;
1153e12c5d1SDavid du Colombier double br, bi;
1163e12c5d1SDavid du Colombier double zr,zi,z2r,z2i,z4r,z4i,sr,si,tr,ti;
1173e12c5d1SDavid du Colombier twhichp(place,&i,&j);
1183e12c5d1SDavid du Colombier copyplace(place,&pl);
1193e12c5d1SDavid du Colombier norm(&pl,&tproj[i][j].projpl,&tproj[i][j].projtw);
1203e12c5d1SDavid du Colombier Xstereographic(&pl,&vr,&vi);
1213e12c5d1SDavid du Colombier zr = vr/2;
1223e12c5d1SDavid du Colombier zi = vi/2;
1233e12c5d1SDavid du Colombier if(zr<=TFUZZ)
1243e12c5d1SDavid du Colombier zr = TFUZZ;
1253e12c5d1SDavid du Colombier csq(zr,zi,&z2r,&z2i);
1263e12c5d1SDavid du Colombier csq(z2r,z2i,&z4r,&z4i);
1273e12c5d1SDavid du Colombier z2r *= two_rt3;
1283e12c5d1SDavid du Colombier z2i *= two_rt3;
1293e12c5d1SDavid du Colombier cdiv(z4r+z2r-1,z4i+z2i,z4r-z2r-1,z4i-z2i,&sr,&si);
1303e12c5d1SDavid du Colombier csqrt(sr-1,si,&tr,&ti);
1313e12c5d1SDavid du Colombier cdiv(tcon*tr,tcon*ti,root3+1-sr,-si,&br,&bi);
1323e12c5d1SDavid du Colombier if(br<0) {
1333e12c5d1SDavid du Colombier br = -br;
1343e12c5d1SDavid du Colombier bi = -bi;
1353e12c5d1SDavid du Colombier if(!elco2(br,bi,tk,1.,1.,&vr,&vi))
1363e12c5d1SDavid du Colombier return 0;
1373e12c5d1SDavid du Colombier vr = fpir - vr;
1383e12c5d1SDavid du Colombier vi = fpii - vi;
1393e12c5d1SDavid du Colombier } else
1403e12c5d1SDavid du Colombier if(!elco2(br,bi,tk,1.,1.,&vr,&vi))
1413e12c5d1SDavid du Colombier return 0;
1423e12c5d1SDavid du Colombier if(si>=0) {
1433e12c5d1SDavid du Colombier tr = f0r - vi;
1443e12c5d1SDavid du Colombier ti = f0i + vr;
1453e12c5d1SDavid du Colombier } else {
1463e12c5d1SDavid du Colombier tr = f0r + vi;
1473e12c5d1SDavid du Colombier ti = f0i - vr;
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier tpp = &tproj[i][j];
1503e12c5d1SDavid du Colombier *x = tr*tpp->postrot.c +
1513e12c5d1SDavid du Colombier ti*tpp->postrot.s + tx[i];
1523e12c5d1SDavid du Colombier *y = ti*tpp->postrot.c -
1533e12c5d1SDavid du Colombier tr*tpp->postrot.s + ty[i];
1543e12c5d1SDavid du Colombier return(1);
1553e12c5d1SDavid du Colombier }
1563e12c5d1SDavid du Colombier
1573e12c5d1SDavid du Colombier int
tetracut(struct place * g,struct place * og,double * cutlon)158219b2ee8SDavid du Colombier tetracut(struct place *g, struct place *og, double *cutlon)
1593e12c5d1SDavid du Colombier {
1603e12c5d1SDavid du Colombier int i,j,k;
1613e12c5d1SDavid du Colombier if((g->nlat.s<=-rt3inv&&og->nlat.s<=-rt3inv) &&
1623e12c5d1SDavid du Colombier (ckcut(g,og,*cutlon=0.)==2||ckcut(g,og,*cutlon=PI)==2))
1633e12c5d1SDavid du Colombier return(2);
1643e12c5d1SDavid du Colombier twhichp(g,&i,&k);
1653e12c5d1SDavid du Colombier twhichp(og,&j,&k);
1663e12c5d1SDavid du Colombier if(i==j||i==0||j==0)
1673e12c5d1SDavid du Colombier return(1);
1683e12c5d1SDavid du Colombier return(0);
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier
1713e12c5d1SDavid du Colombier proj
tetra(void)1723e12c5d1SDavid du Colombier tetra(void)
1733e12c5d1SDavid du Colombier {
1743e12c5d1SDavid du Colombier register i;
1753e12c5d1SDavid du Colombier int j;
1763e12c5d1SDavid du Colombier register struct place *tp;
1773e12c5d1SDavid du Colombier register struct tproj *tpp;
178219b2ee8SDavid du Colombier double t;
1793e12c5d1SDavid du Colombier root3 = sqrt(3.);
1803e12c5d1SDavid du Colombier rt3inv = 1/root3;
1813e12c5d1SDavid du Colombier two_rt3 = 2*root3;
1823e12c5d1SDavid du Colombier tkc = sqrt(.5-.25*root3);
1833e12c5d1SDavid du Colombier tk = sqrt(.5+.25*root3);
1843e12c5d1SDavid du Colombier tcon = 2*sqrt(root3);
1853e12c5d1SDavid du Colombier elco2(tcon/(root3-1),0.,tkc,1.,1.,&f0r,&f0i);
1863e12c5d1SDavid du Colombier elco2(1.e15,0.,tk,1.,1.,&fpir,&fpii);
1873e12c5d1SDavid du Colombier fpir *= 2;
1883e12c5d1SDavid du Colombier fpii *= 2;
1893e12c5d1SDavid du Colombier for(i=0;i<4;i++) {
1903e12c5d1SDavid du Colombier tx[i] *= f0r*root3;
1913e12c5d1SDavid du Colombier ty[i] *= f0r;
1923e12c5d1SDavid du Colombier tp = &tpole[i];
1933e12c5d1SDavid du Colombier t = tp->nlat.s = tpoleinit[i][0]/root3;
1943e12c5d1SDavid du Colombier tp->nlat.c = sqrt(1 - t*t);
1953e12c5d1SDavid du Colombier tp->nlat.l = atan2(tp->nlat.s,tp->nlat.c);
1963e12c5d1SDavid du Colombier deg2rad(tpoleinit[i][1],&tp->wlon);
1973e12c5d1SDavid du Colombier for(j=0;j<4;j++) {
1983e12c5d1SDavid du Colombier tpp = &tproj[i][j];
1993e12c5d1SDavid du Colombier latlon(tpp->tlat,tpp->tlon,&tpp->projpl);
2003e12c5d1SDavid du Colombier deg2rad(tpp->ttwist,&tpp->projtw);
2013e12c5d1SDavid du Colombier deg2rad(tpp->trot,&tpp->postrot);
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier }
2043e12c5d1SDavid du Colombier return(Xtetra);
2053e12c5d1SDavid du Colombier }
2063e12c5d1SDavid du Colombier
207