xref: /plan9/sys/src/cmd/map/libmap/twocirc.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 double
quadratic(double a,double b,double c)63e12c5d1SDavid du Colombier quadratic(double a, double b, double c)
73e12c5d1SDavid du Colombier {
83e12c5d1SDavid du Colombier 	double disc = b*b - 4*a*c;
93e12c5d1SDavid du Colombier 	return disc<0? 0: (-b-sqrt(disc))/(2*a);
103e12c5d1SDavid du Colombier }
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier /* for projections with meridians being circles centered
133e12c5d1SDavid du Colombier on the x axis and parallels being circles centered on the y
143e12c5d1SDavid du Colombier axis.  Find the intersection of the meridian thru (m,0), (90,0),
153e12c5d1SDavid du Colombier with the parallel thru (0,p), (p1,p2) */
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier static int
twocircles(double m,double p,double p1,double p2,double * x,double * y)18219b2ee8SDavid du Colombier twocircles(double m, double p, double p1, double p2, double *x, double *y)
193e12c5d1SDavid du Colombier {
20219b2ee8SDavid du Colombier 	double a;	/* center of meridian circle, a>0 */
21219b2ee8SDavid du Colombier 	double b;	/* center of parallel circle, b>0 */
22219b2ee8SDavid du Colombier 	double t,bb;
233e12c5d1SDavid du Colombier 	if(m > 0) {
243e12c5d1SDavid du Colombier 		twocircles(-m,p,p1,p2,x,y);
253e12c5d1SDavid du Colombier 		*x = -*x;
263e12c5d1SDavid du Colombier 	} else if(p < 0) {
273e12c5d1SDavid du Colombier 		twocircles(m,-p,p1,-p2,x,y);
283e12c5d1SDavid du Colombier 		*y = -*y;
293e12c5d1SDavid du Colombier 	} else if(p < .01) {
303e12c5d1SDavid du Colombier 		*x = m;
313e12c5d1SDavid du Colombier 		t = m/p1;
323e12c5d1SDavid du Colombier 		*y = p + (p2-p)*t*t;
333e12c5d1SDavid du Colombier 	} else if(m > -.01) {
343e12c5d1SDavid du Colombier 		*y = p;
353e12c5d1SDavid du Colombier 		*x = m - m*p*p;
363e12c5d1SDavid du Colombier 	} else {
373e12c5d1SDavid du Colombier 		b = p>=1? 1: p>.99? 0.5*(p+1 + p1*p1/(1-p)):
383e12c5d1SDavid du Colombier 			0.5*(p*p-p1*p1-p2*p2)/(p-p2);
393e12c5d1SDavid du Colombier 		a = .5*(m - 1/m);
403e12c5d1SDavid du Colombier 		t = m*m-p*p+2*(b*p-a*m);
413e12c5d1SDavid du Colombier 		bb = b*b;
423e12c5d1SDavid du Colombier 		*x = quadratic(1+a*a/bb, -2*a + a*t/bb,
433e12c5d1SDavid du Colombier 			t*t/(4*bb) - m*m + 2*a*m);
443e12c5d1SDavid du Colombier 		*y = (*x*a+t/2)/b;
453e12c5d1SDavid du Colombier 	}
463e12c5d1SDavid du Colombier 	return 1;
473e12c5d1SDavid du Colombier }
483e12c5d1SDavid du Colombier 
493e12c5d1SDavid du Colombier static int
Xglobular(struct place * place,double * x,double * y)50219b2ee8SDavid du Colombier Xglobular(struct place *place, double *x, double *y)
513e12c5d1SDavid du Colombier {
523e12c5d1SDavid du Colombier 	twocircles(-2*place->wlon.l/PI,
533e12c5d1SDavid du Colombier 		2*place->nlat.l/PI, place->nlat.c, place->nlat.s, x, y);
543e12c5d1SDavid du Colombier 	return 1;
553e12c5d1SDavid du Colombier }
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier proj
globular(void)583e12c5d1SDavid du Colombier globular(void)
593e12c5d1SDavid du Colombier {
603e12c5d1SDavid du Colombier 	return Xglobular;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier 
633e12c5d1SDavid du Colombier static int
Xvandergrinten(struct place * place,double * x,double * y)64219b2ee8SDavid du Colombier Xvandergrinten(struct place *place, double *x, double *y)
653e12c5d1SDavid du Colombier {
663e12c5d1SDavid du Colombier 	double t = 2*place->nlat.l/PI;
673e12c5d1SDavid du Colombier 	double abst = fabs(t);
683e12c5d1SDavid du Colombier 	double pval = abst>=1? 1: abst/(1+sqrt(1-t*t));
693e12c5d1SDavid du Colombier 	double p2 = 2*pval/(1+pval);
703e12c5d1SDavid du Colombier 	twocircles(-place->wlon.l/PI, pval, sqrt(1-p2*p2), p2, x, y);
713e12c5d1SDavid du Colombier 	if(t < 0)
723e12c5d1SDavid du Colombier 		*y = -*y;
733e12c5d1SDavid du Colombier 	return 1;
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier proj
vandergrinten(void)773e12c5d1SDavid du Colombier vandergrinten(void)
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier 	return Xvandergrinten;
803e12c5d1SDavid du Colombier }
81