]> granicus.if.org Git - graphviz/commitdiff
patchwork integration, courtesy Emden Gansner
authornorth <devnull@localhost>
Mon, 18 Aug 2008 19:34:54 +0000 (19:34 +0000)
committernorth <devnull@localhost>
Mon, 18 Aug 2008 19:34:54 +0000 (19:34 +0000)
lib/patchwork/patchwork.c
lib/patchwork/patchwork.h
lib/patchwork/patchworkinit.c
plugin/neato_layout/gvlayout_neato_layout.c

index 2963062c07fc25877c424753975554b77742338f..d24729c16682073e2d34b2c20a6f1ec7c644f189 100644 (file)
@@ -1,10 +1,12 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <patchwork.h>
 #include "render.h"
 
 extern void patchwork_init_graph(graph_t * g);
 
-typedef struct rect_t {pointf ll; pointf ur;} rect_t;
+typedef boxf rect_t;
+
 typedef struct treenode_t {
        double area;
        rect_t  r;
@@ -19,9 +21,7 @@ typedef struct treenode_t {
 static treenode_t *newtreenode(treenode_t **first, treenode_t **prev)
 {
        treenode_t *p;
-       p = malloc(sizeof(treenode_t));
-       p->leftchild = p->rightsib = 0;
-       p->area = 0.0;
+       p = NEW(treenode_t);
        if (!*first) *first = p;
        if (*prev) (*prev)->rightsib = p;
        *prev = p;
@@ -42,19 +42,21 @@ static treenode_t *treebuilder(Agraph_t *g)
                subg = GD_clust(g)[i];
                if (agnnodes(subg) == 0) continue;
                p = newtreenode(&first,&prev);
-               p->kind = AGRAPH;
+               p->kind = AGGRAPH;
                p->u.subg = subg;
                p->leftchild = treebuilder(subg);
        }
 
        for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
                char *val;
+               if (SPARENT(n)) continue;
                p = newtreenode(&first,&prev);
                val = agget(n,"area");
                if (val) p->area = atof(val);
                if (p->area <= 0.0) p->area = 1.0;
                p->kind = AGNODE;
                p->u.n = n;
+               SPARENT(n) = g;
        }
        return first;
 }
@@ -81,35 +83,35 @@ static void layouter(treenode_t *tree, int dir, rect_t r)
        treenode_t      *p;
 
        tree->r = r;
-       if (dir == BT) delta = (r.ur.y - r.ll.y) / tree->area;
-       else if (dir == LR) delta = (r.ur.x - r.ll.x) / tree->area;
+       if (dir == BT) delta = (r.UR.y - r.LL.y) / tree->area;
+       else if (dir == LR) delta = (r.UR.x - r.LL.x) / tree->area;
        else abort();
-       ref = r.ll;
+       ref = r.LL;
        for (p = tree->leftchild; p; p = p->rightsib) {
-               r0.ll = ref;
+               r0.LL = ref;
                if (dir == BT) {
-                       r0.ur.x = r.ur.x;
-                       r0.ur.y = ref.y + p->area * delta;
+                       r0.UR.x = r.UR.x;
+                       r0.UR.y = ref.y + p->area * delta;
                }
                else {
-                       r0.ur.x = ref.x + p->area * delta;
-                       r0.ur.y = r.ur.y;
+                       r0.UR.x = ref.x + p->area * delta;
+                       r0.UR.y = r.UR.y;
                }
                layouter(p,(dir == BT? LR : BT),r0);
-               if (dir == BT) ref.y = r0.ur.y;
-               else ref.x = r0.ur.x;
+               if (dir == BT) ref.y = r0.UR.y;
+               else ref.x = r0.UR.x;
        }
 }
 
 /* squarified layout */
