xref: /plan9/sys/src/cmd/map/route.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1*59cc4ca5SDavid du Colombier #include <u.h>
2*59cc4ca5SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include "map.h"
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier /* Given two lat-lon pairs, find an orientation for the
67dd7cddfSDavid du Colombier    -o option of "map" that will place those two points
77dd7cddfSDavid du Colombier    on the equator of a standard projection, equally spaced
87dd7cddfSDavid du Colombier    about the prime meridian.
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier    -w and -l options are suggested also.
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier    Option -t prints out a series of
137dd7cddfSDavid du Colombier    coordinates that follows the (great circle) track
147dd7cddfSDavid du Colombier    in the original coordinate system,
157dd7cddfSDavid du Colombier    followed by ".
167dd7cddfSDavid du Colombier    This data is just right for map -t.
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier    Option -i inverts the map top-to-bottom.
197dd7cddfSDavid du Colombier */
207dd7cddfSDavid du Colombier struct place pole;
217dd7cddfSDavid du Colombier struct coord twist;
227dd7cddfSDavid du Colombier int track;
237dd7cddfSDavid du Colombier int inv = -1;
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier extern void doroute(double, double, double, double, double);
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier void
dorot(double a,double b,double * x,double * y,void (* f)(struct place *))287dd7cddfSDavid du Colombier dorot(double a, double b, double *x, double *y, void (*f)(struct place *))
297dd7cddfSDavid du Colombier {
307dd7cddfSDavid du Colombier 	struct place g;
317dd7cddfSDavid du Colombier 	deg2rad(a,&g.nlat);
327dd7cddfSDavid du Colombier 	deg2rad(b,&g.wlon);
337dd7cddfSDavid du Colombier 	(*f)(&g);
347dd7cddfSDavid du Colombier 	*x = g.nlat.l/RAD;
357dd7cddfSDavid du Colombier 	*y = g.wlon.l/RAD;
367dd7cddfSDavid du Colombier }
377dd7cddfSDavid du Colombier 
387dd7cddfSDavid du Colombier void
rotate(double a,double b,double * x,double * y)397dd7cddfSDavid du Colombier rotate(double a, double b, double *x, double *y)
407dd7cddfSDavid du Colombier {
417dd7cddfSDavid du Colombier 	dorot(a,b,x,y,normalize);
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier void
rinvert(double a,double b,double * x,double * y)457dd7cddfSDavid du Colombier rinvert(double a, double b, double *x, double *y)
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier 	dorot(a,b,x,y,invert);
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier 
main(int argc,char ** argv)507dd7cddfSDavid du Colombier main(int argc, char **argv)
517dd7cddfSDavid du Colombier {
527dd7cddfSDavid du Colombier #pragma ref argv
537dd7cddfSDavid du Colombier 	double an,aw,bn,bw;
547dd7cddfSDavid du Colombier 	ARGBEGIN {
557dd7cddfSDavid du Colombier 	case 't':
567dd7cddfSDavid du Colombier 		track = 1;
577dd7cddfSDavid du Colombier 		break;
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier 	case 'i':
607dd7cddfSDavid du Colombier 		inv = 1;
617dd7cddfSDavid du Colombier 		break;
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier 	default:
647dd7cddfSDavid du Colombier 		exits("route: bad option");
657dd7cddfSDavid du Colombier 	} ARGEND;
667dd7cddfSDavid du Colombier 	if (argc<4) {
677dd7cddfSDavid du Colombier 		print("use route [-t] [-i] lat lon lat lon\n");
687dd7cddfSDavid du Colombier 		exits("arg count");
697dd7cddfSDavid du Colombier 	}
707dd7cddfSDavid du Colombier 	an = atof(argv[0]);
717dd7cddfSDavid du Colombier 	aw = atof(argv[1]);
727dd7cddfSDavid du Colombier 	bn = atof(argv[2]);
737dd7cddfSDavid du Colombier 	bw = atof(argv[3]);
747dd7cddfSDavid du Colombier 	doroute(inv*90.,an,aw,bn,bw);
757dd7cddfSDavid du Colombier 	return 0;
767dd7cddfSDavid du Colombier }
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier void
doroute(double dir,double an,double aw,double bn,double bw)797dd7cddfSDavid du Colombier doroute(double dir, double an, double aw, double bn, double bw)
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier 	double an1,aw1,bn1,bw1,pn,pw;
827dd7cddfSDavid du Colombier 	double theta;
837dd7cddfSDavid du Colombier 	double cn,cw,cn1,cw1;
847dd7cddfSDavid du Colombier 	int i,n;
857dd7cddfSDavid du Colombier 	orient(an,aw,0.);
867dd7cddfSDavid du Colombier 	rotate(bn,bw,&bn1,&bw1);
877dd7cddfSDavid du Colombier /*	printf("b %f %f\n",bn1,bw1);*/
887dd7cddfSDavid du Colombier 	orient(an,aw,bw1);
897dd7cddfSDavid du Colombier 	rinvert(0.,dir,&pn,&pw);
907dd7cddfSDavid du Colombier /*	printf("p %f %f\n",pn,pw);*/
917dd7cddfSDavid du Colombier 	orient(pn,pw,0.);
927dd7cddfSDavid du Colombier 	rotate(an,aw,&an1,&aw1);
937dd7cddfSDavid du Colombier 	rotate(bn,bw,&bn1,&bw1);
947dd7cddfSDavid du Colombier 	theta = (aw1+bw1)/2;
957dd7cddfSDavid du Colombier /*	printf("a %f %f \n",an1,aw1);*/
967dd7cddfSDavid du Colombier 	orient(pn,pw,theta);
977dd7cddfSDavid du Colombier 	rotate(an,aw,&an1,&aw1);
987dd7cddfSDavid du Colombier 	rotate(bn,bw,&bn1,&bw1);
997dd7cddfSDavid du Colombier 	if(fabs(aw1-bw1)>180)
1007dd7cddfSDavid du Colombier 		if(theta<0.) theta+=180;
1017dd7cddfSDavid du Colombier 		else theta -= 180;
1027dd7cddfSDavid du Colombier 	orient(pn,pw,theta);
1037dd7cddfSDavid du Colombier 	rotate(an,aw,&an1,&aw1);
1047dd7cddfSDavid du Colombier 	rotate(bn,bw,&bn1,&bw1);
1057dd7cddfSDavid du Colombier 	if(!track) {
1067dd7cddfSDavid du Colombier 		double dlat, dlon, t;
1077dd7cddfSDavid du Colombier 		/* printf("A %.4f %.4f\n",an1,aw1); */
1087dd7cddfSDavid du Colombier 		/* printf("B %.4f %.4f\n",bn1,bw1); */
1097dd7cddfSDavid du Colombier 		cw1 = fabs(bw1-aw1);	/* angular difference for map margins */
1107dd7cddfSDavid du Colombier 		/* while (aw<0.0)
1117dd7cddfSDavid du Colombier 			aw += 360.;
1127dd7cddfSDavid du Colombier 		while (bw<0.0)
1137dd7cddfSDavid du Colombier 			bw += 360.; */
1147dd7cddfSDavid du Colombier 		dlon = fabs(aw-bw);
1157dd7cddfSDavid du Colombier 		if (dlon>180)
1167dd7cddfSDavid du Colombier 			dlon = 360-dlon;
1177dd7cddfSDavid du Colombier 		dlat = fabs(an-bn);
1187dd7cddfSDavid du Colombier 		printf("-o %.4f %.4f %.4f -w %.2f %.2f %.2f %.2f \n",
1197dd7cddfSDavid du Colombier 		  pn,pw,theta, -0.3*cw1, .3*cw1, -.6*cw1, .6*cw1);
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier 	} else {
1227dd7cddfSDavid du Colombier 		cn1 = 0;
1237dd7cddfSDavid du Colombier 		n = 1 + fabs(bw1-aw1)/.2;
1247dd7cddfSDavid du Colombier 		for(i=0;i<=n;i++) {
1257dd7cddfSDavid du Colombier 			cw1 = aw1 + i*(bw1-aw1)/n;
1267dd7cddfSDavid du Colombier 			rinvert(cn1,cw1,&cn,&cw);
1277dd7cddfSDavid du Colombier 			printf("%f %f\n",cn,cw);
1287dd7cddfSDavid du Colombier 		}
1297dd7cddfSDavid du Colombier 		printf("\"\n");
1307dd7cddfSDavid du Colombier 	}
1317dd7cddfSDavid du Colombier }
132