xref: /plan9/sys/src/cmd/map/symbol.c (revision 59cc4ca53493a3c6d2349fe2b7f7c40f7dce7294)
1 #include <u.h>
2 #include <libc.h>
3 #include <stdio.h>
4 #include "map.h"
5 #include "iplot.h"
6 
7 #define NSYMBOL 20
8 
9 enum flag { POINT,ENDSEG,ENDSYM };
10 struct symb {
11 	double x, y;
12 	char name[10+1];
13 	enum flag flag;
14 } *symbol[NSYMBOL];
15 
16 static int nsymbol;
17 static double halfrange = 1;
18 extern int halfwidth;
19 extern int vflag;
20 
21 static int	getrange(FILE *);
22 static int	getsymbol(FILE *, int);
23 static void	setrot(struct place *, double, int);
24 static void	dorot(struct symb *, double *, double *);
25 
26 
27 void
getsyms(char * file)28 getsyms(char *file)
29 {
30 	FILE *sf = fopen(file,"r");
31 	if(sf==0)
32 		filerror("cannot open", file);
33 	while(nsymbol<NSYMBOL-1 && getsymbol(sf,nsymbol))
34 		nsymbol++;
35 	fclose(sf);
36 }
37 
38 static int
getsymbol(FILE * sf,int n)39 getsymbol(FILE *sf, int n)
40 {
41 	double x,y;
42 	char s[2];
43 	int i;
44 	struct symb *sp;
45 	for(;;) {
46 		if(fscanf(sf,"%1s",s)==EOF)
47 			return 0;
48 		switch(s[0]) {
49 		case ':':
50 			break;
51 		case 'o':
52 		case 'c':	/* cl */
53 			fscanf(sf,"%*[^\n]");
54 			continue;
55 		case 'r':
56 			if(getrange(sf))
57 				continue;
58 		default:
59 			error("-y file syntax error");
60 		}
61 		break;
62 	}
63 	sp = (struct symb*)malloc(sizeof(struct symb));
64 	symbol[n] = sp;
65 	if(fscanf(sf,"%10s",sp->name)!=1)
66 		return 0;
67 	i = 0;
68 	while(fscanf(sf,"%1s",s)!=EOF) {
69 		switch(s[0]) {
70 		case 'r':
71 			if(!getrange(sf))
72 				break;
73 			continue;
74 		case 'm':
75 			if(i>0)
76 				symbol[n][i-1].flag = ENDSEG;
77 			continue;
78 		case ':':
79 			ungetc(s[0],sf);
80 			break;
81 		default:
82 			ungetc(s[0],sf);
83 		case 'v':
84 			if(fscanf(sf,"%lf %lf",&x,&y)!=2)
85 				break;
86 			sp[i].x = x*halfwidth/halfrange;
87 			sp[i].y = y*halfwidth/halfrange;
88 			sp[i].flag = POINT;
89 			i++;
90 			sp = symbol[n] = (struct symb*)realloc(symbol[n],
91 					(i+1)*sizeof(struct symb));
92 			continue;
93 		}
94 		break;
95 	}
96 	if(i>0)
97 		symbol[n][i-1].flag = ENDSYM;
98 	else
99 		symbol[n] = 0;
100 	return 1;
101 }
102 
103 static int
getrange(FILE * sf)104 getrange(FILE *sf)
105 {
106 	double x,y,xmin,ymin;
107 	if(fscanf(sf,"%*s %lf %lf %lf %lf",
108 		&xmin,&ymin,&x,&y)!=4)
109 		return 0;
110 	x -= xmin;
111 	y -= ymin;
112 	halfrange = (x>y? x: y)/2;
113 	if(halfrange<=0)
114 		error("bad ra command in -y file");
115 	return 1;
116 }
117 
118 /* r=0 upright;=1 normal;=-1 reverse*/
119 int
putsym(struct place * p,char * name,double s,int r)120 putsym(struct place *p, char *name, double s, int r)
121 {
122 	int x,y,n;
123 	struct symb *sp;
124 	double dx,dy;
125 	int conn = 0;
126 	for(n=0; symbol[n]; n++)
127 		if(strcmp(name,symbol[n]->name)==0)
128 			break;
129 	sp = symbol[n];
130 	if(sp==0)
131 		return 0;
132 	if(doproj(p,&x,&y)*vflag <= 0)
133 		return 1;
134 	setrot(p,s,r);
135 	for(;;) {
136 		dorot(sp,&dx,&dy);
137 		conn = cpoint(x+(int)dx,y+(int)dy,conn);
138 		switch(sp->flag) {
139 		case ENDSEG:
140 			conn = 0;
141 		case POINT:
142 			sp++;
143 			continue;
144 		case ENDSYM:
145 			break;
146 		}
147 		break;
148 	}
149 	return 1;
150 }
151 
152 static double rot[2][2];
153 
154 static void
setrot(struct place * p,double s,int r)155 setrot(struct place *p, double s, int r)
156 {
157 	double x0,y0,x1,y1;
158 	struct place up;
159 	up = *p;
160 	up.nlat.l += .5*RAD;
161 	sincos(&up.nlat);
162 	if(r&&(*projection)(p,&x0,&y0)) {
163 		if((*projection)(&up,&x1,&y1)<=0) {
164 			up.nlat.l -= RAD;
165 			sincos(&up.nlat);
166 			if((*projection)(&up,&x1,&y1)<=0)
167 				goto unit;
168 			x1 = x0 - x1;
169 			y1 = y0 - y1;
170 		} else {
171 			x1 -= x0;
172 			y1 -= y0;
173 		}
174 		x1 = r*x1;
175 		s /= hypot(x1,y1);
176 		rot[0][0] = y1*s;
177 		rot[0][1] = x1*s;
178 		rot[1][0] = -x1*s;
179 		rot[1][1] = y1*s;
180 	} else {
181 unit:
182 		rot[0][0] = rot[1][1] = s;
183 		rot[0][1] = rot[1][0] = 0;
184 	}
185 }
186 
187 static void
dorot(struct symb * sp,double * px,double * py)188 dorot(struct symb *sp, double *px, double *py)
189 {
190 	*px = rot[0][0]*sp->x + rot[0][1]*sp->y;
191 	*py = rot[1][0]*sp->x + rot[1][1]*sp->y;
192 }
193