]> granicus.if.org Git - graphviz/commitdiff
Back out use of state info for routesplines;
authorerg <devnull@localhost>
Tue, 21 Jun 2005 22:56:05 +0000 (22:56 +0000)
committererg <devnull@localhost>
Tue, 21 Jun 2005 22:56:05 +0000 (22:56 +0000)
remove unused static data from routespl.c;
finish flat edge implementation.

lib/common/renderprocs.h
lib/common/routespl.c
lib/common/splines.c
lib/dotgen/dotsplines.c

index bf95fa5243aba2b428cf4c4e490d58c3b49c42e2..b163f4b80eb6c3e474bbb708dd7c6889915024e9 100644 (file)
@@ -161,9 +161,9 @@ extern "C" {
     extern int processClusterEdges(graph_t * g);
     extern char *ps_string(char *s, int);
     extern int rank(graph_t * g, int balance, int maxiter);
-    extern void* routesplinesinit(void);
-    extern point *routesplines(void*, path *, int *);
-    extern void routesplinesterm(void*);
+    extern void routesplinesinit(void);
+    extern point *routesplines(path *, int *);
+    extern void routesplinesterm(void);
     extern char *safefile(char *shapefilename);
     extern attrsym_t* safe_dcl(graph_t*, void*, char*, char*,
          attrsym_t * (*fun) (Agraph_t *, char *, char *));
index 5e47c4bda8d8428d263ea39daa7e0c051e802007..b26c7f13637dfd8c1d531dd95a304c61892dac78 100644 (file)
 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 ||
@@ -70,7 +205,7 @@ static int debugleveln(int 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)
 {
@@ -85,10 +220,14 @@ static int pteq(point p, point q)
     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");
@@ -96,14 +235,11 @@ routesplinesinit()
     }
     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++)
@@ -112,28 +248,27 @@ routesplinesinit()
        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;
@@ -143,6 +278,10 @@ point *routesplines(void* x, path * pp, int *npoints)
     point sp[4];
     int pi, bi, si;
     double t;
+    box *boxes;
+    int boxn;
+    edge_t* realedge;
+    int flip;
 
     nedges++;
     nboxes += pp->nbox;
@@ -157,25 +296,36 @@ point *routesplines(void* x, path * pp, int *npoints)
        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 */
