123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "pic.h"
- #include "y.tab.h"
- obj *linegen(int type)
- {
- static double prevdx = HT;
- static double prevdy = 0;
- static double prevw = HT10;
- static double prevh = HT5;
- int i, j, some, head, ddtype, invis, chop, battr, with;
- double ddval, chop1, chop2, x0, y0, x1, y1;
- double fillval = 0;
- double theta;
- double defx, defy, xwith, ywith;
- obj *p, *ppos;
- static int xtab[] = { 1, 0, -1, 0 }; /* R=0, U=1, L=2, D=3 */
- static int ytab[] = { 0, 1, 0, -1 };
- double dx[500], dy[500];
- int ndxy;
- double nx, ny;
- Attr *ap, *chop_ap[4];
- nx = curx;
- ny = cury;
- defx = getfval("linewid");
- defy = getfval("lineht");
- prevh = getfval("arrowht");
- prevw = getfval("arrowwid");
- dx[0] = dy[0] = ndxy = some = head = invis = battr = with = 0;
- chop = chop1 = chop2 = 0;
- ddtype = ddval = xwith = ywith = 0;
- for (i = 0; i < nattr; i++) {
- ap = &attr[i];
- switch (ap->a_type) {
- case TEXTATTR:
- savetext(ap->a_sub, ap->a_val.p);
- break;
- case HEAD:
- head += ap->a_val.i;
- break;
- case INVIS:
- invis = INVIS;
- break;
- case NOEDGE:
- battr |= NOEDGEBIT;
- break;
- case DOT:
- case DASH:
- ddtype = ap->a_type==DOT ? DOTBIT : DASHBIT;
- if (ap->a_sub == DEFAULT)
- ddval = getfval("dashwid");
- else
- ddval = ap->a_val.f;
- break;
- case SAME:
- dx[ndxy] = prevdx;
- dy[ndxy] = prevdy;
- some++;
- break;
- case LEFT:
- dx[ndxy] -= (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
- some++;
- hvmode = L_DIR;
- break;
- case RIGHT:
- dx[ndxy] += (ap->a_sub==DEFAULT) ? defx : ap->a_val.f;
- some++;
- hvmode = R_DIR;
- break;
- case UP:
- dy[ndxy] += (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
- some++;
- hvmode = U_DIR;
- break;
- case DOWN:
- dy[ndxy] -= (ap->a_sub==DEFAULT) ? defy : ap->a_val.f;
- some++;
- hvmode = D_DIR;
- break;
- case HEIGHT: /* length of arrowhead */
- prevh = ap->a_val.f;
- break;
- case WIDTH: /* width of arrowhead */
- prevw = ap->a_val.f;
- break;
- case TO:
- if (some) {
- nx += dx[ndxy];
- ny += dy[ndxy];
- ndxy++;
- dx[ndxy] = dy[ndxy] = some = 0;
- }
- ppos = attr[i].a_val.o;
- if (ppos == NULL)
- ERROR "no tag defined for `to'" FATAL;
- dx[ndxy] = ppos->o_x - nx;
- dy[ndxy] = ppos->o_y - ny;
- some++;
- break;
- case BY:
- if (some) {
- nx += dx[ndxy];
- ny += dy[ndxy];
- ndxy++;
- dx[ndxy] = dy[ndxy] = some = 0;
- }
- ppos = ap->a_val.o;
- if (ppos == NULL)
- ERROR "no tag defined for `by'" FATAL;
- dx[ndxy] = ppos->o_x;
- dy[ndxy] = ppos->o_y;
- some++;
- break;
- case THEN: /* turn off any previous accumulation */
- if (some) {
- nx += dx[ndxy];
- ny += dy[ndxy];
- ndxy++;
- dx[ndxy] = dy[ndxy] = some = 0;
- }
- break;
- case FROM:
- case AT:
- ppos = ap->a_val.o;
- if (ppos == NULL)
- ERROR "no tag defined for `from' or `at'" FATAL;
- nx = curx = ppos->o_x;
- ny = cury = ppos->o_y;
- break;
- case WITH:
- with = ap->a_val.i;
- break;
- case CHOP:
- if (ap->a_sub != PLACENAME) {
- if( chop == 0)
- chop1 = chop2 = ap->a_val.f;
- else
- chop2 = ap->a_val.f;
- }
- chop_ap[chop++] = ap;
- break;
- case FILL:
- battr |= FILLBIT;
- if (ap->a_sub == DEFAULT)
- fillval = getfval("fillval");
- else
- fillval = ap->a_val.f;
- break;
- }
- }
- if (with) { /* this doesn't work at all */
- switch (with) {
- case CENTER:
- xwith = (dx[1] - dx[0]) / 2; ywith = (dy[1] - dy[0]) / 2; break;
- }
- for (i = 0; i < ndxy; i++) {
- dx[i] -= xwith;
- dy[i] -= ywith;
- }
- curx += xwith;
- cury += ywith;
- }
- if (some) {
- nx += dx[ndxy];
- ny += dy[ndxy];
- ndxy++;
- defx = dx[ndxy-1];
- defy = dy[ndxy-1];
- } else {
- defx *= xtab[hvmode];
- defy *= ytab[hvmode];
- dx[ndxy] = defx;
- dy[ndxy] = defy;
- ndxy++;
- nx += defx;
- ny += defy;
- }
- prevdx = defx;
- prevdy = defy;
- if (chop) {
- if (chop == 1 && chop1 == 0) /* just said "chop", so use default */
- chop1 = chop2 = getfval("circlerad");
- theta = atan2(dy[0], dx[0]);
- x0 = chop1 * cos(theta);
- y0 = chop1 * sin(theta);
- curx += x0;
- cury += y0;
- dx[0] -= x0;
- dy[0] -= y0;
- theta = atan2(dy[ndxy-1], dx[ndxy-1]);
- x1 = chop2 * cos(theta);
- y1 = chop2 * sin(theta);
- nx -= x1;
- ny -= y1;
- dx[ndxy-1] -= x1;
- dy[ndxy-1] -= y1;
- dprintf("chopping %g %g %g %g; cur=%g,%g end=%g,%g\n",
- x0, y0, x1, y1, curx, cury, nx, ny);
- }
- p = makenode(type, 5 + 2 * ndxy);
- curx = p->o_val[0] = nx;
- cury = p->o_val[1] = ny;
- if (head || type == ARROW) {
- p->o_nhead = getfval("arrowhead");
- p->o_val[2] = prevw;
- p->o_val[3] = prevh;
- if (head == 0)
- head = HEAD2; /* default arrow head */
- }
- p->o_attr = head | invis | ddtype | battr;
- p->o_fillval = fillval;
- p->o_val[4] = ndxy;
- nx = p->o_x;
- ny = p->o_y;
- for (i = 0, j = 5; i < ndxy; i++, j += 2) {
- p->o_val[j] = dx[i];
- p->o_val[j+1] = dy[i];
- if (type == LINE || type == ARROW)
- extreme(nx += dx[i], ny += dy[i]);
- else if (type == SPLINE && i < ndxy-1) {
- /* to compute approx extreme of spline at p,
- /* compute midway between p-1 and p+1,
- /* then go 3/4 from there to p */
- double ex, ey, xi, yi, xi1, yi1;
- xi = nx + dx[i]; yi = ny + dy[i]; /* p */
- xi1 = xi + dx[i+1]; yi1 = yi + dy[i+1]; /* p+1 */
- ex = (nx+xi1)/2; ey = (ny+yi1)/2; /* midway */
- ex += 0.75*(xi-ex); ey += 0.75*(yi-ey);
- extreme(ex, ey);
- nx = xi; ny = yi;
- }
-
- }
- p->o_ddval = ddval;
- if (dbg) {
- printf("S or L from %g %g to %g %g with %d elements:\n", p->o_x, p->o_y, curx, cury, ndxy);
- for (i = 0, j = 5; i < ndxy; i++, j += 2)
- printf("%g %g\n", p->o_val[j], p->o_val[j+1]);
- }
- extreme(p->o_x, p->o_y);
- extreme(curx, cury);
- return(p);
- }
|