13e12c5d1SDavid du Colombier #include <stdio.h>
2*392dc269SDavid du Colombier #include <string.h>
3*392dc269SDavid du Colombier #include <stdlib.h>
43e12c5d1SDavid du Colombier #include <math.h>
53e12c5d1SDavid du Colombier #include "pic.h"
63e12c5d1SDavid du Colombier #include "y.tab.h"
73e12c5d1SDavid du Colombier
linegen(int type)83e12c5d1SDavid du Colombier obj *linegen(int type)
93e12c5d1SDavid du Colombier {
103e12c5d1SDavid du Colombier static double prevdx = HT;
113e12c5d1SDavid du Colombier static double prevdy = 0;
123e12c5d1SDavid du Colombier static double prevw = HT10;
133e12c5d1SDavid du Colombier static double prevh = HT5;
147dd7cddfSDavid du Colombier int i, j, some, head, ddtype, invis, chop, battr, with;
153e12c5d1SDavid du Colombier double ddval, chop1, chop2, x0, y0, x1, y1;
167dd7cddfSDavid du Colombier double fillval = 0;
173e12c5d1SDavid du Colombier double theta;
187dd7cddfSDavid du Colombier double defx, defy, xwith, ywith;
193e12c5d1SDavid du Colombier obj *p, *ppos;
203e12c5d1SDavid du Colombier static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */
213e12c5d1SDavid du Colombier static int ytab[] = { 0, 1, 0, -1 };
223e12c5d1SDavid du Colombier double dx[500], dy[500];
233e12c5d1SDavid du Colombier int ndxy;
243e12c5d1SDavid du Colombier double nx, ny;
257dd7cddfSDavid du Colombier Attr *ap, *chop_ap[4];
263e12c5d1SDavid du Colombier
273e12c5d1SDavid du Colombier nx = curx;
283e12c5d1SDavid du Colombier ny = cury;
293e12c5d1SDavid du Colombier defx = getfval("linewid");
303e12c5d1SDavid du Colombier defy = getfval("lineht");
313e12c5d1SDavid du Colombier prevh = getfval("arrowht");
323e12c5d1SDavid du Colombier prevw = getfval("arrowwid");
337dd7cddfSDavid du Colombier dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0;
343e12c5d1SDavid du Colombier chop = chop1 = chop2 = 0;
357dd7cddfSDavid du Colombier ddtype = ddval = xwith = ywith = 0;
363e12c5d1SDavid du Colombier for (i = 0; i < nattr; i++) {
373e12c5d1SDavid du Colombier ap = &attr[i];
383e12c5d1SDavid du Colombier switch (ap->a_type) {
393e12c5d1SDavid du Colombier case TEXTATTR:
403e12c5d1SDavid du Colombier savetext(ap->a_sub, ap->a_val.p);
413e12c5d1SDavid du Colombier break;
423e12c5d1SDavid du Colombier case HEAD:
433e12c5d1SDavid du Colombier head += ap->a_val.i;
443e12c5d1SDavid du Colombier break;
453e12c5d1SDavid du Colombier case INVIS:
463e12c5d1SDavid du Colombier invis = INVIS;
473e12c5d1SDavid du Colombier break;
487dd7cddfSDavid du Colombier case NOEDGE:
497dd7cddfSDavid du Colombier battr |= NOEDGEBIT;
503e12c5d1SDavid du Colombier break;
513e12c5d1SDavid du Colombier case DOT:
523e12c5d1SDavid du Colombier case DASH:
533e12c5d1SDavid du Colombier ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
543e12c5d1SDavid du Colombier if (ap->a_sub == DEFAULT)
553e12c5d1SDavid du Colombier ddval = getfval("dashwid");
563e12c5d1SDavid du Colombier else
573e12c5d1SDavid du Colombier ddval = ap->a_val.f;
583e12c5d1SDavid du Colombier break;
593e12c5d1SDavid du Colombier case SAME:
603e12c5d1SDavid du Colombier dx[ndxy] = prevdx;
613e12c5d1SDavid du Colombier dy[ndxy] = prevdy;
623e12c5d1SDavid du Colombier some++;
633e12c5d1SDavid du Colombier break;
643e12c5d1SDavid du Colombier case LEFT:
653e12c5d1SDavid du Colombier dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
663e12c5d1SDavid du Colombier some++;
673e12c5d1SDavid du Colombier hvmode = L_DIR;
683e12c5d1SDavid du Colombier break;
693e12c5d1SDavid du Colombier case RIGHT:
703e12c5d1SDavid du Colombier dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
713e12c5d1SDavid du Colombier some++;
723e12c5d1SDavid du Colombier hvmode = R_DIR;
733e12c5d1SDavid du Colombier break;
743e12c5d1SDavid du Colombier case UP:
753e12c5d1SDavid du Colombier dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
763e12c5d1SDavid du Colombier some++;
773e12c5d1SDavid du Colombier hvmode = U_DIR;
783e12c5d1SDavid du Colombier break;
793e12c5d1SDavid du Colombier case DOWN:
803e12c5d1SDavid du Colombier dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
813e12c5d1SDavid du Colombier some++;
823e12c5d1SDavid du Colombier hvmode = D_DIR;
833e12c5d1SDavid du Colombier break;
843e12c5d1SDavid du Colombier case HEIGHT: /* length of arrowhead */
853e12c5d1SDavid du Colombier prevh = ap->a_val.f;
863e12c5d1SDavid du Colombier break;
873e12c5d1SDavid du Colombier case WIDTH: /* width of arrowhead */
883e12c5d1SDavid du Colombier prevw = ap->a_val.f;
893e12c5d1SDavid du Colombier break;
903e12c5d1SDavid du Colombier case TO:
913e12c5d1SDavid du Colombier if (some) {
923e12c5d1SDavid du Colombier nx += dx[ndxy];
933e12c5d1SDavid du Colombier ny += dy[ndxy];
943e12c5d1SDavid du Colombier ndxy++;
953e12c5d1SDavid du Colombier dx[ndxy] = dy[ndxy] = some = 0;
963e12c5d1SDavid du Colombier }
973e12c5d1SDavid du Colombier ppos = attr[i].a_val.o;
98*392dc269SDavid du Colombier if (ppos == NULL)
99*392dc269SDavid du Colombier ERROR "no tag defined for `to'" FATAL;
1003e12c5d1SDavid du Colombier dx[ndxy] = ppos->o_x - nx;
1013e12c5d1SDavid du Colombier dy[ndxy] = ppos->o_y - ny;
1023e12c5d1SDavid du Colombier some++;
1033e12c5d1SDavid du Colombier break;
1043e12c5d1SDavid du Colombier case BY:
1053e12c5d1SDavid du Colombier if (some) {
1063e12c5d1SDavid du Colombier nx += dx[ndxy];
1073e12c5d1SDavid du Colombier ny += dy[ndxy];
1083e12c5d1SDavid du Colombier ndxy++;
1093e12c5d1SDavid du Colombier dx[ndxy] = dy[ndxy] = some = 0;
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier ppos = ap->a_val.o;
112*392dc269SDavid du Colombier if (ppos == NULL)
113*392dc269SDavid du Colombier ERROR "no tag defined for `by'" FATAL;
1143e12c5d1SDavid du Colombier dx[ndxy] = ppos->o_x;
1153e12c5d1SDavid du Colombier dy[ndxy] = ppos->o_y;
1163e12c5d1SDavid du Colombier some++;
1173e12c5d1SDavid du Colombier break;
1183e12c5d1SDavid du Colombier case THEN: /* turn off any previous accumulation */
1193e12c5d1SDavid du Colombier if (some) {
1203e12c5d1SDavid du Colombier nx += dx[ndxy];
1213e12c5d1SDavid du Colombier ny += dy[ndxy];
1223e12c5d1SDavid du Colombier ndxy++;
1233e12c5d1SDavid du Colombier dx[ndxy] = dy[ndxy] = some = 0;
1243e12c5d1SDavid du Colombier }
1253e12c5d1SDavid du Colombier break;
1263e12c5d1SDavid du Colombier case FROM:
1273e12c5d1SDavid du Colombier case AT:
1283e12c5d1SDavid du Colombier ppos = ap->a_val.o;
129*392dc269SDavid du Colombier if (ppos == NULL)
130*392dc269SDavid du Colombier ERROR "no tag defined for `from' or `at'" FATAL;
1313e12c5d1SDavid du Colombier nx = curx = ppos->o_x;
1323e12c5d1SDavid du Colombier ny = cury = ppos->o_y;
1333e12c5d1SDavid du Colombier break;
1347dd7cddfSDavid du Colombier case WITH:
1357dd7cddfSDavid du Colombier with = ap->a_val.i;
1367dd7cddfSDavid du Colombier break;
1377dd7cddfSDavid du Colombier case CHOP:
1387dd7cddfSDavid du Colombier if (ap->a_sub != PLACENAME) {
1397dd7cddfSDavid du Colombier if( chop == 0)
1407dd7cddfSDavid du Colombier chop1 = chop2 = ap->a_val.f;
1417dd7cddfSDavid du Colombier else
1427dd7cddfSDavid du Colombier chop2 = ap->a_val.f;
1433e12c5d1SDavid du Colombier }
1447dd7cddfSDavid du Colombier chop_ap[chop++] = ap;
1457dd7cddfSDavid du Colombier break;
1467dd7cddfSDavid du Colombier case FILL:
1477dd7cddfSDavid du Colombier battr |= FILLBIT;
1487dd7cddfSDavid du Colombier if (ap->a_sub == DEFAULT)
1497dd7cddfSDavid du Colombier fillval = getfval("fillval");
1507dd7cddfSDavid du Colombier else
1517dd7cddfSDavid du Colombier fillval = ap->a_val.f;
1527dd7cddfSDavid du Colombier break;
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier if (with) { /* this doesn't work at all */
1567dd7cddfSDavid du Colombier switch (with) {
1577dd7cddfSDavid du Colombier case CENTER:
1587dd7cddfSDavid du Colombier xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break;
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier for (i = 0; i < ndxy; i++) {
1617dd7cddfSDavid du Colombier dx[i] -= xwith;
1627dd7cddfSDavid du Colombier dy[i] -= ywith;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier curx += xwith;
1657dd7cddfSDavid du Colombier cury += ywith;
1663e12c5d1SDavid du Colombier }
1673e12c5d1SDavid du Colombier if (some) {
1683e12c5d1SDavid du Colombier nx += dx[ndxy];
1693e12c5d1SDavid du Colombier ny += dy[ndxy];
1703e12c5d1SDavid du Colombier ndxy++;
1713e12c5d1SDavid du Colombier defx = dx[ndxy-1];
1723e12c5d1SDavid du Colombier defy = dy[ndxy-1];
1733e12c5d1SDavid du Colombier } else {
1743e12c5d1SDavid du Colombier defx *= xtab[hvmode];
1753e12c5d1SDavid du Colombier defy *= ytab[hvmode];
1763e12c5d1SDavid du Colombier dx[ndxy] = defx;
1773e12c5d1SDavid du Colombier dy[ndxy] = defy;
1783e12c5d1SDavid du Colombier ndxy++;
1793e12c5d1SDavid du Colombier nx += defx;
1803e12c5d1SDavid du Colombier ny += defy;
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier prevdx = defx;
1833e12c5d1SDavid du Colombier prevdy = defy;
1843e12c5d1SDavid du Colombier if (chop) {
1853e12c5d1SDavid du Colombier if (chop == 1 && chop1 == 0) /* just said "chop", so use default */
1863e12c5d1SDavid du Colombier chop1 = chop2 = getfval("circlerad");
1873e12c5d1SDavid du Colombier theta = atan2(dy[0], dx[0]);
1883e12c5d1SDavid du Colombier x0 = chop1 * cos(theta);
1893e12c5d1SDavid du Colombier y0 = chop1 * sin(theta);
1903e12c5d1SDavid du Colombier curx += x0;
1913e12c5d1SDavid du Colombier cury += y0;
1923e12c5d1SDavid du Colombier dx[0] -= x0;
1933e12c5d1SDavid du Colombier dy[0] -= y0;
1943e12c5d1SDavid du Colombier
1953e12c5d1SDavid du Colombier theta = atan2(dy[ndxy-1], dx[ndxy-1]);
1963e12c5d1SDavid du Colombier x1 = chop2 * cos(theta);
1973e12c5d1SDavid du Colombier y1 = chop2 * sin(theta);
1983e12c5d1SDavid du Colombier nx -= x1;
1993e12c5d1SDavid du Colombier ny -= y1;
2003e12c5d1SDavid du Colombier dx[ndxy-1] -= x1;
2013e12c5d1SDavid du Colombier dy[ndxy-1] -= y1;
2023e12c5d1SDavid du Colombier dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
2033e12c5d1SDavid du Colombier x0, y0, x1, y1, curx, cury, nx, ny);
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier p = makenode(type, 5 + 2 * ndxy);
2063e12c5d1SDavid du Colombier curx = p->o_val[0] = nx;
2073e12c5d1SDavid du Colombier cury = p->o_val[1] = ny;
2083e12c5d1SDavid du Colombier if (head || type == ARROW) {
2093e12c5d1SDavid du Colombier p->o_nhead = getfval("arrowhead");
2103e12c5d1SDavid du Colombier p->o_val[2] = prevw;
2113e12c5d1SDavid du Colombier p->o_val[3] = prevh;
2123e12c5d1SDavid du Colombier if (head == 0)
2133e12c5d1SDavid du Colombier head = HEAD2; /* default arrow head */
2143e12c5d1SDavid du Colombier }
2157dd7cddfSDavid du Colombier p->o_attr = head | invis | ddtype | battr;
2167dd7cddfSDavid du Colombier p->o_fillval = fillval;
2173e12c5d1SDavid du Colombier p->o_val[4] = ndxy;
2183e12c5d1SDavid du Colombier nx = p->o_x;
2193e12c5d1SDavid du Colombier ny = p->o_y;
2203e12c5d1SDavid du Colombier for (i = 0, j = 5; i < ndxy; i++, j += 2) {
2213e12c5d1SDavid du Colombier p->o_val[j] = dx[i];
2223e12c5d1SDavid du Colombier p->o_val[j+1] = dy[i];
2233e12c5d1SDavid du Colombier if (type == LINE || type == ARROW)
2243e12c5d1SDavid du Colombier extreme(nx += dx[i], ny += dy[i]);
2253e12c5d1SDavid du Colombier else if (type == SPLINE && i < ndxy-1) {
2263e12c5d1SDavid du Colombier /* to compute approx extreme of spline at p,
2273e12c5d1SDavid du Colombier /* compute midway between p-1 and p+1,
2283e12c5d1SDavid du Colombier /* then go 3/4 from there to p */
2293e12c5d1SDavid du Colombier double ex, ey, xi, yi, xi1, yi1;
2303e12c5d1SDavid du Colombier xi = nx + dx[i]; yi = ny + dy[i]; /* p */
2313e12c5d1SDavid du Colombier xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
2323e12c5d1SDavid du Colombier ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */
2333e12c5d1SDavid du Colombier ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
2343e12c5d1SDavid du Colombier extreme(ex, ey);
2353e12c5d1SDavid du Colombier nx = xi; ny = yi;
2363e12c5d1SDavid du Colombier }
2373e12c5d1SDavid du Colombier
2383e12c5d1SDavid du Colombier }
2393e12c5d1SDavid du Colombier p->o_ddval = ddval;
2403e12c5d1SDavid du Colombier if (dbg) {
2413e12c5d1SDavid du Colombier printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
2423e12c5d1SDavid du Colombier for (i = 0, j = 5; i < ndxy; i++, j += 2)
2433e12c5d1SDavid du Colombier printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
2443e12c5d1SDavid du Colombier }
2453e12c5d1SDavid du Colombier extreme(p->o_x, p->o_y);
2463e12c5d1SDavid du Colombier extreme(curx, cury);
2473e12c5d1SDavid du Colombier return(p);
2483e12c5d1SDavid du Colombier }
249