@@ -239,7 +389,7 @@ point *routesplines(void* x, path * pp, int *npoints)
                    /* 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;
@@ -279,9 +429,18 @@ point *routesplines(void* x, path * pp, int *npoints)
            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++)
@@ -291,10 +450,12 @@ point *routesplines(void* x, path * pp, int *npoints)
     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;
@@ -316,24 +477,28 @@ point *routesplines(void* x, path * pp, int *npoints)
 
     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);
@@ -358,14 +523,16 @@ point *routesplines(void* x, path * pp, int *npoints)
     }
     *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)
@@ -390,7 +557,7 @@ 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;
@@ -547,20 +714,19 @@ static void checkpath(void)
     }
 }
 
-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
@@ -582,11 +748,11 @@ static int sideofB(point p, box B)
     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)
@@ -616,24 +782,27 @@ 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];
@@ -656,19 +825,19 @@ void append(route_info_t* ri, path * path, int bi, point p0, point p1)
            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]))
@@ -677,7 +846,7 @@ void append(route_info_t* ri, path * path, int bi, point p0, point p1)
 
     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]))
@@ -690,21 +859,22 @@ void append(route_info_t* ri, path * path, int bi, point p0, point p1)
 
        /* 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)
@@ -730,154 +900,3 @@ 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;
-}
-
index 0132f9e13cc5e5cd032ff36cdca932edf6cdad28..11fe65d1c03887e043ae981bdb0948c0c503a28e 100644 (file)
@@ -460,42 +460,58 @@ beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
        endp->sidemask = side;
        return;
     }
-    if ((et == FLATEDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_tail_port(e).side))) {
+    if ((et == FLATEDGE) && ((side = ED_tail_port(e).side))) {
        box b0, b = endp->nb;
        edge_t* orig;
        switch (side) {
        case LEFT:
-           b.UR.x = P->start.p.x;
-           b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
-           b.UR.y = P->start.p.y;
-           b.LL.y = P->start.p.y;
+           b.UR.x = P->start.p.x+1;
+           if (endp->sidemask == TOP) {
+               b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+               b.LL.y = P->start.p.y-1;
+           }
+           else {
+               b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+               b.UR.y = P->start.p.y+1;
+           }
            endp->boxes[0] = b;
            endp->boxn = 1;
            break;
        case RIGHT:
            b.LL.x = P->start.p.x;
-           b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
-           b.LL.y = P->start.p.y;
+           if (endp->sidemask == TOP) {
+               b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+               b.LL.y = P->start.p.y;
+           }
+           else {
+               b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+               b.UR.y = P->start.p.y+1;
+           }
            endp->boxes[0] = b;
            endp->boxn = 1;
            break;
        case TOP:
-           b.LL.y = MIN(b.LL.y,P->end.p.y);
-           endp->boxes[0] = b;
-           endp->boxn = 1;
+           abort();
            break;
        case BOTTOM:
-           b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
-           b0.UR.x = b.UR.x+1;
-           b0.LL.x = P->start.p.x;
-           b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
-           b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + 2;
-           b.LL.y = b0.UR.y;
-           b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
-           b.UR.x += 1;
-           endp->boxes[0] = b0;
-           endp->boxes[1] = b;
-           endp->boxn = 2;
+           if (endp->sidemask == TOP) {
+               b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+               b0.UR.x = b.UR.x+1;
+               b0.LL.x = P->start.p.x;
+               b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
+               b.LL.x = ND_coord_i(n).x + ND_rw_i(n) + 2;
+               b.LL.y = b0.UR.y;
+               b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+               b.UR.x += 1;
+               endp->boxes[0] = b0;
+               endp->boxes[1] = b;
+               endp->boxn = 2;
+           }
+           else {
+               b.UR.y = MAX(b.UR.y,P->start.p.y);
+               endp->boxes[0] = b;
+               endp->boxn = 1;
+           }
            break;
        }
        for (orig = e; ED_edge_type(orig) != NORMAL; orig = ED_to_orig(orig));
@@ -508,7 +524,7 @@ beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
     }
 
     if (et == REGULAREDGE) side = BOTTOM;
-    else side = TOP;  /* for flat edges */
+    else side = endp->sidemask;  /* for flat edges */
     if (pboxfn
        && (mask = (*pboxfn) (n, &ED_tail_port(e), side, &endp->boxes[0], &endp->boxn)))
        endp->sidemask = mask;
@@ -526,8 +542,10 @@ beginpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
            endp->sidemask = BOTTOM;
            break;
        case FLATEDGE:
-           endp->boxes[0].LL.y = P->start.p.y;
-           endp->sidemask = TOP;
+           if (endp->sidemask == TOP)
+               endp->boxes[0].LL.y = P->start.p.y;
+           else
+               endp->boxes[0].UR.y = P->start.p.y;
            break;
        case REGULAREDGE:
            endp->boxes[0].UR.y = P->start.p.y;
@@ -623,41 +641,58 @@ void endpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
        return;
     }
 
