1 /* arcgen.c (Berkeley) 1.2 86/03/11 */ 2 3 #include <stdio.h> 4 #include "pic.h" 5 #include "y.tab.h" 6 7 struct obj *arcgen(type) /* handles circular and (eventually) elliptical arcs */ 8 { 9 static float prevw = HT10; 10 static float prevh = HT5; 11 static float prevrad = HT2; 12 static int dtox[2][4] ={ 1, -1, -1, 1, 1, 1, -1, -1 }; 13 static int dtoy[2][4] ={ 1, 1, -1, -1, -1, 1, 1, -1 }; 14 static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 }; 15 static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 }; 16 static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, R_DIR, U_DIR, L_DIR }; 17 double sqrt(), atan2(), sin(), cos(); 18 float dx2, dy2, ht, phi, r, d; 19 int i, head, to, at, cw, invis; 20 struct obj *p, *ppos; 21 float fromx, fromy, tox, toy; 22 23 prevrad = getfval("arcrad"); 24 prevh = getfval("arrowht"); 25 prevw = getfval("arrowwid"); 26 fromx = curx; 27 fromy = cury; 28 head = to = at = cw = invis = 0; 29 for (i = 0; i < nattr; i++) { 30 switch (attr[i].a_type) { 31 case LJUST: case RJUST: case CENTER: case SPREAD: case FILL: case ABOVE: case BELOW: 32 savetext(attr[i].a_type, attr[i].a_val.p); 33 break; 34 case HEAD: 35 head += attr[i].a_val.i; 36 break; 37 case INVIS: 38 invis = INVIS; 39 break; 40 case HEIGHT: /* length of arrowhead */ 41 prevh = attr[i].a_val.f; 42 break; 43 case WIDTH: /* width of arrowhead */ 44 prevw = attr[i].a_val.f; 45 break; 46 case RADIUS: 47 prevrad = attr[i].a_val.f; 48 break; 49 case DIAMETER: 50 prevrad = attr[i].a_val.f / 2; 51 break; 52 case CW: 53 cw = 1; 54 break; 55 case FROM: /* start point of arc */ 56 ppos = attr[i].a_val.o; 57 fromx = ppos->o_x; 58 fromy = ppos->o_y; 59 break; 60 case TO: /* end point of arc */ 61 ppos = attr[i].a_val.o; 62 tox = ppos->o_x; 63 toy = ppos->o_y; 64 to++; 65 break; 66 case AT: /* center of arc */ 67 ppos = attr[i].a_val.o; 68 curx = ppos->o_x; 69 cury = ppos->o_y; 70 at = 1; 71 break; 72 case UP: 73 hvmode = U_DIR; 74 break; 75 case DOWN: 76 hvmode = D_DIR; 77 break; 78 case RIGHT: 79 hvmode = R_DIR; 80 break; 81 case LEFT: 82 hvmode = L_DIR; 83 break; 84 } 85 } 86 if (!at && !to) { /* the defaults are mostly OK */ 87 curx = fromx + prevrad * dctrx[cw][hvmode]; 88 cury = fromy + prevrad * dctry[cw][hvmode]; 89 tox = fromx + prevrad * dtox[cw][hvmode]; 90 toy = fromy + prevrad * dtoy[cw][hvmode]; 91 hvmode = nexthv[cw][hvmode]; 92 } 93 else if (!at) { 94 dx2 = (tox - fromx) / 2; 95 dy2 = (toy - fromy) / 2; 96 phi = atan2(dy2, dx2) + (cw ? -PI2 : PI2); 97 r = prevrad; 98 if ((d = r*r - (dx2*dx2+dy2*dy2)) < 0.0) { 99 /* this kludge gets around too-small radii */ 100 r = sqrt(dx2*dx2+dy2*dy2); /* smallest radius */ 101 d = 0; 102 } 103 prevrad = r; 104 ht = sqrt(d); 105 curx = fromx + dx2 + ht * cos(phi); 106 cury = fromy + dy2 + ht * sin(phi); 107 dprintf("dx2,dy2=%g,%g, phi=%g, r,ht=%g,%g\n", 108 dx2, dy2, phi, r, ht); 109 } 110 else if (at && !to) { /* do we have all the cases??? */ 111 tox = fromx + prevrad * dtox[cw][hvmode]; 112 toy = fromy + prevrad * dtoy[cw][hvmode]; 113 hvmode = nexthv[cw][hvmode]; 114 } 115 if (cw) { /* interchange roles of from-to and heads */ 116 float temp; 117 temp = fromx; fromx = tox; tox = temp; 118 temp = fromy; fromy = toy; toy = temp; 119 if (head == HEAD1) 120 head = HEAD2; 121 else if (head == HEAD2) 122 head = HEAD1; 123 } 124 p = makenode(type, 7); 125 /* these are wrong in general */ 126 extreme(fromx, fromy); 127 extreme(tox, toy); 128 p->o_val[0] = fromx; 129 p->o_val[1] = fromy; 130 p->o_val[2] = tox; 131 p->o_val[3] = toy; 132 if (cw) { 133 curx = fromx; 134 cury = fromy; 135 } else { 136 curx = tox; 137 cury = toy; 138 } 139 p->o_val[4] = prevw; 140 p->o_val[5] = prevh; 141 p->o_val[6] = prevrad; 142 p->o_attr = head | (cw ? CW_ARC : 0) | invis; 143 dprintf("arc rad %g at %g %g from %g %g to %g %g head %g %g\n", 144 prevrad, p->o_x, p->o_y, 145 p->o_val[0], p->o_val[1], p->o_val[2], p->o_val[3], p->o_val[4], p->o_val[5]); 146 return(p); 147 } 148