/* mapGraphs: */ static void mapGraphs(graph_t * g, graph_t * cg, distfn dist) { node_t *n; edge_t *e; edge_t *ce; node_t *t; node_t *h; nitem *tp; nitem *hp; int delta; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { tp = (nitem *) ND_alg(n); t = tp->cnode; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { hp = (nitem *) ND_alg(aghead(e)); delta = dist(&tp->bb, &hp->bb); h = hp->cnode; #ifndef WITH_CGRAPH ce = agedge(cg, t, h); #else ce = agedge(cg, t, h, NULL, 1); agbindrec(ce, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); #endif ED_weight(ce) = 1; if (ED_minlen(ce) < delta) { if (ED_minlen(ce) == 0.0) { elist_append(ce, ND_out(t)); elist_append(ce, ND_in(h)); } ED_minlen(ce) = delta; } } } }
/* mapGraphs: */ static void mapGraphs(graph_t * g, graph_t * cg, distfn dist) { node_t *n; edge_t *e; edge_t *ce; node_t *t; node_t *h; nitem *tp; nitem *hp; int delta; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { tp = (nitem *) ND_alg(n); t = tp->cnode; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { hp = (nitem *) ND_alg(e->head); delta = dist(&tp->bb, &hp->bb); h = hp->cnode; ce = agedge(cg, t, h); ED_weight(ce) = 1; if (ED_minlen(ce) < delta) { if (ED_minlen(ce) == 0.0) { elist_append(ce, ND_out(t)); elist_append(ce, ND_in(h)); } ED_minlen(ce) = delta; } } } }
void fdp_init_node_edge(graph_t * g) { attrsym_t *E_len; node_t *n; edge_t *e; int nn = agnnodes(g); int i; ndata* alg = N_NEW(nn, ndata); processClusterEdges(g); GD_neato_nlist(g) = N_NEW(nn + 1, node_t *); for (i = 0, n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node (n); ND_alg(n) = alg + i; GD_neato_nlist(g)[i] = n; ND_id(n) = i++; } E_len = agfindattr(g->proto->e, "len"); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { init_edge(e, E_len); } } initialPositions(g); }
static void twopi_init_node(node_t * n) { common_init_node(n); neato_nodesize(n, GD_flip(n->graph)); ND_pos(n) = ALLOC(GD_ndim(n->graph), 0, double); ND_alg(n) = (void *) NEW(rdata); }
static void twopi_cleanup_node(node_t * n) { free(ND_alg(n)); if (ND_shape(n)) ND_shape(n)->fns->freefn(n); free_label(ND_label(n)); memset(&(n->u), 0, sizeof(Agnodeinfo_t)); }
/* mkMaze: */ maze* mkMaze (graph_t* g, int doLbls) { node_t* n; maze* mp = NEW(maze); boxf* rects; int i, nrect; cell* cp; double w2, h2; boxf bb, BB; mp->ngcells = agnnodes(g); cp = mp->gcells = N_NEW(mp->ngcells, cell); BB.LL.x = BB.LL.y = MAXDOUBLE; BB.UR.x = BB.UR.y = -MAXDOUBLE; for (n = agfstnode (g); n; n = agnxtnode(g,n)) { w2 = ND_xsize(n)/2.0; if (w2 < 1) w2 = 1; h2 = ND_ysize(n)/2.0; if (h2 < 1) h2 = 1; bb.LL.x = ND_coord(n).x - w2; bb.UR.x = ND_coord(n).x + w2; bb.LL.y = ND_coord(n).y - h2; bb.UR.y = ND_coord(n).y + h2; BB.LL.x = MIN(BB.LL.x, bb.LL.x); BB.LL.y = MIN(BB.LL.y, bb.LL.y); BB.UR.x = MAX(BB.UR.x, bb.UR.x); BB.UR.y = MAX(BB.UR.y, bb.UR.y); cp->bb = bb; cp->flags |= MZ_ISNODE; ND_alg(n) = cp; cp++; } if (doLbls) { } BB.LL.x -= MARGIN; BB.LL.y -= MARGIN; BB.UR.x += MARGIN; BB.UR.y += MARGIN; rects = partition (mp->gcells, mp->ngcells, &nrect, BB); #ifdef DEBUG if (odb_flags & ODB_MAZE) psdump (mp->gcells, mp->ngcells, BB, rects, nrect); #endif mp->cells = N_NEW(nrect, cell); mp->ncells = nrect; for (i = 0; i < nrect; i++) { mp->cells[i].bb = rects[i]; } free (rects); mp->sg = mkMazeGraph (mp, BB); return mp; }
/* clone_graph: * Create two copies of the argument graph * One is a subgraph, the other is an actual copy since we will be * adding edges to it. */ static Agraph_t* clone_graph(Agraph_t* ing, Agraph_t** xg) { Agraph_t* clone; Agraph_t* xclone; Agnode_t* n; Agnode_t* xn; Agnode_t* xh; Agedge_t* e; Agedge_t* xe; char gname[SMALLBUF]; static int id = 0; sprintf (gname, "_clone_%d", id++); clone = agsubg(ing, gname); sprintf (gname, "_clone_%d", id++); xclone = agopen(gname, ing->kind); for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) { aginsert (clone, n); xn = agnode (xclone, n->name); CLONE(n) = xn; } for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) { xn = CLONE(n); for(e = agfstout(ing, n); e; e = agnxtout(ing, e)) { aginsert (clone, e); xh = CLONE(e->head); xe = agedge (xclone, xn, xh); ORIGE(xe) = e; DEGREE(xn) += 1; DEGREE(xh) += 1; } } *xg = xclone; #ifdef OLD clone = agopen("clone", root->kind); for(n = agfstnode(root); n; n = agnxtnode(root, n)) { cn = agnode(clone, n->name); ND_alg(cn) = DATA(n); BCDONE(cn) = 0; } for(n = agfstnode(root); n; n = agnxtnode(root, n)) { Agnode_t *t = agnode(clone, n); for(e = agfstout(root, n); e; e = agnxtout(root, e)) { Agnode_t *h = agnode(clone, e->head->name); agedge(clone, t, h); } } #endif return clone; }
/* mkDeriveNode: * Constructor for a node in a derived graph. * Allocates dndata. */ static node_t *mkDeriveNode(graph_t * dg, char *name) { node_t *dn; dn = agnode(dg, name,1); agbindrec(dn, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data ND_alg(dn) = (void *) NEW(dndata); /* free in freeDeriveNode */ ND_pos(dn) = N_GNEW(GD_ndim(dg), double); /* fprintf (stderr, "Creating %s\n", dn->name); */ return dn; }
/* makeDerivedNode: * Make a node in the derived graph, with the given name. * orig points to what it represents, either a real node or * a cluster. Copy size info from original node; needed for * adjustNodes and packSubgraphs. */ static node_t *makeDerivedNode(graph_t * dg, char *name, int isNode, void *orig) { node_t *n = agnode(dg, name,1); agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data ND_alg(n) = (void *) NEW(cdata); if (isNode) { ND_pos(n) = N_NEW(Ndim, double); ND_lw(n) = ND_lw((node_t *) orig); ND_rw(n) = ND_rw((node_t *) orig); ND_ht(n) = ND_ht((node_t *) orig); ORIGN(n) = (node_t *) orig; } else
void fdp_cleanup(graph_t * g) { node_t *n; edge_t *e; n = agfstnode(g); free(ND_alg(n)); for (; n; n = agnxtnode(g, n)) { for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) { gv_cleanup_edge(e); } gv_cleanup_node(n); } fdp_cleanup_graph(g); }
static void circular_init_node_edge(graph_t * g) { node_t *n; edge_t *e; int i = 0; ndata* alg = N_NEW(agnnodes(g), ndata); GD_neato_nlist(g) = N_NEW(agnnodes(g) + 1, node_t *); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); ND_alg(n) = alg + i; GD_neato_nlist(g)[i++] = n; } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { circular_init_edge(e); } } }
static void twopi_init_node_edge(graph_t * g) { node_t *n; edge_t *e; int i = 0; int n_nodes = agnnodes(g); rdata* alg; alg = N_NEW(n_nodes, rdata); GD_neato_nlist(g) = N_NEW(n_nodes + 1, node_t *); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); ND_alg(n) = alg + i; GD_neato_nlist(g)[i++] = n; } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { twopi_init_edge(e); } } }
/* twopi_layout: */ void twopi_layout(Agraph_t * g) { Agnode_t *ctr = 0; char *s; int setRoot = 0; pointf sc; int doScale = 0; int r; if (agnnodes(g) == 0) return; twopi_init_graph(g); s = agget(g, "root"); if ((s = agget(g, "root"))) { if (*s) { ctr = agfindnode(g, s); if (!ctr) { agerr(AGWARN, "specified root node \"%s\" was not found.", s); agerr(AGPREV, "Using default calculation for root node\n"); setRoot = 1; } } else { setRoot = 1; } } if ((s = agget(g, "scale")) && *s) { if ((r = sscanf (s, "%lf,%lf",&sc.x,&sc.y))) { if (r == 1) sc.y = sc.x; doScale = 1; if (Verbose) fprintf (stderr, "scale = (%f,%f)\n", sc.x, sc.y); } } if (agnnodes(g)) { Agraph_t **ccs; Agraph_t *sg; Agnode_t *c = NULL; Agnode_t *n; int ncc; int i; ccs = ccomps(g, &ncc, 0); if (ncc == 1) { c = circleLayout(g, ctr); if (setRoot && !ctr) ctr = c; n = agfstnode(g); free(ND_alg(n)); ND_alg(n) = NULL; if (doScale) scaleGraph (g, c, sc); adjustNodes(g); spline_edges(g); } else { pack_info pinfo; getPackInfo (g, l_node, CL_OFFSET, &pinfo); pinfo.doSplines = 0; for (i = 0; i < ncc; i++) { sg = ccs[i]; if (ctr && agcontains(sg, ctr)) c = ctr; else c = 0; nodeInduce(sg); c = circleLayout(sg, c); if (setRoot && !ctr) ctr = c; if (doScale) scaleGraph (sg, c, sc); adjustNodes(sg); } n = agfstnode(g); free(ND_alg(n)); ND_alg(n) = NULL; packSubgraphs(ncc, ccs, g, &pinfo); spline_edges(g); } for (i = 0; i < ncc; i++) { agdelete(g, ccs[i]); } free(ccs); } if (setRoot) agset (g, "root", agnameof (ctr)); dotneato_postprocess(g); }
/* mkConstraintG: */ static graph_t *mkConstraintG(graph_t * g, Dt_t * list, intersectfn intersect, distfn dist) { nitem *p; nitem *nxt = NULL; nitem *nxp; graph_t *vg; node_t *prev = NULL; node_t *root = NULL; node_t *n = NULL; edge_t *e; int lcnt, cnt; int oldval = -INT_MAX; #ifdef OLD double root_val; #endif node_t *lastn = NULL; #ifndef WITH_CGRAPH graph_t *cg = agopen("cg", AGDIGRAPHSTRICT); #else graph_t *cg = agopen("cg", Agstrictdirected, NIL(Agdisc_t *)); agbindrec(cg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); // graph custom data #endif /* count distinct nodes */ cnt = 0; for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { if (oldval != p->val) { oldval = p->val; cnt++; } } /* construct basic chain to enforce left to right order */ oldval = -INT_MAX; lcnt = 0; for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { if (oldval != p->val) { oldval = p->val; /* n = newNode (cg); */ #ifndef WITH_CGRAPH n = agnode(cg, agnameof(p->np)); /* FIX */ #else n = agnode(cg, agnameof(p->np), 1); /* FIX */ agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data #endif ND_alg(n) = p; if (root) { ND_next(lastn) = n; lastn = n; } else { root = n; #ifdef OLD root_val = p->val; #endif lastn = GD_nlist(cg) = n; } alloc_elist(lcnt, ND_in(n)); if (prev) { if (prev == root) alloc_elist(2 * (cnt - 1), ND_out(prev)); else alloc_elist(cnt - lcnt - 1, ND_out(prev)); #ifndef WITH_CGRAPH e = agedge(cg, prev, n); #else e = agedge(cg, prev, n, NULL, 1); agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); // edge custom data #endif ED_minlen(e) = SCALE; ED_weight(e) = 1; elist_append(e, ND_out(prev)); elist_append(e, ND_in(n)); } lcnt++; prev = n; } p->cnode = n; } alloc_elist(0, ND_out(prev)); /* add immediate right neighbor constraints * Construct visibility graph, then perform transitive reduction. * Remaining outedges are immediate right neighbors. * FIX: Incremental algorithm to construct trans. reduction? */ #ifndef WITH_CGRAPH vg = agopen("vg", AGDIGRAPHSTRICT); #else vg = agopen("vg", Agstrictdirected, NIL(Agdisc_t *)); #endif for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { #ifndef WITH_CGRAPH n = agnode(vg, agnameof(p->np)); /* FIX */ #else n = agnode(vg, agnameof(p->np), 1); /* FIX */ agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data #endif p->vnode = n; ND_alg(n) = p; } oldval = -INT_MAX; for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { if (oldval != p->val) { /* new pos: reset nxt */ oldval = p->val; for (nxt = (nitem *) dtlink(link, (Dtlink_t *) p); nxt; nxt = (nitem *) dtlink(list, (Dtlink_t *) nxt)) { if (nxt->val != oldval) break; } if (!nxt) break; } for (nxp = nxt; nxp; nxp = (nitem *) dtlink(list, (Dtlink_t *) nxp)) { if (intersect(p, nxp)) #ifndef WITH_CGRAPH agedge(vg, p->vnode, nxp->vnode); #else agedge(vg, p->vnode, nxp->vnode, NULL, 1); #endif } } /* Remove redundant constraints here. However, the cost of doing this * may be a good deal more than the time saved in network simplex. Also, * if the graph is changed, the ND_in and ND_out data has to be updated. */ mapGraphs(vg, cg, dist); agclose(vg); /* add dummy constraints for absolute values and initial positions */ #ifdef OLD for (n = agfstnode(cg); n; n = agnxtnode(cg, n)) { node_t *vn; /* slack node for absolute value */ node_t *an; /* node representing original position */ p = (nitem *) ND_alg(n); if ((n == root) || (!p)) continue; vn = newNode(cg); ND_next(lastn) = vn; lastn = vn; alloc_elist(0, ND_out(vn)); alloc_elist(2, ND_in(vn)); an = newNode(cg); ND_next(lastn) = an; lastn = an; alloc_elist(1, ND_in(an)); alloc_elist(1, ND_out(an)); #ifndef WITH_CGRAPH e = agedge(cg, root, an); #else e = agedge(cg, root, an, 1); #endif ED_minlen(e) = p->val - root_val; elist_append(e, ND_out(root)); elist_append(e, ND_in(an)); #ifndef WITH_CGRAPH e = agedge(cg, an, vn); #else e = agedge(cg, an, vn, 1); #endif elist_append(e, ND_out(an)); elist_append(e, ND_in(vn)); #ifndef WITH_CGRAPH e = agedge(cg, n, vn); #else e = agedge(cg, n, vn, 1); #endif elist_append(e, ND_out(n)); elist_append(e, ND_in(vn)); } #endif /* OLD */ return cg; }
/* mkNConstraintG: * Similar to mkConstraintG, except it doesn't enforce orthogonal * ordering. If there is overlap, as defined by intersect, the * nodes will kept/pushed apart in the current order. If not, no * constraint is enforced. If a constraint edge is added, and it * corresponds to a real edge, we increase the weight in an attempt * to keep the resulting shift short. */ static graph_t *mkNConstraintG(graph_t * g, Dt_t * list, intersectfn intersect, distfn dist) { nitem *p; nitem *nxp; node_t *n; edge_t *e; node_t *lastn = NULL; #ifndef WITH_CGRAPH graph_t *cg = agopen("cg", AGDIGRAPHSTRICT); #else graph_t *cg = agopen("cg", Agstrictdirected, NIL(Agdisc_t *)); agbindrec(cg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); // graph custom data #endif for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { #ifndef WITH_CGRAPH n = agnode(cg, agnameof(p->np)); /* FIX */ #else n = agnode(cg, agnameof(p->np), 1); /* FIX */ agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data #endif ND_alg(n) = p; p->cnode = n; alloc_elist(0, ND_in(n)); alloc_elist(0, ND_out(n)); if (lastn) { ND_next(lastn) = n; lastn = n; } else { lastn = GD_nlist(cg) = n; } } for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { for (nxp = (nitem *) dtlink(link, (Dtlink_t *) p); nxp; nxp = (nitem *) dtlink(list, (Dtlink_t *) nxp)) { e = NULL; if (intersect(p, nxp)) { double delta = dist(&p->bb, &nxp->bb); #ifndef WITH_CGRAPH e = agedge(cg, p->cnode, nxp->cnode); #else e = agedge(cg, p->cnode, nxp->cnode, NULL, 1); agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); // edge custom data #endif assert (delta <= 0xFFFF); ED_minlen(e) = delta; ED_weight(e) = 1; } if (e && agfindedge(g,p->np, nxp->np)) { ED_weight(e) = 100; } #if 0 if (agfindedge(g,p->np, nxp->np)) { if (e == NULL) e = agedge(cg, p->cnode, nxp->cnode); ED_weight(e) = 100; /* If minlen < SCALE, the nodes can't conflict or there's * an overlap but it will be removed in the orthogonal pass. * So we just keep the node's basically where they are. */ if (SCALE > ED_minlen(e)) ED_minlen(e) = SCALE; } #endif } } for (p = (nitem *) dtflatten(list); p; p = (nitem *) dtlink(list, (Dtlink_t *) p)) { n = p->cnode; for (e = agfstout(cg,n); e; e = agnxtout(cg,e)) { elist_append(e, ND_out(n)); elist_append(e, ND_in(aghead(e))); } } /* We could remove redundant constraints here. However, the cost of doing * this may be a good deal more than the time saved in network simplex. * Also, if the graph is changed, the ND_in and ND_out data has to be * updated. */ return cg; }
static void freeDeriveNode(node_t * n) { free(ND_alg(n)); free(ND_pos(n)); agdelrec(n, "Agnodeinfo_t"); }