-    if ((et == FLATEDGE) && (ND_node_type(n) == NORMAL) && ((side = ED_head_port(e).side))) {
+    if ((et == FLATEDGE) && ((side = ED_head_port(e).side))) {
        edge_t* orig;
        box b0, b = endp->nb;
        switch (side) {
        case LEFT:
            b.UR.x = P->end.p.x;
-           b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
-           b.LL.y = P->end.p.y;
+           if (endp->sidemask == TOP) {
+               b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+               b.LL.y = P->end.p.y;
+           }
+           else {
+               b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+               b.UR.y = P->end.p.y;
+           }
            endp->boxes[0] = b;
            endp->boxn = 1;
            break;
        case RIGHT:
            b.LL.x = P->end.p.x-1;
-           b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
-           b.LL.y = P->end.p.y-1;
+           if (endp->sidemask == TOP) {
+               b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+               b.LL.y = P->end.p.y-1;
+           }
+           else {
+               b.LL.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+               b.UR.y = P->end.p.y;
+           }
            endp->boxes[0] = b;
            endp->boxn = 1;
            break;
        case TOP:
-           b.LL.y = MIN(b.LL.y,P->end.p.y);
-           endp->boxes[0] = b;
-           endp->boxn = 1;
+           abort();
            break;
        case BOTTOM:
-           b0.LL.x = b.LL.x-1;
-           b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
-           b0.UR.x = P->end.p.x;
-           b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
-           b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - 2;
-           b.LL.y = b0.UR.y;
-           b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
-           b.LL.x -= 1;
-           endp->boxes[0] = b0;
-           endp->boxes[1] = b;
-           endp->boxn = 2;
+           if (endp->sidemask == TOP) {
+               b0.LL.x = b.LL.x-1;
+               b0.UR.y = ND_coord_i(n).y - ND_ht_i(n)/2;
+               b0.UR.x = P->end.p.x;
+               b0.LL.y = b0.UR.y - GD_ranksep(n->graph)/2;
+               b.UR.x = ND_coord_i(n).x - ND_lw_i(n) - 2;
+               b.LL.y = b0.UR.y;
+               b.UR.y = ND_coord_i(n).y + ND_ht_i(n)/2;
+               b.LL.x -= 1;
+               endp->boxes[0] = b0;
+               endp->boxes[1] = b;
+               endp->boxn = 2;
+           }
+           else {
+               b.UR.y = MAX(b.UR.y,P->start.p.y);
+               endp->boxes[0] = b;
+               endp->boxn = 1;
+           }
            break;
        }
        if (n == orig->head)
@@ -668,7 +703,8 @@ void endpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
        return;
     }
 
-    side = TOP; 
+    if (et == REGULAREDGE) side = TOP;
+    else side = endp->sidemask;  /* for flat edges */
     if (pboxfn
        && (mask = (*pboxfn) (n, &ED_head_port(e), side, &endp->boxes[0], &endp->boxn)))
        endp->sidemask = mask;
@@ -685,8 +721,10 @@ void endpath(path * P, edge_t * e, int et, pathend_t * endp, boolean merge)
            endp->sidemask = TOP;
            break;
        case FLATEDGE:
-           endp->boxes[0].LL.y = P->end.p.y;
-           endp->sidemask = TOP;
+           if (endp->sidemask == TOP)
+               endp->boxes[0].LL.y = P->start.p.y;
+           else
+               endp->boxes[0].UR.y = P->start.p.y;
            break;
        case REGULAREDGE:
            endp->boxes[0].LL.y = P->end.p.y;
index 5a5307190b7b5ca3d7139c1e4c95fe992b24cd6a..1a83373e52d448862fa2de575c91e842b41b0d7d 100644 (file)
@@ -77,27 +77,26 @@ static box boxes[1000];
 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 *);
@@ -228,7 +227,7 @@ void dot_splines(graph_t * g)
     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;
@@ -400,7 +399,7 @@ void dot_splines(graph_t * g)
     free(P->boxes);
     free(P);
     free(sd.Rank_box);
-    routesplinesterm(sd.ri);
+    routesplinesterm();
     State = GVSPLINES;
 }
 
@@ -863,6 +862,46 @@ make_flat_adj_edges(path* P, edge_t** edges, int ind, int cnt, edge_t* e0)
     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
@@ -872,7 +911,7 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e)
     node_t *tn, *hn, *ln;
     point *ps;
     pathend_t tend, hend;
-    box b, lb;
+    box lb;
     int boxn, i, pn, ydelta;
     edge_t *f;
 
@@ -893,23 +932,8 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e)
     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; 
@@ -931,7 +955,7 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e)
     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);
 }
@@ -939,8 +963,68 @@ make_flat_labeled_edge(spline_info_t* sp, path* P, edge_t* e)
 /* 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:
@@ -957,14 +1041,14 @@ make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt)
 {
     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);
@@ -983,49 +1067,59 @@ make_flat_edge(spline_info_t* sp, path * P, edge_t ** edges, int ind, int cnt)
     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;
     }
 }
 
@@ -1115,7 +1209,7 @@ static void make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int
            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++)
@@ -1147,7 +1241,7 @@ static void make_regular_edge(spline_info_t* sp, path * P, edge_t ** edges, int
        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++)
@@ -1250,7 +1344,6 @@ completeflatpath(path * P,
     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)
@@ -1933,7 +2026,6 @@ node_t *n, *adj;
  * 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)
 {