linegen.c (4704B)
1 #include <math.h> 2 #include <stdio.h> 3 #include "pic.h" 4 #include "y.tab.h" 5 6 obj* 7 linegen(int type) 8 { 9 static double prevdx = HT; 10 static double prevdy = 0; 11 static double prevw = HT10; 12 static double prevh = HT5; 13 int i, j, some, head, ddtype, invis, chop; 14 double ddval, chop1, chop2, x0, y0, x1, y1; 15 double theta; 16 double defx, defy; 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 = 0; 32 chop = chop1 = chop2 = 0; 33 ddtype = ddval = 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 CHOP: 47 if (chop++ == 0) 48 chop1 = chop2 = ap->a_val.f; 49 else 50 chop2 = ap->a_val.f; 51 break; 52 case DOT: 53 case DASH: 54 ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT; 55 if (ap->a_sub == DEFAULT) 56 ddval = getfval("dashwid"); 57 else 58 ddval = ap->a_val.f; 59 break; 60 case SAME: 61 dx[ndxy] = prevdx; 62 dy[ndxy] = prevdy; 63 some++; 64 break; 65 case LEFT: 66 dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; 67 some++; 68 hvmode = L_DIR; 69 break; 70 case RIGHT: 71 dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f; 72 some++; 73 hvmode = R_DIR; 74 break; 75 case UP: 76 dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; 77 some++; 78 hvmode = U_DIR; 79 break; 80 case DOWN: 81 dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f; 82 some++; 83 hvmode = D_DIR; 84 break; 85 case HEIGHT: /* length of arrowhead */ 86 prevh = ap->a_val.f; 87 break; 88 case WIDTH: /* width of arrowhead */ 89 prevw = ap->a_val.f; 90 break; 91 case TO: 92 if (some) { 93 nx += dx[ndxy]; 94 ny += dy[ndxy]; 95 ndxy++; 96 dx[ndxy] = dy[ndxy] = some = 0; 97 } 98 ppos = attr[i].a_val.o; 99 dx[ndxy] = ppos->o_x - nx; 100 dy[ndxy] = ppos->o_y - ny; 101 some++; 102 break; 103 case BY: 104 if (some) { 105 nx += dx[ndxy]; 106 ny += dy[ndxy]; 107 ndxy++; 108 dx[ndxy] = dy[ndxy] = some = 0; 109 } 110 ppos = ap->a_val.o; 111 dx[ndxy] = ppos->o_x; 112 dy[ndxy] = ppos->o_y; 113 some++; 114 break; 115 case THEN: /* turn off any previous accumulation */ 116 if (some) { 117 nx += dx[ndxy]; 118 ny += dy[ndxy]; 119 ndxy++; 120 dx[ndxy] = dy[ndxy] = some = 0; 121 } 122 break; 123 case FROM: 124 case AT: 125 ppos = ap->a_val.o; 126 nx = curx = ppos->o_x; 127 ny = cury = ppos->o_y; 128 break; 129 } 130 } 131 if (some) { 132 nx += dx[ndxy]; 133 ny += dy[ndxy]; 134 ndxy++; 135 defx = dx[ndxy-1]; 136 defy = dy[ndxy-1]; 137 } else { 138 defx *= xtab[hvmode]; 139 defy *= ytab[hvmode]; 140 dx[ndxy] = defx; 141 dy[ndxy] = defy; 142 ndxy++; 143 nx += defx; 144 ny += defy; 145 } 146 prevdx = defx; 147 prevdy = defy; 148 if (chop) { 149 if (chop == 1 && chop1 == 0) /* just said "chop", so use default */ 150 chop1 = chop2 = getfval("circlerad"); 151 theta = atan2(dy[0], dx[0]); 152 x0 = chop1 * cos(theta); 153 y0 = chop1 * sin(theta); 154 curx += x0; 155 cury += y0; 156 dx[0] -= x0; 157 dy[0] -= y0; 158 159 theta = atan2(dy[ndxy-1], dx[ndxy-1]); 160 x1 = chop2 * cos(theta); 161 y1 = chop2 * sin(theta); 162 nx -= x1; 163 ny -= y1; 164 dx[ndxy-1] -= x1; 165 dy[ndxy-1] -= y1; 166 dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n", 167 x0, y0, x1, y1, curx, cury, nx, ny); 168 } 169 p = makenode(type, 5 + 2 * ndxy); 170 curx = p->o_val[0] = nx; 171 cury = p->o_val[1] = ny; 172 if (head || type == ARROW) { 173 p->o_nhead = getfval("arrowhead"); 174 p->o_val[2] = prevw; 175 p->o_val[3] = prevh; 176 if (head == 0) 177 head = HEAD2; /* default arrow head */ 178 } 179 p->o_attr = head | invis | ddtype; 180 p->o_val[4] = ndxy; 181 nx = p->o_x; 182 ny = p->o_y; 183 for (i = 0, j = 5; i < ndxy; i++, j += 2) { 184 p->o_val[j] = dx[i]; 185 p->o_val[j+1] = dy[i]; 186 if (type == LINE || type == ARROW) 187 extreme(nx += dx[i], ny += dy[i]); 188 else if (type == SPLINE && i < ndxy-1) { 189 /* to compute approx extreme of spline at p, 190 /* compute midway between p-1 and p+1, 191 /* then go 3/4 from there to p */ 192 double ex, ey, xi, yi, xi1, yi1; 193 xi = nx + dx[i]; yi = ny + dy[i]; /* p */ 194 xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */ 195 ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */ 196 ex += 0.75*(xi-ex); ey += 0.75*(yi-ey); 197 extreme(ex, ey); 198 nx = xi; ny = yi; 199 } 200 201 } 202 p->o_ddval = ddval; 203 if (dbg) { 204 printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy); 205 for (i = 0, j = 5; i < ndxy; i++, j += 2) 206 printf("%g %g\n", p->o_val[j], p->o_val[j+1]); 207 } 208 extreme(p->o_x, p->o_y); 209 extreme(curx, cury); 210 return(p); 211 }