linegen.c (5351B)
1 #include <stdio.h> 2 #include <math.h> 3 #include "pic.h" 4 #include "y.tab.h" 5 6 obj *linegen(int type) 7 { 8 static double prevdx = HT; 9 static double prevdy = 0; 10 static double prevw = HT10; 11 static double prevh = HT5; 12 int i, j, some, head, ddtype, invis, chop, battr, with; 13 double ddval, chop1, chop2, x0, y0, x1, y1; 14 double fillval = 0; 15 double theta; 16 double defx, defy, xwith, ywith; 17 obj *p, *ppos; 18 static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */ 19 static int ytab[] = { 0, 1, 0, -1 }; 20 double dx[500], dy[500]; 21 int ndxy; 22 double nx, ny; 23 Attr *ap; 24 25 nx = curx; 26 ny = cury; 27 defx = getfval("linewid"); 28 defy = getfval("lineht"); 29 prevh = getfval("arrowht"); 30 prevw = getfval("arrowwid"); 31 dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0; 32 chop = chop1 = chop2 = 0; 33 ddtype = ddval = xwith = ywith = 0; 34 for (i = 0; i < nattr; i++) { 35 ap = &attr[i]; 36 switch (ap->a_type) { 37 case TEXTATTR: 38 savetext(ap->a_sub, ap->a_val.p); 39 break; 40 case HEAD: 41 head += ap->a_val.i; 42 break; 43 case INVIS: 44 invis = INVIS; 45 break; 46 case NOEDGE: 47 battr |= NOEDGEBIT; 48 break; 49 case DOT: 50 case DASH: 51 ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT; 52 if (ap->a_sub == DEFAULT) 53 ddval = getfval("dashwid"); 54 else 55 ddval = ap->a_val.f; 56 break; 57 case SAME: 58 dx[ndxy] = prevdx; 59 dy[ndxy] = prevdy; 60 some++; 61 break; 62 case LEFT: 63 dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; 64 some++; 65 hvmode = L_DIR; 66 break; 67 case RIGHT: 68 dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; 69 some++; 70 hvmode = R_DIR; 71 break; 72 case UP: 73 dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; 74 some++; 75 hvmode = U_DIR; 76 break; 77 case DOWN: 78 dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; 79 some++; 80 hvmode = D_DIR; 81 break; 82 case HEIGHT: /* length of arrowhead */ 83 prevh = ap->a_val.f; 84 break; 85 case WIDTH: /* width of arrowhead */ 86 prevw = ap->a_val.f; 87 break; 88 case TO: 89 if (some) { 90 nx += dx[ndxy]; 91 ny += dy[ndxy]; 92 ndxy++; 93 dx[ndxy] = dy[ndxy] = some = 0; 94 } 95 ppos = attr[i].a_val.o; 96 dx[ndxy] = ppos->o_x - nx; 97 dy[ndxy] = ppos->o_y - ny; 98 some++; 99 break; 100 case BY: 101 if (some) { 102 nx += dx[ndxy]; 103 ny += dy[ndxy]; 104 ndxy++; 105 dx[ndxy] = dy[ndxy] = some = 0; 106 } 107 ppos = ap->a_val.o; 108 dx[ndxy] = ppos->o_x; 109 dy[ndxy] = ppos->o_y; 110 some++; 111 break; 112 case THEN: /* turn off any previous accumulation */ 113 if (some) { 114 nx += dx[ndxy]; 115 ny += dy[ndxy]; 116 ndxy++; 117 dx[ndxy] = dy[ndxy] = some = 0; 118 } 119 break; 120 case FROM: 121 case AT: 122 ppos = ap->a_val.o; 123 nx = curx = ppos->o_x; 124 ny = cury = ppos->o_y; 125 break; 126 case WITH: 127 with = ap->a_val.i; 128 break; 129 case CHOP: 130 if (ap->a_sub != PLACENAME) { 131 if( chop == 0) 132 chop1 = chop2 = ap->a_val.f; 133 else 134 chop2 = ap->a_val.f; 135 } 136 break; 137 case FILL: 138 battr |= FILLBIT; 139 if (ap->a_sub == DEFAULT) 140 fillval = getfval("fillval"); 141 else 142 fillval = ap->a_val.f; 143 break; 144 } 145 } 146 if (with) { /* this doesn't work at all */ 147 switch (with) { 148 case CENTER: 149 xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break; 150 } 151 for (i = 0; i < ndxy; i++) { 152 dx[i] -= xwith; 153 dy[i] -= ywith; 154 } 155 curx += xwith; 156 cury += ywith; 157 } 158 if (some) { 159 nx += dx[ndxy]; 160 ny += dy[ndxy]; 161 ndxy++; 162 defx = dx[ndxy-1]; 163 defy = dy[ndxy-1]; 164 } else { 165 defx *= xtab[hvmode]; 166 defy *= ytab[hvmode]; 167 dx[ndxy] = defx; 168 dy[ndxy] = defy; 169 ndxy++; 170 nx += defx; 171 ny += defy; 172 } 173 prevdx = defx; 174 prevdy = defy; 175 if (chop) { 176 if (chop == 1 && chop1 == 0) /* just said "chop", so use default */ 177 chop1 = chop2 = getfval("circlerad"); 178 theta = atan2(dy[0], dx[0]); 179 x0 = chop1 * cos(theta); 180 y0 = chop1 * sin(theta); 181 curx += x0; 182 cury += y0; 183 dx[0] -= x0; 184 dy[0] -= y0; 185 186 theta = atan2(dy[ndxy-1], dx[ndxy-1]); 187 x1 = chop2 * cos(theta); 188 y1 = chop2 * sin(theta); 189 nx -= x1; 190 ny -= y1; 191 dx[ndxy-1] -= x1; 192 dy[ndxy-1] -= y1; 193 dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n", 194 x0, y0, x1, y1, curx, cury, nx, ny); 195 } 196 p = makenode(type, 5 + 2 * ndxy); 197 curx = p->o_val[0] = nx; 198 cury = p->o_val[1] = ny; 199 if (head || type == ARROW) { 200 p->o_nhead = getfval("arrowhead"); 201 p->o_val[2] = prevw; 202 p->o_val[3] = prevh; 203 if (head == 0) 204 head = HEAD2; /* default arrow head */ 205 } 206 p->o_attr = head | invis | ddtype | battr; 207 p->o_fillval = fillval; 208 p->o_val[4] = ndxy; 209 nx = p->o_x; 210 ny = p->o_y; 211 for (i = 0, j = 5; i < ndxy; i++, j += 2) { 212 p->o_val[j] = dx[i]; 213 p->o_val[j+1] = dy[i]; 214 if (type == LINE || type == ARROW) 215 extreme(nx += dx[i], ny += dy[i]); 216 else if (type == SPLINE && i < ndxy-1) { 217 /* to compute approx extreme of spline at p, 218 /* compute midway between p-1 and p+1, 219 /* then go 3/4 from there to p */ 220 double ex, ey, xi, yi, xi1, yi1; 221 xi = nx + dx[i]; yi = ny + dy[i]; /* p */ 222 xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */ 223 ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */ 224 ex += 0.75*(xi-ex); ey += 0.75*(yi-ey); 225 extreme(ex, ey); 226 nx = xi; ny = yi; 227 } 228 229 } 230 p->o_ddval = ddval; 231 if (dbg) { 232 printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy); 233 for (i = 0, j = 5; i < ndxy; i++, j += 2) 234 printf("%g %g\n", p->o_val[j], p->o_val[j+1]); 235 } 236 extreme(p->o_x, p->o_y); 237 extreme(curx, cury); 238 return(p); 239 }