]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/map/symbol.c
fix ref822 again: remove uniqarray(), fix case with many entries in 'n'.
[plan9front.git] / sys / src / cmd / map / symbol.c
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
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
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
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
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
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
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 }