|
|
1.1 ! root 1: /* Copyright (c) 1988 AT&T */ ! 2: /* All Rights Reserved */ ! 3: ! 4: /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ ! 5: /* The copyright notice above does not evidence any */ ! 6: /* actual or intended publication of such source code. */ ! 7: ! 8: /* @(#)picasso:arcgen.c 1.0 */ ! 9: #include "picasso.h" ! 10: #include "y.tab.h" ! 11: ! 12: obj *arcgen(type) /* handles circular and (eventually) elliptical arcs */ ! 13: { ! 14: static double prevwid = HT10; ! 15: static double prevht = HT5; ! 16: static double prevrad = HT2; ! 17: static int dtox[2][4] ={ 1, -1, -1, 1, 1, 1, -1, -1 }; ! 18: static int dtoy[2][4] ={ 1, 1, -1, -1, -1, 1, 1, -1 }; ! 19: static int dctrx[2][4] ={ 0, -1, 0, 1, 0, 1, 0, -1 }; ! 20: static int dctry[2][4] ={ 1, 0, -1, 0, -1, 0, 1, 0 }; ! 21: static int nexthv[2][4] ={ U_DIR, L_DIR, D_DIR, R_DIR, D_DIR, ! 22: R_DIR, U_DIR, L_DIR }; ! 23: struct objattr obat; ! 24: double dx2, dy2, phi, r, d, fromx, fromy, tox, toy; ! 25: int i, head, to, at, cw; ! 26: obj *p, *ppos; ! 27: Attr *ap; ! 28: ! 29: obat.a_ht = getfval("arrowht"); ! 30: obat.a_wid = getfval("arrowwid"); ! 31: obat.a_rad = getfval("arcrad"); ! 32: obat.a_layer = (int)getfval("curlayer"); ! 33: obat.a_flags = EDGED; ! 34: obat.a_weight = obat.a_lcolor = obat.a_pcolor = obat.a_tcolor = -1; ! 35: obat.a_dashpat.a = (float *)0; ! 36: set_text(); ! 37: fromx = curx; ! 38: fromy = cury; ! 39: head = to = at = cw = 0; ! 40: for (i = 0; i < nattr; i++) { ! 41: ap = &attr[i]; ! 42: switch (ap->a_type) { ! 43: default: ! 44: miscattrs(ap, &obat); ! 45: break; ! 46: case HEAD: ! 47: head += ap->a_val.i; ! 48: break; ! 49: case CW: ! 50: cw = 1; ! 51: break; ! 52: case FROM: /* start point of arc */ ! 53: ppos = ap->a_val.o; ! 54: fromx = Xformx(ppos, 1, ppos->o_x, ppos->o_y); ! 55: fromy = Xformy(ppos, 0, ppos->o_x, ppos->o_y); ! 56: break; ! 57: case TO: /* end point of arc */ ! 58: ppos = ap->a_val.o; ! 59: tox = Xformx(ppos, 1, ppos->o_x, ppos->o_y); ! 60: toy = Xformy(ppos, 0, ppos->o_x, ppos->o_y); ! 61: to++; ! 62: break; ! 63: case AT: /* center of arc */ ! 64: ppos = ap->a_val.o; ! 65: curx = Xformx(ppos, 1, ppos->o_x, ppos->o_y); ! 66: cury = Xformy(ppos, 0, ppos->o_x, ppos->o_y); ! 67: at = 1; ! 68: break; ! 69: case UP: ! 70: hvmode = U_DIR; ! 71: break; ! 72: case DOWN: ! 73: hvmode = D_DIR; ! 74: break; ! 75: case RIGHT: ! 76: hvmode = R_DIR; ! 77: break; ! 78: case LEFT: ! 79: hvmode = L_DIR; ! 80: break; ! 81: case SAME: ! 82: obat.a_ht = prevht; ! 83: obat.a_wid = prevwid; ! 84: obat.a_rad = prevrad; ! 85: break; ! 86: } ! 87: } ! 88: if (!at && !to) { /* the defaults are mostly OK */ ! 89: curx = fromx + obat.a_rad * dctrx[cw][hvmode]; ! 90: cury = fromy + obat.a_rad * dctry[cw][hvmode]; ! 91: tox = fromx + obat.a_rad * dtox[cw][hvmode]; ! 92: toy = fromy + obat.a_rad * dtoy[cw][hvmode]; ! 93: hvmode = nexthv[cw][hvmode]; ! 94: } ! 95: else if (!at) { ! 96: dx2 = (tox - fromx) / 2; ! 97: dy2 = (toy - fromy) / 2; ! 98: phi = atan2(dy2, dx2) + (cw ? -M_PI_2 : M_PI_2); ! 99: if (obat.a_rad <= 0.0) ! 100: obat.a_rad = sqrt(dx2*dx2+dy2*dy2); ! 101: for (r=obat.a_rad; (d = r*r - (dx2*dx2+dy2*dy2)) <= 0.0; r *= 2) ! 102: ; /* this kludge gets around too-small radii */ ! 103: obat.a_rad = r; ! 104: d = sqrt(d); ! 105: curx = fromx + dx2 + d * cos(phi); ! 106: cury = fromy + dy2 + d * sin(phi); ! 107: } ! 108: else if (at && !to) { /* do we have all the cases??? */ ! 109: tox = fromx + obat.a_rad * dtox[cw][hvmode]; ! 110: toy = fromy + obat.a_rad * dtoy[cw][hvmode]; ! 111: hvmode = nexthv[cw][hvmode]; ! 112: } ! 113: p = makenode(type, N_VAL + 10, obat.a_layer); ! 114: prevrad = p->o_val[N_VAL+0].f = p->o_val[N_VAL+1].f = obat.a_rad; ! 115: prevwid = p->o_val[N_VAL+8].f = obat.a_wid; ! 116: prevht = p->o_val[N_VAL+9].f = obat.a_ht; ! 117: if (cw) { /* interchange roles of from-to and heads */ ! 118: double temp; ! 119: temp = fromx; curx = fromx = tox; tox = temp; ! 120: temp = fromy; cury = fromy = toy; toy = temp; ! 121: if (head == HEAD1) ! 122: head = HEAD2; ! 123: else if (head == HEAD2) ! 124: head = HEAD1; ! 125: p->o_attr |= CW_ARC; ! 126: } ! 127: else { ! 128: curx = tox; ! 129: cury = toy; ! 130: } ! 131: p->o_val[N_VAL+2].f = fromx; ! 132: p->o_val[N_VAL+3].f = fromy; ! 133: p->o_val[N_VAL+4].f = tox; ! 134: p->o_val[N_VAL+5].f = toy; ! 135: if (head) ! 136: p->o_attr |= head | arrowfill(); ! 137: primattrs(p, &obat); ! 138: text_bounds(p); ! 139: arc_extreme(p); ! 140: return(p); ! 141: } ! 142: ! 143: quadrant(x,y) ! 144: double x, y; ! 145: { ! 146: if ( x>=0.0 && y> 0.0) return(1); ! 147: else if( x< 0.0 && y>=0.0) return(2); ! 148: else if( x<=0.0 && y< 0.0) return(3); ! 149: else if( x> 0.0 && y<=0.0) return(4); ! 150: else ! 151: { fprintf(stderr,"can't happen: x,y=%g,%g",x,y); exit(1);} ! 152: } ! 153: ! 154: /*************************************************************************** ! 155: bounding box of a circular arc Eric Grosse 24 May 84 ! 156: ! 157: Conceptually, this routine generates a list consisting of the start, ! 158: end, and whichever north, east, south, and west points lie on the arc. ! 159: The bounding box is then the range of this list. ! 160: list = {start,end} ! 161: j = quadrant(start) ! 162: k = quadrant(end) ! 163: if( j==k && long way 'round ) append north,west,south,east ! 164: else ! 165: while( j != k ) ! 166: append center+radius*[j-th of north,west,south,east unit vectors] ! 167: j += 1 (mod 4) ! 168: set bounds (return object with wid/ht and offset from arc center) ! 169: The following code implements this, with simple optimizations. ! 170: ***********************************************************************/ ! 171: ! 172: arc_extreme(p) ! 173: obj *p; ! 174: { ! 175: /* assumes center isn't too far out */ ! 176: ! 177: double x0, y0, x1, y1, xc, yc; /* start, end, center */ ! 178: double r, xmin, ymin, xmax, ymax, wgt; ! 179: int j, k; ! 180: ! 181: x0 = p->o_val[N_VAL+2].f - (xc = p->o_x); /* translate to center */ ! 182: y0 = p->o_val[N_VAL+3].f - (yc = p->o_y); ! 183: x1 = p->o_val[N_VAL+4].f - xc; ! 184: y1 = p->o_val[N_VAL+5].f - yc; ! 185: xmin = (x0<x1)?x0:x1; ymin = (y0<y1)?y0:y1; ! 186: xmax = (x0>x1)?x0:x1; ymax = (y0>y1)?y0:y1; ! 187: r = p->o_val[N_VAL].f; ! 188: if (r > 0.0) { ! 189: j = quadrant(x0,y0); ! 190: k = quadrant(x1,y1); ! 191: if (j == k && y1*x0 < x1*y0) { ! 192: /* viewed as complex numbers, if Im(z1/z0)<0, arc is big */ ! 193: if( xmin > -r) xmin = -r; if( ymin > -r) ymin = -r; ! 194: if( xmax < r) xmax = r; if( ymax < r) ymax = r; ! 195: } else { ! 196: while (j != k) { ! 197: switch (j) { ! 198: case 1: if( ymax < r) ymax = r; break; /* north */ ! 199: case 2: if( xmin > -r) xmin = -r; break; /* west */ ! 200: case 3: if( ymin > -r) ymin = -r; break; /* south */ ! 201: case 4: if( xmax < r) xmax = r; break; /* east */ ! 202: } ! 203: j = j%4 + 1; ! 204: } ! 205: } ! 206: } ! 207: if (p->o_type == SECTOR) { /* include center */ ! 208: if (xmin * xmax > 0) ! 209: if (xmin > 0) xmin = 0; else xmax = 0; ! 210: if (ymin * ymax > 0) ! 211: if (ymin > 0) ymin = 0; else ymax = 0; ! 212: } ! 213: p->o_wid = xmax - xmin; ! 214: p->o_ht = ymax - ymin; ! 215: p->o_val[N_VAL+6].f = -0.5 * (xmin+xmax); /* record offset to center */ ! 216: p->o_val[N_VAL+7].f = -0.5 * (ymin+ymax); ! 217: wgt = p->o_weight/2; ! 218: track_bounds(xmin+xc-wgt, ymin+yc-wgt, xmax+xc+wgt, ymax+yc+wgt); ! 219: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.