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