diff options
Diffstat (limited to 'src/cmd/map/symbol.c')
-rw-r--r-- | src/cmd/map/symbol.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/cmd/map/symbol.c b/src/cmd/map/symbol.c new file mode 100644 index 00000000..e8f3c680 --- /dev/null +++ b/src/cmd/map/symbol.c @@ -0,0 +1,192 @@ +#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; +} |