]> granicus.if.org Git - graphviz/commitdiff
Enhanced and cleaned debug printing;
authorerg <devnull@localhost>
Thu, 17 Feb 2005 23:21:25 +0000 (23:21 +0000)
committererg <devnull@localhost>
Thu, 17 Feb 2005 23:21:25 +0000 (23:21 +0000)
fixed bug where graph attributes were not being copied to the derived graph;
removed unused global parameter fields;
extend "overlap" parameter to support a 2-phase overlap removal process (gets rid of -Lt flag).

lib/fdpgen/fdp.h
lib/fdpgen/layout.c
lib/fdpgen/tlayout.c
lib/fdpgen/tlayout.h
lib/fdpgen/xlayout.c

index 905c29594c48bb899189bad7609295cefd76bdde..e33c26e14869862c444633851a8d795a1d807f16 100644 (file)
@@ -41,6 +41,9 @@ typedef struct {
     int flags;
     int level;                 /* depth in graph hierarchy */
     graph_t *parent;           /* smallest containing cluster */
+#ifdef DEBUG
+    graph_t *orig;             /* original of derived graph */
+#endif
 } gdata;
 
 #define GDATA(g)    ((gdata*)(GD_alg(g)))
@@ -49,6 +52,9 @@ typedef struct {
 #define NPORTS(g)   (GDATA(g)->nports)
 #define LEVEL(g)    (GDATA(g)->level)
 #define GPARENT(g)  (GDATA(g)->parent)
+#ifdef DEBUG
+#define GORIG(g)    (GDATA(g)->orig)
+#endif
 
 /* ndata is attached to nodes in real graphs.
  * Real nodes also use "builtin" fields:
index 9dbb9e1ac0564e5c80f5cdf650cdfba5f6bde55b..162978781ebb1d32b68a8a2bca65099345013e8c 100644 (file)
@@ -53,8 +53,6 @@
 #include <clusteredges.h>
 #include <dbg.h>
 
-#define DFLT_overlap   "scale"    /* default overlap value */
-
 typedef struct {
     attrsym_t *G_coord;
     attrsym_t *G_width;
@@ -385,6 +383,25 @@ static void addEdge(edge_t * de, edge_t * e)
     ED_count(de)++;
 }
 
+/* copyAttr:
+ * Copy given attribute from g to dg.
+ */
+static void
+copyAttr (graph_t* g, graph_t* dg, char* attr)
+{
+    char*     ov_val;
+    Agsym_t*  ov;
+
+    if ((ov = agfindattr(g, attr))) {
+       ov_val = agxget(g,ov->index);
+       ov = agfindattr(dg, attr);
+       if (ov)
+           agxset (dg, ov->index, ov_val);
+       else
+           agraphattr(dg, attr, ov_val);
+    }
+}
+
 /* deriveGraph:
  * Create derived graph of g by collapsing clusters into
  * nodes. An edge is created between nodes if there is
@@ -408,20 +425,15 @@ static graph_t *deriveGraph(graph_t * g, layout_info * infop)
        fprintf(stderr, "derive graph %s of %s\n", name, g->name);
     dg = agopen(name, AGRAPHSTRICT);
     GD_alg(dg) = (void *) NEW(gdata);  /* freed in freeDeriveGraph */
+#ifdef DEBUG
+    GORIG(dg) = g;
+#endif
     GD_ndim(dg) = GD_ndim(g);
 
-    /* Set up overlap value in case needed.
-     * If already set, probably came from command line.
-     * Otherwise, if set in the graph, use it.
-     * Else, use default.
+    /* Copy attributes from g.
      */
-    if (!agfindattr(dg, "overlap")) {
-       Agsym_t* ov;
-       if ((ov = agfindattr(g, "overlap")))
-           agraphattr(dg, "overlap", agxget(g,ov->index));
-       else
-           agraphattr(dg, "overlap", DFLT_overlap);
-    }
+    copyAttr(g,dg,"overlap");
+    copyAttr(g,dg,"sep");
 
     /* create derived nodes from clusters */
     for (i = 1; i <= GD_n_cluster(g); i++) {
@@ -838,6 +850,15 @@ setClustNodes(graph_t* root)
     int pinned;
     xparams xpms;
 
+#ifdef DEBUG
+    incInd();
+#endif
+    if (Verbose) {
+#ifdef DEBUG
+       prIndent();
+#endif
+       fprintf (stderr, "layout %s\n", g->name);
+    }
     /* initialize derived node pointers */
     for (n = agfstnode(g); n; n = agnxtnode(g, n))
        DNODE(n) = 0;
@@ -930,6 +951,15 @@ setClustNodes(graph_t* root)
     /* clean up temp graphs */
     freeDerivedGraph(dg, cc);
     free(cc);
+    if (Verbose) {
+#ifdef DEBUG
+       prIndent ();
+#endif
+       fprintf (stderr, "end %s\n", g->name);
+    }
+#ifdef DEBUG
+    decInd();
+#endif
 }
 
 /* setBB;
index 00aaea579b76a75e05ecff71ccab6231edbc0afa..08284ed57ce2ec2f595f3b9f4ebbdf536376ce45 100644 (file)
@@ -63,30 +63,22 @@ extern double drand48(void);
 fdpParms_t fdp_parms = {
     1,                         /* useGrid */
     1,                         /* useNew */
-    1,                         /* seed */
     -1,                                /* numIters */
-    -1,                                /* maxIter */
     50,                                /* unscaled */
     0.0,                       /* C */
     1.0,                       /* Tfact */
-    -1.0,                      /* K */
+    -1.0,                      /* K - set in initParams; used in init_edge */
     -1.0,                      /* T0 */
-    seed_val,                   /* seed mode */
-    10,                         /* overlap removal mode */
 };
 
 #define D_useGrid   (fdp_parms.useGrid)
 #define D_useNew    (fdp_parms.useNew)
