From: erg Date: Thu, 17 Feb 2005 23:21:25 +0000 (+0000) Subject: Enhanced and cleaned debug printing; X-Git-Tag: LAST_LIBGRAPH~32^2~7919 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=17473afdb7847b1c6dbd306520121f93b2dcd2ad;p=graphviz Enhanced and cleaned debug printing; 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). --- diff --git a/lib/fdpgen/fdp.h b/lib/fdpgen/fdp.h index 905c29594..e33c26e14 100644 --- a/lib/fdpgen/fdp.h +++ b/lib/fdpgen/fdp.h @@ -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: diff --git a/lib/fdpgen/layout.c b/lib/fdpgen/layout.c index 9dbb9e1ac..162978781 100644 --- a/lib/fdpgen/layout.c +++ b/lib/fdpgen/layout.c @@ -53,8 +53,6 @@ #include #include -#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; diff --git a/lib/fdpgen/tlayout.c b/lib/fdpgen/tlayout.c index 00aaea579..08284ed57 100644 --- a/lib/fdpgen/tlayout.c +++ b/lib/fdpgen/tlayout.c @@ -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) diff --git a/lib/fdpgen/tlayout.h b/lib/fdpgen/tlayout.h index 96aeeb04a..aad4dc6ea 100644 --- a/lib/fdpgen/tlayout.h +++ b/lib/fdpgen/tlayout.h @@ -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; diff --git a/lib/fdpgen/xlayout.c b/lib/fdpgen/xlayout.c index 3e1c8f448..40dfaa6ab 100644 --- a/lib/fdpgen/xlayout.c +++ b/lib/fdpgen/xlayout.c @@ -33,10 +33,12 @@ /* #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); + }