void class1(graph_t * g) { node_t *n, *t, *h; edge_t *e, *rep; mark_clusters(g); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { /* skip edges already processed */ if (ED_to_virt(e)) continue; /* skip edges that we want to ignore in this phase */ if (nonconstraint_edge(e)) continue; t = UF_find(agtail(e)); h = UF_find(aghead(e)); /* skip self, flat, and intra-cluster edges */ if (t == h) continue; /* inter-cluster edges require special treatment */ if (ND_clust(t) || ND_clust(h)) { interclust1(g, agtail(e), aghead(e), e); continue; } if ((rep = find_fast_edge(t, h))) merge_oneway(e, rep); else virtual_edge(t, h, e); #ifdef NOTDEF if ((t == agtail(e)) && (h == aghead(e))) { if (rep = find_fast_edge(t, h)) merge_oneway(e, rep); else virtual_edge(t, h, e); } else { f = agfindedge(g, t, h); if (f && (ED_to_virt(f) == NULL)) rep = virtual_edge(t, h, f); else rep = find_fast_edge(t, h); if (rep) merge_oneway(e, rep); else virtual_edge(t, h, e); } #endif } } }
void prTree(Agraph_t * g) { Agnode_t *n; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (TPARENT(n)) fprintf(stderr, "%s -> %s\n", n->name, TPARENT(n)->name); } }
int agnedges(Agraph_t * g) { Agnode_t *n; int rv = 0; for (n = agfstnode(g); n; n = agnxtnode(n)) rv += agdegree(n, FALSE, TRUE); /* must use OUT to get self-arcs */ return rv; }
static void closeGraph(graph_t * cg) { node_t *n; for (n = agfstnode(cg); n; n = agnxtnode(cg, n)) { free_list(ND_in(n)); free_list(ND_out(n)); } agclose(cg); }
/* place_residual_nodes: * Add nodes not in list to list. */ static void place_residual_nodes(Agraph_t * g, nodelist_t * list) { Agnode_t *n; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (!ONPATH(n)) place_node(g, n, list); } }
/* 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; }
static void add_edge_attr(Agraph_t * g, Agsym_t * attr) { Agnode_t *n; Agedge_t *e; Agproto_t *proto; for (n = agfstnode(g); n; n = agnxtnode(g, n)) for (e = agfstout(g, n); e; e = agnxtout(g, e)) obj_init_attr(e, attr); if (g->meta_node) { for (n = agfstnode(g->meta_node->graph); n; n = agnxtnode(g->meta_node->graph, n)) for (proto = agusergraph(n)->proto; proto; proto = proto->prev) obj_init_attr(proto->e, attr); } else for (proto = g->proto; proto; proto = proto->prev) obj_init_attr(proto->e, attr); }
//----------------------------------------------------------------------------- // own graph display function (no need to traverse the whole tree for the map // so this should replace dotneato_write_one( G ); void MapCodegenState::display( graph_t *pGraph ) { box tmpbox; point tmppnt; begin_graph(pGraph, tmpbox , tmppnt ); for (Agnode_t *node = agfstnode(pGraph); node!=NULL; node = agnxtnode(pGraph,node)) { begin_node( node ); } end_graph(); }
/* undoClusterEdges: * Replace cluster nodes with originals. Make sure original has * no attributes. Replace original edges. Delete cluster nodes, * which will also delete cluster edges. */ void undoClusterEdges(graph_t * g) { node_t *n; edge_t *e; graph_t *clg; clg = agsubg(g, "__clusternodes",1); agbindrec(clg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { undoCompound(e, clg); } } for (n = agfstnode(clg); n; n = agnxtnode(clg, n)) { agdelete(g, n); } agclose(clg); }
static void flat_edges(Agraph_t *clust) { #ifdef NOTDEF for (n = agfstnode(clust); n; n = agnxtnode(clust)) { for (e = agfstedge(root,n); e; e = agnxtedge(root,e,n)) { } } ordered_edges(); #endif }
/* fillList: * Add nodes to deg_list, which stores them by degree. */ static deglist_t *getList(Agraph_t * g) { deglist_t *dl = mkDeglist(); Agnode_t *n; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { insertDeglist(dl, n); } return dl; }
/* scan_graph_mode: * Prepare the graph and data structures depending on the layout mode. * If Reduce is true, eliminate singletons and trees. Since G may be a * subgraph, we remove the nodes from the root graph. * Return the number of nodes in the reduced graph. */ int scan_graph_mode(graph_t * G, int mode) { int i, lenx, nV, nE, deg; char *str; node_t *np, *xp, *other; double total_len = 0.0; if (Verbose) fprintf(stderr, "Scanning graph %s, %d nodes\n", G->name, agnnodes(G)); /* Eliminate singletons and trees */ if (Reduce) { for (np = agfstnode(G); np; np = xp) { xp = agnxtnode(G, np); deg = degreeKind(G, np, &other); if (deg == 0) { /* singleton node */ agdelete(G->root, np); } else if (deg == 1) { agdelete(G->root, np); xp = prune(G, other, xp); } } } nV = agnnodes(G); nE = agnedges(G); lenx = agindex(G->root->proto->e, "len"); if (mode == MODE_KK) { Epsilon = .0001 * nV; getdouble(G, "epsilon", &Epsilon); if ((str = agget(G->root, "Damping"))) Damping = atof(str); else Damping = .99; GD_neato_nlist(G) = N_NEW(nV + 1, node_t *); for (i = 0, np = agfstnode(G); np; np = agnxtnode(G, np)) { GD_neato_nlist(G)[i] = np; ND_id(np) = i++; ND_heapindex(np) = -1; total_len += setEdgeLen(G, np, lenx); } } else {
/* nodesToClusters: * If dummy nodes belong to a cluster, add them. */ void nodesToClusters(Agraph_t* g) { Agnode_t* v; Agraph_t* c; for (v = agfstnode(g); v; v = agnxtnode(g, v)) { if ((c = MND_highCluster(v))) agsubnode(c,v,1); /*i hope this routine is optimized!*/ } }
void neato_init_node_edge(graph_t * g) { node_t *n; edge_t *e; int nG = agnnodes(g); attrsym_t *N_pin; N_pos = agfindattr(g->proto->n, "pos"); N_pin = agfindattr(g->proto->n, "pin"); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); user_pos(N_pos, N_pin, n, nG); /* set user position if given */ } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) neato_init_edge(e); } }
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); } } }
/* * attach and install edges between clusters. * essentially, class2() for interclust edges. */ void interclexp(graph_t* subg) { graph_t *g; node_t *n; edge_t *e,*prev; g = subg->root; for (n = agfstnode(subg); n; n = agnxtnode(subg,n)) { /* N.B. n may be in a sub-cluster of subg */ prev = NULL; for (e = agfstedge(subg->root,n); e; e = agnxtedge(subg->root,e,n)) { if (agcontains(subg,e)) continue; /* short/flat multi edges */ if (mergeable(prev,e)) { if (e->tail->u.rank == e->head->u.rank) e->u.to_virt = prev; else e->u.to_virt = NULL; if (prev->u.to_virt == NULL) continue; /* internal edge */ merge_chain(subg,e,prev->u.to_virt,FALSE); safe_other_edge(e); continue; } /* flat edges */ if (e->tail->u.rank == e->head->u.rank) { if (find_flat_edge(e->tail,e->head) == NULL) { flat_edge(g,e); prev = e; } else prev = NULL; continue; } assert (e->u.to_virt != NULL); /* forward edges */ if (e->head->u.rank > e->tail->u.rank) { make_interclust_chain(g,e->tail,e->head,e); prev = e; continue; } /* backward edges */ else { /* I think that make_interclust_chain should create call other_edge(e) anyway if (agcontains(subg,e->tail) && agfindedge(subg->root,e->head,e->tail)) other_edge(e); */ make_interclust_chain(g,e->head,e->tail,e); prev = e; } } } }
static void saveVirtualEdges(graph_t *g) { edge_t *e; node_t *n; int cnt = 0; int lc; if (virtualEdgeHeadList != NULL) { free(virtualEdgeHeadList); } if (virtualEdgeTailList != NULL) { free(virtualEdgeTailList); } /* allocate memory */ for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (lc = 0; lc < ND_in(n).size; lc++) { e = ND_in(n).list[lc]; if (ED_edge_type(e) == VIRTUAL) cnt++; } } nVirtualEdges = cnt; virtualEdgeHeadList = N_GNEW(cnt, node_t*); virtualEdgeTailList = N_GNEW(cnt, node_t*); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (lc = 0, cnt = 0; lc < ND_in(n).size; lc++) { e = ND_in(n).list[lc]; if (ED_edge_type(e) == VIRTUAL) { virtualEdgeHeadList[cnt] = e->head; virtualEdgeTailList[cnt] = e->tail; if (Verbose) printf("saved virtual edge: %s->%s\n", virtualEdgeTailList[cnt]->name, virtualEdgeHeadList[cnt]->name); cnt++; } } } }
static void deleteGraphNodes(gctx_t * gctx, Agraph_t *g) { Agnode_t *n, *n1; n = agfstnode(g); while (n) { n1 = agnxtnode(g, n); deleteNode(gctx, g, n); n = n1; } }
static void add_graph_attr(Agraph_t * g, Agsym_t * attr) { Agnode_t *n; if (g->meta_node) { for (n = agfstnode(g->meta_node->graph); n; n = agnxtnode(g->meta_node->graph, n)) obj_init_attr(agusergraph(n), attr); } else obj_init_attr(g, attr); }
static void write_graph(Agraph_t * g, GVJ_t * job, int top, state_t* sp) { Agnode_t* np; Agedge_t* ep; int ncnt = 0; int ecnt = 0; int sgcnt = 0; int has_subgs; Dt_t* map; if (top) { map = dtopen (&intDisc, Dtoset); aginit(g, AGNODE, ID, sizeof(gvid_t), FALSE); aginit(g, AGEDGE, ID, sizeof(gvid_t), FALSE); aginit(g, AGRAPH, ID, -((int)sizeof(gvid_t)), FALSE); sgcnt = label_subgs(g, sgcnt, map); for (np = agfstnode(g); np; np = agnxtnode(g,np)) { if (IS_CLUSTER(np)) { ND_gid(np) = lookup(map, agnameof(np)); } else { ND_gid(np) = sgcnt + ncnt++; } for (ep = agfstout(g, np); ep; ep = agnxtout(g,ep)) { ED_gid(ep) = ecnt++; } } dtclose(map); } indent(job, sp->Level++); gvputs(job, "{\n"); write_hdr(g, job, top, sp); write_attrs((Agobj_t*)g, job, sp); if (top) { gvputs(job, ",\n"); indent(job, sp->Level); gvprintf(job, "\"_subgraph_cnt\": %d", sgcnt); } else { gvputs(job, ",\n"); indent(job, sp->Level); gvprintf(job, "\"_gvid\": %d", GD_gid(g)); } has_subgs = write_subgs(g, job, top, sp); write_nodes (g, job, top, has_subgs, sp); write_edges (g, job, top, sp); gvputs(job, "\n"); sp->Level--; indent(job, sp->Level); if (top) gvputs(job, "}\n"); else gvputs(job, "}"); }
static void transform(Agraph_t * g) { Agnode_t *n; Agedge_t *e; char *str; Agsym_t *m_ix, *s_ix; int cnt, d; m_ix = bindedgeattr(g, "minlen"); s_ix = bindedgeattr(g, "style"); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { d = myindegree(n) + myoutdegree(n); if (d == 0) { if (ChainLimit < 1) continue; if (ChainNode) { e = agedge(g, ChainNode, n, "", TRUE); agxset(e, s_ix, "invis"); ChainSize++; if (ChainSize < ChainLimit) ChainNode = n; else { ChainNode = NULL; ChainSize = 0; } } else ChainNode = n; } else if (d > 1) { if (MaxMinlen < 1) continue; cnt = 0; for (e = agfstin(g, n); e; e = agnxtin(g, e)) { if (isleaf(agtail(e))) { str = agxget(e, m_ix); if (str[0] == 0) { adjustlen(e, m_ix, (cnt % MaxMinlen) + 1); cnt++; } } } cnt = 0; for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (isleaf(e->node) || (Do_fans && ischainnode(e->node))) { str = agxget(e, m_ix); if (str[0] == 0) adjustlen(e, m_ix, (cnt % MaxMinlen) + 1); cnt++; } } } } }
static int write_edges(Agraph_t * g, GVJ_t * job, int top, state_t* sp) { Agnode_t* np; Agedge_t* ep; int not_first = 0; np = agfstnode(g); if (!np) return 0; ep = NULL; /* find a first edge */ for (; np; np = agnxtnode(g,np)) { for (ep = agfstout(g, np); ep; ep = agnxtout(g,ep)) { if (ep) break; } if (ep) break; } if (!ep) return 0; gvputs(job, ",\n"); indent(job, sp->Level++); gvputs(job, "\"edges\": [\n"); if (!top) indent(job, sp->Level); for (; np; np = agnxtnode(g,np)) { for (ep = agfstout(g, np); ep; ep = agnxtout(g,ep)) { if (not_first) if (top) gvputs(job, ",\n"); else gvputs(job, ","); else not_first = 1; write_edge(ep, job, top, sp); } } sp->Level--; gvputs(job, "\n"); indent(job, sp->Level); gvputs(job, "]"); return 1; }
/* cloneSubg: * Clone subgraph sg in tgt. */ static Agraph_t *cloneSubg(Agraph_t * tgt, Agraph_t * g) { Agraph_t *ng; Agraph_t *sg; Agnode_t *t; Agnode_t *newt; Agnode_t *newh; Agedge_t *e; Agedge_t *newe; ng = (Agraph_t *) (copy(tgt, OBJ(g))); if (!ng) return 0; for (t = agfstnode(g); t; t = agnxtnode(t)) { newt = agnode(tgt, agnameof(t), 0); if (!newt) error(ERROR_PANIC, "node %s not found in cloned graph %s", agnameof(t), agnameof(tgt)); agsubnode(ng, newt, 1); } for (t = agfstnode(g); t; t = agnxtnode(t)) { newt = agnode(tgt, agnameof(t), 0); for (e = agfstout(t); e; e = agnxtout(e)) { newh = agnode(tgt, agnameof(aghead(e)), 0); newe = agedge(newt, newh, agnameof(e), 0); if (!newe) error(ERROR_PANIC, "edge (%s,%s)[%s] not found in cloned graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(e), agnameof(tgt)); agsubedge(ng, newe, 1); } } for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(ng, sg)) { error(ERROR_FATAL, "error cloning subgraph %s from graph %s", agnameof(sg), agnameof(g)); } } return ng; }
/* create_block_tree: * Construct block tree by peeling nodes from block list in state. * When done, return root. The block list is empty * FIX: use largest block as root */ block_t *createBlocktree(Agraph_t * g, circ_state * state) { block_t *bp; block_t *next; block_t *root; int min; /* int ordercnt; */ find_blocks(g, state); bp = state->bl.first; /* if root chosen, will be first */ /* Otherwise, just pick first as root */ root = bp; /* Find node with minimum VAL value to find parent block */ /* FIX: Should be some way to avoid search below. */ /* ordercnt = state->orderCount; */ for (bp = bp->next; bp; bp = next) { Agnode_t *n; Agnode_t *parent; Agnode_t *child; Agraph_t *subg = bp->sub_graph; child = n = agfstnode(subg); min = VAL(n); parent = PARENT(n); for (n = agnxtnode(subg, n); n; n = agnxtnode(subg, n)) { if (VAL(n) < min) { child = n; min = VAL(n); parent = PARENT(n); } } SET_PARENT(parent); CHILD(bp) = child; next = bp->next; /* save next since list insertion destroys it */ appendBlock(&(BLOCK(parent)->children), bp); } initBlocklist(&state->bl); /* zero out list */ return root; }
static void rebuild_vlists(graph_t * g) { int c, i, r, maxi; node_t *n, *lead; edge_t *e, *rep; for (r = GD_minrank(g); r <= GD_maxrank(g); r++) GD_rankleader(g)[r] = NULL; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { infuse(g, n); for (e = agfstout(g, n); e; e = agnxtout(g, e)) { for (rep = e; ED_to_virt(rep); rep = ED_to_virt(rep)); while (ND_rank(rep->head) < ND_rank(e->head)) { infuse(g, rep->head); rep = ND_out(rep->head).list[0]; } } } for (r = GD_minrank(g); r <= GD_maxrank(g); r++) { lead = GD_rankleader(g)[r]; if (ND_rank(g->root)[r].v[ND_order(lead)] != lead) abort(); GD_rank(g)[r].v = ND_rank(g->root)[r].v + GD_rankleader(g)[r]->u.order; maxi = -1; for (i = 0; i < GD_rank(g)[r].n; i++) { if ((n = GD_rank(g)[r].v[i]) == NULL) break; if (ND_node_type(n) == NORMAL) { if (agcontains(g, n)) maxi = i; else break; } else { edge_t *e; for (e = ND_in(n).list[0]; e && ED_to_orig(e); e = ED_to_orig(e)); if (e && (agcontains(g, e->tail)) && agcontains(g, e->head)) maxi = i; } } if (maxi == -1) agerr(AGWARN, "degenerate concentrated rank %s,%d\n", g->name, r); GD_rank(g)[r].n = maxi + 1; } for (c = 1; c <= GD_n_cluster(g); c++) rebuild_vlists(GD_clust(g)[c]); }
/* When there are edge labels, extra ranks are reserved here for the virtual * nodes of the labels. This is done by doubling the input edge lengths. * The input rank separation is adjusted to compensate. */ void edgelabel_ranks(graph_t* g) { node_t *n; edge_t *e; if (GD_has_labels(g)&EDGE_LABEL) { for (n = agfstnode(g); n; n = agnxtnode(g,n)) for (e = agfstout(g,n); e; e = agnxtout(g,e)) ED_minlen(e) *= 2; GD_ranksep(g) = (GD_ranksep(g) + 1) / 2; } }
void mark_lowclusters(graph_t* g) { node_t *n; graph_t *clust; int c; for (n = agfstnode(g); n; n = agnxtnode(g,n)) n->u.clust = g; for (c = 1; c <= g->u.n_cluster; c++) { clust = g->u.clust[c]; mark_lowclusters(clust); } }
static void sfdp_init_node_edge(graph_t * g) { node_t *n; edge_t *e; #if 0 int nnodes = agnnodes(g); attrsym_t *N_pos = agfindnodeattr(g, "pos"); #endif for (n = agfstnode(g); n; n = agnxtnode(g, n)) { neato_init_node(n); #if 0 FIX so that user positions works with multiscale user_pos(N_pos, NULL, n, nnodes); #endif } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) sfdp_init_edge(e); } }
void GraphvizPlotter::parseNodes(Agraph_t *g, GraphComponent *g_component, processedProperties *props) { Agnode_t *n = agfstnode(g); // prochazim vsechny vrcholy while (n) { // pokud byl tento vrchol uz zpracovan, preskocime if (isWalkedObject(n, &props->nodes)) { n = agnxtnode(g, n); continue; } // pokud vrchol jeste nebyl zpracovan, vytvorime novy vrchol Node *node = g_component->addNode(agnameof(n)); // k tomuto vrcholu pridame i jeho atributy parseNodeAttrs(n, node, props); // pridame mezi zpracovane props->nodes.push_back(n); // nacteme dalsi n = agnxtnode(g, n); } }
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); } } }