Blame


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