static box *bs = NULL;
static int bn;
static int maxbn = 0;
-#endif
#define BINC 300
-
-typedef struct {
- point *ps;
- int pn;
- int maxpn;
- box minbbox;
-} route_info_t;
+#endif
#define PINC 300
-static box *boxes;
-static int boxn;
-
-
#ifdef NOTNOW
static edge_t *origedge;
#endif
-static edge_t *realedge;
-static path *thepath;
-
-static int nedges, nboxes, nsplines;
-static Ppoint_t *polypoints;
-static int polypointn, polysz;
+static int nedges, nboxes; /* total no. of edges and boxes used in routing */
-static Pedge_t *edges;
-static int edgen;
+static int routeinit;
+/* static data used across multiple edges */
+static point *ps; /* final spline points */
+static int maxpn; /* size of ps[] */
+static Ppoint_t *polypoints; /* vertices of polygon defined by boxes */
+static int polypointn; /* size of polypoints[] */
+static Pedge_t *edges; /* polygon edges passed to Proutespline */
+static int edgen; /* size of edges[] */
-static void checkpath(void);
-static void mkspacep(route_info_t*, int size);
+static void checkpath(int, box*, path*);
+static void mkspacep(int size);
static void printpath(path * pp);
-static void printboxes(void);
-static void psprintinit (int);
-static void psprintboxes(box * b, int bn);
-static void psprintspline(Ppolyline_t);
-static void psprintline(Ppolyline_t);
-static void psprintpoly(Ppoly_t p);
-static int debugleveln(int i)
+static int append(path * path, int bi, point p0, point p1, int);
+#ifdef DEBUG
+static void printboxes(int boxn, box* boxes)
+{
+ point ll, ur;
+ int bi;
+ char buf[BUFSIZ];
+ int newcnt = Show_cnt + boxn;
+
+ Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
+ for (bi = 0; bi < boxn; bi++) {
+ ll = boxes[bi].LL, ur = boxes[bi].UR;
+ sprintf(buf, "%d %d %d %d pathbox", ll.x, ll.y, ur.x, ur.y);
+ Show_boxes[bi+1+Show_cnt] = strdup (buf);
+ }
+ Show_cnt = newcnt;
+ Show_boxes[Show_cnt+1] = NULL;
+}
+
+static void psprintpolypts(Ppoint_t * p, int sz)
+{
+ int i;
+
+ fprintf(stderr, "%%!\n");
+ fprintf(stderr, "%% constraint poly\n");
+ fprintf(stderr, "newpath\n");
+ for (i = 0; i < sz; i++)
+ fprintf(stderr, "%f %f %s\n", p[i].x, p[i].y,
+ (i == 0 ? "moveto" : "lineto"));
+ fprintf(stderr, "closepath stroke\n");
+}
+static void psprintpoint(point p)
+{
+ fprintf(stderr, "gsave\n");
+ fprintf(stderr,
+ "newpath %d %d moveto %d %d 2 0 360 arc closepath fill stroke\n",
+ p.x, p.y, p.x, p.y);
+ fprintf(stderr, "/Times-Roman findfont 4 scalefont setfont\n");
+ fprintf(stderr, "%d %d moveto (\\(%d,%d\\)) show\n", p.x + 5, p.y + 5,
+ p.x, p.y);
+ fprintf(stderr, "grestore\n");
+}
+
+static void psprintspline(Ppolyline_t spl)
+{
+ char buf[BUFSIZ];
+ int newcnt = Show_cnt + spl.pn + 4;
+ int li, i;
+
+ Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
+ li = Show_cnt+1;
+ Show_boxes[li++] = strdup ("%%!");
+ Show_boxes[li++] = strdup ("%% spline");
+ Show_boxes[li++] = strdup ("gsave 1 0 0 setrgbcolor newpath");
+ for (i = 0; i < spl.pn; i++) {
+ sprintf(buf, "%f %f %s", spl.ps[i].x, spl.ps[i].y,
+ (i == 0) ? "moveto" : ((i % 3 == 0) ? "curveto" : ""));
+ Show_boxes[li++] = strdup (buf);
+ }
+ Show_boxes[li++] = strdup ("stroke grestore");
+ Show_cnt = newcnt;
+ Show_boxes[Show_cnt+1] = NULL;
+}
+static void psprintline(Ppolyline_t pl)
+{
+ char buf[BUFSIZ];
+ int newcnt = Show_cnt + pl.pn + 4;
+ int i, li;
+
+ Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
+ li = Show_cnt+1;
+ Show_boxes[li++] = strdup ("%%!");
+ Show_boxes[li++] = strdup ("%% line");
+ Show_boxes[li++] = strdup ("gsave 0 0 1 setrgbcolor newpath");
+ for (i = 0; i < pl.pn; i++) {
+ sprintf(buf, "%f %f %s", pl.ps[i].x, pl.ps[i].y,
+ (i == 0 ? "moveto" : "lineto"));
+ Show_boxes[li++] = strdup (buf);
+ }
+ Show_boxes[li++] = strdup ("stroke grestore");
+ Show_cnt = newcnt;
+ Show_boxes[Show_cnt+1] = NULL;
+}
+static void psprintpoly(Ppoly_t p)
+{
+ char buf[BUFSIZ];
+ int newcnt = Show_cnt + p.pn + 3;
+ point tl, hd;
+ int bi, li;
+ char* pfx;
+
+ Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
+ li = Show_cnt+1;
+ Show_boxes[li++] = strdup ("%% poly list");
+ Show_boxes[li++] = strdup ("gsave 0 1 0 setrgbcolor");
+ for (bi = 0; bi < p.pn; bi++) {
+ tl.x = (int)p.ps[bi].x;
+ tl.y = (int)p.ps[bi].y;
+ hd.x = (int)p.ps[(bi+1) % p.pn].x;
+ hd.y = (int)p.ps[(bi+1) % p.pn].y;
+ if ((tl.x == hd.x) && (tl.y == hd.y)) pfx = "%%";
+ else pfx ="";
+ sprintf(buf, "%s%d %d %d %d makevec", pfx, tl.x, tl.y, hd.x, hd.y);
+ Show_boxes[li++] = strdup (buf);
+ }
+ Show_boxes[li++] = strdup ("grestore");
+
+ Show_cnt = newcnt;
+ Show_boxes[Show_cnt+1] = NULL;
+}
+static void psprintboxes(int boxn, box* boxes)
+{
+ char buf[BUFSIZ];
+ int newcnt = Show_cnt + 5*boxn + 3;
+ point ll, ur;
+ int bi, li;
+
+ Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
+ li = Show_cnt+1;
+ Show_boxes[li++] = strdup ("%% box list");
+ Show_boxes[li++] = strdup ("gsave 0 1 0 setrgbcolor");
+ for (bi = 0; bi < boxn; bi++) {
+ ll = boxes[bi].LL, ur = boxes[bi].UR;
+ sprintf(buf, "newpath\n%d %d moveto", ll.x, ll.y);
+ Show_boxes[li++] = strdup (buf);
+ sprintf(buf, "%d %d lineto", ll.x, ur.y);
+ Show_boxes[li++] = strdup (buf);
+ sprintf(buf, "%d %d lineto", ur.x, ur.y);
+ Show_boxes[li++] = strdup (buf);
+ sprintf(buf, "%d %d lineto", ur.x, ll.y);
+ Show_boxes[li++] = strdup (buf);
+ Show_boxes[li++] = strdup ("closepath stroke");
+ }
+ Show_boxes[li++] = strdup ("grestore");
+
+ Show_cnt = newcnt;
+ Show_boxes[Show_cnt+1] = NULL;
+}
+static void psprintinit (int begin)
+{
+ int newcnt = Show_cnt + 1;
+
+ Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
+ if (begin)
+ Show_boxes[1+Show_cnt] = strdup ("dbgstart");
+ else
+ Show_boxes[1+Show_cnt] = strdup ("grestore");
+ Show_cnt = newcnt;
+ Show_boxes[Show_cnt+1] = NULL;
+}
+
+static int debugleveln(edge_t* realedge, int i)
{
return (GD_showboxes(realedge->head->graph) == i ||
GD_showboxes(realedge->tail->graph) == i ||
ND_showboxes(realedge->head) == i ||
ND_showboxes(realedge->tail) == i);
}
-static void append(route_info_t*, path * path, int bi, point p0, point p1);
+#endif
static point mkpt(int x, int y)
{
return ((p.x == q.x) && (p.y == q.y));
}
-void*
+/* routesplinesinit:
+ * Data initialized once until matching call to routeplineterm
+ * Allows recursive calls to dot
+ */
+void
routesplinesinit()
{
- route_info_t* ri = NEW(route_info_t);
+ if (++routeinit > 1) return;
#ifdef UNUSED
if (!(bs = N_GNEW(BINC, box))) {
agerr(AGERR, "cannot allocate bs\n");
}
maxbn = BINC;
#endif
- if (!(ri->ps = N_GNEW(PINC, point))) {
+ if (!(ps = N_GNEW(PINC, point))) {
agerr(AGERR, "cannot allocate ps\n");
abort();
}
- ri->maxpn = PINC;
- ri->pn = 0;
- ri->minbbox.LL.x = ri->minbbox.LL.y = INT_MAX;
- ri->minbbox.UR.x = ri->minbbox.UR.y = INT_MIN;
+ maxpn = PINC;
if (Show_boxes) {
int i;
for (i = 0; Show_boxes[i]; i++)
Show_boxes = NULL;
Show_cnt = 0;
}
+ nedges = 0;
+ nboxes = 0;
if (Verbose)
start_timer();
- return ri;
}
-void routesplinesterm(void* x)
+void routesplinesterm()
{
- route_info_t* ri = (route_info_t*)x;
- free(ri->ps);
- free(ri);
+ if (--routeinit > 0) return;
+ free(ps);
#ifdef UNUSED
free(bs), bs = NULL /*, maxbn = bn = 0 */ ;
#endif
if (Verbose)
fprintf(stderr,
- "routesplines: %d edges, %d boxes, %d splines %.2f sec\n",
- nedges, nboxes, nsplines, elapsed_sec());
+ "routesplines: %d edges, %d boxes %.2f sec\n",
+ nedges, nboxes, elapsed_sec());
}
-point *routesplines(void* x, path * pp, int *npoints)
+point *routesplines(path * pp, int *npoints)
{
- route_info_t* ri = (route_info_t*)x;
Ppoly_t poly;
Ppolyline_t pl, spl;
int splinepi;
point sp[4];
int pi, bi, si;
double t;
+ box *boxes;
+ int boxn;
+ edge_t* realedge;
+ int flip;
nedges++;
nboxes += pp->nbox;
agerr(AGERR, "in routesplines, cannot find NORMAL edge\n");
abort();
}
- thepath = pp;
boxes = pp->boxes;
boxn = pp->nbox;
- checkpath();
+ checkpath(boxn, boxes, pp);
- if (debugleveln(1))
- printboxes();
- if (debugleveln(3)) {
+#ifdef DEBUG
+ if (debugleveln(realedge, 1))
+ printboxes(boxn, boxes);
+ if (debugleveln(realedge, 3)) {
psprintinit(1);
- psprintboxes(boxes, boxn);
+ psprintboxes(boxn, boxes);
}
+#endif
if (boxn * 8 > polypointn) {
polypoints = ALLOC(boxn * 8, polypoints, Ppoint_t);
polypointn = boxn * 8;
}
+ if ((boxn > 1) && (boxes[0].LL.y > boxes[1].LL.y)) {
+ flip = 1;
+ for (bi = 0; bi < boxn; bi++) {
+ int v = boxes[bi].UR.y;
+ boxes[bi].UR.y = -1*boxes[bi].LL.y;
+ boxes[bi].LL.y = -v;
+ }
+ }
+ else flip = 0;
+
if (realedge->tail != realedge->head) {
/* I assume that the path goes either down only or
up - right - down */
/* it went badly, e.g. degenerate box in boxlist */
*npoints = 0;
abort(); /* for correctness sake, it's best to just stop */
- return ri->ps; /* could also be reported as a lost edge (no spline) */
+ return ps; /* could also be reported as a lost edge (no spline) */
}
polypoints[pi].x = boxes[bi].UR.x;
polypoints[pi++].y = boxes[bi].LL.y;
p1 = b0.LL;
} else
abort();
- polysz = 0;
- append(ri, pp, 0, p0, p1);
- pi = polysz;
+ pi = append(pp, 0, p0, p1, 0);
+ }
+
+ if (flip) {
+ int i;
+ for (bi = 0; bi < boxn; bi++) {
+ int v = boxes[bi].UR.y;
+ boxes[bi].UR.y = -1*boxes[bi].LL.y;
+ boxes[bi].LL.y = -v;
+ }
+ for (i = 0; i < pi; i++)
+ polypoints[i].y *= -1;
}
for (bi = 0; bi < boxn; bi++)
eps[1].x = pp->end.p.x, eps[1].y = pp->end.p.y;
if (Pshortestpath(&poly, eps, &pl) == -1)
abort();
- if (debugleveln(3)) {
+#ifdef DEBUG
+ if (debugleveln(realedge, 3)) {
psprintpoly(poly);
psprintline(pl);
}
+#endif
if (poly.pn > edgen) {
edges = ALLOC(poly.pn, edges, Pedge_t);
edgen = poly.pn;
if (Proutespline(edges, poly.pn, pl, evs, &spl) == -1)
abort();
- if (debugleveln(3)) {
+#ifdef DEBUG
+ if (debugleveln(realedge, 3)) {
psprintspline(spl);
psprintinit(0);
}
- mkspacep(ri, spl.pn);
- for (bi = 0; bi <= boxn; bi++)
- boxes[bi].LL.x = ri->minbbox.LL.x, boxes[bi].UR.x = ri->minbbox.UR.x;
+#endif
+ mkspacep(spl.pn);
+ for (bi = 0; bi <= boxn; bi++) {
+ boxes[bi].LL.x = INT_MAX;
+ boxes[bi].UR.x = INT_MIN;
+ }
for (splinepi = 0; splinepi < spl.pn; splinepi++) {
- ri->ps[splinepi].x = spl.ps[splinepi].x;
- ri->ps[splinepi].y = spl.ps[splinepi].y;
+ ps[splinepi].x = spl.ps[splinepi].x;
+ ps[splinepi].y = spl.ps[splinepi].y;
}
for (splinepi = 0; splinepi + 3 < spl.pn; splinepi += 3) {
for (si = 0; si <= 10 * boxn; si++) {
t = si / (10.0 * boxn);
- sp[0] = ri->ps[splinepi];
- sp[1] = ri->ps[splinepi + 1];
- sp[2] = ri->ps[splinepi + 2];
- sp[3] = ri->ps[splinepi + 3];
+ sp[0] = ps[splinepi];
+ sp[1] = ps[splinepi + 1];
+ sp[2] = ps[splinepi + 2];
+ sp[3] = ps[splinepi + 3];
sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
sp[1].x = sp[1].x + t * (sp[2].x - sp[1].x);
}
*npoints = spl.pn;
+#ifdef DEBUG
if (GD_showboxes(realedge->head->graph) == 2 ||
GD_showboxes(realedge->tail->graph) == 2 ||
ED_showboxes(realedge) == 2 ||
ND_showboxes(realedge->head) == 2 ||
ND_showboxes(realedge->tail) == 2)
- printboxes();
+ printboxes(boxn, boxes);
+#endif
- return ri->ps;
+ return ps;
}
static int overlap(int i0, int i1, int j0, int j1)
* fixing all the bugs, at least try to engineer around them!
* in postmodern CS, we could call this "self-healing code."
*/
-static void checkpath(void)
+static void checkpath(int boxn, box* boxes, path* thepath)
{
box *ba, *bb;
int bi, i, errs, l, r, d, u;
}
}
-static void mkspacep(route_info_t* ri, int size)
+static void mkspacep(int size)
{
- if (ri->pn + size > ri->maxpn) {
- int newmax = ri->maxpn + (size / PINC + 1) * PINC;
- ri->ps = RALLOC(newmax, ri->ps, point);
- ri->maxpn = newmax;
+ if (size > maxpn) {
+ int newmax = maxpn + (size / PINC + 1) * PINC;
+ ps = RALLOC(newmax, ps, point);
+ maxpn = newmax;
}
}
-
-/* new code to create poly from box list */
-/* given that we entered the box b on segment p0,p1
-(p0==p1 allowed) then add successive points to the constraint poly
-*/
+/* new code to create poly from box list
+ * given that we entered the box b on segment p0,p1 (p0==p1 allowed)
+ * then add successive points to the constraint poly
+ */
#define BOXLEFT 0
#define BOXTOP 1
return 0;
}
-static void appendpt(point p)
+static int appendpt(point p, int polysz)
{
polypoints[polysz].x = p.x;
polypoints[polysz].y = p.y;
- polysz++;
+ return (polysz+1);
}
static int cmpf(const void *pp0, const void *pp1)
return 0; /* not reached */
}
-void append(route_info_t* ri, path * path, int bi, point p0, point p1)
+/* append:
+ */
+static int
+append(path * path, int bi, point p0, point p1, int polysz)
{
- point v[8]; /* worse case 4 corners + 2 segs * 2 points each */
+ point v[8]; /* worst case 4 corners + 2 segs * 2 points each */
point w[8];
box b = path->boxes[bi];
box bb;
int i, i0, npw, delta;
- point q0 = { 0, 0 }, q1 = {
- 0, 0}, r;
+ point q0 = { 0, 0 }, q1 = { 0, 0}, r;
+ int pn;
/* v = 4 corners of b, p0 and p1 */
- ri->pn = 0;
- v[ri->pn++] = b.LL;
- v[ri->pn++] = mkpt(b.UR.x, b.LL.y);
- v[ri->pn++] = b.UR;
- v[ri->pn++] = mkpt(b.LL.x, b.UR.y);
- v[ri->pn++] = p0;
- v[ri->pn++] = p1;
+ pn = 0;
+ v[pn++] = b.LL;
+ v[pn++] = mkpt(b.UR.x, b.LL.y);
+ v[pn++] = b.UR;
+ v[pn++] = mkpt(b.LL.x, b.UR.y);
+ v[pn++] = p0;
+ v[pn++] = p1;
if (bi + 1 < path->nbox) {
bb = path->boxes[bi + 1];
q1.x = MAX(b.LL.x, bb.LL.x);
} else
abort();
- v[ri->pn++] = q0;
- v[ri->pn++] = q1;
+ v[pn++] = q0;
+ v[pn++] = q1;
}
/* sort v so that the cyclic order is p0, all other points, p1 */
B = b;
- qsort(v, ri->pn, sizeof(v[0]), cmpf);
+ qsort(v, pn, sizeof(v[0]), cmpf);
/* eliminate duplicates and record i0 = index of p0 in w */
w[0] = v[0];
npw = 1;
i0 = -1;
- for (i = 0; i < ri->pn; i++) {
+ for (i = 0; i < pn; i++) {
if (pteq(w[npw - 1], p0))
i0 = npw - 1;
if (!pteq(v[i], w[npw - 1]))
i = i0;
if (bi == 0)
- appendpt(p0);
+ polysz = appendpt(p0, polysz);
if (pteq(p1, w[(i0 + 1) % npw]))
delta = -1;
else if (pteq(p1, w[(i0 - 1 + npw) % npw]))
/* append r to current poly, except p0 and p1 are special cases */
if ((bi == 0) || (!pteq(r, p0) && !pteq(r, p1)))
- appendpt(r);
+ polysz = appendpt(r, polysz);
if (pteq(r, p1))
break;
if (bi + 1 < path->nbox) { /* recur when we hit the next box */
if (pteq(r, q0)) {
- append(ri, path, bi + 1, q0, q1);
- appendpt(q1); /* assumes q1 != p0 and p1 */
+ polysz = append(path, bi + 1, q0, q1, polysz);
+ polysz = appendpt(q1, polysz); /* assumes q1 != p0 and p1 */
i += delta; /* skip q1 */
} else if (pteq(r, q1)) {
- append(ri, path, bi + 1, q1, q0);
- appendpt(q0);
+ polysz = append(path, bi + 1, q1, q0, polysz);
+ polysz = appendpt(q0, polysz);
i += delta;
}
}
} while (i != i0);
+ return polysz;
}
static void printpath(path * pp)
pp->end.constrained ? "constrained" : "not constrained");
}
-static void printboxes(void)
-{
- point ll, ur;
- int bi;
- char buf[BUFSIZ];
- int newcnt = Show_cnt + boxn;
-
- Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
- for (bi = 0; bi < boxn; bi++) {
- ll = boxes[bi].LL, ur = boxes[bi].UR;
- sprintf(buf, "%d %d %d %d pathbox", ll.x, ll.y, ur.x, ur.y);
- Show_boxes[bi+1+Show_cnt] = strdup (buf);
- }
- Show_cnt = newcnt;
- Show_boxes[Show_cnt+1] = NULL;
-}
-
-#ifdef DEBUG
-static void psprintpoly(Ppoint_t * p, int sz)
-{
- int i;
-
- fprintf(stderr, "%%!\n");
- fprintf(stderr, "%% constraint poly\n");
- fprintf(stderr, "newpath\n");
- for (i = 0; i < polysz; i++)
- fprintf(stderr, "%f %f %s\n", p[i].x, p[i].y,
- (i == 0 ? "moveto" : "lineto"));
- fprintf(stderr, "closepath stroke\n");
-}
-static void psprintpoint(point p)
-{
- fprintf(stderr, "gsave\n");
- fprintf(stderr,
- "newpath %d %d moveto %d %d 2 0 360 arc closepath fill stroke\n",
- p.x, p.y, p.x, p.y);
- fprintf(stderr, "/Times-Roman findfont 4 scalefont setfont\n");
- fprintf(stderr, "%d %d moveto (\\(%d,%d\\)) show\n", p.x + 5, p.y + 5,
- p.x, p.y);
- fprintf(stderr, "grestore\n");
-}
-#endif
-
-static void psprintspline(Ppolyline_t spl)
-{
- char buf[BUFSIZ];
- int newcnt = Show_cnt + spl.pn + 4;
- int li, i;
-
- Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
- li = Show_cnt+1;
- Show_boxes[li++] = strdup ("%%!");
- Show_boxes[li++] = strdup ("%% spline");
- Show_boxes[li++] = strdup ("gsave 1 0 0 setrgbcolor newpath");
- for (i = 0; i < spl.pn; i++) {
- sprintf(buf, "%f %f %s", spl.ps[i].x, spl.ps[i].y,
- (i == 0) ? "moveto" : ((i % 3 == 0) ? "curveto" : ""));
- Show_boxes[li++] = strdup (buf);
- }
- Show_boxes[li++] = strdup ("stroke grestore");
- Show_cnt = newcnt;
- Show_boxes[Show_cnt+1] = NULL;
-}
-static void psprintline(Ppolyline_t pl)
-{
- char buf[BUFSIZ];
- int newcnt = Show_cnt + pl.pn + 4;
- int i, li;
-
- Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
- li = Show_cnt+1;
- Show_boxes[li++] = strdup ("%%!");
- Show_boxes[li++] = strdup ("%% line");
- Show_boxes[li++] = strdup ("gsave 0 0 1 setrgbcolor newpath");
- for (i = 0; i < pl.pn; i++) {
- sprintf(buf, "%f %f %s", pl.ps[i].x, pl.ps[i].y,
- (i == 0 ? "moveto" : "lineto"));
- Show_boxes[li++] = strdup (buf);
- }
- Show_boxes[li++] = strdup ("stroke grestore");
- Show_cnt = newcnt;
- Show_boxes[Show_cnt+1] = NULL;
-}
-static void psprintpoly(Ppoly_t p)
-{
- char buf[BUFSIZ];
- int newcnt = Show_cnt + p.pn + 3;
- point tl, hd;
- int bi, li;
- char* pfx;
-
- Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
- li = Show_cnt+1;
- Show_boxes[li++] = strdup ("%% poly list");
- Show_boxes[li++] = strdup ("gsave 0 1 0 setrgbcolor");
- for (bi = 0; bi < p.pn; bi++) {
- tl.x = (int)p.ps[bi].x;
- tl.y = (int)p.ps[bi].y;
- hd.x = (int)p.ps[(bi+1) % p.pn].x;
- hd.y = (int)p.ps[(bi+1) % p.pn].y;
- if ((tl.x == hd.x) && (tl.y == hd.y)) pfx = "%%";
- else pfx ="";
- sprintf(buf, "%s%d %d %d %d makevec", pfx, tl.x, tl.y, hd.x, hd.y);
- Show_boxes[li++] = strdup (buf);
- }
- Show_boxes[li++] = strdup ("grestore");
-
- Show_cnt = newcnt;
- Show_boxes[Show_cnt+1] = NULL;
-}
-static void psprintboxes(box * b, int bn)
-{
- char buf[BUFSIZ];
- int newcnt = Show_cnt + 5*bn + 3;
- point ll, ur;
- int bi, li;
-
- Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
- li = Show_cnt+1;
- Show_boxes[li++] = strdup ("%% box list");
- Show_boxes[li++] = strdup ("gsave 0 1 0 setrgbcolor");
- for (bi = 0; bi < boxn; bi++) {
- ll = boxes[bi].LL, ur = boxes[bi].UR;
- sprintf(buf, "newpath\n%d %d moveto", ll.x, ll.y);
- Show_boxes[li++] = strdup (buf);
- sprintf(buf, "%d %d lineto", ll.x, ur.y);
- Show_boxes[li++] = strdup (buf);
- sprintf(buf, "%d %d lineto", ur.x, ur.y);
- Show_boxes[li++] = strdup (buf);
- sprintf(buf, "%d %d lineto", ur.x, ll.y);
- Show_boxes[li++] = strdup (buf);
- Show_boxes[li++] = strdup ("closepath stroke");
- }
- Show_boxes[li++] = strdup ("grestore");
-
- Show_cnt = newcnt;
- Show_boxes[Show_cnt+1] = NULL;
-}
-static void psprintinit (int begin)
-{
- int newcnt = Show_cnt + 1;
-
- Show_boxes = ALLOC(newcnt+2,Show_boxes,char*);
- if (begin)
- Show_boxes[1+Show_cnt] = strdup ("dbgstart");
- else
- Show_boxes[1+Show_cnt] = strdup ("grestore");
- Show_cnt = newcnt;
- Show_boxes[Show_cnt+1] = NULL;
-}
-
typedef struct {
int LeftBound, RightBound, Splinesep, Multisep;
box* Rank_box;
- void* ri;
} spline_info_t;
static void adjustregularpath(path *, int, int);
static Agedge_t *bot_bound(Agedge_t *, int);
static unsigned char pathscross(Agnode_t *, Agnode_t *, Agedge_t *,
Agedge_t *);
-/*
+#ifdef OBSOLETE
static void chooseflatsides(pathend_t *, pathend_t *, int *, int *, int *,
int *, int *, int *);
-*/
-static Agraph_t *cl_bound(Agnode_t *, Agnode_t *);
-static int cl_vninside(Agraph_t *, Agnode_t *);
static void completeflatpath(path *, pathend_t *, pathend_t *,
box *, box *, int, int);
+static box makeflatend(box, int, int, box);
+static box makeflatcomponent(box, box, int, int, int, int, int);
+#endif
+static Agraph_t *cl_bound(Agnode_t *, Agnode_t *);
+static int cl_vninside(Agraph_t *, Agnode_t *);
static void completeregularpath(path *, Agedge_t *, Agedge_t *,
pathend_t *, pathend_t *, box *, int, int);
static int edgecmp(Agedge_t **, Agedge_t **);
-static box makeflatcomponent(box, box, int, int, int, int, int);
static void make_flat_edge(spline_info_t*, path *, Agedge_t **, int, int);
-static box makeflatend(box, int, int, box);
static void make_regular_edge(spline_info_t*, path *, Agedge_t **, int, int);
static box makeregularend(box, int, int);
static box maximal_bbox(spline_info_t*, Agnode_t *, Agedge_t *, Agedge_t *);
spline_info_t sd;
mark_lowclusters(g);
- sd.ri = routesplinesinit();
+ routesplinesinit();
P = NEW(path);
/* FlatHeight = 2 * GD_nodesep(g); */
sd.Splinesep = GD_nodesep(g) / 4;
free(P->boxes);
free(P);
free(sd.Rank_box);
- routesplinesterm(sd.ri);
+ routesplinesterm();
State = GVSPLINES;
}
cleanupCloneGraph (auxg);
}
+/* makeFlatEnd;
+ */
+static void
+makeFlatEnd (spline_info_t* sp, path* P, node_t* n, edge_t* e, pathend_t* endp,
+ boolean isBegin)
+{
+ box b;
+ graph_t* g = n->graph;
+
+ b = endp->nb = maximal_bbox(sp, n, NULL, e);
+ endp->sidemask = TOP;
+ if (isBegin) beginpath(P, e, FLATEDGE, endp, FALSE);
+ else endpath(P, e, FLATEDGE, endp, FALSE);
+ b.UR.y = endp->boxes[endp->boxn - 1].UR.y;
+ b.LL.y = endp->boxes[endp->boxn - 1].LL.y;
+ b = makeregularend(b, TOP, ND_coord_i(n).y + GD_rank(g)[ND_rank(n)].ht2);
+ if (b.LL.x < b.UR.x && b.LL.y < b.UR.y)
+ endp->boxes[endp->boxn++] = b;
+}
+/* makeBottomFlatEnd;
+ */
+static void
+makeBottomFlatEnd (spline_info_t* sp, path* P, node_t* n, edge_t* e,
+ pathend_t* endp, boolean isBegin)
+{
+ box b;
+ graph_t* g = n->graph;
+
+ b = endp->nb = maximal_bbox(sp, n, NULL, e);
+ endp->sidemask = BOTTOM;
+ if (isBegin) beginpath(P, e, FLATEDGE, endp, FALSE);
+ else endpath(P, e, FLATEDGE, endp, FALSE);
+ b.UR.y = endp->boxes[endp->boxn - 1].UR.y;
+ b.LL.y = endp->boxes[endp->boxn - 1].LL.y;
+ b = makeregularend(b, BOTTOM, ND_coord_i(n).y - GD_rank(g)[ND_rank(n)].ht2);
+ if (b.LL.x < b.UR.x && b.LL.y < b.UR.y)
+ endp->boxes[endp->boxn++] = b;
+}
+
+
/* make_flat_labeled_edge:
*/
static void
node_t *tn, *hn, *ln;
point *ps;
pathend_t tend, hend;
- box b, lb;
+ box lb;
int boxn, i, pn, ydelta;
edge_t *f;
lb.LL.y = lb.UR.y - MAX(5,ydelta);
boxn = 0;
- b = tend.nb = maximal_bbox(sp, tn, NULL, e);
- beginpath(P, e, FLATEDGE, &tend, FALSE);
- b.UR.y = tend.boxes[tend.boxn - 1].UR.y;
- b.LL.y = tend.boxes[tend.boxn - 1].LL.y;
- b = makeregularend(b, TOP,
- ND_coord_i(tn).y + GD_rank(g)[ND_rank(tn)].ht2);
- if (b.LL.x < b.UR.x && b.LL.y < b.UR.y)
- tend.boxes[tend.boxn++] = b;
-
- b = hend.nb = maximal_bbox(sp, hn, e, NULL);
- endpath(P, e, FLATEDGE, &hend, FALSE);
- b.UR.y = hend.boxes[hend.boxn - 1].UR.y;
- b.LL.y = hend.boxes[hend.boxn - 1].LL.y;
- b = makeregularend(b, TOP,
- ND_coord_i(hn).y + GD_rank(g)[ND_rank(hn)].ht2);
- if (b.LL.x < b.UR.x && b.LL.y < b.UR.y)
- hend.boxes[hend.boxn++] = b;
+ makeFlatEnd (sp, P, tn, e, &tend, TRUE);
+ makeFlatEnd (sp, P, hn, e, &hend, FALSE);
boxes[boxn].LL.x = tend.boxes[tend.boxn - 1].LL.x;
boxes[boxn].LL.y = tend.boxes[tend.boxn - 1].UR.y;
for (i = 0; i < boxn; i++) add_box(P, boxes[i]);
for (i = hend.boxn - 1; i >= 0; i--) add_box(P, hend.boxes[i]);
- ps = routesplines(sp->ri, P, &pn);
+ routesplines(P, &pn);
if (pn == 0) return;
clip_and_install(e, e, ps, pn, &sinfo);
}
/* make_flat_bottom_edges:
*/
static void
-make_flat_bottom_edges(path * P, edge_t ** edges, int ind, int cnt, edge_t* e0)
+make_flat_bottom_edges(spline_info_t* sp, path * P, edge_t ** edges, int
+ ind, int cnt, edge_t* e)
{
+ node_t *tn, *hn;
+ int j, i, stepx, stepy, vspace, r;
+ rank_t* nextr;
+ int pn;
+ point *ps;
+ pathend_t tend, hend;
+ graph_t* g;
+
+ tn = e->tail, hn = e->head;
+ g = tn->graph;
+ r = ND_rank(tn);
+ if (r < GD_maxrank(g)) {
+ nextr = GD_rank(g) + (r+1);
+ vspace = ND_coord_i(tn).y - GD_rank(g)[r].pht1 -
+ (ND_coord_i(nextr->v[0]).y + nextr->pht2);
+ }
+ else {
+ vspace = GD_ranksep(g);
+ }
+ stepx = sp->Multisep / (cnt+1);
+ stepy = vspace / (cnt+1);
+
+ makeBottomFlatEnd (sp, P, tn, e, &tend, TRUE);
+ makeBottomFlatEnd (sp, P, hn, e, &hend, FALSE);
+
+ for (i = 0; i < cnt; i++) {
+ int boxn;
+ box b;
+ e = edges[ind + i];
+ boxn = 0;
+
+ b = tend.boxes[tend.boxn - 1];
+ boxes[boxn].LL.x = b.LL.x;
+ boxes[boxn].UR.y = b.LL.y;
+ boxes[boxn].UR.x = b.UR.x + (i + 1) * stepx;
+ boxes[boxn].LL.y = b.LL.y - (i + 1) * stepy;
+ boxn++;
+ boxes[boxn].LL.x = tend.boxes[tend.boxn - 1].LL.x;
+ boxes[boxn].UR.y = boxes[boxn-1].LL.y;
+ boxes[boxn].UR.x = hend.boxes[hend.boxn - 1].UR.x;
+ boxes[boxn].LL.y = boxes[boxn].UR.y - stepy;
+ boxn++;
+ b = hend.boxes[hend.boxn - 1];
+ boxes[boxn].UR.x = b.UR.x;
+ boxes[boxn].UR.y = b.LL.y;
+ boxes[boxn].LL.x = b.LL.x - (i + 1) * stepx;
+ boxes[boxn].LL.y = boxes[boxn-1].UR.y;
+ boxn++;
+
+ for (j = 0; j < tend.boxn; j++) add_box(P, tend.boxes[j]);
+ for (j = 0; j < boxn; j++) add_box(P, boxes[j]);
+ for (j = hend.boxn - 1; j >= 0; j--) add_box(P, hend.boxes[j]);
+
+ ps = routesplines(P, &pn);
+ if (pn == 0)
+ return;
+ clip_and_install(e, e, ps, pn, &sinfo);
+ P->nbox = 0;
+ }
}
/* make_flat_edge:
{
node_t *tn, *hn;
edge_t fwdedge, *e;
- int i, stepx, stepy, ht1, ht2, vspace, r;
+ int j, i, stepx, stepy, vspace, r;
rank_t* prevr;
int tside, hside, pn;
point *ps;
pathend_t tend, hend;
- box lb, rb, wlb, wrb;
graph_t* g;
+ /* Get sample edge; normalize to go from left to right */
e = edges[ind];
if (ED_tree_index(e) & BWDEDGE) {
MAKEFWDEDGE(&fwdedge, e);
hside = ED_head_port(e).side;
if (((tside == BOTTOM) && (hside != TOP)) ||
((hside == BOTTOM) && (tside != TOP))) {
- make_flat_bottom_edges (P, edges, ind, cnt, e);
+ make_flat_bottom_edges (sp, P, edges, ind, cnt, e);
return;
}
tn = e->tail, hn = e->head;
g = tn->graph;
- ht1 = GD_rank(g)[ND_rank(tn)].ht1;
- ht2 = GD_rank(g)[ND_rank(tn)].ht2;
r = ND_rank(tn);
if (r > 0) {
prevr = GD_rank(g) + (r-1);
- vspace = ND_coord_i(prevr->v[0]).y - prevr->pht1 - ND_coord_i(tn).y + GD_rank(g)[r].pht2;
+ vspace = ND_coord_i(prevr->v[0]).y - prevr->pht1 - ND_coord_i(tn).y - GD_rank(g)[r].pht2;
}
else {
vspace = GD_ranksep(g);
}
- stepx = sp->Multisep / cnt;
- stepy = vspace / cnt;
+ stepx = sp->Multisep / (cnt+1);
+ stepy = vspace / (cnt+1);
- lb = tend.nb = maximal_bbox(sp, tn, NULL, e);
- beginpath(P, e, FLATEDGE, &tend, FALSE);
- rb = hend.nb = maximal_bbox(sp, hn, NULL, e);
- endpath(P, e, FLATEDGE, &hend, FALSE);
+ makeFlatEnd (sp, P, tn, e, &tend, TRUE);
+ makeFlatEnd (sp, P, hn, e, &hend, FALSE);
for (i = 0; i < cnt; i++) {
+ int boxn;
+ box b;
e = edges[ind + i];
- if (ED_tree_index(e) & BWDEDGE) {
- MAKEFWDEDGE(&fwdedge, e);
- e = &fwdedge;
- }
-
- wlb.LL = lb.LL;
- wlb.UR.x = lb.UR.x + (i + 1) * stepx;
- wlb.UR.y = lb.UR.y + (i + 1) * stepy;
- wrb.LL.x = rb.LL.x - (i + 1) * stepx;
- wrb.LL.y = rb.LL.y - (i + 1) * stepy;
- wrb.UR = rb.UR;
- completeflatpath(P, &tend, &hend, &wlb, &wrb, stepx, stepy);
+ boxn = 0;
- ps = routesplines(sp->ri, P, &pn);
+ b = tend.boxes[tend.boxn - 1];
+ boxes[boxn].LL.x = b.LL.x;
+ boxes[boxn].LL.y = b.UR.y;
+ boxes[boxn].UR.x = b.UR.x + (i + 1) * stepx;
+ boxes[boxn].UR.y = b.UR.y + (i + 1) * stepy;
+ boxn++;
+ boxes[boxn].LL.x = tend.boxes[tend.boxn - 1].LL.x;
+ boxes[boxn].LL.y = boxes[boxn-1].UR.y;
+ boxes[boxn].UR.x = hend.boxes[hend.boxn - 1].UR.x;
+ boxes[boxn].UR.y = boxes[boxn].LL.y + stepy;
+ boxn++;
+ b = hend.boxes[hend.boxn - 1];
+ boxes[boxn].UR.x = b.UR.x;
+ boxes[boxn].LL.y = b.UR.y;
+ boxes[boxn].LL.x = b.LL.x - (i + 1) * stepx;
+ boxes[boxn].UR.y = boxes[boxn-1].LL.y;
+ boxn++;
+
+ for (j = 0; j < tend.boxn; j++) add_box(P, tend.boxes[j]);
+ for (j = 0; j < boxn; j++) add_box(P, boxes[j]);
+ for (j = hend.boxn - 1; j >= 0; j--) add_box(P, hend.boxes[j]);
+
+ ps = routesplines(P, &pn);
if (pn == 0)
return;
clip_and_install(e, e, ps, pn, &sinfo);
+ P->nbox = 0;
}
}
hend.boxes[hend.boxn++] = b;
P->end.theta = PI / 2, P->end.constrained = TRUE;
completeregularpath(P, segfirst, e, &tend, &hend, boxes, boxn, 1);
- ps = routesplines(sp->ri, P, &pn);
+ ps = routesplines(P, &pn);
if (pn == 0)
return;
for (i = 0; i < pn; i++)
hend.boxes[hend.boxn++] = b;
completeregularpath(P, segfirst, e, &tend, &hend, boxes, boxn,
longedge);
- ps = routesplines(sp->ri, P, &pn);
+ ps = routesplines(P, &pn);
if (pn == 0)
return;
for (i = 0; i < pn; i++)
for (i = hendp->boxn - 1; i >= 0; i--)
add_box(P, hendp->boxes[i]);
}
-#else
static box
makeflatend(box b, int side, int dir, box bb)
* Return an initial bounding box to be used for building the
* beginning or ending of the path of boxes.
* Height reflects height of tallest node on rank.
- * At present, used only in make_regular_edge.
*/
static box maximal_bbox(spline_info_t* sp, node_t* vn, edge_t* ie, edge_t* oe)
{