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