| #include <u.h> |
| #include <libc.h> |
| #include <stdio.h> |
| #include "map.h" |
| #include "iplot.h" |
| |
| #define NSYMBOL 20 |
| |
| enum flag { POINT,ENDSEG,ENDSYM }; |
| struct symb { |
| double x, y; |
| char name[10+1]; |
| enum flag flag; |
| } *symbol[NSYMBOL]; |
| |
| static int nsymbol; |
| static double halfrange = 1; |
| extern int halfwidth; |
| extern int vflag; |
| |
| static int getrange(FILE *); |
| static int getsymbol(FILE *, int); |
| static void setrot(struct place *, double, int); |
| static void dorot(struct symb *, double *, double *); |
| |
| |
| void |
| getsyms(char *file) |
| { |
| FILE *sf = fopen(file,"r"); |
| if(sf==0) |
| filerror("cannot open", file); |
| while(nsymbol<NSYMBOL-1 && getsymbol(sf,nsymbol)) |
| nsymbol++; |
| fclose(sf); |
| } |
| |
| static int |
| getsymbol(FILE *sf, int n) |
| { |
| double x,y; |
| char s[2]; |
| int i; |
| struct symb *sp; |
| for(;;) { |
| if(fscanf(sf,"%1s",s)==EOF) |
| return 0; |
| switch(s[0]) { |
| case ':': |
| break; |
| case 'o': |
| case 'c': /* cl */ |
| fscanf(sf,"%*[^\n]"); |
| continue; |
| case 'r': |
| if(getrange(sf)) |
| continue; |
| default: |
| error("-y file syntax error"); |
| } |
| break; |
| } |
| sp = (struct symb*)malloc(sizeof(struct symb)); |
| symbol[n] = sp; |
| if(fscanf(sf,"%10s",sp->name)!=1) |
| return 0; |
| i = 0; |
| while(fscanf(sf,"%1s",s)!=EOF) { |
| switch(s[0]) { |
| case 'r': |
| if(!getrange(sf)) |
| break; |
| continue; |
| case 'm': |
| if(i>0) |
| symbol[n][i-1].flag = ENDSEG; |
| continue; |
| case ':': |
| ungetc(s[0],sf); |
| break; |
| default: |
| ungetc(s[0],sf); |
| case 'v': |
| if(fscanf(sf,"%lf %lf",&x,&y)!=2) |
| break; |
| sp[i].x = x*halfwidth/halfrange; |
| sp[i].y = y*halfwidth/halfrange; |
| sp[i].flag = POINT; |
| i++; |
| sp = symbol[n] = (struct symb*)realloc(symbol[n], |
| (i+1)*sizeof(struct symb)); |
| continue; |
| } |
| break; |
| } |
| if(i>0) |
| symbol[n][i-1].flag = ENDSYM; |
| else |
| symbol[n] = 0; |
| return 1; |
| } |
| |
| static int |
| getrange(FILE *sf) |
| { |
| double x,y,xmin,ymin; |
| if(fscanf(sf,"%*s %lf %lf %lf %lf", |
| &xmin,&ymin,&x,&y)!=4) |
| return 0; |
| x -= xmin; |
| y -= ymin; |
| halfrange = (x>y? x: y)/2; |
| if(halfrange<=0) |
| error("bad ra command in -y file"); |
| return 1; |
| } |
| |
| /* r=0 upright;=1 normal;=-1 reverse*/ |
| int |
| putsym(struct place *p, char *name, double s, int r) |
| { |
| int x,y,n; |
| struct symb *sp; |
| double dx,dy; |
| int conn = 0; |
| for(n=0; symbol[n]; n++) |
| if(strcmp(name,symbol[n]->name)==0) |
| break; |
| sp = symbol[n]; |
| if(sp==0) |
| return 0; |
| if(doproj(p,&x,&y)*vflag <= 0) |
| return 1; |
| setrot(p,s,r); |
| for(;;) { |
| dorot(sp,&dx,&dy); |
| conn = cpoint(x+(int)dx,y+(int)dy,conn); |
| switch(sp->flag) { |
| case ENDSEG: |
| conn = 0; |
| case POINT: |
| sp++; |
| continue; |
| case ENDSYM: |
| break; |
| } |
| break; |
| } |
| return 1; |
| } |
| |
| static double rot[2][2]; |
| |
| static void |
| setrot(struct place *p, double s, int r) |
| { |
| double x0,y0,x1,y1; |
| struct place up; |
| up = *p; |
| up.nlat.l += .5*RAD; |
| sincos(&up.nlat); |
| if(r&&(*projection)(p,&x0,&y0)) { |
| if((*projection)(&up,&x1,&y1)<=0) { |
| up.nlat.l -= RAD; |
| sincos(&up.nlat); |
| if((*projection)(&up,&x1,&y1)<=0) |
| goto unit; |
| x1 = x0 - x1; |
| y1 = y0 - y1; |
| } else { |
| x1 -= x0; |
| y1 -= y0; |
| } |
| x1 = r*x1; |
| s /= hypot(x1,y1); |
| rot[0][0] = y1*s; |
| rot[0][1] = x1*s; |
| rot[1][0] = -x1*s; |
| rot[1][1] = y1*s; |
| } else { |
| unit: |
| rot[0][0] = rot[1][1] = s; |
| rot[0][1] = rot[1][0] = 0; |
| } |
| } |
| |
| static void |
| dorot(struct symb *sp, double *px, double *py) |
| { |
| *px = rot[0][0]*sp->x + rot[0][1]*sp->y; |
| *py = rot[1][0]*sp->x + rot[1][1]*sp->y; |
| } |