tetra.c 4.8 KB

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