-static double aspect(rect_t r) { return (r.ur.y - r.ll.y)/(r.ur.x - r.ll.x); }
+static double aspect(rect_t r) { return (r.UR.y - r.LL.y)/(r.UR.x - r.LL.x); }
 
 static void sqlayouter(treenode_t *list, int dir, rect_t r, double total)
 {
        double frac = list->area / total;
        rect_t s = r;
-       if (dir == BT) s.ur.y = s.ll.y +  frac * (r.ur.y - r.ll.y);
-       else s.ur.x = s.ll.x + frac * (r.ur.x - r.ll.x);
+       if (dir == BT) s.UR.y = s.LL.y +  frac * (r.UR.y - r.LL.y);
+       else s.UR.x = s.LL.x + frac * (r.UR.x - r.LL.x);
        list->r = s;
 
        if (list->leftchild) {
@@ -119,8 +121,8 @@ static void sqlayouter(treenode_t *list, int dir, rect_t r, double total)
 
        if (list->rightsib) {
                total = total - list->area;
-               if (dir == BT) r.ll.y = s.ur.y;
-               else r.ll.x = s.ur.x;
+               if (dir == BT) r.LL.y = s.UR.y;
+               else r.LL.x = s.UR.x;
                if (aspect(r) > 1) sqlayouter(list->rightsib, BT, r, total);
                else sqlayouter(list->rightsib, LR, r, total);
        }
@@ -133,10 +135,10 @@ static void printer(treenode_t *tree)
 
        if (onetime) { fprintf(stderr,"%%!PS\n"); onetime=0;}
        fprintf(stderr,"newpath %.3lf %.3lf moveto %.3lf %.3lf lineto %.3lf %.3lf lineto %.3lf %.3lf lineto closepath \n",
-               tree->r.ll.x,tree->r.ll.y,
-               tree->r.ur.x,tree->r.ll.y,
-               tree->r.ur.x,tree->r.ur.y,
-               tree->r.ll.x,tree->r.ur.y);
+               tree->r.LL.x,tree->r.LL.y,
+               tree->r.UR.x,tree->r.LL.y,
+               tree->r.UR.x,tree->r.UR.y,
+               tree->r.LL.x,tree->r.UR.y);
        if (tree->leftchild) {
                fprintf(stderr,"stroke \n");
                for (p = tree->leftchild; p; p = p->rightsib) printer(p);
@@ -146,32 +148,55 @@ static void printer(treenode_t *tree)
        }
 }
 
-static void walker(treenode_t *tree)
+static void finishNode (node_t* n)
+{
+    char* str = strdup_and_subst_obj(NODENAME_ESC, (void*)n);
+    ND_shape(n) = bind_shape("box", n);
+    ND_label(n) = make_label(n->graph, LT_NONE, str,
+               late_double(n, N_fontsize, DEFAULT_FONTSIZE, MIN_FONTSIZE),
+               late_nnstring(n, N_fontname, DEFAULT_FONTNAME),
+               late_nnstring(n, N_fontcolor, DEFAULT_COLOR));
+    ND_shape(n)->fns->initfn(n);
+}
+
+static rect_t walker(treenode_t *tree)
 {
        treenode_t      *p;
        Agnode_t        *n;
        point           center;
+    rect_t      r, rr;
 
        switch(tree->kind) {
+               case AGGRAPH:
                case AGRAPH:
                        break;
                case AGNODE:
-                       center.x = (tree->r.ur.x + tree->r.ll.x) / 2.0;
-                       center.y = (tree->r.ur.y + tree->r.ll.y) / 2.0;
+                       rr = tree->r;
+                       center.x = (tree->r.UR.x + tree->r.LL.x) / 2.0;
+                       center.y = (tree->r.UR.y + tree->r.LL.y) / 2.0;
 
                        n = tree->u.n;
                        ND_coord_i(n) = center;
-                       ND_height(n) = PS2INCH(tree->r.ur.y - tree->r.ll.y);
-                       ND_width(n) = PS2INCH(tree->r.ur.x - tree->r.ll.x);
+                       ND_height(n) = PS2INCH(tree->r.UR.y - tree->r.LL.y);
+                       ND_width(n) = PS2INCH(tree->r.UR.x - tree->r.LL.x);
                        gv_nodesize(n,GD_flip(n->graph));
+                       finishNode (n);
                        /*fprintf(stderr,"%s coord %d %d ht %d width %d\n",
                                n->name, ND_coord_i(n).x, ND_coord_i(n).y, ND_ht_i(n),
                                ND_rw_i(n)+ND_lw_i(n));*/
                        break;
                default: abort();
        }
-       if (tree->leftchild)
-               for (p = tree->leftchild; p; p = p->rightsib) walker(p);
+       if ((p = tree->leftchild)) {
+               rr = walker (p);
+               p = p->rightsib;
+               for (; p; p = p->rightsib) {
+                       r = walker(p);
+                       EXPANDBB(rr,r);
+               }
+               GD_bb(tree->u.subg) = rr;
+       }
+    return rr;
 }
 
 #ifdef PWDRIVER
@@ -198,12 +223,13 @@ void patchwork_layout(Agraph_t *g)
        rect_t r = {{0.0, 0.0}, {100.0, 100.0}};
        patchwork_init_graph(g);
        root.leftchild = treebuilder(g);
+       root.u.subg = g;
        sizeit(&root);
        sqlayouter(&root,LR,r,root.area);
-       printer(&root);
+       /* printer(&root); */
        walker(&root);
