symbol.c 3.2 KB

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