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