linegen.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include "pic.h"
  4. #include "y.tab.h"
  5. obj *linegen(int type)
  6. {
  7. static double prevdx = HT;
  8. static double prevdy = 0;
  9. static double prevw = HT10;
  10. static double prevh = HT5;
  11. int i, j, some, head, ddtype, invis, chop, battr, with;
  12. double ddval, chop1, chop2, x0, y0, x1, y1;
  13. double fillval = 0;
  14. double theta;
  15. double defx, defy, xwith, ywith;
  16. obj *p, *ppos;
  17. static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */
  18. static int ytab[] = { 0, 1, 0, -1 };
  19. double dx[500], dy[500];
  20. int ndxy;
  21. double nx, ny;
  22. Attr *ap, *chop_ap[4];
  23. nx = curx;
  24. ny = cury;
  25. defx = getfval("linewid");
  26. defy = getfval("lineht");
  27. prevh = getfval("arrowht");
  28. prevw = getfval("arrowwid");
  29. dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0;
  30. chop = chop1 = chop2 = 0;
  31. ddtype = ddval = xwith = ywith = 0;
  32. for (i = 0; i < nattr; i++) {
  33. ap = &attr[i];
  34. switch (ap->a_type) {
  35. case TEXTATTR:
  36. savetext(ap->a_sub, ap->a_val.p);
  37. break;
  38. case HEAD:
  39. head += ap->a_val.i;
  40. break;
  41. case INVIS:
  42. invis = INVIS;
  43. break;
  44. case NOEDGE:
  45. battr |= NOEDGEBIT;
  46. break;
  47. case DOT:
  48. case DASH:
  49. ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
  50. if (ap->a_sub == DEFAULT)
  51. ddval = getfval("dashwid");
  52. else
  53. ddval = ap->a_val.f;
  54. break;
  55. case SAME:
  56. dx[ndxy] = prevdx;
  57. dy[ndxy] = prevdy;
  58. some++;
  59. break;
  60. case LEFT:
  61. dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
  62. some++;
  63. hvmode = L_DIR;
  64. break;
  65. case RIGHT:
  66. dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
  67. some++;
  68. hvmode = R_DIR;
  69. break;
  70. case UP:
  71. dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
  72. some++;
  73. hvmode = U_DIR;
  74. break;
  75. case DOWN:
  76. dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
  77. some++;
  78. hvmode = D_DIR;
  79. break;
  80. case HEIGHT: /* length of arrowhead */
  81. prevh = ap->a_val.f;
  82. break;
  83. case WIDTH: /* width of arrowhead */
  84. prevw = ap->a_val.f;
  85. break;
  86. case TO:
  87. if (some) {
  88. nx += dx[ndxy];
  89. ny += dy[ndxy];
  90. ndxy++;
  91. dx[ndxy] = dy[ndxy] = some = 0;
  92. }
  93. ppos = attr[i].a_val.o;
  94. dx[ndxy] = ppos->o_x - nx;
  95. dy[ndxy] = ppos->o_y - ny;
  96. some++;
  97. break;
  98. case BY:
  99. if (some) {
  100. nx += dx[ndxy];
  101. ny += dy[ndxy];
  102. ndxy++;
  103. dx[ndxy] = dy[ndxy] = some = 0;
  104. }
  105. ppos = ap->a_val.o;
  106. dx[ndxy] = ppos->o_x;
  107. dy[ndxy] = ppos->o_y;
  108. some++;
  109. break;
  110. case THEN: /* turn off any previous accumulation */
  111. if (some) {
  112. nx += dx[ndxy];
  113. ny += dy[ndxy];
  114. ndxy++;
  115. dx[ndxy] = dy[ndxy] = some = 0;
  116. }
  117. break;
  118. case FROM:
  119. case AT:
  120. ppos = ap->a_val.o;
  121. nx = curx = ppos->o_x;
  122. ny = cury = ppos->o_y;
  123. break;
  124. case WITH:
  125. with = ap->a_val.i;
  126. break;
  127. case CHOP:
  128. if (ap->a_sub != PLACENAME) {
  129. if( chop == 0)
  130. chop1 = chop2 = ap->a_val.f;
  131. else
  132. chop2 = ap->a_val.f;
  133. }
  134. chop_ap[chop++] = ap;
  135. break;
  136. case FILL:
  137. battr |= FILLBIT;
  138. if (ap->a_sub == DEFAULT)
  139. fillval = getfval("fillval");
  140. else
  141. fillval = ap->a_val.f;
  142. break;
  143. }
  144. }
  145. if (with) { /* this doesn't work at all */
  146. switch (with) {
  147. case CENTER:
  148. xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break;
  149. }
  150. for (i = 0; i < ndxy; i++) {
  151. dx[i] -= xwith;
  152. dy[i] -= ywith;
  153. }
  154. curx += xwith;
  155. cury += ywith;
  156. }
  157. if (some) {
  158. nx += dx[ndxy];
  159. ny += dy[ndxy];
  160. ndxy++;
  161. defx = dx[ndxy-1];
  162. defy = dy[ndxy-1];
  163. } else {
  164. defx *= xtab[hvmode];
  165. defy *= ytab[hvmode];
  166. dx[ndxy] = defx;
  167. dy[ndxy] = defy;
  168. ndxy++;
  169. nx += defx;
  170. ny += defy;
  171. }
  172. prevdx = defx;
  173. prevdy = defy;
  174. if (chop) {
  175. if (chop == 1 && chop1 == 0) /* just said "chop", so use default */
  176. chop1 = chop2 = getfval("circlerad");
  177. theta = atan2(dy[0], dx[0]);
  178. x0 = chop1 * cos(theta);
  179. y0 = chop1 * sin(theta);
  180. curx += x0;
  181. cury += y0;
  182. dx[0] -= x0;
  183. dy[0] -= y0;
  184. theta = atan2(dy[ndxy-1], dx[ndxy-1]);
  185. x1 = chop2 * cos(theta);
  186. y1 = chop2 * sin(theta);
  187. nx -= x1;
  188. ny -= y1;
  189. dx[ndxy-1] -= x1;
  190. dy[ndxy-1] -= y1;
  191. dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
  192. x0, y0, x1, y1, curx, cury, nx, ny);
  193. }
  194. p = makenode(type, 5 + 2 * ndxy);
  195. curx = p->o_val[0] = nx;
  196. cury = p->o_val[1] = ny;
  197. if (head || type == ARROW) {
  198. p->o_nhead = getfval("arrowhead");
  199. p->o_val[2] = prevw;
  200. p->o_val[3] = prevh;
  201. if (head == 0)
  202. head = HEAD2; /* default arrow head */
  203. }
  204. p->o_attr = head | invis | ddtype | battr;
  205. p->o_fillval = fillval;
  206. p->o_val[4] = ndxy;
  207. nx = p->o_x;
  208. ny = p->o_y;
  209. for (i = 0, j = 5; i < ndxy; i++, j += 2) {
  210. p->o_val[j] = dx[i];
  211. p->o_val[j+1] = dy[i];
  212. if (type == LINE || type == ARROW)
  213. extreme(nx += dx[i], ny += dy[i]);
  214. else if (type == SPLINE && i < ndxy-1) {
  215. /* to compute approx extreme of spline at p,
  216. /* compute midway between p-1 and p+1,
  217. /* then go 3/4 from there to p */
  218. double ex, ey, xi, yi, xi1, yi1;
  219. xi = nx + dx[i]; yi = ny + dy[i]; /* p */
  220. xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
  221. ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */
  222. ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
  223. extreme(ex, ey);
  224. nx = xi; ny = yi;
  225. }
  226. }
  227. p->o_ddval = ddval;
  228. if (dbg) {
  229. printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
  230. for (i = 0, j = 5; i < ndxy; i++, j += 2)
  231. printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
  232. }
  233. extreme(p->o_x, p->o_y);
  234. extreme(curx, cury);
  235. return(p);
  236. }