-       compute_bb(g);
-       fprintf(stderr,"bb %.3g %.3g %.3g %.3g\n",
-               GD_bb(g).LL.x, GD_bb(g).LL.y, GD_bb(g).UR.x, GD_bb(g).UR.y);
+       /* compute_bb(g); */
+       /* fprintf(stderr,"bb %d %d %d %d\n", */
+               /* GD_bb(g).LL.x, GD_bb(g).LL.y, GD_bb(g).UR.x, GD_bb(g).UR.y); */
        dotneato_postprocess(g);
 }
index 7e1948b5ade829c1b77a1448adf22263ea2ec37c..a65498fb9a559303b739b8dd82d0ed6222439493 100644 (file)
@@ -28,7 +28,7 @@ extern "C" {
        int subtreeSize;
        int nChildren;
        int nStepsToCenter;
-       node_t *parent;
+       graph_t *parent;
        double span;
        double theta;
     } rdata;
index f4cdffc546ecacb1954d76cdcdc1c2a2e8a20942..4a1d79733fb580a07358ad93a178eb3d56922bac 100644 (file)
@@ -104,9 +104,9 @@ mkClusters (graph_t * g, clist_t* pclist, graph_t* parent)
 static void patchwork_init_node(node_t * n)
 {
     agset(n,"shape","box");
-    common_init_node(n);
-    gv_nodesize(n, GD_flip(n->graph));
-    ND_pos(n) = ALLOC(GD_ndim(n->graph), 0, double);
+    /* common_init_node(n); */
+    /* gv_nodesize(n, GD_flip(n->graph)); */
+    /* ND_pos(n) = ALLOC(GD_ndim(n->graph), 0, double); */
 }
 
 static void patchwork_init_edge(edge_t * e)
@@ -138,11 +138,11 @@ static void patchwork_init_node_edge(graph_t * g)
 
 void patchwork_init_graph(graph_t * g)
 {
-       agnodeattr(g,"shape","box");
+    N_shape = agnodeattr(g,"shape","box");
     setEdgeType (g, ET_LINE);
     /* GD_ndim(g) = late_int(g,agfindattr(g,"dim"),2,2); */
     Ndim = GD_ndim(g) = 2;     /* The algorithm only makes sense in 2D */
-       mkClusters(g, NULL, g);
+    mkClusters(g, NULL, g);
     patchwork_init_node_edge(g);
 }
 
index 0c8c3d4ab7e627ccf238a9c43ca24ca4c8f1bf5a..f6dcc00b3dfd51cb501cd37f3fa6be8c6ed52f93 100644 (file)
@@ -36,6 +36,7 @@ typedef enum { LAYOUT_NEATO,
                LAYOUT_SFDP,
                LAYOUT_TWOPI,
                LAYOUT_CIRCO,
+               LAYOUT_PATCHWORK,
                LAYOUT_NOP1,
                LAYOUT_NOP2,
        } layout_type;
@@ -45,12 +46,14 @@ extern void fdp_layout(graph_t * g);
 extern void sfdp_layout(graph_t * g);
 extern void twopi_layout(graph_t * g);
 extern void circo_layout(graph_t * g);
+extern void patchwork_layout(graph_t * g);
 
 extern void neato_cleanup(graph_t * g);
 extern void fdp_cleanup(graph_t * g);
 extern void sfdp_cleanup(graph_t * g);
 extern void twopi_cleanup(graph_t * g);
 extern void circo_cleanup(graph_t * g);
+extern void patchwork_cleanup(graph_t * g);
 
 static void nop1_layout(graph_t * g)
 {
@@ -101,6 +104,11 @@ gvlayout_engine_t nop2gen_engine = {
     neato_cleanup,
 };
 
+gvlayout_engine_t patchwork_engine = {
+    patchwork_layout,
+    patchwork_cleanup,
+};
+
 gvlayout_features_t neatogen_features = {
         0,
 };
@@ -113,6 +121,7 @@ gvplugin_installed_t gvlayout_neato_types[] = {
 #endif
     {LAYOUT_TWOPI, "twopi", 0, &twopigen_engine, &neatogen_features},
     {LAYOUT_CIRCO, "circo", 0, &circogen_engine, &neatogen_features},
+    {LAYOUT_PATCHWORK, "patchwork", 0, &patchwork_engine, &neatogen_features},
     {LAYOUT_NOP1, "nop", 0, &nop1gen_engine, &neatogen_features},
     {LAYOUT_NOP1, "nop1", 0, &nop1gen_engine, &neatogen_features},
     {LAYOUT_NOP1, "nop2", 0, &nop2gen_engine, &neatogen_features},