xref: /plan9/sys/src/cmd/map/libmap/homing.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
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 static struct coord p0;		/* standard parallel */
63e12c5d1SDavid du Colombier 
7219b2ee8SDavid du Colombier int first;
8219b2ee8SDavid du Colombier 
93e12c5d1SDavid du Colombier static double
trigclamp(double x)103e12c5d1SDavid du Colombier trigclamp(double x)
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	return x>1? 1: x<-1? -1: x;
133e12c5d1SDavid du Colombier }
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier static struct coord az;		/* azimuth of p0 seen from place */
163e12c5d1SDavid du Colombier static struct coord rad;	/* angular dist from place to p0 */
173e12c5d1SDavid du Colombier 
183e12c5d1SDavid du Colombier static int
azimuth(struct place * place)193e12c5d1SDavid du Colombier azimuth(struct place *place)
203e12c5d1SDavid du Colombier {
21219b2ee8SDavid du Colombier 	if(place->nlat.c < FUZZ) {
22219b2ee8SDavid du Colombier 		az.l = PI/2 + place->nlat.l - place->wlon.l;
23219b2ee8SDavid du Colombier 		sincos(&az);
24219b2ee8SDavid du Colombier 		rad.l = fabs(place->nlat.l - p0.l);
25219b2ee8SDavid du Colombier 		if(rad.l > PI)
26219b2ee8SDavid du Colombier 			rad.l = 2*PI - rad.l;
27219b2ee8SDavid du Colombier 		sincos(&rad);
28219b2ee8SDavid du Colombier 		return 1;
29219b2ee8SDavid du Colombier 	}
303e12c5d1SDavid du Colombier 	rad.c = trigclamp(p0.s*place->nlat.s +	/* law of cosines */
313e12c5d1SDavid du Colombier 		p0.c*place->nlat.c*place->wlon.c);
323e12c5d1SDavid du Colombier 	rad.s = sqrt(1 - rad.c*rad.c);
333e12c5d1SDavid du Colombier 	if(fabs(rad.s) < .001) {
343e12c5d1SDavid du Colombier 		az.s = 0;
353e12c5d1SDavid du Colombier 		az.c = 1;
363e12c5d1SDavid du Colombier 	} else {
373e12c5d1SDavid du Colombier 		az.s = trigclamp(p0.c*place->wlon.s/rad.s); /* sines */
383e12c5d1SDavid du Colombier 		az.c = trigclamp((p0.s - rad.c*place->nlat.s)
393e12c5d1SDavid du Colombier 				/(rad.s*place->nlat.c));
403e12c5d1SDavid du Colombier 	}
413e12c5d1SDavid du Colombier 	rad.l = atan2(rad.s, rad.c);
423e12c5d1SDavid du Colombier 	return 1;
433e12c5d1SDavid du Colombier }
443e12c5d1SDavid du Colombier 
453e12c5d1SDavid du Colombier static int
Xmecca(struct place * place,double * x,double * y)46219b2ee8SDavid du Colombier Xmecca(struct place *place, double *x, double *y)
473e12c5d1SDavid du Colombier {
483e12c5d1SDavid du Colombier 	if(!azimuth(place))
493e12c5d1SDavid du Colombier 		return 0;
503e12c5d1SDavid du Colombier 	*x = -place->wlon.l;
513e12c5d1SDavid du Colombier 	*y = fabs(az.s)<.02? -az.c*rad.s/p0.c: *x*az.c/az.s;
52219b2ee8SDavid du Colombier 	return fabs(*y)>2? -1:
53219b2ee8SDavid du Colombier 	       rad.c<0? 0:
543e12c5d1SDavid du Colombier 	       1;
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier proj
mecca(double par)58219b2ee8SDavid du Colombier mecca(double par)
593e12c5d1SDavid du Colombier {
60219b2ee8SDavid du Colombier 	first = 1;
613e12c5d1SDavid du Colombier 	if(fabs(par)>80.)
623e12c5d1SDavid du Colombier 		return(0);
633e12c5d1SDavid du Colombier 	deg2rad(par,&p0);
643e12c5d1SDavid du Colombier 	return(Xmecca);
653e12c5d1SDavid du Colombier }
663e12c5d1SDavid du Colombier 
673e12c5d1SDavid du Colombier static int
Xhoming(struct place * place,double * x,double * y)68219b2ee8SDavid du Colombier Xhoming(struct place *place, double *x, double *y)
693e12c5d1SDavid du Colombier {
703e12c5d1SDavid du Colombier 	if(!azimuth(place))
713e12c5d1SDavid du Colombier 		return 0;
723e12c5d1SDavid du Colombier 	*x = -rad.l*az.s;
733e12c5d1SDavid du Colombier 	*y = -rad.l*az.c;
74219b2ee8SDavid du Colombier 	return place->wlon.c<0? 0: 1;
753e12c5d1SDavid du Colombier }
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier proj
homing(double par)78219b2ee8SDavid du Colombier homing(double par)
793e12c5d1SDavid du Colombier {
80219b2ee8SDavid du Colombier 	first = 1;
813e12c5d1SDavid du Colombier 	if(fabs(par)>80.)
823e12c5d1SDavid du Colombier 		return(0);
833e12c5d1SDavid du Colombier 	deg2rad(par,&p0);
843e12c5d1SDavid du Colombier 	return(Xhoming);
853e12c5d1SDavid du Colombier }
86219b2ee8SDavid du Colombier 
87219b2ee8SDavid du Colombier int
hlimb(double * lat,double * lon,double res)88219b2ee8SDavid du Colombier hlimb(double *lat, double *lon, double res)
89219b2ee8SDavid du Colombier {
90219b2ee8SDavid du Colombier 	if(first) {
91219b2ee8SDavid du Colombier 		*lon = -90;
92219b2ee8SDavid du Colombier 		*lat = -90;
93219b2ee8SDavid du Colombier 		first = 0;
94219b2ee8SDavid du Colombier 		return 0;
95219b2ee8SDavid du Colombier 	}
96219b2ee8SDavid du Colombier 	*lat += res;
97219b2ee8SDavid du Colombier 	if(*lat <= 90)
98219b2ee8SDavid du Colombier 		return 1;
99219b2ee8SDavid du Colombier 	if(*lon == 90)
100219b2ee8SDavid du Colombier 		return -1;
101219b2ee8SDavid du Colombier 	*lon = 90;
102219b2ee8SDavid du Colombier 	*lat = -90;
103219b2ee8SDavid du Colombier 	return 0;
104219b2ee8SDavid du Colombier }
105219b2ee8SDavid du Colombier 
106219b2ee8SDavid du Colombier int
mlimb(double * lat,double * lon,double res)107219b2ee8SDavid du Colombier mlimb(double *lat, double *lon, double res)
108219b2ee8SDavid du Colombier {
109219b2ee8SDavid du Colombier 	int ret = !first;
110219b2ee8SDavid du Colombier 	if(fabs(p0.s) < .01)
111219b2ee8SDavid du Colombier 		return -1;
112219b2ee8SDavid du Colombier 	if(first) {
113219b2ee8SDavid du Colombier 		*lon = -180;
114219b2ee8SDavid du Colombier 		first = 0;
115219b2ee8SDavid du Colombier 	} else
116219b2ee8SDavid du Colombier 		*lon += res;
117219b2ee8SDavid du Colombier 	if(*lon > 180)
118219b2ee8SDavid du Colombier 		return -1;
119219b2ee8SDavid du Colombier 	*lat = atan(-cos(*lon*RAD)/p0.s*p0.c)/RAD;
120219b2ee8SDavid du Colombier 	return ret;
121219b2ee8SDavid du Colombier }
122