Blame


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