xref: /plan9/sys/src/cmd/map/libmap/zcoord.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1*59cc4ca5SDavid du Colombier #include <u.h>
2*59cc4ca5SDavid du Colombier #include <libc.h>
3*59cc4ca5SDavid du Colombier #include <stdio.h>
43e12c5d1SDavid du Colombier #include "map.h"
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier static double cirmod(double);
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier static struct place pole;	/* map pole is tilted to here */
93e12c5d1SDavid du Colombier static struct coord twist;	/* then twisted this much */
103e12c5d1SDavid du Colombier static struct place ipole;	/* inverse transfrom */
113e12c5d1SDavid du Colombier static struct coord itwist;
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier void
orient(double lat,double lon,double theta)14219b2ee8SDavid du Colombier orient(double lat, double lon, double theta)
153e12c5d1SDavid du Colombier {
163e12c5d1SDavid du Colombier 	lat = cirmod(lat);
173e12c5d1SDavid du Colombier 	if(lat>90.) {
183e12c5d1SDavid du Colombier 		lat = 180. - lat;
193e12c5d1SDavid du Colombier 		lon -= 180.;
203e12c5d1SDavid du Colombier 		theta -= 180.;
213e12c5d1SDavid du Colombier 	} else if(lat < -90.) {
223e12c5d1SDavid du Colombier 		lat = -180. - lat;
233e12c5d1SDavid du Colombier 		lon -= 180.;
243e12c5d1SDavid du Colombier 		theta -= 180;
253e12c5d1SDavid du Colombier 	}
263e12c5d1SDavid du Colombier 	latlon(lat,lon,&pole);
273e12c5d1SDavid du Colombier 	deg2rad(theta, &twist);
283e12c5d1SDavid du Colombier 	latlon(lat,180.-theta,&ipole);
293e12c5d1SDavid du Colombier 	deg2rad(180.-lon, &itwist);
303e12c5d1SDavid du Colombier }
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier void
latlon(double lat,double lon,struct place * p)33219b2ee8SDavid du Colombier latlon(double lat, double lon, struct place *p)
343e12c5d1SDavid du Colombier {
353e12c5d1SDavid du Colombier 	lat = cirmod(lat);
363e12c5d1SDavid du Colombier 	if(lat>90.) {
373e12c5d1SDavid du Colombier 		lat = 180. - lat;
383e12c5d1SDavid du Colombier 		lon -= 180.;
393e12c5d1SDavid du Colombier 	} else if(lat < -90.) {
403e12c5d1SDavid du Colombier 		lat = -180. - lat;
413e12c5d1SDavid du Colombier 		lon -= 180.;
423e12c5d1SDavid du Colombier 	}
433e12c5d1SDavid du Colombier 	deg2rad(lat,&p->nlat);
443e12c5d1SDavid du Colombier 	deg2rad(lon,&p->wlon);
453e12c5d1SDavid du Colombier }
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier void
deg2rad(double theta,struct coord * coord)48219b2ee8SDavid du Colombier deg2rad(double theta, struct coord *coord)
493e12c5d1SDavid du Colombier {
503e12c5d1SDavid du Colombier 	theta = cirmod(theta);
513e12c5d1SDavid du Colombier 	coord->l = theta*RAD;
523e12c5d1SDavid du Colombier 	if(theta==90) {
533e12c5d1SDavid du Colombier 		coord->s = 1;
543e12c5d1SDavid du Colombier 		coord->c = 0;
553e12c5d1SDavid du Colombier 	} else if(theta== -90) {
563e12c5d1SDavid du Colombier 		coord->s = -1;
573e12c5d1SDavid du Colombier 		coord->c = 0;
583e12c5d1SDavid du Colombier 	} else
593e12c5d1SDavid du Colombier 		sincos(coord);
603e12c5d1SDavid du Colombier }
613e12c5d1SDavid du Colombier 
623e12c5d1SDavid du Colombier static double
cirmod(double theta)633e12c5d1SDavid du Colombier cirmod(double theta)
643e12c5d1SDavid du Colombier {
653e12c5d1SDavid du Colombier 	while(theta >= 180.)
663e12c5d1SDavid du Colombier 		theta -= 360;
673e12c5d1SDavid du Colombier 	while(theta<-180.)
683e12c5d1SDavid du Colombier 		theta += 360.;
693e12c5d1SDavid du Colombier 	return(theta);
703e12c5d1SDavid du Colombier }
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier void
sincos(struct coord * coord)733e12c5d1SDavid du Colombier sincos(struct coord *coord)
743e12c5d1SDavid du Colombier {
753e12c5d1SDavid du Colombier 	coord->s = sin(coord->l);
763e12c5d1SDavid du Colombier 	coord->c = cos(coord->l);
773e12c5d1SDavid du Colombier }
783e12c5d1SDavid du Colombier 
793e12c5d1SDavid du Colombier void
normalize(struct place * gg)803e12c5d1SDavid du Colombier normalize(struct place *gg)
813e12c5d1SDavid du Colombier {
823e12c5d1SDavid du Colombier 	norm(gg,&pole,&twist);
833e12c5d1SDavid du Colombier }
843e12c5d1SDavid du Colombier 
853e12c5d1SDavid du Colombier void
invert(struct place * g)863e12c5d1SDavid du Colombier invert(struct place *g)
873e12c5d1SDavid du Colombier {
883e12c5d1SDavid du Colombier 	norm(g,&ipole,&itwist);
893e12c5d1SDavid du Colombier }
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier void
norm(struct place * gg,struct place * pp,struct coord * tw)923e12c5d1SDavid du Colombier norm(struct place *gg, struct place *pp, struct coord *tw)
933e12c5d1SDavid du Colombier {
943e12c5d1SDavid du Colombier 	register struct place *g;	/*geographic coords */
953e12c5d1SDavid du Colombier 	register struct place *p;	/* new pole in old coords*/
963e12c5d1SDavid du Colombier 	struct place m;			/* standard map coords*/
973e12c5d1SDavid du Colombier 	g = gg;
983e12c5d1SDavid du Colombier 	p = pp;
993e12c5d1SDavid du Colombier 	if(p->nlat.s == 1.) {
1003e12c5d1SDavid du Colombier 		if(p->wlon.l+tw->l == 0.)
1013e12c5d1SDavid du Colombier 			return;
1023e12c5d1SDavid du Colombier 		g->wlon.l -= p->wlon.l+tw->l;
1033e12c5d1SDavid du Colombier 	} else {
1043e12c5d1SDavid du Colombier 		if(p->wlon.l != 0) {
1053e12c5d1SDavid du Colombier 			g->wlon.l -= p->wlon.l;
1063e12c5d1SDavid du Colombier 			sincos(&g->wlon);
1073e12c5d1SDavid du Colombier 		}
1083e12c5d1SDavid du Colombier 		m.nlat.s = p->nlat.s * g->nlat.s
1093e12c5d1SDavid du Colombier 			+ p->nlat.c * g->nlat.c * g->wlon.c;
1103e12c5d1SDavid du Colombier 		m.nlat.c = sqrt(1. - m.nlat.s * m.nlat.s);
1113e12c5d1SDavid du Colombier 		m.nlat.l = atan2(m.nlat.s, m.nlat.c);
1123e12c5d1SDavid du Colombier 		m.wlon.s = g->nlat.c * g->wlon.s;
1133e12c5d1SDavid du Colombier 		m.wlon.c = p->nlat.c * g->nlat.s
1143e12c5d1SDavid du Colombier 			- p->nlat.s * g->nlat.c * g->wlon.c;
1153e12c5d1SDavid du Colombier 		m.wlon.l = atan2(m.wlon.s, - m.wlon.c)
1163e12c5d1SDavid du Colombier 			- tw->l;
1173e12c5d1SDavid du Colombier 		*g = m;
1183e12c5d1SDavid du Colombier 	}
1193e12c5d1SDavid du Colombier 	sincos(&g->wlon);
1203e12c5d1SDavid du Colombier 	if(g->wlon.l>PI)
1213e12c5d1SDavid du Colombier 		g->wlon.l -= 2*PI;
1223e12c5d1SDavid du Colombier 	else if(g->wlon.l<-PI)
1233e12c5d1SDavid du Colombier 		g->wlon.l += 2*PI;
1243e12c5d1SDavid du Colombier }
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier double
tan(double x)1273e12c5d1SDavid du Colombier tan(double x)
1283e12c5d1SDavid du Colombier {
1293e12c5d1SDavid du Colombier 	return(sin(x)/cos(x));
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier void
printp(struct place * g)1333e12c5d1SDavid du Colombier printp(struct place *g)
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier printf("%.3f %.3f %.3f %.3f %.3f %.3f\n",
1363e12c5d1SDavid du Colombier g->nlat.l,g->nlat.s,g->nlat.c,g->wlon.l,g->wlon.s,g->wlon.c);
1373e12c5d1SDavid du Colombier }
1383e12c5d1SDavid du Colombier 
1393e12c5d1SDavid du Colombier void
copyplace(struct place * g1,struct place * g2)1403e12c5d1SDavid du Colombier copyplace(struct place *g1, struct place *g2)
1413e12c5d1SDavid du Colombier {
1423e12c5d1SDavid du Colombier 	*g2 = *g1;
1433e12c5d1SDavid du Colombier }
144