Blob


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