xref: /plan9/sys/src/cmd/map/map.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
159cc4ca5SDavid du Colombier #include <u.h>
259cc4ca5SDavid du Colombier #include <libc.h>
359cc4ca5SDavid du Colombier #include <stdio.h>
43e12c5d1SDavid du Colombier #include "map.h"
57dd7cddfSDavid du Colombier #include "iplot.h"
63e12c5d1SDavid du Colombier 
73e12c5d1SDavid du Colombier #define NVERT 20	/* max number of vertices in a -v polygon */
83e12c5d1SDavid du Colombier #define HALFWIDTH 8192	/* output scaled to fit in -HALFWIDTH,HALFWIDTH */
93e12c5d1SDavid du Colombier #define LONGLINES (HALFWIDTH*4)	/* permissible segment lengths */
103e12c5d1SDavid du Colombier #define SHORTLINES (HALFWIDTH/8)
113e12c5d1SDavid du Colombier #define SCALERATIO 10	/* of abs to rel data (see map(5)) */
123e12c5d1SDavid du Colombier #define RESOL 2.	/* coarsest resolution for tracing grid (degrees) */
133e12c5d1SDavid du Colombier #define TWO_THRD 0.66666666666666667
143e12c5d1SDavid du Colombier 
15219b2ee8SDavid du Colombier int normproj(double, double, double *, double *);
16219b2ee8SDavid du Colombier int posproj(double, double, double *, double *);
17219b2ee8SDavid du Colombier int picut(struct place *, struct place *, double *);
18219b2ee8SDavid du Colombier double reduce(double);
193e12c5d1SDavid du Colombier short getshort(FILE *);
203e12c5d1SDavid du Colombier char *mapindex(char *);
213e12c5d1SDavid du Colombier proj projection;
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier 
243e12c5d1SDavid du Colombier static char *mapdir = "/lib/map";	/* default map directory */
25219b2ee8SDavid du Colombier struct file {
26219b2ee8SDavid du Colombier 	char *name;
27219b2ee8SDavid du Colombier 	char *color;
28219b2ee8SDavid du Colombier 	char *style;
293e12c5d1SDavid du Colombier };
30219b2ee8SDavid du Colombier static struct file dfltfile = {
31219b2ee8SDavid du Colombier 	"world", BLACK, SOLID	/* default map */
32219b2ee8SDavid du Colombier };
33219b2ee8SDavid du Colombier static struct file *file = &dfltfile;	/* list of map files */
34219b2ee8SDavid du Colombier static int nfile = 1;			/* length of list */
35219b2ee8SDavid du Colombier static char *currcolor = BLACK;		/* current color */
36219b2ee8SDavid du Colombier static char *gridcolor = BLACK;
37219b2ee8SDavid du Colombier static char *bordcolor = BLACK;
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier extern struct index index[];
403e12c5d1SDavid du Colombier int halfwidth = HALFWIDTH;
413e12c5d1SDavid du Colombier 
42219b2ee8SDavid du Colombier static int (*cut)(struct place *, struct place *, double *);
43219b2ee8SDavid du Colombier static int (*limb)(double*, double*, double);
44219b2ee8SDavid du Colombier static void dolimb(void);
45219b2ee8SDavid du Colombier static int onlimb;
463e12c5d1SDavid du Colombier static int poles;
47219b2ee8SDavid du Colombier static double orientation[3] = { 90., 0., 0. };	/* -o option */
483e12c5d1SDavid du Colombier static oriented;	/* nonzero if -o option occurred */
493e12c5d1SDavid du Colombier static upright;		/* 1 if orientation[0]==90, -1 if -90, else 0*/
503e12c5d1SDavid du Colombier static int delta = 1;	/* -d setting */
51219b2ee8SDavid du Colombier static double limits[4] = {	/* -l parameters */
523e12c5d1SDavid du Colombier 	-90., 90., -180., 180.
533e12c5d1SDavid du Colombier };
54219b2ee8SDavid du Colombier static double klimits[4] = {	/* -k parameters */
553e12c5d1SDavid du Colombier 	-90., 90., -180., 180.
563e12c5d1SDavid du Colombier };
573e12c5d1SDavid du Colombier static int limcase;
58219b2ee8SDavid du Colombier static double rlimits[4];	/* limits expressed in radians */
59219b2ee8SDavid du Colombier static double lolat, hilat, lolon, hilon;
60219b2ee8SDavid du Colombier static double window[4] = {	/* option -w */
613e12c5d1SDavid du Colombier 	-90., 90., -180., 180.
623e12c5d1SDavid du Colombier };
633e12c5d1SDavid du Colombier static windowed;	/* nozero if option -w */
64219b2ee8SDavid du Colombier static struct vert { double x, y; } v[NVERT+2];	/*clipping polygon*/
65219b2ee8SDavid du Colombier static struct edge { double a, b, c; } e[NVERT]; /* coeffs for linear inequality */
663e12c5d1SDavid du Colombier static int nvert;	/* number of vertices in clipping polygon */
673e12c5d1SDavid du Colombier 
68219b2ee8SDavid du Colombier static double rwindow[4];	/* window, expressed in radians */
69219b2ee8SDavid du Colombier static double params[2];		/* projection params */
703e12c5d1SDavid du Colombier /* bounds on output values before scaling; found by coarse survey */
71219b2ee8SDavid du Colombier static double xmin = 100.;
72219b2ee8SDavid du Colombier static double xmax = -100.;
73219b2ee8SDavid du Colombier static double ymin = 100.;
74219b2ee8SDavid du Colombier static double ymax = -100.;
75219b2ee8SDavid du Colombier static double xcent, ycent;
76219b2ee8SDavid du Colombier static double xoff, yoff;
77219b2ee8SDavid du Colombier double xrange, yrange;
783e12c5d1SDavid du Colombier static int left = -HALFWIDTH;
793e12c5d1SDavid du Colombier static int right = HALFWIDTH;
803e12c5d1SDavid du Colombier static int bottom = -HALFWIDTH;
813e12c5d1SDavid du Colombier static int top = HALFWIDTH;
823e12c5d1SDavid du Colombier static int longlines = SHORTLINES; /* drop longer segments */
833e12c5d1SDavid du Colombier static int shortlines = SHORTLINES;
843e12c5d1SDavid du Colombier static int bflag = 1;	/* 0 for option -b */
85219b2ee8SDavid du Colombier static int s1flag = 0;	/* 1 for option -s1 */
86219b2ee8SDavid du Colombier static int s2flag = 0;	/* 1 for option -s2 */
873e12c5d1SDavid du Colombier static int rflag = 0;	/* 1 for option -r */
883e12c5d1SDavid du Colombier static int kflag = 0;	/* 1 if option -k occurred */
897dd7cddfSDavid du Colombier static int xflag = 0;	/* 1 for option -x */
90219b2ee8SDavid du Colombier        int vflag = 1;	/* -1 if option -v occurred */
91219b2ee8SDavid du Colombier static double position[3];	/* option -p */
92219b2ee8SDavid du Colombier static double center[3] = {0., 0., 0.};	/* option -c */
933e12c5d1SDavid du Colombier static struct coord crot;		/* option -c */
94219b2ee8SDavid du Colombier static double grid[3] = { 10., 10., RESOL };	/* option -g */
95219b2ee8SDavid du Colombier static double dlat, dlon;	/* resolution for tracing grid in lat and lon */
96219b2ee8SDavid du Colombier static double scaling;	/* to compute final integer output */
97219b2ee8SDavid du Colombier static struct file *track;	/* options -t and -u */
983e12c5d1SDavid du Colombier static int ntrack;		/* number of tracks present */
993e12c5d1SDavid du Colombier static char *symbolfile;	/* option -y */
1003e12c5d1SDavid du Colombier 
101219b2ee8SDavid du Colombier void	clamp(double *px, double v);
1023e12c5d1SDavid du Colombier void	clipinit(void);
103219b2ee8SDavid du Colombier double	diddle(struct place *, double, double);
104219b2ee8SDavid du Colombier double	diddle(struct place *, double, double);
105219b2ee8SDavid du Colombier void	dobounds(double, double, double, double, int);
106219b2ee8SDavid du Colombier void	dogrid(double, double, double, double);
107219b2ee8SDavid du Colombier int	duple(struct place *, double);
1083e12c5d1SDavid du Colombier double	fmax(double, double);
1093e12c5d1SDavid du Colombier double	fmin(double, double);
1103e12c5d1SDavid du Colombier void	getdata(char *);
111219b2ee8SDavid du Colombier int	gridpt(double, double, int);
112219b2ee8SDavid du Colombier int	inpoly(double, double);
1133e12c5d1SDavid du Colombier int	inwindow(struct place *);
1143e12c5d1SDavid du Colombier void	pathnames(void);
115219b2ee8SDavid du Colombier int	pnorm(double);
116219b2ee8SDavid du Colombier void	radbds(double *w, double *rw);
117219b2ee8SDavid du Colombier void	revlon(struct place *, double);
118219b2ee8SDavid du Colombier void	satellite(struct file *);
119219b2ee8SDavid du Colombier int	seeable(double, double);
1203e12c5d1SDavid du Colombier void	windlim(void);
1213e12c5d1SDavid du Colombier void	realcut(void);
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier int
option(char * s)1243e12c5d1SDavid du Colombier option(char *s)
1253e12c5d1SDavid du Colombier {
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	if(s[0]=='-' && (s[1]<'0'||s[1]>'9'))
1283e12c5d1SDavid du Colombier 		return(s[1]!='.'&&s[1]!=0);
1293e12c5d1SDavid du Colombier 	else
1303e12c5d1SDavid du Colombier 		return(0);
1313e12c5d1SDavid du Colombier }
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier void
conv(int k,struct coord * g)1343e12c5d1SDavid du Colombier conv(int k, struct coord *g)
1353e12c5d1SDavid du Colombier {
1363e12c5d1SDavid du Colombier 	g->l = (0.0001/SCALERATIO)*k;
1373e12c5d1SDavid du Colombier 	sincos(g);
1383e12c5d1SDavid du Colombier }
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier int
main(int argc,char * argv[])1413e12c5d1SDavid du Colombier main(int argc, char *argv[])
1423e12c5d1SDavid du Colombier {
1433e12c5d1SDavid du Colombier 	int i,k;
144219b2ee8SDavid du Colombier 	char *s, *t, *style;
145219b2ee8SDavid du Colombier 	double x, y;
1463e12c5d1SDavid du Colombier 	double lat, lon;
147219b2ee8SDavid du Colombier 	double *wlim;
1483e12c5d1SDavid du Colombier 	double dd;
1493e12c5d1SDavid du Colombier 	if(sizeof(short)!=2)
1503e12c5d1SDavid du Colombier 		abort();	/* getshort() won't work */
1513e12c5d1SDavid du Colombier 	s = getenv("MAP");
1523e12c5d1SDavid du Colombier 	if(s)
153219b2ee8SDavid du Colombier 		file[0].name = s;
1543e12c5d1SDavid du Colombier 	s = getenv("MAPDIR");
1553e12c5d1SDavid du Colombier 	if(s)
1563e12c5d1SDavid du Colombier 		mapdir = s;
1573e12c5d1SDavid du Colombier 	if(argc<=1)
1583e12c5d1SDavid du Colombier 		error("usage: map projection params options");
1593e12c5d1SDavid du Colombier 	for(k=0;index[k].name;k++) {
1603e12c5d1SDavid du Colombier 		s = index[k].name;
1613e12c5d1SDavid du Colombier 		t = argv[1];
1623e12c5d1SDavid du Colombier 		while(*s == *t){
1633e12c5d1SDavid du Colombier 			if(*s==0) goto found;
1643e12c5d1SDavid du Colombier 			s++;
1653e12c5d1SDavid du Colombier 			t++;
1663e12c5d1SDavid du Colombier 		}
1673e12c5d1SDavid du Colombier 	}
1683e12c5d1SDavid du Colombier 	fprintf(stderr,"projections:\n");
1693e12c5d1SDavid du Colombier 	for(i=0;index[i].name;i++)  {
1703e12c5d1SDavid du Colombier 		fprintf(stderr,"%s",index[i].name);
1713e12c5d1SDavid du Colombier 		for(k=0; k<index[i].npar; k++)
1723e12c5d1SDavid du Colombier 			fprintf(stderr," p%d", k);
1733e12c5d1SDavid du Colombier 		fprintf(stderr,"\n");
1743e12c5d1SDavid du Colombier 	}
1753e12c5d1SDavid du Colombier 	exits("error");
1763e12c5d1SDavid du Colombier found:
1773e12c5d1SDavid du Colombier 	argv += 2;
1783e12c5d1SDavid du Colombier 	argc -= 2;
1793e12c5d1SDavid du Colombier 	cut = index[k].cut;
180219b2ee8SDavid du Colombier 	limb = index[k].limb;
1813e12c5d1SDavid du Colombier 	poles = index[k].poles;
1823e12c5d1SDavid du Colombier 	for(i=0;i<index[k].npar;i++) {
1833e12c5d1SDavid du Colombier 		if(i>=argc||option(argv[i])) {
1843e12c5d1SDavid du Colombier 			fprintf(stderr,"%s needs %d params\n",index[k].name,index[k].npar);
1853e12c5d1SDavid du Colombier 			exits("error");
1863e12c5d1SDavid du Colombier 		}
1873e12c5d1SDavid du Colombier 		params[i] = atof(argv[i]);
1883e12c5d1SDavid du Colombier 	}
1893e12c5d1SDavid du Colombier 	argv += i;
1903e12c5d1SDavid du Colombier 	argc -= i;
1913e12c5d1SDavid du Colombier 	while(argc>0&&option(argv[0])) {
1923e12c5d1SDavid du Colombier 		argc--;
1933e12c5d1SDavid du Colombier 		argv++;
1943e12c5d1SDavid du Colombier 		switch(argv[-1][1]) {
1953e12c5d1SDavid du Colombier 		case 'm':
196219b2ee8SDavid du Colombier 			if(file == &dfltfile) {
197219b2ee8SDavid du Colombier 				file = 0;
198219b2ee8SDavid du Colombier 				nfile = 0;
199219b2ee8SDavid du Colombier 			}
200219b2ee8SDavid du Colombier 			while(argc && !option(*argv)) {
201219b2ee8SDavid du Colombier 				file = realloc(file,(nfile+1)*sizeof(*file));
202219b2ee8SDavid du Colombier 				file[nfile].name = *argv;
203219b2ee8SDavid du Colombier 				file[nfile].color = currcolor;
204219b2ee8SDavid du Colombier 				file[nfile].style = SOLID;
205219b2ee8SDavid du Colombier 				nfile++;
206219b2ee8SDavid du Colombier 				argv++;
207219b2ee8SDavid du Colombier 				argc--;
208219b2ee8SDavid du Colombier 			}
2093e12c5d1SDavid du Colombier 			break;
2103e12c5d1SDavid du Colombier 		case 'b':
2113e12c5d1SDavid du Colombier 			bflag = 0;
2123e12c5d1SDavid du Colombier 			for(nvert=0;nvert<NVERT&&argc>=2;nvert++) {
2133e12c5d1SDavid du Colombier 				if(option(*argv))
2143e12c5d1SDavid du Colombier 					break;
2153e12c5d1SDavid du Colombier 				v[nvert].x = atof(*argv++);
2163e12c5d1SDavid du Colombier 				argc--;
2173e12c5d1SDavid du Colombier 				if(option(*argv))
2183e12c5d1SDavid du Colombier 					break;
2193e12c5d1SDavid du Colombier 				v[nvert].y = atof(*argv++);
2203e12c5d1SDavid du Colombier 				argc--;
2213e12c5d1SDavid du Colombier 			}
2223e12c5d1SDavid du Colombier 			if(nvert>=NVERT)
2233e12c5d1SDavid du Colombier 				error("too many clipping vertices");
2243e12c5d1SDavid du Colombier 			break;
2253e12c5d1SDavid du Colombier 		case 'g':
226219b2ee8SDavid du Colombier 			gridcolor = currcolor;
2273e12c5d1SDavid du Colombier 			for(i=0;i<3&&argc>i&&!option(argv[i]);i++)
2283e12c5d1SDavid du Colombier 				grid[i] = atof(argv[i]);
2293e12c5d1SDavid du Colombier 			switch(i) {
2303e12c5d1SDavid du Colombier 			case 0:
2313e12c5d1SDavid du Colombier 				grid[0] = grid[1] = 0.;
2323e12c5d1SDavid du Colombier 				break;
2333e12c5d1SDavid du Colombier 			case 1:
2343e12c5d1SDavid du Colombier 				grid[1] = grid[0];
2353e12c5d1SDavid du Colombier 			}
2363e12c5d1SDavid du Colombier 			argc -= i;
2373e12c5d1SDavid du Colombier 			argv += i;
2383e12c5d1SDavid du Colombier 			break;
2393e12c5d1SDavid du Colombier 		case 't':
240219b2ee8SDavid du Colombier 			style = SOLID;
241219b2ee8SDavid du Colombier 			goto casetu;
2423e12c5d1SDavid du Colombier 		case 'u':
243219b2ee8SDavid du Colombier 			style = DOTDASH;
244219b2ee8SDavid du Colombier 		casetu:
245219b2ee8SDavid du Colombier 			while(argc && !option(*argv)) {
246219b2ee8SDavid du Colombier 				track = realloc(track,(ntrack+1)*sizeof(*track));
247219b2ee8SDavid du Colombier 				track[ntrack].name = *argv;
248219b2ee8SDavid du Colombier 				track[ntrack].color = currcolor;
249219b2ee8SDavid du Colombier 				track[ntrack].style = style;
250219b2ee8SDavid du Colombier 				ntrack++;
251219b2ee8SDavid du Colombier 				argv++;
252219b2ee8SDavid du Colombier 				argc--;
2533e12c5d1SDavid du Colombier 			}
2543e12c5d1SDavid du Colombier 			break;
2553e12c5d1SDavid du Colombier 		case 'r':
2563e12c5d1SDavid du Colombier 			rflag++;
2573e12c5d1SDavid du Colombier 			break;
2583e12c5d1SDavid du Colombier 		case 's':
259219b2ee8SDavid du Colombier 			switch(argv[-1][2]) {
260219b2ee8SDavid du Colombier 			case '1':
261219b2ee8SDavid du Colombier 				s1flag++;
262219b2ee8SDavid du Colombier 				break;
263219b2ee8SDavid du Colombier 			case 0:		/* compatibility */
264219b2ee8SDavid du Colombier 			case '2':
265219b2ee8SDavid du Colombier 				s2flag++;
266219b2ee8SDavid du Colombier 			}
2673e12c5d1SDavid du Colombier 			break;
2683e12c5d1SDavid du Colombier 		case 'o':
2693e12c5d1SDavid du Colombier 			for(i=0;i<3&&i<argc&&!option(argv[i]);i++)
2703e12c5d1SDavid du Colombier 				orientation[i] = atof(argv[i]);
2713e12c5d1SDavid du Colombier 			oriented++;
2723e12c5d1SDavid du Colombier 			argv += i;
2733e12c5d1SDavid du Colombier 			argc -= i;
2743e12c5d1SDavid du Colombier 			break;
2753e12c5d1SDavid du Colombier 		case 'l':
276219b2ee8SDavid du Colombier 			bordcolor = currcolor;
2773e12c5d1SDavid du Colombier 			for(i=0;i<argc&&i<4&&!option(argv[i]);i++)
2783e12c5d1SDavid du Colombier 				limits[i] = atof(argv[i]);
2793e12c5d1SDavid du Colombier 			argv += i;
2803e12c5d1SDavid du Colombier 			argc -= i;
2813e12c5d1SDavid du Colombier 			break;
2823e12c5d1SDavid du Colombier 		case 'k':
2833e12c5d1SDavid du Colombier 			kflag++;
2843e12c5d1SDavid du Colombier 			for(i=0;i<argc&&i<4&&!option(argv[i]);i++)
2853e12c5d1SDavid du Colombier 				klimits[i] = atof(argv[i]);
2863e12c5d1SDavid du Colombier 			argv += i;
2873e12c5d1SDavid du Colombier 			argc -= i;
2883e12c5d1SDavid du Colombier 			break;
2893e12c5d1SDavid du Colombier 		case 'd':
2903e12c5d1SDavid du Colombier 			if(argc>0&&!option(argv[0])) {
2913e12c5d1SDavid du Colombier 				delta = atoi(argv[0]);
2923e12c5d1SDavid du Colombier 				argv++;
2933e12c5d1SDavid du Colombier 				argc--;
2943e12c5d1SDavid du Colombier 			}
2953e12c5d1SDavid du Colombier 			break;
2963e12c5d1SDavid du Colombier 		case 'w':
297219b2ee8SDavid du Colombier 			bordcolor = currcolor;
2983e12c5d1SDavid du Colombier 			windowed++;
2993e12c5d1SDavid du Colombier 			for(i=0;i<argc&&i<4&&!option(argv[i]);i++)
3003e12c5d1SDavid du Colombier 				window[i] = atof(argv[i]);
3013e12c5d1SDavid du Colombier 			argv += i;
3023e12c5d1SDavid du Colombier 			argc -= i;
3033e12c5d1SDavid du Colombier 			break;
3043e12c5d1SDavid du Colombier 		case 'c':
3053e12c5d1SDavid du Colombier 			for(i=0;i<3&&argc>i&&!option(argv[i]);i++)
3063e12c5d1SDavid du Colombier 				center[i] = atof(argv[i]);
3073e12c5d1SDavid du Colombier 			argc -= i;
3083e12c5d1SDavid du Colombier 			argv += i;
3093e12c5d1SDavid du Colombier 			break;
3103e12c5d1SDavid du Colombier 		case 'p':
3113e12c5d1SDavid du Colombier 			for(i=0;i<3&&argc>i&&!option(argv[i]);i++)
3123e12c5d1SDavid du Colombier 				position[i] = atof(argv[i]);
3133e12c5d1SDavid du Colombier 			argc -= i;
3143e12c5d1SDavid du Colombier 			argv += i;
3153e12c5d1SDavid du Colombier 			if(i!=3||position[2]<=0)
3163e12c5d1SDavid du Colombier 				error("incomplete positioning");
3173e12c5d1SDavid du Colombier 			break;
3183e12c5d1SDavid du Colombier 		case 'y':
319219b2ee8SDavid du Colombier 			if(argc>0&&!option(argv[0])) {
3203e12c5d1SDavid du Colombier 				symbolfile = argv[0];
3213e12c5d1SDavid du Colombier 				argc--;
3223e12c5d1SDavid du Colombier 				argv++;
323219b2ee8SDavid du Colombier 			}
324219b2ee8SDavid du Colombier 			break;
325219b2ee8SDavid du Colombier 		case 'v':
326219b2ee8SDavid du Colombier 			if(index[k].limb == 0)
327219b2ee8SDavid du Colombier 				error("-v does not apply here");
328219b2ee8SDavid du Colombier 			vflag = -1;
329219b2ee8SDavid du Colombier 			break;
3307dd7cddfSDavid du Colombier 		case 'x':
3317dd7cddfSDavid du Colombier 			xflag = 1;
3327dd7cddfSDavid du Colombier 			break;
333219b2ee8SDavid du Colombier 		case 'C':
334219b2ee8SDavid du Colombier 			if(argc && !option(*argv)) {
3357dd7cddfSDavid du Colombier 				currcolor = colorcode(*argv);
336219b2ee8SDavid du Colombier 				argc--;
337219b2ee8SDavid du Colombier 				argv++;
338219b2ee8SDavid du Colombier 			}
3393e12c5d1SDavid du Colombier 			break;
3403e12c5d1SDavid du Colombier 		}
3413e12c5d1SDavid du Colombier 	}
3423e12c5d1SDavid du Colombier 	if(argc>0)
3433e12c5d1SDavid du Colombier 		error("error in arguments");
3443e12c5d1SDavid du Colombier 	pathnames();
3453e12c5d1SDavid du Colombier 	clamp(&limits[0],-90.);
3463e12c5d1SDavid du Colombier 	clamp(&limits[1],90.);
3473e12c5d1SDavid du Colombier 	clamp(&klimits[0],-90.);
3483e12c5d1SDavid du Colombier 	clamp(&klimits[1],90.);
3493e12c5d1SDavid du Colombier 	clamp(&window[0],-90.);
3503e12c5d1SDavid du Colombier 	clamp(&window[1],90.);
3513e12c5d1SDavid du Colombier 	radbds(limits,rlimits);
3523e12c5d1SDavid du Colombier 	limcase = limits[2]<-180.?0:
3533e12c5d1SDavid du Colombier 		  limits[3]>180.?2:
3543e12c5d1SDavid du Colombier 		  1;
3553e12c5d1SDavid du Colombier 	if(
3563e12c5d1SDavid du Colombier 		window[0]>=window[1]||
3573e12c5d1SDavid du Colombier 		window[2]>=window[3]||
3583e12c5d1SDavid du Colombier 		window[0]>90.||
3593e12c5d1SDavid du Colombier 		window[1]<-90.||
3603e12c5d1SDavid du Colombier 		window[2]>180.||
3613e12c5d1SDavid du Colombier 		window[3]<-180.)
3623e12c5d1SDavid du Colombier 		error("unreasonable window");
3633e12c5d1SDavid du Colombier 	windlim();
3643e12c5d1SDavid du Colombier 	radbds(window,rwindow);
3653e12c5d1SDavid du Colombier 	upright = orientation[0]==90? 1: orientation[0]==-90? -1: 0;
3663e12c5d1SDavid du Colombier 	if(index[k].spheroid && !upright)
3673e12c5d1SDavid du Colombier 		error("can't tilt the spheroid");
3683e12c5d1SDavid du Colombier 	if(limits[2]>limits[3])
3693e12c5d1SDavid du Colombier 		limits[3] += 360;
3703e12c5d1SDavid du Colombier 	if(!oriented)
3713e12c5d1SDavid du Colombier 		orientation[2] = (limits[2]+limits[3])/2;
3723e12c5d1SDavid du Colombier 	orient(orientation[0],orientation[1],orientation[2]);
3733e12c5d1SDavid du Colombier 	projection = (*index[k].prog)(params[0],params[1]);
3743e12c5d1SDavid du Colombier 	if(projection == 0)
3753e12c5d1SDavid du Colombier 		error("unreasonable projection parameters");
3763e12c5d1SDavid du Colombier 	clipinit();
3773e12c5d1SDavid du Colombier 	grid[0] = fabs(grid[0]);
3783e12c5d1SDavid du Colombier 	grid[1] = fabs(grid[1]);
3793e12c5d1SDavid du Colombier 	if(!kflag)
3803e12c5d1SDavid du Colombier 		for(i=0;i<4;i++)
3813e12c5d1SDavid du Colombier 			klimits[i] = limits[i];
3823e12c5d1SDavid du Colombier 	if(klimits[2]>klimits[3])
3833e12c5d1SDavid du Colombier 		klimits[3] += 360;
3843e12c5d1SDavid du Colombier 	lolat = limits[0];
3853e12c5d1SDavid du Colombier 	hilat = limits[1];
3863e12c5d1SDavid du Colombier 	lolon = limits[2];
3873e12c5d1SDavid du Colombier 	hilon = limits[3];
3883e12c5d1SDavid du Colombier 	if(lolon>=hilon||lolat>=hilat||lolat<-90.||hilat>90.)
3893e12c5d1SDavid du Colombier 		error("unreasonable limits");
3903e12c5d1SDavid du Colombier 	wlim = kflag? klimits: window;
3913e12c5d1SDavid du Colombier 	dlat = fmin(hilat-lolat,wlim[1]-wlim[0])/16;
3923e12c5d1SDavid du Colombier 	dlon = fmin(hilon-lolon,wlim[3]-wlim[2])/32;
3933e12c5d1SDavid du Colombier 	dd = fmax(dlat,dlon);
3943e12c5d1SDavid du Colombier 	while(grid[2]>fmin(dlat,dlon)/2)
3953e12c5d1SDavid du Colombier 		grid[2] /= 2;
3963e12c5d1SDavid du Colombier 	realcut();
3973e12c5d1SDavid du Colombier 	if(nvert<=0) {
3983e12c5d1SDavid du Colombier 		for(lat=klimits[0];lat<klimits[1]+dd-FUZZ;lat+=dd) {
3993e12c5d1SDavid du Colombier 			if(lat>klimits[1])
4003e12c5d1SDavid du Colombier 				lat = klimits[1];
4013e12c5d1SDavid du Colombier 			for(lon=klimits[2];lon<klimits[3]+dd-FUZZ;lon+=dd) {
402219b2ee8SDavid du Colombier 				i = (kflag?posproj:normproj)
4033e12c5d1SDavid du Colombier 					(lat,lon+(lon<klimits[3]?FUZZ:-FUZZ),
404219b2ee8SDavid du Colombier 				   &x,&y);
405219b2ee8SDavid du Colombier 				if(i*vflag <= 0)
4063e12c5d1SDavid du Colombier 					continue;
4073e12c5d1SDavid du Colombier 				if(x<xmin) xmin = x;
4083e12c5d1SDavid du Colombier 				if(x>xmax) xmax = x;
4093e12c5d1SDavid du Colombier 				if(y<ymin) ymin = y;
4103e12c5d1SDavid du Colombier 				if(y>ymax) ymax = y;
4113e12c5d1SDavid du Colombier 			}
4123e12c5d1SDavid du Colombier 		}
4133e12c5d1SDavid du Colombier 	} else {
4143e12c5d1SDavid du Colombier 		for(i=0; i<nvert; i++) {
4153e12c5d1SDavid du Colombier 			x = v[i].x;
4163e12c5d1SDavid du Colombier 			y = v[i].y;
4173e12c5d1SDavid du Colombier 			if(x<xmin) xmin = x;
4183e12c5d1SDavid du Colombier 			if(x>xmax) xmax = x;
4193e12c5d1SDavid du Colombier 			if(y<ymin) ymin = y;
4203e12c5d1SDavid du Colombier 			if(y>ymax) ymax = y;
4213e12c5d1SDavid du Colombier 		}
4223e12c5d1SDavid du Colombier 	}
4233e12c5d1SDavid du Colombier 	xrange = xmax - xmin;
4243e12c5d1SDavid du Colombier 	yrange = ymax - ymin;
4253e12c5d1SDavid du Colombier 	if(xrange<=0||yrange<=0)
4263e12c5d1SDavid du Colombier 		error("map seems to be empty");
4273e12c5d1SDavid du Colombier 	scaling = 2;	/*plotting area from -1 to 1*/
4283e12c5d1SDavid du Colombier 	if(position[2]!=0) {
429219b2ee8SDavid du Colombier 		if(posproj(position[0]-.5,position[1],&xcent,&ycent)==0||
430219b2ee8SDavid du Colombier 		   posproj(position[0]+.5,position[1],&x,&y)==0)
4313e12c5d1SDavid du Colombier 			error("unreasonable position");
4323e12c5d1SDavid du Colombier 		scaling /= (position[2]*hypot(x-xcent,y-ycent));
433219b2ee8SDavid du Colombier 		if(posproj(position[0],position[1],&xcent,&ycent)==0)
4343e12c5d1SDavid du Colombier 			error("unreasonable position");
4353e12c5d1SDavid du Colombier 	} else {
4363e12c5d1SDavid du Colombier 		scaling /= (xrange>yrange?xrange:yrange);
4373e12c5d1SDavid du Colombier 		xcent = (xmin+xmax)/2;
4383e12c5d1SDavid du Colombier 		ycent = (ymin+ymax)/2;
4393e12c5d1SDavid du Colombier 	}
4403e12c5d1SDavid du Colombier 	xoff = center[0]/scaling;
4413e12c5d1SDavid du Colombier 	yoff = center[1]/scaling;
4423e12c5d1SDavid du Colombier 	crot.l = center[2]*RAD;
4433e12c5d1SDavid du Colombier 	sincos(&crot);
4443e12c5d1SDavid du Colombier 	scaling *= HALFWIDTH*0.9;
4453e12c5d1SDavid du Colombier 	if(symbolfile)
4463e12c5d1SDavid du Colombier 		getsyms(symbolfile);
447219b2ee8SDavid du Colombier 	if(!s2flag) {
4483e12c5d1SDavid du Colombier 		openpl();
4493e12c5d1SDavid du Colombier 		erase();
4503e12c5d1SDavid du Colombier 	}
451219b2ee8SDavid du Colombier 	range(left,bottom,right,top);
4527dd7cddfSDavid du Colombier 	comment("grid","");
453219b2ee8SDavid du Colombier 	colorx(gridcolor);
454219b2ee8SDavid du Colombier 	pen(DOTTED);
4553e12c5d1SDavid du Colombier 	if(grid[0]>0.)
4563e12c5d1SDavid du Colombier 		for(lat=ceil(lolat/grid[0])*grid[0];
4573e12c5d1SDavid du Colombier 		    lat<=hilat;lat+=grid[0])
4583e12c5d1SDavid du Colombier 			dogrid(lat,lat,lolon,hilon);
4593e12c5d1SDavid du Colombier 	if(grid[1]>0.)
4603e12c5d1SDavid du Colombier 		for(lon=ceil(lolon/grid[1])*grid[1];
4613e12c5d1SDavid du Colombier 		    lon<=hilon;lon+=grid[1])
4623e12c5d1SDavid du Colombier 			dogrid(lolat,hilat,lon,lon);
4637dd7cddfSDavid du Colombier 	comment("border","");
464219b2ee8SDavid du Colombier 	colorx(bordcolor);
465219b2ee8SDavid du Colombier 	pen(SOLID);
4663e12c5d1SDavid du Colombier 	if(bflag) {
467219b2ee8SDavid du Colombier 		dolimb();
4683e12c5d1SDavid du Colombier 		dobounds(lolat,hilat,lolon,hilon,0);
4693e12c5d1SDavid du Colombier 		dobounds(window[0],window[1],window[2],window[3],1);
4703e12c5d1SDavid du Colombier 	}
4713e12c5d1SDavid du Colombier 	lolat = floor(limits[0]/10)*10;
4723e12c5d1SDavid du Colombier 	hilat = ceil(limits[1]/10)*10;
4733e12c5d1SDavid du Colombier 	lolon = floor(limits[2]/10)*10;
4743e12c5d1SDavid du Colombier 	hilon = ceil(limits[3]/10)*10;
4753e12c5d1SDavid du Colombier 	if(lolon>hilon)
4763e12c5d1SDavid du Colombier 		hilon += 360.;
4773e12c5d1SDavid du Colombier 	/*do tracks first so as not to lose the standard input*/
4783e12c5d1SDavid du Colombier 	for(i=0;i<ntrack;i++) {
4793e12c5d1SDavid du Colombier 		longlines = LONGLINES;
4803e12c5d1SDavid du Colombier 		satellite(&track[i]);
4813e12c5d1SDavid du Colombier 		longlines = shortlines;
4823e12c5d1SDavid du Colombier 	}
483219b2ee8SDavid du Colombier 	for(i=0;i<nfile;i++) {
4847dd7cddfSDavid du Colombier 		comment("mapfile",file[i].name);
485219b2ee8SDavid du Colombier 		colorx(file[i].color);
4867dd7cddfSDavid du Colombier 		pen(file[i].style);
487219b2ee8SDavid du Colombier 		getdata(file[i].name);
488219b2ee8SDavid du Colombier 	}
4893e12c5d1SDavid du Colombier 	move(right,bottom);
490219b2ee8SDavid du Colombier 	if(!s1flag)
491219b2ee8SDavid du Colombier 		closepl();
4923e12c5d1SDavid du Colombier 	return 0;
4933e12c5d1SDavid du Colombier }
4943e12c5d1SDavid du Colombier 
495219b2ee8SDavid du Colombier /* Out of perverseness (really to recover from a dubious,
496219b2ee8SDavid du Colombier    but documented, convention) the returns from projection
497219b2ee8SDavid du Colombier    functions (-1 unplottable, 0 wrong sheet, 1 good) are
498219b2ee8SDavid du Colombier    recoded into -1 wrong sheet, 0 unplottable, 1 good. */
4993e12c5d1SDavid du Colombier 
5003e12c5d1SDavid du Colombier int
fixproj(struct place * g,double * x,double * y)501219b2ee8SDavid du Colombier fixproj(struct place *g, double *x, double *y)
502219b2ee8SDavid du Colombier {
503219b2ee8SDavid du Colombier 	int i = (*projection)(g,x,y);
504219b2ee8SDavid du Colombier 	return i<0? 0: i==0? -1: 1;
505219b2ee8SDavid du Colombier }
506219b2ee8SDavid du Colombier 
507219b2ee8SDavid du Colombier int
normproj(double lat,double lon,double * x,double * y)508219b2ee8SDavid du Colombier normproj(double lat, double lon, double *x, double *y)
5093e12c5d1SDavid du Colombier {
5103e12c5d1SDavid du Colombier 	int i;
5113e12c5d1SDavid du Colombier 	struct place geog;
5123e12c5d1SDavid du Colombier 	latlon(lat,lon,&geog);
5133e12c5d1SDavid du Colombier /*
5143e12c5d1SDavid du Colombier 	printp(&geog);
5153e12c5d1SDavid du Colombier */
5163e12c5d1SDavid du Colombier 	normalize(&geog);
5173e12c5d1SDavid du Colombier 	if(!inwindow(&geog))
5183e12c5d1SDavid du Colombier 		return(-1);
519219b2ee8SDavid du Colombier 	i = fixproj(&geog,x,y);
5203e12c5d1SDavid du Colombier 	if(rflag)
5213e12c5d1SDavid du Colombier 		*x = -*x;
5223e12c5d1SDavid du Colombier /*
5233e12c5d1SDavid du Colombier 	printp(&geog);
5243e12c5d1SDavid du Colombier 	fprintf(stderr,"%d %.3f %.3f\n",i,*x,*y);
5253e12c5d1SDavid du Colombier */
5263e12c5d1SDavid du Colombier 	return(i);
5273e12c5d1SDavid du Colombier }
5283e12c5d1SDavid du Colombier 
5293e12c5d1SDavid du Colombier int
posproj(double lat,double lon,double * x,double * y)530219b2ee8SDavid du Colombier posproj(double lat, double lon, double *x, double *y)
5313e12c5d1SDavid du Colombier {
5323e12c5d1SDavid du Colombier 	int i;
5333e12c5d1SDavid du Colombier 	struct place geog;
5343e12c5d1SDavid du Colombier 	latlon(lat,lon,&geog);
5353e12c5d1SDavid du Colombier 	normalize(&geog);
536219b2ee8SDavid du Colombier 	i = fixproj(&geog,x,y);
5373e12c5d1SDavid du Colombier 	if(rflag)
5383e12c5d1SDavid du Colombier 		*x = -*x;
5393e12c5d1SDavid du Colombier 	return(i);
5403e12c5d1SDavid du Colombier }
5413e12c5d1SDavid du Colombier 
5423e12c5d1SDavid du Colombier int
inwindow(struct place * geog)5433e12c5d1SDavid du Colombier inwindow(struct place *geog)
5443e12c5d1SDavid du Colombier {
545219b2ee8SDavid du Colombier 	if(geog->nlat.l<rwindow[0]-FUZZ||
546219b2ee8SDavid du Colombier 	   geog->nlat.l>rwindow[1]+FUZZ||
547219b2ee8SDavid du Colombier 	   geog->wlon.l<rwindow[2]-FUZZ||
548219b2ee8SDavid du Colombier 	   geog->wlon.l>rwindow[3]+FUZZ)
5493e12c5d1SDavid du Colombier 		return(0);
5503e12c5d1SDavid du Colombier 	else return(1);
5513e12c5d1SDavid du Colombier }
5523e12c5d1SDavid du Colombier 
5533e12c5d1SDavid du Colombier int
inlimits(struct place * g)5543e12c5d1SDavid du Colombier inlimits(struct place *g)
5553e12c5d1SDavid du Colombier {
556219b2ee8SDavid du Colombier 	if(rlimits[0]-FUZZ>g->nlat.l||
557219b2ee8SDavid du Colombier 	   rlimits[1]+FUZZ<g->nlat.l)
5583e12c5d1SDavid du Colombier 		return(0);
5593e12c5d1SDavid du Colombier 	switch(limcase) {
5603e12c5d1SDavid du Colombier 	case 0:
561219b2ee8SDavid du Colombier 		if(rlimits[2]+TWOPI-FUZZ>g->wlon.l&&
562219b2ee8SDavid du Colombier 		   rlimits[3]+FUZZ<g->wlon.l)
5633e12c5d1SDavid du Colombier 			return(0);
5643e12c5d1SDavid du Colombier 		break;
5653e12c5d1SDavid du Colombier 	case 1:
566219b2ee8SDavid du Colombier 		if(rlimits[2]-FUZZ>g->wlon.l||
567219b2ee8SDavid du Colombier 		   rlimits[3]+FUZZ<g->wlon.l)
5683e12c5d1SDavid du Colombier 			return(0);
5693e12c5d1SDavid du Colombier 		break;
5703e12c5d1SDavid du Colombier 	case 2:
5713e12c5d1SDavid du Colombier 		if(rlimits[2]>g->wlon.l&&
572219b2ee8SDavid du Colombier 		   rlimits[3]-TWOPI+FUZZ<g->wlon.l)
5733e12c5d1SDavid du Colombier 			return(0);
5743e12c5d1SDavid du Colombier 		break;
5753e12c5d1SDavid du Colombier 	}
5763e12c5d1SDavid du Colombier 	return(1);
5773e12c5d1SDavid du Colombier }
5783e12c5d1SDavid du Colombier 
5793e12c5d1SDavid du Colombier 
5803e12c5d1SDavid du Colombier long patch[18][36];
5813e12c5d1SDavid du Colombier 
5823e12c5d1SDavid du Colombier void
getdata(char * mapfile)5833e12c5d1SDavid du Colombier getdata(char *mapfile)
5843e12c5d1SDavid du Colombier {
5853e12c5d1SDavid du Colombier 	char *indexfile;
5863e12c5d1SDavid du Colombier 	int kx,ky,c;
5873e12c5d1SDavid du Colombier 	int k;
5883e12c5d1SDavid du Colombier 	long b;
5893e12c5d1SDavid du Colombier 	long *p;
5903e12c5d1SDavid du Colombier 	int ip, jp;
5913e12c5d1SDavid du Colombier 	int n;
5923e12c5d1SDavid du Colombier 	struct place g;
5933e12c5d1SDavid du Colombier 	int i, j;
594219b2ee8SDavid du Colombier 	double lat, lon;
5953e12c5d1SDavid du Colombier 	int conn;
5963e12c5d1SDavid du Colombier 	FILE *ifile, *xfile;
5973e12c5d1SDavid du Colombier 
5983e12c5d1SDavid du Colombier 	indexfile = mapindex(mapfile);
5993e12c5d1SDavid du Colombier 	xfile = fopen(indexfile,"r");
6003e12c5d1SDavid du Colombier 	if(xfile==NULL)
6013e12c5d1SDavid du Colombier 		filerror("can't find map index", indexfile);
6023e12c5d1SDavid du Colombier 	free(indexfile);
6033e12c5d1SDavid du Colombier 	for(i=0,p=patch[0];i<18*36;i++,p++)
6043e12c5d1SDavid du Colombier 		*p = 1;
6053e12c5d1SDavid du Colombier 	while(!feof(xfile) && fscanf(xfile,"%d%d%ld",&i,&j,&b)==3)
6063e12c5d1SDavid du Colombier 		patch[i+9][j+18] = b;
6073e12c5d1SDavid du Colombier 	fclose(xfile);
6083e12c5d1SDavid du Colombier 	ifile = fopen(mapfile,"r");
6093e12c5d1SDavid du Colombier 	if(ifile==NULL)
6103e12c5d1SDavid du Colombier 		filerror("can't find map data", mapfile);
6113e12c5d1SDavid du Colombier 	for(lat=lolat;lat<hilat;lat+=10.)
6123e12c5d1SDavid du Colombier 		for(lon=lolon;lon<hilon;lon+=10.) {
6133e12c5d1SDavid du Colombier 			if(!seeable(lat,lon))
6143e12c5d1SDavid du Colombier 				continue;
6153e12c5d1SDavid du Colombier 			i = pnorm(lat);
6163e12c5d1SDavid du Colombier 			j = pnorm(lon);
6173e12c5d1SDavid du Colombier 			if((b=patch[i+9][j+18])&1)
6183e12c5d1SDavid du Colombier 				continue;
6193e12c5d1SDavid du Colombier 			fseek(ifile,b,0);
6203e12c5d1SDavid du Colombier 			while((ip=getc(ifile))>=0&&(jp=getc(ifile))>=0){
6213e12c5d1SDavid du Colombier 				if(ip!=(i&0377)||jp!=(j&0377))
6223e12c5d1SDavid du Colombier 					break;
6233e12c5d1SDavid du Colombier 				n = getshort(ifile);
6243e12c5d1SDavid du Colombier 				conn = 0;
6253e12c5d1SDavid du Colombier 				if(n > 0) {	/* absolute coordinates */
626219b2ee8SDavid du Colombier 					kx = ky = 0;	/* set */
6273e12c5d1SDavid du Colombier 					for(k=0;k<n;k++){
6283e12c5d1SDavid du Colombier 						kx = SCALERATIO*getshort(ifile);
6293e12c5d1SDavid du Colombier 						ky = SCALERATIO*getshort(ifile);
6303e12c5d1SDavid du Colombier 						if (((k%delta) != 0) && (k != (n-1)))
6313e12c5d1SDavid du Colombier 							continue;
6323e12c5d1SDavid du Colombier 						conv(kx,&g.nlat);
6333e12c5d1SDavid du Colombier 						conv(ky,&g.wlon);
6343e12c5d1SDavid du Colombier 						conn = plotpt(&g,conn);
6353e12c5d1SDavid du Colombier 					}
6363e12c5d1SDavid du Colombier 				} else {	/* differential, scaled by SCALERATI0 */
6373e12c5d1SDavid du Colombier 					n = -n;
6383e12c5d1SDavid du Colombier 					kx = SCALERATIO*getshort(ifile);
6393e12c5d1SDavid du Colombier 					ky = SCALERATIO*getshort(ifile);
6403e12c5d1SDavid du Colombier 					for(k=0; k<n; k++) {
6413e12c5d1SDavid du Colombier 						c = getc(ifile);
6423e12c5d1SDavid du Colombier 						if(c&0200) c|= ~0177;
6433e12c5d1SDavid du Colombier 						kx += c;
6443e12c5d1SDavid du Colombier 						c = getc(ifile);
6453e12c5d1SDavid du Colombier 						if(c&0200) c|= ~0177;
6463e12c5d1SDavid du Colombier 						ky += c;
6473e12c5d1SDavid du Colombier 						if(k%delta!=0&&k!=n-1)
6483e12c5d1SDavid du Colombier 							continue;
6493e12c5d1SDavid du Colombier 						conv(kx,&g.nlat);
6503e12c5d1SDavid du Colombier 						conv(ky,&g.wlon);
6513e12c5d1SDavid du Colombier 						conn = plotpt(&g,conn);
6523e12c5d1SDavid du Colombier 					}
6533e12c5d1SDavid du Colombier 				}
6543e12c5d1SDavid du Colombier 				if(k==1) {
6553e12c5d1SDavid du Colombier 					conv(kx,&g.nlat);
6563e12c5d1SDavid du Colombier 					conv(ky,&g.wlon);
657bd389b36SDavid du Colombier 					plotpt(&g,conn);
6583e12c5d1SDavid du Colombier 				}
6593e12c5d1SDavid du Colombier 			}
6603e12c5d1SDavid du Colombier 		}
6613e12c5d1SDavid du Colombier 	fclose(ifile);
6623e12c5d1SDavid du Colombier }
6633e12c5d1SDavid du Colombier 
6643e12c5d1SDavid du Colombier int
seeable(double lat0,double lon0)665219b2ee8SDavid du Colombier seeable(double lat0, double lon0)
6663e12c5d1SDavid du Colombier {
667219b2ee8SDavid du Colombier 	double x, y;
668219b2ee8SDavid du Colombier 	double lat, lon;
6693e12c5d1SDavid du Colombier 	for(lat=lat0;lat<=lat0+10;lat+=2*grid[2])
6703e12c5d1SDavid du Colombier 		for(lon=lon0;lon<=lon0+10;lon+=2*grid[2])
671219b2ee8SDavid du Colombier 			if(normproj(lat,lon,&x,&y)*vflag>0)
6723e12c5d1SDavid du Colombier 				return(1);
6733e12c5d1SDavid du Colombier 	return(0);
6743e12c5d1SDavid du Colombier }
6753e12c5d1SDavid du Colombier 
6763e12c5d1SDavid du Colombier void
satellite(struct file * t)677219b2ee8SDavid du Colombier satellite(struct file *t)
6783e12c5d1SDavid du Colombier {
6793e12c5d1SDavid du Colombier 	char sym[50];
6803e12c5d1SDavid du Colombier 	char lbl[50];
681219b2ee8SDavid du Colombier 	double scale;
6823e12c5d1SDavid du Colombier 	register conn;
683219b2ee8SDavid du Colombier 	double lat,lon;
6843e12c5d1SDavid du Colombier 	struct place place;
6853e12c5d1SDavid du Colombier 	static FILE *ifile = stdin;
686219b2ee8SDavid du Colombier 	if(t->name[0]!='-'||t->name[1]!=0) {
6873e12c5d1SDavid du Colombier 		fclose(ifile);
688219b2ee8SDavid du Colombier 		if((ifile=fopen(t->name,"r"))==NULL)
689219b2ee8SDavid du Colombier 			filerror("can't find track", t->name);
6903e12c5d1SDavid du Colombier 	}
6917dd7cddfSDavid du Colombier 	comment("track",t->name);
692219b2ee8SDavid du Colombier 	colorx(t->color);
693219b2ee8SDavid du Colombier 	pen(t->style);
6943e12c5d1SDavid du Colombier 	for(;;) {
6953e12c5d1SDavid du Colombier 		conn = 0;
696219b2ee8SDavid du Colombier 		while(!feof(ifile) && fscanf(ifile,"%lf%lf",&lat,&lon)==2){
6973e12c5d1SDavid du Colombier 			latlon(lat,lon,&place);
6983e12c5d1SDavid du Colombier 			if(fscanf(ifile,"%1s",lbl) == 1) {
699219b2ee8SDavid du Colombier 				if(strchr("+-.0123456789",*lbl)==0)
7003e12c5d1SDavid du Colombier 					break;
7013e12c5d1SDavid du Colombier 				ungetc(*lbl,ifile);
7023e12c5d1SDavid du Colombier 			}
7033e12c5d1SDavid du Colombier 			conn = plotpt(&place,conn);
7043e12c5d1SDavid du Colombier 		}
7053e12c5d1SDavid du Colombier 		if(feof(ifile))
7063e12c5d1SDavid du Colombier 			return;
7073e12c5d1SDavid du Colombier 		fscanf(ifile,"%[^\n]",lbl+1);
7083e12c5d1SDavid du Colombier 		switch(*lbl) {
7093e12c5d1SDavid du Colombier 		case '"':
7103e12c5d1SDavid du Colombier 			if(plotpt(&place,conn))
7113e12c5d1SDavid du Colombier 				text(lbl+1);
7123e12c5d1SDavid du Colombier 			break;
7133e12c5d1SDavid du Colombier 		case ':':
7143e12c5d1SDavid du Colombier 		case '!':
715219b2ee8SDavid du Colombier 			if(sscanf(lbl+1,"%s %lf",sym,&scale) <= 1)
7163e12c5d1SDavid du Colombier 				scale = 1;
7173e12c5d1SDavid du Colombier 			if(plotpt(&place,conn?conn:-1)) {
7183e12c5d1SDavid du Colombier 				int r = *lbl=='!'?0:rflag?-1:1;
7197dd7cddfSDavid du Colombier 				pen(SOLID);
720219b2ee8SDavid du Colombier 				if(putsym(&place,sym,scale,r) == 0)
721219b2ee8SDavid du Colombier 					text(lbl);
7227dd7cddfSDavid du Colombier 				pen(t->style);
7233e12c5d1SDavid du Colombier 			}
724219b2ee8SDavid du Colombier 			break;
7253e12c5d1SDavid du Colombier 		default:
7263e12c5d1SDavid du Colombier 			if(plotpt(&place,conn))
7273e12c5d1SDavid du Colombier 				text(lbl);
7283e12c5d1SDavid du Colombier 			break;
7293e12c5d1SDavid du Colombier 		}
7303e12c5d1SDavid du Colombier 	}
7313e12c5d1SDavid du Colombier }
7323e12c5d1SDavid du Colombier 
7333e12c5d1SDavid du Colombier int
pnorm(double x)734219b2ee8SDavid du Colombier pnorm(double x)
7353e12c5d1SDavid du Colombier {
7363e12c5d1SDavid du Colombier 	int i;
7373e12c5d1SDavid du Colombier 	i = x/10.;
7383e12c5d1SDavid du Colombier 	i %= 36;
7393e12c5d1SDavid du Colombier 	if(i>=18) return(i-36);
7403e12c5d1SDavid du Colombier 	if(i<-18) return(i+36);
7413e12c5d1SDavid du Colombier 	return(i);
7423e12c5d1SDavid du Colombier }
7433e12c5d1SDavid du Colombier 
7443e12c5d1SDavid du Colombier void
error(char * s)7453e12c5d1SDavid du Colombier error(char *s)
7463e12c5d1SDavid du Colombier {
7473e12c5d1SDavid du Colombier 	fprintf(stderr,"map: \r\n%s\n",s);
7483e12c5d1SDavid du Colombier 	exits("error");
7493e12c5d1SDavid du Colombier }
7503e12c5d1SDavid du Colombier 
7513e12c5d1SDavid du Colombier void
filerror(char * s,char * f)7523e12c5d1SDavid du Colombier filerror(char *s, char *f)
7533e12c5d1SDavid du Colombier {
7543e12c5d1SDavid du Colombier 	fprintf(stderr,"\r\n%s %s\n",s,f);
7553e12c5d1SDavid du Colombier 	exits("error");
7563e12c5d1SDavid du Colombier }
7573e12c5d1SDavid du Colombier 
7583e12c5d1SDavid du Colombier char *
mapindex(char * s)7593e12c5d1SDavid du Colombier mapindex(char *s)
7603e12c5d1SDavid du Colombier {
7613e12c5d1SDavid du Colombier 	char *t = malloc(strlen(s)+3);
7623e12c5d1SDavid du Colombier 	strcpy(t,s);
7633e12c5d1SDavid du Colombier 	strcat(t,".x");
7643e12c5d1SDavid du Colombier 	return t;
7653e12c5d1SDavid du Colombier }
7663e12c5d1SDavid du Colombier 
7673e12c5d1SDavid du Colombier #define NOPT 32767
7683e12c5d1SDavid du Colombier static ox = NOPT, oy = NOPT;
7693e12c5d1SDavid du Colombier 
7703e12c5d1SDavid du Colombier int
cpoint(int xi,int yi,int conn)7713e12c5d1SDavid du Colombier cpoint(int xi, int yi, int conn)
7723e12c5d1SDavid du Colombier {
7733e12c5d1SDavid du Colombier 	int dx = abs(ox-xi);
7743e12c5d1SDavid du Colombier 	int dy = abs(oy-yi);
7757dd7cddfSDavid du Colombier 	if(!xflag && (xi<left||xi>=right || yi<bottom||yi>=top)) {
7763e12c5d1SDavid du Colombier 		ox = oy = NOPT;
7773e12c5d1SDavid du Colombier 		return 0;
7783e12c5d1SDavid du Colombier 	}
7793e12c5d1SDavid du Colombier 	if(conn == -1)		/* isolated plotting symbol */
780*9a747e4fSDavid du Colombier 		{}
7813e12c5d1SDavid du Colombier 	else if(!conn)
7823e12c5d1SDavid du Colombier 		point(xi,yi);
7833e12c5d1SDavid du Colombier 	else {
7843e12c5d1SDavid du Colombier 		if(dx+dy>longlines) {
7853e12c5d1SDavid du Colombier 			ox = oy = NOPT;	/* don't leap across cuts */
7863e12c5d1SDavid du Colombier 			return 0;
7873e12c5d1SDavid du Colombier 		}
7883e12c5d1SDavid du Colombier 		if(dx || dy)
7893e12c5d1SDavid du Colombier 			vec(xi,yi);
7903e12c5d1SDavid du Colombier 	}
7913e12c5d1SDavid du Colombier 	ox = xi, oy = yi;
7923e12c5d1SDavid du Colombier 	return dx+dy<=2? 2: 1;	/* 2=very near; see dogrid */
7933e12c5d1SDavid du Colombier }
7943e12c5d1SDavid du Colombier 
7953e12c5d1SDavid du Colombier 
7963e12c5d1SDavid du Colombier struct place oldg;
7973e12c5d1SDavid du Colombier 
7983e12c5d1SDavid du Colombier int
plotpt(struct place * g,int conn)7993e12c5d1SDavid du Colombier plotpt(struct place *g, int conn)
8003e12c5d1SDavid du Colombier {
8013e12c5d1SDavid du Colombier 	int kx,ky;
8023e12c5d1SDavid du Colombier 	int ret;
803219b2ee8SDavid du Colombier 	double cutlon;
8043e12c5d1SDavid du Colombier 	if(!inlimits(g)) {
8053e12c5d1SDavid du Colombier 		return(0);
8063e12c5d1SDavid du Colombier }
8073e12c5d1SDavid du Colombier 	normalize(g);
8083e12c5d1SDavid du Colombier 	if(!inwindow(g)) {
8093e12c5d1SDavid du Colombier 		return(0);
8103e12c5d1SDavid du Colombier }
8113e12c5d1SDavid du Colombier 	switch((*cut)(g,&oldg,&cutlon)) {
8123e12c5d1SDavid du Colombier 	case 2:
8133e12c5d1SDavid du Colombier 		if(conn) {
8143e12c5d1SDavid du Colombier 			ret = duple(g,cutlon)|duple(g,cutlon);
8153e12c5d1SDavid du Colombier 			oldg = *g;
8163e12c5d1SDavid du Colombier 			return(ret);
8173e12c5d1SDavid du Colombier 		}
8183e12c5d1SDavid du Colombier 	case 0:
8193e12c5d1SDavid du Colombier 		conn = 0;
8203e12c5d1SDavid du Colombier 	default:	/* prevent diags about bad return value */
8213e12c5d1SDavid du Colombier 	case 1:
8223e12c5d1SDavid du Colombier 		oldg = *g;
823219b2ee8SDavid du Colombier 		ret = doproj(g,&kx,&ky);
824219b2ee8SDavid du Colombier 		if(ret==0 || !onlimb && ret*vflag<=0)
8253e12c5d1SDavid du Colombier 			return(0);
8263e12c5d1SDavid du Colombier 		ret = cpoint(kx,ky,conn);
8273e12c5d1SDavid du Colombier 		return ret;
8283e12c5d1SDavid du Colombier 	}
8293e12c5d1SDavid du Colombier }
8303e12c5d1SDavid du Colombier 
8313e12c5d1SDavid du Colombier int
doproj(struct place * g,int * kx,int * ky)8323e12c5d1SDavid du Colombier doproj(struct place *g, int *kx, int *ky)
8333e12c5d1SDavid du Colombier {
834219b2ee8SDavid du Colombier 	int i;
835219b2ee8SDavid du Colombier 	double x,y,x1,y1;
8363e12c5d1SDavid du Colombier /*fprintf(stderr,"dopr1 %f %f \n",g->nlat.l,g->wlon.l);*/
837219b2ee8SDavid du Colombier 	i = fixproj(g,&x,&y);
838219b2ee8SDavid du Colombier 	if(i == 0)
8393e12c5d1SDavid du Colombier 		return(0);
8403e12c5d1SDavid du Colombier 	if(rflag)
8413e12c5d1SDavid du Colombier 		x = -x;
8423e12c5d1SDavid du Colombier /*fprintf(stderr,"dopr2 %f %f\n",x,y);*/
8433e12c5d1SDavid du Colombier 	if(!inpoly(x,y)) {
8443e12c5d1SDavid du Colombier 		return 0;
8453e12c5d1SDavid du Colombier }
8463e12c5d1SDavid du Colombier 	x1 = x - xcent;
8473e12c5d1SDavid du Colombier 	y1 = y - ycent;
8483e12c5d1SDavid du Colombier 	x = (x1*crot.c - y1*crot.s + xoff)*scaling;
8493e12c5d1SDavid du Colombier 	y = (x1*crot.s + y1*crot.c + yoff)*scaling;
8503e12c5d1SDavid du Colombier 	*kx = x + (x>0?.5:-.5);
8513e12c5d1SDavid du Colombier 	*ky = y + (y>0?.5:-.5);
852219b2ee8SDavid du Colombier 	return(i);
8533e12c5d1SDavid du Colombier }
8543e12c5d1SDavid du Colombier 
8553e12c5d1SDavid du Colombier int
duple(struct place * g,double cutlon)856219b2ee8SDavid du Colombier duple(struct place *g, double cutlon)
8573e12c5d1SDavid du Colombier {
8583e12c5d1SDavid du Colombier 	int kx,ky;
8593e12c5d1SDavid du Colombier 	int okx,oky;
8603e12c5d1SDavid du Colombier 	struct place ig;
8613e12c5d1SDavid du Colombier 	revlon(g,cutlon);
8623e12c5d1SDavid du Colombier 	revlon(&oldg,cutlon);
8633e12c5d1SDavid du Colombier 	ig = *g;
8643e12c5d1SDavid du Colombier 	invert(&ig);
8653e12c5d1SDavid du Colombier 	if(!inlimits(&ig))
8663e12c5d1SDavid du Colombier 		return(0);
867219b2ee8SDavid du Colombier 	if(doproj(g,&kx,&ky)*vflag<=0 ||
868219b2ee8SDavid du Colombier 	   doproj(&oldg,&okx,&oky)*vflag<=0)
8693e12c5d1SDavid du Colombier 		return(0);
8703e12c5d1SDavid du Colombier 	cpoint(okx,oky,0);
8713e12c5d1SDavid du Colombier 	cpoint(kx,ky,1);
8723e12c5d1SDavid du Colombier 	return(1);
8733e12c5d1SDavid du Colombier }
8743e12c5d1SDavid du Colombier 
8753e12c5d1SDavid du Colombier void
revlon(struct place * g,double cutlon)876219b2ee8SDavid du Colombier revlon(struct place *g, double cutlon)
8773e12c5d1SDavid du Colombier {
8783e12c5d1SDavid du Colombier 	g->wlon.l = reduce(cutlon-reduce(g->wlon.l-cutlon));
8793e12c5d1SDavid du Colombier 	sincos(&g->wlon);
8803e12c5d1SDavid du Colombier }
8813e12c5d1SDavid du Colombier 
8823e12c5d1SDavid du Colombier 
8833e12c5d1SDavid du Colombier /*	recognize problems of cuts
8843e12c5d1SDavid du Colombier  *	move a point across cut to side of its predecessor
8853e12c5d1SDavid du Colombier  *	if its very close to the cut
8863e12c5d1SDavid du Colombier  *	return(0) if cut interrupts the line
8873e12c5d1SDavid du Colombier  *	return(1) if line is to be drawn normally
8883e12c5d1SDavid du Colombier  *	return(2) if line is so close to cut as to
8893e12c5d1SDavid du Colombier  *	be properly drawn on both sheets
8903e12c5d1SDavid du Colombier */
8913e12c5d1SDavid du Colombier 
8923e12c5d1SDavid du Colombier int
picut(struct place * g,struct place * og,double * cutlon)893219b2ee8SDavid du Colombier picut(struct place *g, struct place *og, double *cutlon)
8943e12c5d1SDavid du Colombier {
8953e12c5d1SDavid du Colombier 	*cutlon = PI;
8963e12c5d1SDavid du Colombier 	return(ckcut(g,og,PI));
8973e12c5d1SDavid du Colombier }
8983e12c5d1SDavid du Colombier 
8993e12c5d1SDavid du Colombier int
nocut(struct place * g,struct place * og,double * cutlon)900219b2ee8SDavid du Colombier nocut(struct place *g, struct place *og, double *cutlon)
9013e12c5d1SDavid du Colombier {
902bd389b36SDavid du Colombier 	USED(g, og, cutlon);
903bd389b36SDavid du Colombier /*
9043e12c5d1SDavid du Colombier #pragma	ref g
9053e12c5d1SDavid du Colombier #pragma	ref og
9063e12c5d1SDavid du Colombier #pragma	ref cutlon
907bd389b36SDavid du Colombier */
9083e12c5d1SDavid du Colombier 	return(1);
9093e12c5d1SDavid du Colombier }
9103e12c5d1SDavid du Colombier 
9113e12c5d1SDavid du Colombier int
ckcut(struct place * g1,struct place * g2,double lon)912219b2ee8SDavid du Colombier ckcut(struct place *g1, struct place *g2, double lon)
9133e12c5d1SDavid du Colombier {
914219b2ee8SDavid du Colombier 	double d1, d2;
915219b2ee8SDavid du Colombier 	double f1, f2;
9163e12c5d1SDavid du Colombier 	int kx,ky;
9173e12c5d1SDavid du Colombier 	d1 = reduce(g1->wlon.l -lon);
9183e12c5d1SDavid du Colombier 	d2 = reduce(g2->wlon.l -lon);
9193e12c5d1SDavid du Colombier 	if((f1=fabs(d1))<FUZZ)
9203e12c5d1SDavid du Colombier 		d1 = diddle(g1,lon,d2);
9213e12c5d1SDavid du Colombier 	if((f2=fabs(d2))<FUZZ) {
9223e12c5d1SDavid du Colombier 		d2 = diddle(g2,lon,d1);
923219b2ee8SDavid du Colombier 		if(doproj(g2,&kx,&ky)*vflag>0)
9243e12c5d1SDavid du Colombier 			cpoint(kx,ky,0);
9253e12c5d1SDavid du Colombier 	}
9263e12c5d1SDavid du Colombier 	if(f1<FUZZ&&f2<FUZZ)
9273e12c5d1SDavid du Colombier 		return(2);
9283e12c5d1SDavid du Colombier 	if(f1>PI*TWO_THRD||f2>PI*TWO_THRD)
9293e12c5d1SDavid du Colombier 		return(1);
9303e12c5d1SDavid du Colombier 	return(d1*d2>=0);
9313e12c5d1SDavid du Colombier }
9323e12c5d1SDavid du Colombier 
933219b2ee8SDavid du Colombier double
diddle(struct place * g,double lon,double d)934219b2ee8SDavid du Colombier diddle(struct place *g, double lon, double d)
9353e12c5d1SDavid du Colombier {
936219b2ee8SDavid du Colombier 	double d1;
9373e12c5d1SDavid du Colombier 	d1 = FUZZ/2;
9383e12c5d1SDavid du Colombier 	if(d<0)
9393e12c5d1SDavid du Colombier 		d1 = -d1;
9403e12c5d1SDavid du Colombier 	g->wlon.l = reduce(lon+d1);
9413e12c5d1SDavid du Colombier 	sincos(&g->wlon);
9423e12c5d1SDavid du Colombier 	return(d1);
9433e12c5d1SDavid du Colombier }
9443e12c5d1SDavid du Colombier 
945219b2ee8SDavid du Colombier double
reduce(double lon)946219b2ee8SDavid du Colombier reduce(double lon)
9473e12c5d1SDavid du Colombier {
9483e12c5d1SDavid du Colombier 	if(lon>PI)
9493e12c5d1SDavid du Colombier 		lon -= 2*PI;
9503e12c5d1SDavid du Colombier 	else if(lon<-PI)
9513e12c5d1SDavid du Colombier 		lon += 2*PI;
9523e12c5d1SDavid du Colombier 	return(lon);
9533e12c5d1SDavid du Colombier }
9543e12c5d1SDavid du Colombier 
9553e12c5d1SDavid du Colombier 
956219b2ee8SDavid du Colombier double tetrapt = 35.26438968;	/* atan(1/sqrt(2)) */
9573e12c5d1SDavid du Colombier 
9583e12c5d1SDavid du Colombier void
dogrid(double lat0,double lat1,double lon0,double lon1)959219b2ee8SDavid du Colombier dogrid(double lat0, double lat1, double lon0, double lon1)
9603e12c5d1SDavid du Colombier {
961219b2ee8SDavid du Colombier 	double slat,slon,tlat,tlon;
9623e12c5d1SDavid du Colombier 	register int conn, oconn;
9633e12c5d1SDavid du Colombier 	slat = tlat = slon = tlon = 0;
9643e12c5d1SDavid du Colombier 	if(lat1>lat0)
9653e12c5d1SDavid du Colombier 		slat = tlat = fmin(grid[2],dlat);
9663e12c5d1SDavid du Colombier 	else
9673e12c5d1SDavid du Colombier 		slon = tlon = fmin(grid[2],dlon);;
9683e12c5d1SDavid du Colombier 	conn = oconn = 0;
9693e12c5d1SDavid du Colombier 	while(lat0<=lat1&&lon0<=lon1) {
9703e12c5d1SDavid du Colombier 		conn = gridpt(lat0,lon0,conn);
9713e12c5d1SDavid du Colombier 		if(projection==Xguyou&&slat>0) {
9723e12c5d1SDavid du Colombier 			if(lat0<-45&&lat0+slat>-45)
9733e12c5d1SDavid du Colombier 				conn = gridpt(-45.,lon0,conn);
9743e12c5d1SDavid du Colombier 			else if(lat0<45&&lat0+slat>45)
9753e12c5d1SDavid du Colombier 				conn = gridpt(45.,lon0,conn);
9763e12c5d1SDavid du Colombier 		} else if(projection==Xtetra&&slat>0) {
9773e12c5d1SDavid du Colombier 			if(lat0<-tetrapt&&lat0+slat>-tetrapt) {
9783e12c5d1SDavid du Colombier 				gridpt(-tetrapt-.001,lon0,conn);
9793e12c5d1SDavid du Colombier 				conn = gridpt(-tetrapt+.001,lon0,0);
9803e12c5d1SDavid du Colombier 			}
9813e12c5d1SDavid du Colombier 			else if(lat0<tetrapt&&lat0+slat>tetrapt) {
9823e12c5d1SDavid du Colombier 				gridpt(tetrapt-.001,lon0,conn);
9833e12c5d1SDavid du Colombier 				conn = gridpt(tetrapt+.001,lon0,0);
9843e12c5d1SDavid du Colombier 			}
9853e12c5d1SDavid du Colombier 		}
9863e12c5d1SDavid du Colombier 		if(conn==0 && oconn!=0) {
9873e12c5d1SDavid du Colombier 			if(slat+slon>.05) {
9883e12c5d1SDavid du Colombier 				lat0 -= slat;	/* steps too big */
9893e12c5d1SDavid du Colombier 				lon0 -= slon;	/* or near bdry */
9903e12c5d1SDavid du Colombier 				slat /= 2;
9913e12c5d1SDavid du Colombier 				slon /= 2;
9923e12c5d1SDavid du Colombier 				conn = oconn = gridpt(lat0,lon0,conn);
9933e12c5d1SDavid du Colombier 			} else
9943e12c5d1SDavid du Colombier 				oconn = 0;
9953e12c5d1SDavid du Colombier 		} else {
9963e12c5d1SDavid du Colombier 			if(conn==2) {
9973e12c5d1SDavid du Colombier 				slat = tlat;
9983e12c5d1SDavid du Colombier 				slon = tlon;
9993e12c5d1SDavid du Colombier 				conn = 1;
10003e12c5d1SDavid du Colombier 			}
10013e12c5d1SDavid du Colombier 			oconn = conn;
10023e12c5d1SDavid du Colombier 	 	}
10033e12c5d1SDavid du Colombier 		lat0 += slat;
10043e12c5d1SDavid du Colombier 		lon0 += slon;
10053e12c5d1SDavid du Colombier 	}
10063e12c5d1SDavid du Colombier 	gridpt(lat1,lon1,conn);
10073e12c5d1SDavid du Colombier }
10083e12c5d1SDavid du Colombier 
10093e12c5d1SDavid du Colombier static gridinv;		/* nonzero when doing window bounds */
10103e12c5d1SDavid du Colombier 
10113e12c5d1SDavid du Colombier int
gridpt(double lat,double lon,int conn)1012219b2ee8SDavid du Colombier gridpt(double lat, double lon, int conn)
10133e12c5d1SDavid du Colombier {
10143e12c5d1SDavid du Colombier 	struct place g;
10153e12c5d1SDavid du Colombier /*fprintf(stderr,"%f %f\n",lat,lon);*/
10163e12c5d1SDavid du Colombier 	latlon(lat,lon,&g);
10173e12c5d1SDavid du Colombier 	if(gridinv)
10183e12c5d1SDavid du Colombier 		invert(&g);
10193e12c5d1SDavid du Colombier 	return(plotpt(&g,conn));
10203e12c5d1SDavid du Colombier }
10213e12c5d1SDavid du Colombier 
10223e12c5d1SDavid du Colombier /* win=0 ordinary grid lines, win=1 window lines */
10233e12c5d1SDavid du Colombier 
10243e12c5d1SDavid du Colombier void
dobounds(double lolat,double hilat,double lolon,double hilon,int win)1025219b2ee8SDavid du Colombier dobounds(double lolat, double hilat, double lolon, double hilon, int win)
10263e12c5d1SDavid du Colombier {
10273e12c5d1SDavid du Colombier 	gridinv = win;
10283e12c5d1SDavid du Colombier 	if(lolat>-90 || win && (poles&1)!=0)
10293e12c5d1SDavid du Colombier 		dogrid(lolat+FUZZ,lolat+FUZZ,lolon,hilon);
10303e12c5d1SDavid du Colombier 	if(hilat<90 || win && (poles&2)!=0)
10313e12c5d1SDavid du Colombier 		dogrid(hilat-FUZZ,hilat-FUZZ,lolon,hilon);
10323e12c5d1SDavid du Colombier 	if(hilon-lolon<360 || win && cut==picut) {
10333e12c5d1SDavid du Colombier 		dogrid(lolat,hilat,lolon+FUZZ,lolon+FUZZ);
10343e12c5d1SDavid du Colombier 		dogrid(lolat,hilat,hilon-FUZZ,hilon-FUZZ);
10353e12c5d1SDavid du Colombier 	}
10363e12c5d1SDavid du Colombier 	gridinv = 0;
10373e12c5d1SDavid du Colombier }
10383e12c5d1SDavid du Colombier 
1039219b2ee8SDavid du Colombier static void
dolimb(void)1040219b2ee8SDavid du Colombier dolimb(void)
1041219b2ee8SDavid du Colombier {
1042219b2ee8SDavid du Colombier 	double lat, lon;
1043219b2ee8SDavid du Colombier 	double res = fmin(dlat, dlon)/4;
1044219b2ee8SDavid du Colombier 	int conn = 0;
1045219b2ee8SDavid du Colombier 	int newconn;
1046219b2ee8SDavid du Colombier 	if(limb == 0)
1047219b2ee8SDavid du Colombier 		return;
1048219b2ee8SDavid du Colombier 	onlimb = gridinv = 1;
1049219b2ee8SDavid du Colombier 	for(;;) {
1050219b2ee8SDavid du Colombier 		newconn = (*limb)(&lat, &lon, res);
1051219b2ee8SDavid du Colombier 		if(newconn == -1)
1052219b2ee8SDavid du Colombier 			break;
1053219b2ee8SDavid du Colombier 		conn = gridpt(lat, lon, conn*newconn);
1054219b2ee8SDavid du Colombier 	}
1055219b2ee8SDavid du Colombier 	onlimb = gridinv = 0;
1056219b2ee8SDavid du Colombier }
1057219b2ee8SDavid du Colombier 
1058219b2ee8SDavid du Colombier 
10593e12c5d1SDavid du Colombier void
radbds(double * w,double * rw)1060219b2ee8SDavid du Colombier radbds(double *w, double *rw)
10613e12c5d1SDavid du Colombier {
10623e12c5d1SDavid du Colombier 	int i;
10633e12c5d1SDavid du Colombier 	for(i=0;i<4;i++)
10643e12c5d1SDavid du Colombier 		rw[i] = w[i]*RAD;
10653e12c5d1SDavid du Colombier 	rw[0] -= FUZZ;
10663e12c5d1SDavid du Colombier 	rw[1] += FUZZ;
10673e12c5d1SDavid du Colombier 	rw[2] -= FUZZ;
10683e12c5d1SDavid du Colombier 	rw[3] += FUZZ;
10693e12c5d1SDavid du Colombier }
10703e12c5d1SDavid du Colombier 
10713e12c5d1SDavid du Colombier void
windlim(void)10723e12c5d1SDavid du Colombier windlim(void)
10733e12c5d1SDavid du Colombier {
1074219b2ee8SDavid du Colombier 	double center = orientation[0];
1075219b2ee8SDavid du Colombier 	double colat;
10763e12c5d1SDavid du Colombier 	if(center>90)
10773e12c5d1SDavid du Colombier 		center = 180 - center;
10783e12c5d1SDavid du Colombier 	if(center<-90)
10793e12c5d1SDavid du Colombier 		center = -180 - center;
10803e12c5d1SDavid du Colombier 	if(fabs(center)>90)
10813e12c5d1SDavid du Colombier 		error("unreasonable orientation");
10823e12c5d1SDavid du Colombier 	colat = 90 - window[0];
10833e12c5d1SDavid du Colombier 	if(center-colat>limits[0])
10843e12c5d1SDavid du Colombier 		limits[0] = center - colat;
10853e12c5d1SDavid du Colombier 	if(center+colat<limits[1])
10863e12c5d1SDavid du Colombier 		limits[1] = center + colat;
10873e12c5d1SDavid du Colombier }
10883e12c5d1SDavid du Colombier 
10893e12c5d1SDavid du Colombier 
10903e12c5d1SDavid du Colombier short
getshort(FILE * f)10913e12c5d1SDavid du Colombier getshort(FILE *f)
10923e12c5d1SDavid du Colombier {
10933e12c5d1SDavid du Colombier 	int c, r;
10943e12c5d1SDavid du Colombier 	c = getc(f);
10953e12c5d1SDavid du Colombier 	r = (c | getc(f)<<8);
10963e12c5d1SDavid du Colombier 	if (r&0x8000)
10973e12c5d1SDavid du Colombier 		r |= ~0xFFFF;	/* in case short > 16 bits */
10983e12c5d1SDavid du Colombier 	return r;
10993e12c5d1SDavid du Colombier }
11003e12c5d1SDavid du Colombier 
11013e12c5d1SDavid du Colombier double
fmin(double x,double y)11023e12c5d1SDavid du Colombier fmin(double x, double y)
11033e12c5d1SDavid du Colombier {
11043e12c5d1SDavid du Colombier 	return(x<y?x:y);
11053e12c5d1SDavid du Colombier }
11063e12c5d1SDavid du Colombier 
11073e12c5d1SDavid du Colombier double
fmax(double x,double y)11083e12c5d1SDavid du Colombier fmax(double x, double y)
11093e12c5d1SDavid du Colombier {
11103e12c5d1SDavid du Colombier 	return(x>y?x:y);
11113e12c5d1SDavid du Colombier }
11123e12c5d1SDavid du Colombier 
11133e12c5d1SDavid du Colombier void
clamp(double * px,double v)1114219b2ee8SDavid du Colombier clamp(double *px, double v)
11153e12c5d1SDavid du Colombier {
11163e12c5d1SDavid du Colombier 	*px = (v<0?fmax:fmin)(*px,v);
11173e12c5d1SDavid du Colombier }
11183e12c5d1SDavid du Colombier 
11193e12c5d1SDavid du Colombier void
pathnames(void)11203e12c5d1SDavid du Colombier pathnames(void)
11213e12c5d1SDavid du Colombier {
11223e12c5d1SDavid du Colombier 	int i;
1123219b2ee8SDavid du Colombier 	char *t, *indexfile, *name;
11243e12c5d1SDavid du Colombier 	FILE *f, *fx;
1125219b2ee8SDavid du Colombier 	for(i=0; i<nfile; i++) {
1126219b2ee8SDavid du Colombier 		name = file[i].name;
1127219b2ee8SDavid du Colombier 		if(*name=='/')
11283e12c5d1SDavid du Colombier 			continue;
1129219b2ee8SDavid du Colombier 		indexfile = mapindex(name);
11303e12c5d1SDavid du Colombier 			/* ansi equiv of unix access() call */
1131219b2ee8SDavid du Colombier 		f = fopen(name, "r");
11323e12c5d1SDavid du Colombier 		fx = fopen(indexfile, "r");
11333e12c5d1SDavid du Colombier 		if(f) fclose(f);
11343e12c5d1SDavid du Colombier 		if(fx) fclose(fx);
11353e12c5d1SDavid du Colombier 		free(indexfile);
11363e12c5d1SDavid du Colombier 		if(f && fx)
11373e12c5d1SDavid du Colombier 			continue;
1138219b2ee8SDavid du Colombier 		t = malloc(strlen(name)+strlen(mapdir)+2);
11393e12c5d1SDavid du Colombier 		strcpy(t,mapdir);
11403e12c5d1SDavid du Colombier 		strcat(t,"/");
1141219b2ee8SDavid du Colombier 		strcat(t,name);
1142219b2ee8SDavid du Colombier 		file[i].name = t;
11433e12c5d1SDavid du Colombier 	}
11443e12c5d1SDavid du Colombier }
11453e12c5d1SDavid du Colombier 
11463e12c5d1SDavid du Colombier void
clipinit(void)11473e12c5d1SDavid du Colombier clipinit(void)
11483e12c5d1SDavid du Colombier {
11493e12c5d1SDavid du Colombier 	register i;
1150219b2ee8SDavid du Colombier 	double s,t;
11513e12c5d1SDavid du Colombier 	if(nvert<=0)
11523e12c5d1SDavid du Colombier 		return;
11533e12c5d1SDavid du Colombier 	for(i=0; i<nvert; i++) {	/*convert latlon to xy*/
1154219b2ee8SDavid du Colombier 		if(normproj(v[i].x,v[i].y,&v[i].x,&v[i].y)==0)
11553e12c5d1SDavid du Colombier 			error("invisible clipping vertex");
11563e12c5d1SDavid du Colombier 	}
11573e12c5d1SDavid du Colombier 	if(nvert==2) {			/*rectangle with diag specified*/
11583e12c5d1SDavid du Colombier 		nvert = 4;
11593e12c5d1SDavid du Colombier 		v[2] = v[1];
11603e12c5d1SDavid du Colombier 		v[1].x=v[0].x, v[1].y=v[2].y, v[3].x=v[2].x, v[3].y=v[0].y;
11613e12c5d1SDavid du Colombier 	}
11623e12c5d1SDavid du Colombier 	v[nvert] = v[0];
11633e12c5d1SDavid du Colombier 	v[nvert+1] = v[1];
11643e12c5d1SDavid du Colombier 	s = 0;
11653e12c5d1SDavid du Colombier 	for(i=1; i<=nvert; i++) {	/*test for convexity*/
11663e12c5d1SDavid du Colombier 		t = (v[i-1].x-v[i].x)*(v[i+1].y-v[i].y) -
11673e12c5d1SDavid du Colombier 		    (v[i-1].y-v[i].y)*(v[i+1].x-v[i].x);
11683e12c5d1SDavid du Colombier 		if(t<-FUZZ && s>=0) s = 1;
11693e12c5d1SDavid du Colombier 		if(t>FUZZ && s<=0) s = -1;
11703e12c5d1SDavid du Colombier 		if(-FUZZ<=t&&t<=FUZZ || t*s>0) {
11713e12c5d1SDavid du Colombier 			s = 0;
11723e12c5d1SDavid du Colombier 			break;
11733e12c5d1SDavid du Colombier 		}
11743e12c5d1SDavid du Colombier 	}
11753e12c5d1SDavid du Colombier 	if(s==0)
11763e12c5d1SDavid du Colombier 		error("improper clipping polygon");
11773e12c5d1SDavid du Colombier 	for(i=0; i<nvert; i++) {	/*edge equation ax+by=c*/
11783e12c5d1SDavid du Colombier 		e[i].a = s*(v[i+1].y - v[i].y);
11793e12c5d1SDavid du Colombier 		e[i].b = s*(v[i].x - v[i+1].x);
11803e12c5d1SDavid du Colombier 		e[i].c = s*(v[i].x*v[i+1].y - v[i].y*v[i+1].x);
11813e12c5d1SDavid du Colombier 	}
11823e12c5d1SDavid du Colombier }
11833e12c5d1SDavid du Colombier 
11843e12c5d1SDavid du Colombier int
inpoly(double x,double y)1185219b2ee8SDavid du Colombier inpoly(double x, double y)
11863e12c5d1SDavid du Colombier {
11873e12c5d1SDavid du Colombier 	register i;
11883e12c5d1SDavid du Colombier 	for(i=0; i<nvert; i++) {
11893e12c5d1SDavid du Colombier 		register struct edge *ei = &e[i];
11903e12c5d1SDavid du Colombier 		double val = x*ei->a + y*ei->b - ei->c;
11913e12c5d1SDavid du Colombier 		if(val>10*FUZZ)
11923e12c5d1SDavid du Colombier 			return(0);
11933e12c5d1SDavid du Colombier 	}
11943e12c5d1SDavid du Colombier 	return 1;
11953e12c5d1SDavid du Colombier }
11963e12c5d1SDavid du Colombier 
11973e12c5d1SDavid du Colombier void
realcut()11983e12c5d1SDavid du Colombier realcut()
11993e12c5d1SDavid du Colombier {
12003e12c5d1SDavid du Colombier 	struct place g;
1201219b2ee8SDavid du Colombier 	double lat;
12023e12c5d1SDavid du Colombier 
12033e12c5d1SDavid du Colombier 	if(cut != picut)	/* punt on unusual cuts */
12043e12c5d1SDavid du Colombier 		return;
12053e12c5d1SDavid du Colombier 	for(lat=window[0]; lat<=window[1]; lat+=grid[2]) {
12063e12c5d1SDavid du Colombier 		g.wlon.l = PI;
12073e12c5d1SDavid du Colombier 		sincos(&g.wlon);
12083e12c5d1SDavid du Colombier 		g.nlat.l = lat*RAD;
12093e12c5d1SDavid du Colombier 		sincos(&g.nlat);
12103e12c5d1SDavid du Colombier 		if(!inwindow(&g)) {
12113e12c5d1SDavid du Colombier 			break;
12123e12c5d1SDavid du Colombier }
12133e12c5d1SDavid du Colombier 		invert(&g);
12143e12c5d1SDavid du Colombier 		if(inlimits(&g)) {
12153e12c5d1SDavid du Colombier 			return;
12163e12c5d1SDavid du Colombier }
12173e12c5d1SDavid du Colombier 	}
12183e12c5d1SDavid du Colombier 	longlines = shortlines = LONGLINES;
12193e12c5d1SDavid du Colombier 	cut = nocut;		/* not necessary; small eff. gain */
12203e12c5d1SDavid du Colombier }
1221