From: erg Date: Wed, 30 Apr 2008 20:55:00 +0000 (+0000) Subject: Install original sfdp files, with development logs; X-Git-Tag: LAST_LIBGRAPH~32^2~4125 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03cf2697e8dc9f71514ecd3db076a48510213520;p=graphviz Install original sfdp files, with development logs; recommit new sfdp files --- diff --git a/lib/sfdpgen/sfdpinit.c b/lib/sfdpgen/sfdpinit.c new file mode 100644 index 000000000..329084e87 --- /dev/null +++ b/lib/sfdpgen/sfdpinit.c @@ -0,0 +1,382 @@ +/* vim:set shiftwidth=4 ts=8: */ + +/********************************************************** +* This software is part of the graphviz package * +* http://www.graphviz.org/ * +* * +* Copyright (c) 1994-2004 AT&T Corp. * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Corp. * +* * +* Information and Software Systems Research * +* AT&T Research, Florham Park NJ * +**********************************************************/ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef HAVE_LIMITS_H +#include +#else +#ifdef HAVE_VALUES_H +#include +#endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +double _statistics[10]; +#endif + +static void sfdp_init_node(node_t * n) +{ + common_init_node(n); + ND_pos(n) = N_NEW(GD_ndim(n->graph), double); + gv_nodesize(n, GD_flip(n->graph)); +} + +static void sfdp_init_edge(edge_t * e) +{ + common_init_edge(e); +} + +static void sfdp_init_node_edge(graph_t * g) +{ + node_t *n; + edge_t *e; + int nnodes = agnnodes(g); + attrsym_t *N_pos = agfindattr(g->proto->n, "pos"); + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + sfdp_init_node(n); + user_pos(N_pos, NULL, n, nnodes); + } + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + for (e = agfstout(g, n); e; e = agnxtout(g, e)) + sfdp_init_edge(e); + } +} + +static void sfdp_init_graph(Agraph_t * g) +{ + setEdgeType(g, ET_LINE); + g->u.ndim = late_int(g, agfindattr(g, "dim"), 2, 2); + Ndim = g->u.ndim = MIN(g->u.ndim, MAXDIM); + + sfdp_init_node_edge(g); +} + +/* getPos: + */ +static real *getPos(Agraph_t * g) +{ + Agnode_t *n; + real *pos = N_NEW(Ndim * agnnodes(g), real); + int ix, i; + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + i = ND_id(n); + if (hasPos(n)) { + for (ix = 0; ix < Ndim; ix++) { + pos[i * Ndim + ix] = ND_pos(n)[ix]; + } + } + } + + return pos; +} + +/* getSizes: + * Set up array of half sizes in inches. + */ +static real *getSizes(Agraph_t * g, pointf pad) +{ + Agnode_t *n; + real *sizes = N_GNEW(2 * agnnodes(g), real); + int i; + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + i = ND_id(n); + sizes[i * 2] = ND_width(n) * .5 + pad.x; + sizes[i * 2 + 1] = ND_height(n) * .5 + pad.y; + } + + return sizes; +} + +/* makeMatrix: + * Assumes g is connected and simple, i.e., we can have a->b and b->a + * but not a->b and a->b + */ +static SparseMatrix *makeMatrix(Agraph_t * g, int dim) +{ + SparseMatrix *A = 0; + Agnode_t *n; + Agedge_t *e; + Agsym_t *sym; + int nnodes; + int nedges; + int i, row; + int *I; + int *J; + real *val; + real v; + int type = MATRIX_TYPE_REAL; + + if (!g) + return NULL; + nnodes = agnnodes(g); + nedges = agnedges(g); + + /* Assign node ids */ + i = 0; + for (n = agfstnode(g); n; n = agnxtnode(g, n)) + ND_id(n) = i++; + + I = N_GNEW(nedges, int); + J = N_GNEW(nedges, int); + val = N_GNEW(nedges, real); + + sym = agfindattr(g->proto->e, "wt"); + i = 0; + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + row = ND_id(n); + for (e = agfstout(g, n); e; e = agnxtout(g, e)) { + I[i] = row; + J[i] = ND_id(e->head); + if (!sym || (sscanf(agxget(e, sym->index), "%lf", &v) != 1)) + v = 1; + val[i] = v; + i++; + } + } + + A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, + val, type); + + free(I); + free(J); + free(val); + + return A; +} + +int +fdpAdjust (graph_t* g) +{ + SparseMatrix *A = makeMatrix(g, Ndim); + real *sizes; + real *pos = N_NEW(Ndim * agnnodes(g), real); + Agnode_t *n; + int flag, i; + expand_t sep = sepFactor(g); + pointf pad; + + if (sep.doAdd) { + pad.x = PS2INCH(sep.x); + pad.y = PS2INCH(sep.y); + } else { + pad.x = PS2INCH(DFLT_MARGIN); + pad.y = PS2INCH(DFLT_MARGIN); + } + sizes = getSizes(g, pad); + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + real* npos = pos + (Ndim * ND_id(n)); + for (i = 0; i < Ndim; i++) { + npos[i] = ND_pos(n)[i]; + } + } + + flag = remove_overlap(Ndim, A, pos, sizes, 3); + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + real *npos = pos + (Ndim * ND_id(n)); + for (i = 0; i < Ndim; i++) { + ND_pos(n)[i] = npos[i]; + } + } + + free(sizes); + free(pos); + SparseMatrix_delete (A); + + return flag; +} + +static void sfdpLayout(graph_t * g, spring_electrical_control * ctrl, + pointf pad) +{ + real *sizes; + real *pos; + Agnode_t *n; + int flag, i; + + SparseMatrix *A = makeMatrix(g, Ndim); + if (ctrl->overlap) + sizes = getSizes(g, pad); + else + sizes = NULL; + pos = getPos(g); + + flag = multilevel_spring_electrical_embedding(Ndim, A, ctrl, NULL, sizes, pos); + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + real *npos = pos + (Ndim * ND_id(n)); + for (i = 0; i < Ndim; i++) { + ND_pos(n)[i] = npos[i]; + } + } + + free(sizes); + free(pos); + SparseMatrix_delete (A); +} + +static smooth_t +late_smooth (graph_t* g, Agsym_t* sym, smooth_t dflt) +{ + char* s; + int v; + smooth_t rv; + + if (!sym) return dflt; + s = agxget (g, sym->index); + if (isdigit(*s)) { +#if HAVE_GTS + if ((v = atoi (s)) <= SMOOTHING_RNG) +#else + if ((v = atoi (s)) <= SMOOTHING_SPRING) +#endif + rv = (smooth_t)v; + else + rv = dflt; + } + else if (isalpha(*s)) { + if (!strcasecmp(s, "avg_dist")) + rv = SMOOTHING_STRESS_MAJORIZATION_AVG_DIST; + else if (!strcasecmp(s, "graph_dist")) + rv = SMOOTHING_STRESS_MAJORIZATION_GRAPH_DIST; + else if (!strcasecmp(s, "none")) + rv = SMOOTHING_NONE; + else if (!strcasecmp(s, "power_dist")) + rv = SMOOTHING_STRESS_MAJORIZATION_POWER_DIST; +#if HAVE_GTS + else if (!strcasecmp(s, "rng")) + rv = SMOOTHING_RNG; +#endif + else if (!strcasecmp(s, "spring")) + rv = SMOOTHING_SPRING; +#if HAVE_GTS + else if (!strcasecmp(s, "triangle")) + rv = SMOOTHING_TRIANGLE; +#endif + else + rv = dflt; + } + else + rv = dflt; + return rv; +} + +/* tuneControl: + * Use user values to reset control + * + * Possible parameters: + * ctrl->use_node_weights + */ +static void +tuneControl (graph_t* g, spring_electrical_control* ctrl) +{ + ctrl->p = -1.0*late_double(g, agfindattr(g, "K"), -AUTOP, 0.0); + ctrl->multilevels = late_int(g, agfindattr(g, "maxiter"), INT_MAX, 0); + ctrl->smoothing = late_smooth(g, agfindattr(g, "smooth"), SMOOTHING_NONE); +} + +void sfdp_layout(graph_t * g) +{ + sfdp_init_graph(g); + + if (agnnodes(g)) { + Agraph_t **ccs; + Agraph_t *sg; + int ncc; + int i; + expand_t sep; + pointf pad; + spring_electrical_control *ctrl = spring_electrical_control_new(); + + tuneControl (g, ctrl); + +#if HAVE_GTS + if (!agget(g, "overlap") || (graphAdjustMode(g)->mode == AM_FDP)) { + ctrl->overlap = 3; /* FIX: User control? */ + sep = sepFactor(g); + if (sep.doAdd) { + pad.x = PS2INCH(sep.x); + pad.y = PS2INCH(sep.y); + } else { + pad.x = PS2INCH(DFLT_MARGIN); + pad.y = PS2INCH(DFLT_MARGIN); + } + } +#endif + + ccs = ccomps(g, &ncc, 0); + if (ncc == 1) { + sfdpLayout(g, ctrl, pad); + adjustNodes(g); + spline_edges(g); + } else { + pack_info pinfo; + pack_mode pmode = getPackMode(g, l_node); + + for (i = 0; i < ncc; i++) { + sg = ccs[i]; + nodeInduce(sg); + sfdpLayout(g, ctrl, pad); + adjustNodes(sg); + } + spline_edges(g); + pinfo.margin = getPack(g, CL_OFFSET, CL_OFFSET); + pinfo.doSplines = 1; + pinfo.mode = pmode; + pinfo.fixed = 0; + packSubgraphs(ncc, ccs, g, &pinfo); + } + for (i = 0; i < ncc; i++) { + agdelete(g, ccs[i]); + } + free(ccs); + spring_electrical_control_delete(ctrl); + } + + dotneato_postprocess(g); +} + +static void sfdp_cleanup_graph(graph_t * g) +{ +} + +void sfdp_cleanup(graph_t * g) +{ + node_t *n; + edge_t *e; + + for (n = agfstnode(g); n; n = agnxtnode(g, n)) { + for (e = agfstout(g, n); e; e = agnxtout(g, e)) { + gv_cleanup_edge(e); + } + gv_cleanup_node(n); + } + sfdp_cleanup_graph(g); +}