-#define D_seed      (fdp_parms.seed)
 #define D_numIters  (fdp_parms.numIters)
-#define D_maxIters  (fdp_parms.maxIters)
 #define D_unscaled  (fdp_parms.unscaled)
 #define D_C         (fdp_parms.C)
 #define D_Tfact     (fdp_parms.Tfact)
 #define D_K         (fdp_parms.K)
 #define D_T0        (fdp_parms.T0)
-#define D_smode     (fdp_parms.smode)
-#define D_tries     (fdp_parms.tries)
 
   /* Actual parameters used; initialized using fdp_parms, then possibly
    * updated with graph-specific values.
@@ -103,7 +95,6 @@ typedef struct {
     double K;          /* spring constant; ideal distance */
     double T0;          /* initial temperature */
     seedMode smode;     /* seed mode */
-    int tries;          /* overlap removal mode */
     double Cell;       /* grid cell size */
     double Cell2;      /* Cell*Cell */
     double K2;         /* K*K */
@@ -137,12 +128,13 @@ static parms_t parms;
 #define T_Ht2       (parms.Ht2)
 #define T_pass1     (parms.pass1)
 #define T_loopcnt   (parms.loopcnt)
-#define T_tries     (parms.tries)
 
 #define EXPFACTOR  1.2
 #define DFLT_maxIters 600
 #define DFLT_K  0.3
 #define DFLT_Cell  0.0
+#define DFLT_seed  1
+#define DFLT_smode seed_val
 
 static double cool(double temp, int t)
 {
@@ -174,7 +166,7 @@ static int init_params(graph_t * g, xparams * xpms)
 #ifdef DEBUG
        if (Verbose) {
            prIndent();
-           fprintf(stderr, "tlayout %s : T0 %f\n", g->name, T_T0);
+           fprintf(stderr, "tlayout %s(%s) : T0 %f\n", g->name, GORIG(g->root)->name, T_T0);
        }
 #endif
        ret = 1;
@@ -183,7 +175,6 @@ static int init_params(graph_t * g, xparams * xpms)
     xpms->T0 = cool(T_T0, T_pass1);
     xpms->K = T_K;
     xpms->C = T_C;
-    xpms->tries = T_tries;
     xpms->numIters = T_maxIters - T_pass1;
 
     if (T_numIters >= 0) {
@@ -248,32 +239,26 @@ static int fdp_setSeed(seedMode * sm, char *arg)
 
 /* fdp_initParams:
  * Initialize parameters based on root graph attributes.
+ * Return K value.
  */
 void fdp_initParams(graph_t * g)
 {
     T_useGrid = D_useGrid;
     T_useNew = D_useNew;
-    T_tries = D_tries;
     T_numIters = D_numIters;
     T_unscaled = D_unscaled;
     T_Cell = DFLT_Cell;
     T_C = D_C;
     T_Tfact = D_Tfact;
-    if (D_maxIters == -1)
-       T_maxIters = late_int(g, agfindattr(g, "maxiter"), DFLT_maxIters, 0);
-    else
-       T_maxIters = D_maxIters;
-    if (D_K == -1.0)
-       T_K = late_double(g, agfindattr(g, "K"), DFLT_K, 0.0);
-    else
-       T_K = D_K;
+    T_maxIters = late_int(g, agfindattr(g, "maxiter"), DFLT_maxIters, 0);
+    D_K = T_K = late_double(g, agfindattr(g, "K"), DFLT_K, 0.0);
     if (D_T0 == -1.0) {
        T_T0 = late_double(g, agfindattr(g, "T0"), -1.0, 0.0);
     } else
        T_T0 = D_T0;
     if (fdp_setSeed(&T_smode, agget(g, "start"))) {
-       T_smode = D_smode;
-       T_seed = D_seed;
+       T_smode = DFLT_smode;
+       T_seed = DFLT_seed;
     }
 
     T_pass1 = (T_unscaled * T_maxIters) / 100;
@@ -284,11 +269,15 @@ void fdp_initParams(graph_t * g)
            T_Cell = 3 * T_K;
        T_Cell2 = T_Cell * T_Cell;
     }
+#ifdef DEBUG
     if (Verbose) {
+       prIndent();
        fprintf(stderr,
-               "Params %s: K %f T0 %f Tfact %f maxIters %d unscaled %d\n",
-               g->name, T_K, T_T0, T_Tfact, T_maxIters, T_unscaled);
+               "Params %s : K %f T0 %f Tfact %f maxIters %d unscaled %d\n",
+               g->name, 
+                T_K, T_T0, T_Tfact, T_maxIters, T_unscaled);
     }
+#endif
 }
 
 static void
