aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/map/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/map/symbol.c')
-rw-r--r--src/cmd/map/symbol.c192
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;
+}