Blame


1 3ebbd193 2017-06-19 rsc #include <stdio.h>
2 3ebbd193 2017-06-19 rsc #include <math.h>
3 3ebbd193 2017-06-19 rsc #include "pic.h"
4 3ebbd193 2017-06-19 rsc #include "y.tab.h"
5 3ebbd193 2017-06-19 rsc
6 3ebbd193 2017-06-19 rsc void arc_extreme(double, double, double, double, double, double);
7 3ebbd193 2017-06-19 rsc int quadrant(double x, double y);
8 3ebbd193 2017-06-19 rsc
9 3ebbd193 2017-06-19 rsc obj *arcgen(int type) /* handles circular and (eventually) elliptical arcs */
10 3ebbd193 2017-06-19 rsc {
11 3ebbd193 2017-06-19 rsc static double prevw = HT10;
12 3ebbd193 2017-06-19 rsc static double prevh = HT5;
13 3ebbd193 2017-06-19 rsc static double prevrad = HT2;
14 3ebbd193 2017-06-19 rsc static int dtox[2][4] ={ { 1, -1, -1, 1}, {1, 1, -1, -1} };
15 3ebbd193 2017-06-19 rsc static int dtoy[2][4] ={ {1, 1, -1, -1}, {-1, 1, 1, -1} };
16 3ebbd193 2017-06-19 rsc static int dctrx[2][4] ={ {0, -1, 0, 1}, {0, 1, 0, -1} };
17 3ebbd193 2017-06-19 rsc static int dctry[2][4] ={ {1, 0, -1, 0}, {-1, 0, 1, 0} };
18 3ebbd193 2017-06-19 rsc static int nexthv[2][4] ={ {U_DIR, L_DIR, D_DIR, R_DIR}, {D_DIR, R_DIR, U_DIR, L_DIR} };
19 3ebbd193 2017-06-19 rsc double dx2, dy2, ht, phi, r, d;
20 3ebbd193 2017-06-19 rsc int i, head, to, at, cw, invis, ddtype, battr;
21 3ebbd193 2017-06-19 rsc obj *p, *ppos;
22 3ebbd193 2017-06-19 rsc double fromx, fromy, tox, toy, fillval = 0;
23 3ebbd193 2017-06-19 rsc Attr *ap;
24 3ebbd193 2017-06-19 rsc
25 3ebbd193 2017-06-19 rsc tox=toy=0.0; /* Botch? (gcc) */
26 3ebbd193 2017-06-19 rsc
27 3ebbd193 2017-06-19 rsc prevrad = getfval("arcrad");
28 3ebbd193 2017-06-19 rsc prevh = getfval("arrowht");
29 3ebbd193 2017-06-19 rsc prevw = getfval("arrowwid");
30 3ebbd193 2017-06-19 rsc fromx = curx;
31 3ebbd193 2017-06-19 rsc fromy = cury;
32 3ebbd193 2017-06-19 rsc head = to = at = cw = invis = ddtype = battr = 0;
33 3ebbd193 2017-06-19 rsc for (i = 0; i < nattr; i++) {
34 3ebbd193 2017-06-19 rsc ap = &attr[i];
35 3ebbd193 2017-06-19 rsc switch (ap->a_type) {
36 3ebbd193 2017-06-19 rsc case TEXTATTR:
37 3ebbd193 2017-06-19 rsc savetext(ap->a_sub, ap->a_val.p);
38 3ebbd193 2017-06-19 rsc break;
39 3ebbd193 2017-06-19 rsc case HEAD:
40 3ebbd193 2017-06-19 rsc head += ap->a_val.i;
41 3ebbd193 2017-06-19 rsc break;
42 3ebbd193 2017-06-19 rsc case INVIS:
43 3ebbd193 2017-06-19 rsc invis = INVIS;
44 3ebbd193 2017-06-19 rsc break;
45 3ebbd193 2017-06-19 rsc case HEIGHT: /* length of arrowhead */
46 3ebbd193 2017-06-19 rsc prevh = ap->a_val.f;
47 3ebbd193 2017-06-19 rsc break;
48 3ebbd193 2017-06-19 rsc case WIDTH: /* width of arrowhead */
49 3ebbd193 2017-06-19 rsc prevw = ap->a_val.f;
50 3ebbd193 2017-06-19 rsc break;
51 3ebbd193 2017-06-19 rsc case RADIUS:
52 3ebbd193 2017-06-19 rsc prevrad = ap->a_val.f;
53 3ebbd193 2017-06-19 rsc break;
54 3ebbd193 2017-06-19 rsc case DIAMETER:
55 3ebbd193 2017-06-19 rsc prevrad = ap->a_val.f / 2;
56 3ebbd193 2017-06-19 rsc break;
57 3ebbd193 2017-06-19 rsc case CW:
58 3ebbd193 2017-06-19 rsc cw = 1;
59 3ebbd193 2017-06-19 rsc break;
60 3ebbd193 2017-06-19 rsc case FROM: /* start point of arc */
61 3ebbd193 2017-06-19 rsc ppos = ap->a_val.o;
62 3ebbd193 2017-06-19 rsc fromx = ppos->o_x;
63 3ebbd193 2017-06-19 rsc fromy = ppos->o_y;
64 3ebbd193 2017-06-19 rsc break;
65 3ebbd193 2017-06-19 rsc case TO: /* end point of arc */
66 3ebbd193 2017-06-19 rsc ppos = ap->a_val.o;
67 3ebbd193 2017-06-19 rsc tox = ppos->o_x;
68 3ebbd193 2017-06-19 rsc toy = ppos->o_y;
69 3ebbd193 2017-06-19 rsc to++;
70 3ebbd193 2017-06-19 rsc break;
71 3ebbd193 2017-06-19 rsc case AT: /* center of arc */
72 3ebbd193 2017-06-19 rsc ppos = ap->a_val.o;
73 3ebbd193 2017-06-19 rsc curx = ppos->o_x;
74 3ebbd193 2017-06-19 rsc cury = ppos->o_y;
75 3ebbd193 2017-06-19 rsc at = 1;
76 3ebbd193 2017-06-19 rsc break;
77 3ebbd193 2017-06-19 rsc case UP:
78 3ebbd193 2017-06-19 rsc hvmode = U_DIR;
79 3ebbd193 2017-06-19 rsc break;
80 3ebbd193 2017-06-19 rsc case DOWN:
81 3ebbd193 2017-06-19 rsc hvmode = D_DIR;
82 3ebbd193 2017-06-19 rsc break;
83 3ebbd193 2017-06-19 rsc case RIGHT:
84 3ebbd193 2017-06-19 rsc hvmode = R_DIR;
85 3ebbd193 2017-06-19 rsc break;
86 3ebbd193 2017-06-19 rsc case LEFT:
87 3ebbd193 2017-06-19 rsc hvmode = L_DIR;
88 3ebbd193 2017-06-19 rsc break;
89 3ebbd193 2017-06-19 rsc case FILL:
90 3ebbd193 2017-06-19 rsc battr |= FILLBIT;
91 3ebbd193 2017-06-19 rsc if (ap->a_sub == DEFAULT)
92 3ebbd193 2017-06-19 rsc fillval = getfval("fillval");
93 3ebbd193 2017-06-19 rsc else
94 3ebbd193 2017-06-19 rsc fillval = ap->a_val.f;
95 3ebbd193 2017-06-19 rsc break;
96 3ebbd193 2017-06-19 rsc }
97 3ebbd193 2017-06-19 rsc }
98 3ebbd193 2017-06-19 rsc if (!at && !to) { /* the defaults are mostly OK */
99 3ebbd193 2017-06-19 rsc curx = fromx + prevrad * dctrx[cw][hvmode];
100 3ebbd193 2017-06-19 rsc cury = fromy + prevrad * dctry[cw][hvmode];
101 3ebbd193 2017-06-19 rsc tox = fromx + prevrad * dtox[cw][hvmode];
102 3ebbd193 2017-06-19 rsc toy = fromy + prevrad * dtoy[cw][hvmode];
103 3ebbd193 2017-06-19 rsc hvmode = nexthv[cw][hvmode];
104 3ebbd193 2017-06-19 rsc }
105 3ebbd193 2017-06-19 rsc else if (!at) {
106 3ebbd193 2017-06-19 rsc dx2 = (tox - fromx) / 2;
107 3ebbd193 2017-06-19 rsc dy2 = (toy - fromy) / 2;
108 3ebbd193 2017-06-19 rsc phi = atan2(dy2, dx2) + (cw ? -PI/2 : PI/2);
109 3ebbd193 2017-06-19 rsc if (prevrad <= 0.0)
110 3ebbd193 2017-06-19 rsc prevrad = dx2*dx2+dy2*dy2;
111 3ebbd193 2017-06-19 rsc for (r=prevrad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2)
112 3ebbd193 2017-06-19 rsc ; /* this kludge gets around too-small radii */
113 3ebbd193 2017-06-19 rsc prevrad = r;
114 3ebbd193 2017-06-19 rsc ht = sqrt(d);
115 3ebbd193 2017-06-19 rsc curx = fromx + dx2 + ht * cos(phi);
116 3ebbd193 2017-06-19 rsc cury = fromy + dy2 + ht * sin(phi);
117 3ebbd193 2017-06-19 rsc dprintf("dx2,dy2=%g,%g, phi=%g, r,ht=%g,%g\n",
118 3ebbd193 2017-06-19 rsc dx2, dy2, phi, r, ht);
119 3ebbd193 2017-06-19 rsc }
120 3ebbd193 2017-06-19 rsc else if (at && !to) { /* do we have all the cases??? */
121 3ebbd193 2017-06-19 rsc tox = fromx + prevrad * dtox[cw][hvmode];
122 3ebbd193 2017-06-19 rsc toy = fromy + prevrad * dtoy[cw][hvmode];
123 3ebbd193 2017-06-19 rsc hvmode = nexthv[cw][hvmode];
124 3ebbd193 2017-06-19 rsc }
125 3ebbd193 2017-06-19 rsc if (cw) { /* interchange roles of from-to and heads */
126 3ebbd193 2017-06-19 rsc double temp;
127 3ebbd193 2017-06-19 rsc temp = fromx; fromx = tox; tox = temp;
128 3ebbd193 2017-06-19 rsc temp = fromy; fromy = toy; toy = temp;
129 3ebbd193 2017-06-19 rsc if (head == HEAD1)
130 3ebbd193 2017-06-19 rsc head = HEAD2;
131 3ebbd193 2017-06-19 rsc else if (head == HEAD2)
132 3ebbd193 2017-06-19 rsc head = HEAD1;
133 3ebbd193 2017-06-19 rsc }
134 3ebbd193 2017-06-19 rsc p = makenode(type, 7);
135 3ebbd193 2017-06-19 rsc arc_extreme(fromx, fromy, tox, toy, curx, cury);
136 3ebbd193 2017-06-19 rsc p->o_val[0] = fromx;
137 3ebbd193 2017-06-19 rsc p->o_val[1] = fromy;
138 3ebbd193 2017-06-19 rsc p->o_val[2] = tox;
139 3ebbd193 2017-06-19 rsc p->o_val[3] = toy;
140 3ebbd193 2017-06-19 rsc if (cw) {
141 3ebbd193 2017-06-19 rsc curx = fromx;
142 3ebbd193 2017-06-19 rsc cury = fromy;
143 3ebbd193 2017-06-19 rsc } else {
144 3ebbd193 2017-06-19 rsc curx = tox;
145 3ebbd193 2017-06-19 rsc cury = toy;
146 3ebbd193 2017-06-19 rsc }
147 3ebbd193 2017-06-19 rsc p->o_val[4] = prevw;
148 3ebbd193 2017-06-19 rsc p->o_val[5] = prevh;
149 3ebbd193 2017-06-19 rsc p->o_val[6] = prevrad;
150 3ebbd193 2017-06-19 rsc p->o_attr = head | (cw ? CW_ARC : 0) | invis | ddtype | battr;
151 3ebbd193 2017-06-19 rsc p->o_fillval = fillval;
152 3ebbd193 2017-06-19 rsc if (head)
153 3ebbd193 2017-06-19 rsc p->o_nhead = getfval("arrowhead");
154 3ebbd193 2017-06-19 rsc dprintf("arc rad %g at %g %g from %g %g to %g %g head %g %g\n",
155 3ebbd193 2017-06-19 rsc prevrad, p->o_x, p->o_y,
156 3ebbd193 2017-06-19 rsc p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]);
157 3ebbd193 2017-06-19 rsc return(p);
158 3ebbd193 2017-06-19 rsc }
159 3ebbd193 2017-06-19 rsc
160 3ebbd193 2017-06-19 rsc /***************************************************************************
161 3ebbd193 2017-06-19 rsc bounding box of a circular arc Eric Grosse 24 May 84
162 3ebbd193 2017-06-19 rsc
163 3ebbd193 2017-06-19 rsc Conceptually, this routine generates a list consisting of the start,
164 3ebbd193 2017-06-19 rsc end, and whichever north, east, south, and west points lie on the arc.
165 3ebbd193 2017-06-19 rsc The bounding box is then the range of this list.
166 3ebbd193 2017-06-19 rsc list = {start,end}
167 3ebbd193 2017-06-19 rsc j = quadrant(start)
168 3ebbd193 2017-06-19 rsc k = quadrant(end)
169 3ebbd193 2017-06-19 rsc if( j==k && long way 'round ) append north,west,south,east
170 3ebbd193 2017-06-19 rsc else
171 3ebbd193 2017-06-19 rsc while( j != k )
172 3ebbd193 2017-06-19 rsc append center+radius*[j-th of north,west,south,east unit vectors]
173 3ebbd193 2017-06-19 rsc j += 1 (mod 4)
174 3ebbd193 2017-06-19 rsc return( bounding box of list )
175 3ebbd193 2017-06-19 rsc The following code implements this, with simple optimizations.
176 3ebbd193 2017-06-19 rsc ***********************************************************************/
177 3ebbd193 2017-06-19 rsc
178 3ebbd193 2017-06-19 rsc
179 3ebbd193 2017-06-19 rsc void arc_extreme(double x0, double y0, double x1, double y1, double xc, double yc)
180 3ebbd193 2017-06-19 rsc /* start, end, center */
181 3ebbd193 2017-06-19 rsc {
182 3ebbd193 2017-06-19 rsc /* assumes center isn't too far out */
183 3ebbd193 2017-06-19 rsc double r, xmin, ymin, xmax, ymax;
184 3ebbd193 2017-06-19 rsc int j, k;
185 3ebbd193 2017-06-19 rsc x0 -= xc; y0 -= yc; /* move to center */
186 3ebbd193 2017-06-19 rsc x1 -= xc; y1 -= yc;
187 3ebbd193 2017-06-19 rsc xmin = (x0<x1)?x0:x1; ymin = (y0<y1)?y0:y1;
188 3ebbd193 2017-06-19 rsc xmax = (x0>x1)?x0:x1; ymax = (y0>y1)?y0:y1;
189 3ebbd193 2017-06-19 rsc r = sqrt(x0*x0 + y0*y0);
190 3ebbd193 2017-06-19 rsc if (r > 0.0) {
191 3ebbd193 2017-06-19 rsc j = quadrant(x0,y0);
192 3ebbd193 2017-06-19 rsc k = quadrant(x1,y1);
193 3ebbd193 2017-06-19 rsc if (j == k && y1*x0 < x1*y0) {
194 3ebbd193 2017-06-19 rsc /* viewed as complex numbers, if Im(z1/z0)<0, arc is big */
195 3ebbd193 2017-06-19 rsc if( xmin > -r) xmin = -r; if( ymin > -r) ymin = -r;
196 3ebbd193 2017-06-19 rsc if( xmax < r) xmax = r; if( ymax < r) ymax = r;
197 3ebbd193 2017-06-19 rsc } else {
198 3ebbd193 2017-06-19 rsc while (j != k) {
199 3ebbd193 2017-06-19 rsc switch (j) {
200 3ebbd193 2017-06-19 rsc case 1: if( ymax < r) ymax = r; break; /* north */
201 3ebbd193 2017-06-19 rsc case 2: if( xmin > -r) xmin = -r; break; /* west */
202 3ebbd193 2017-06-19 rsc case 3: if( ymin > -r) ymin = -r; break; /* south */
203 3ebbd193 2017-06-19 rsc case 4: if( xmax < r) xmax = r; break; /* east */
204 3ebbd193 2017-06-19 rsc }
205 3ebbd193 2017-06-19 rsc j = j%4 + 1;
206 3ebbd193 2017-06-19 rsc }
207 3ebbd193 2017-06-19 rsc }
208 3ebbd193 2017-06-19 rsc }
209 3ebbd193 2017-06-19 rsc xmin += xc; ymin += yc;
210 3ebbd193 2017-06-19 rsc xmax += xc; ymax += yc;
211 3ebbd193 2017-06-19 rsc extreme(xmin, ymin);
212 3ebbd193 2017-06-19 rsc extreme(xmax, ymax);
213 3ebbd193 2017-06-19 rsc }
214 3ebbd193 2017-06-19 rsc
215 3ebbd193 2017-06-19 rsc int
216 3ebbd193 2017-06-19 rsc quadrant(double x, double y)
217 3ebbd193 2017-06-19 rsc {
218 3ebbd193 2017-06-19 rsc if ( x>=0.0 && y> 0.0) return(1);
219 3ebbd193 2017-06-19 rsc else if( x< 0.0 && y>=0.0) return(2);
220 3ebbd193 2017-06-19 rsc else if( x<=0.0 && y< 0.0) return(3);
221 3ebbd193 2017-06-19 rsc else if( x> 0.0 && y<=0.0) return(4);
222 3ebbd193 2017-06-19 rsc else return 0; /* shut up lint */
223 3ebbd193 2017-06-19 rsc }