@@ -338,9 +327,13 @@ static void doNeighbor(Grid * grid, int i, int j, node_list * nodes)
     double dist2;
 
     if (cellp) {
-       if (Verbose >= 3)
+#ifdef DEBUG
+       if (Verbose >= 3) {
+           prIndent();
            fprintf(stderr, "  doNeighbor (%d,%d) : %d\n", i, j,
                    gLength(cellp));
+       }
+#endif
        for (; nodes != 0; nodes = nodes->next) {
            p = nodes->node;
            for (qs = cellp->nodes; qs != 0; qs = qs->next) {
@@ -364,9 +357,13 @@ static int gridRepulse(Dt_t * dt, cell * cellp, Grid * grid)
     node_list *q;
 
     NOTUSED(dt);
-    if (Verbose >= 3)
+#ifdef DEBUG
+    if (Verbose >= 3) {
+       prIndent();
        fprintf(stderr, "gridRepulse (%d,%d) : %d\n", i, j,
                gLength(cellp));
+    }
+#endif
     for (p = nodes; p != 0; p = p->next) {
        for (q = nodes; q != 0; q = q->next)
            if (p != q)
index 96aeeb04a378f5979d840fe80a684268b37748ce..aad4dc6ea1bafbae415684408f58922c369eb346 100644 (file)
@@ -31,16 +31,12 @@ typedef enum {
     typedef struct {
        int useGrid;            /* use grid for speed up */
        int useNew;             /* encode x-K into attractive force */
-       long seed;              /* seed for position RNG */
        int numIters;           /* actual iterations in layout */
-       int maxIters;           /* max iterations in layout */
        int unscaled;           /* % of iterations used in pass 1 */
        double C;               /* Repulsion factor in xLayout */
        double Tfact;           /* scale temp from default expression */
        double K;               /* spring constant; ideal distance */
        double T0;              /* initial temperature */
-       seedMode smode;         /* seed mode */
-       int tries;              /* overlap removal */
     } fdpParms_t;
 
     extern fdpParms_t fdp_parms;
index 3e1c8f448a77c2021e97c53a249ef55c64e27565..40dfaa6ab2a1867b355114b9f28d7a476726d742 100644 (file)
 /* #define MS */
 /* Use alternate force function */
 /* #define ALT      */
-#define BOX                    /* Use bbox to determine overlap, else use circles */
+#define BOX    /* Use bbox to determine overlap, else use circles */
 /* #define OFF 0.0 */
 #define OFF PS2INCH(8)
 
+#define DFLT_overlap   "scale"    /* default overlap value */
+
 #define WD2(n) (ND_width(n)/2.0 + OFF)
 #define HT2(n) (ND_height(n)/2.0 + OFF)
 
@@ -59,7 +61,7 @@ static double K2;
 /* init_params:
  * Initialize local parameters
  */
-static void init_params(char *name, int n, xparams * xpms)
+static void init_params(graph_t* g, int n, xparams * xpms)
 {
     xParams.K = xpms->K;
     xParams.numIters = xpms->numIters;
@@ -74,22 +76,25 @@ static void init_params(char *name, int n, xparams * xpms)
     if (Verbose) {
        prIndent();
        fprintf(stderr,
-               "xLayout %s : n = %d K = %f T0 = %f loop %d C %f\n", name,
+               "xLayout %s(%s) : n = %d K = %f T0 = %f loop %d C %f\n", 
+               g->name, GORIG(g->root)->name,
                xParams.numIters, xParams.K, xParams.T0, xParams.loopcnt,
                xParams.C);
     }
 #endif
 }
 
-#define T0 xParams.T0
-#define K xParams.K
-#define numIters xParams.numIters
-#define loopcnt xParams.loopcnt
-#define C xParams.C
+#define X_T0         xParams.T0
+#define X_K          xParams.K
+#define X_numIters   xParams.numIters
+#define X_loopcnt    xParams.loopcnt
+#define X_C          xParams.C
+
+#define DFLT_tries 9
 
 static double cool(int t)
 {
-    return (T0 * (numIters - t)) / numIters;
+    return (X_T0 * (X_numIters - t)) / X_numIters;
 }
 
 #define EPSILON 0.01
@@ -261,11 +266,11 @@ doRep(node_t * p, node_t * q, double xdelta, double ydelta, double dist2)
     dist = sqrt(dist2);
     din = RAD(p) + RAD(q);
     if (ov = overlap(p, q)) {
-       factor = C;
+       factor = X_C;
     } else {
        ov = 0;
-       if (dist <= din + K)
-           factor = C * (K - (dist - din)) / K;
+       if (dist <= din + X_K)
+           factor = X_C * (X_K - (dist - din)) / X_K;
        else
            factor = 0.0;
     }
@@ -273,12 +278,15 @@ doRep(node_t * p, node_t * q, double xdelta, double ydelta, double dist2)
 #else
     force = K2 / dist2;
     if ((ov = overlap(p, q)))
-       force *= C;
+       force *= X_C;
 #endif
+#ifdef DEBUG
     if (Verbose == 4) {
+       prIndent();
        dist = sqrt(dist2);
        fprintf(stderr, " ov Fr %f dist %f\n", force * dist, dist);
     }
+#endif
     DISP(q)[0] += xdelta * force;
     DISP(q)[1] += ydelta * force;
     DISP(p)[0] -= xdelta * force;
@@ -314,20 +322,24 @@ static void applyAttr(Agnode_t * p, Agnode_t * q)
     xdelta = ND_pos(q)[0] - ND_pos(p)[0];
     ydelta = ND_pos(q)[1] - ND_pos(p)[1];
     dist = sqrt(xdelta * xdelta + ydelta * ydelta);
-    force = (dout * dout) / (K * dist);
+    force = (dout * dout) / (X_K * dist);
 #elif defined(ALT)
     xdelta = ND_pos(q)[0] - ND_pos(p)[0];
     ydelta = ND_pos(q)[1] - ND_pos(p)[1];
     dist = sqrt(xdelta * xdelta + ydelta * ydelta);
     din = RAD(p) + RAD(q);
-    if (dist < K + din)
+    if (dist < X_K + din)
        return;
     dout = dist - din;
-    force = (dout * dout) / ((K + din) * dist);
+    force = (dout * dout) / ((X_K + din) * dist);
 #else
     if (overlap(p, q)) {
-       if (Verbose == 4)
+#ifdef DEBUG
+       if (Verbose == 4) {
+           prIndent();
            fprintf(stderr, "ov 1 Fa 0 din %f\n", RAD(p) + RAD(q));
+       }
+#endif
        return;
     }
     xdelta = ND_pos(q)[0] - ND_pos(p)[0];
@@ -335,10 +347,14 @@ static void applyAttr(Agnode_t * p, Agnode_t * q)
     dist = sqrt(xdelta * xdelta + ydelta * ydelta);
     din = RAD(p) + RAD(q);
     dout = dist - din;
-    force = (dout * dout) / ((K + din) * dist);
+    force = (dout * dout) / ((X_K + din) * dist);
 #endif
-    if (Verbose == 4)
+#ifdef DEBUG
+    if (Verbose == 4) {
+       prIndent();
        fprintf(stderr, " ov 0 Fa %f din %f \n", force * dist, din);
+    }
+#endif
     DISP(q)[0] -= xdelta * force;
     DISP(q)[1] -= ydelta * force;
     DISP(p)[0] += xdelta * force;
@@ -360,8 +376,10 @@ static int adjust(Agraph_t * g, double temp)
     double disp[NDIM];         /* incremental displacement */
     int overlaps = 0;
 
+#ifdef DEBUG
     if (Verbose == 4)
        fprintf(stderr, "=================\n");
+#endif
 
     for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
        DISP(n)[0] = DISP(n)[1] = 0;
@@ -411,7 +429,6 @@ static int adjust(Agraph_t * g, double temp)
  * at this stage.
  * Returns non-zero if overlaps still exist.
  */
-#undef K
 
 static int x_layout(graph_t * g, xparams * pxpms, int tries)
 {
@@ -423,7 +440,6 @@ static int x_layout(graph_t * g, xparams * pxpms, int tries)
     double K;
     xparams xpms;
 
-
     ov = cntOverlaps(g);;
     if (ov == 0)
        return 0;
@@ -432,13 +448,17 @@ static int x_layout(graph_t * g, xparams * pxpms, int tries)
     xpms = *pxpms;
     K = xpms.K;
     while (ov && (try < tries)) {
+
+#ifdef DEBUG
        if (Verbose) {
-           fprintf(stderr, "try %d (%d): %d overlaps on %s \n", try, tries, ov,
-                   g->name);
+           prIndent();
+           fprintf(stderr, "try %d (%d): %d overlaps on %s(%s) \n", try, tries, ov,
+                   g->name, GORIG(g->root)->name);
        }
+#endif
 
-       init_params(g->name, nnodes, &xpms);
-       for (i = 0; i < loopcnt; i++) {
+       init_params(g, nnodes, &xpms);
+       for (i = 0; i < X_loopcnt; i++) {
            temp = cool(i);
            if (temp <= 0.0)
                break;
@@ -450,29 +470,58 @@ static int x_layout(graph_t * g, xparams * pxpms, int tries)
        xpms.K += K;            /* increase distance */
     }
     if (Verbose && ov)
-       fprintf(stderr, "Warning: %d overlaps remain on %s\n", ov,
-               g->name);
+       fprintf(stderr, "Warning: %d overlaps remain on %s(%s)\n", ov,
+               g->name, GORIG(g->root)->name);
 
     return ov;
 }
 
-/* set shape of derived cluster nodes as boxes before calling
- * adjustNodes
+/* fdp_xLayout:
+ * Use overlap parameter to determine if and how to remove overlaps.
+ * In addition to the usual values accepted by removeOverlap, overlap
+ * can begin with "n:" to indicate the given number of tries using
+ * x_layout to remove overlaps.
+ * Thus,
+ *  NULL or ""  => dflt overlap
+ *  "mode"      => dflt tries, then removeOverlap with mode
+ *  "n:"        => n tries only
+ *  "n:mode"    => n tries, then removeOverlap with mode
+ *  "0:"        => no overlap removal
  */
 void fdp_xLayout(graph_t * g, xparams * xpms)
 {
-    int tries = xpms->tries;
-
-    if (tries == 0)            /* No overlap removal */
-       return; 
-    else if (tries == 1) {     /* No expansion, just adjust */
-       removeOverlap(g);
-    } 
-    else if (tries > 1) {      /* Try expansion tries times, then adjust */
-       if (x_layout(g, xpms, tries - 1))
-           removeOverlap(g);
-    } 
-    else {                     /* Try expansion -tries times; no adjust */
-       x_layout(g, xpms, -1 * tries);
+    int   tries;
+    char* ovlp = agget (g, "overlap");
+    char* cp;
+    char* rest;
+
+    if (Verbose) {
+#ifdef DEBUG
+       prIndent();
+#endif
+        fprintf (stderr, "xLayout ");
+    }
+    if (!ovlp || (*ovlp == '\0')) {
+       ovlp = DFLT_overlap;
+    }
+    if ((cp = strchr(ovlp, ':'))) {
+      cp++;
+      rest = cp;
+      tries = atoi (ovlp);
+      if (tries < 0) tries = 0;
     }
+    else {
+      tries = DFLT_tries;
+      rest = ovlp;
+    }
+    if (Verbose) {
+#ifdef DEBUG
+       prIndent();
+#endif
+        fprintf (stderr, "tries = %d, mode = %s\n", tries, rest);
+    }
+    if (tries && !x_layout(g, xpms, tries))
+       return;
+    removeOverlapAs(g, rest);
+
 }