/* twopi_layout: */ void twopi_layout(Agraph_t * g) { Agnode_t *ctr = 0; char *s; twopi_init_graph(g); s = agget(g, "root"); if (s && (*s != '\0')) { 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"); } } if (agnnodes(g)) { Agraph_t **ccs; Agraph_t *sg; Agnode_t *c = NULL; int ncc; int i; ccs = ccomps(g, &ncc, 0); if (ncc == 1) { circleLayout(g, ctr); 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]; if (ctr && agcontains(sg, ctr)) c = ctr; else c = 0; nodeInduce(sg); circleLayout(sg, c); 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); } dotneato_postprocess(g); }
static int process(Agraph_t * g, int gcnt) { Agnode_t *n; bcstate state; Agraph_t *blk; Agraph_t *tree; int bcnt; aginit(g, AGNODE, "info", sizeof(Agnodeinfo_t), TRUE); aginit(g, AGEDGE, "info", sizeof(Agedgeinfo_t), TRUE); aginit(g, AGRAPH, "info", sizeof(Agraphinfo_t), TRUE); state.count = 0; state.nComp = 0; state.stk = 0; state.blks = 0; for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (N(n) == 0) dfs(g, n, &state, 0); } for (blk = state.blks; blk; blk = NEXTBLK(blk)) { nodeInduce(blk, g); } if (external) { bcnt = 0; for (blk = state.blks; blk; blk = NEXTBLK(blk)) { gwrite(blk, gcnt, bcnt++); } } else gwrite(g, gcnt, 0); if (doTree) { tree = agopen("blkcut_tree", Agstrictundirected, 0); for (blk = state.blks; blk; blk = NEXTBLK(blk)) addCutPts(tree, blk); gwrite(tree, gcnt, -1); agclose(tree); } if (verbose) { int cuts = 0; bcnt = 0; for (blk = state.blks; blk; blk = NEXTBLK(blk)) bcnt++; for (n = agfstnode(g); n; n = agnxtnode(g, n)) if (Cut(n)) cuts++; fprintf(stderr, "%s: %d blocks %d cutpoints\n", agnameof(g), bcnt, cuts); } if (state.blks && NEXTBLK(state.blks)) return 1; /* >= 2 blocks */ else return 0; }
static int visit(Agnode_t *n, Agraph_t* map, Stack* sp, sccstate* st) { unsigned int m,min; Agnode_t* t; Agraph_t* subg; Agedge_t* e; min = ++(st->ID); setval(n,min); push (sp, n); for (e = agfstout(n); e; e = agnxtout(e)) { t = aghead(e); if (getval(t) == 0) m = visit(t,map,sp,st); else m = getval(t); if (m < min) min = m; } if (getval(n) == min) { if (!wantDegenerateComp && (top(sp) == n)) { setval(n,INF); pop(sp); } else { char name[32]; Agraph_t* G = agraphof(n);; sprintf(name,"cluster_%d",(st->Comp)++); subg = agsubg(G,name,TRUE); agbindrec(subg,"scc_graph",sizeof(Agraphinfo_t),TRUE); setrep(subg,agnode(map,name,TRUE)); do { t = pop(sp); agsubnode(subg,t,TRUE); setval(t,INF); setscc(t,subg); st->N_nodes_in_nontriv_SCC++; } while (t != n); nodeInduce(subg); if (!Silent) agwrite(subg,stdout); } } return min; }
int main (int argc, char* argv[]) { graph_t *g; graph_t *sg; FILE *fp; graph_t** cc; int i, ncc; GVC_t *gvc; gvc = gvContext(); if (argc > 1) fp = fopen(argv[1], "r"); else fp = stdin; g = agread(fp, 0); cc = ccomps(g, &ncc, (char*)0); for (i = 0; i < ncc; i++) { sg = cc[i]; nodeInduce (sg); gvLayout(gvc, sg, "neato"); } pack_graph (ncc, cc, g, 0); gvRender(gvc, g, "ps", stdout); for (i = 0; i < ncc; i++) { sg = cc[i]; gvFreeLayout(gvc, sg); agdelete(g, sg); } agclose(g); return (gvFreeContext(gvc)); }
static int visit(Agnode_t * n, Agraph_t * map, Stack * sp, sccstate * st) { unsigned int m, min; Agnode_t *t; Agraph_t *subg; Agedge_t *e; min = ++(st->ID); setval(n, min); push(sp, n); #ifdef USE_CGRAPH for (e = agfstout(n->root, n); e; e = agnxtout(n->root, e)) { #else for (e = agfstout(n); e; e = agnxtout(e)) { #endif t = aghead(e); if (getval(t) == 0) m = visit(t, map, sp, st); else m = getval(t); if (m < min) min = m; } if (getval(n) == min) { if (!wantDegenerateComp && (top(sp) == n)) { setval(n, INF); pop(sp); } else { char name[32]; Agraph_t *G = agraphof(n);; sprintf(name, "cluster_%d", (st->Comp)++); subg = agsubg(G, name, TRUE); agbindrec(subg, "scc_graph", sizeof(Agraphinfo_t), TRUE); setrep(subg, agnode(map, name, TRUE)); do { t = pop(sp); agsubnode(subg, t, TRUE); setval(t, INF); setscc(t, subg); st->N_nodes_in_nontriv_SCC++; } while (t != n); #ifdef USE_CGRAPH nodeInduce(subg, map); #else nodeInduce(subg); #endif if (!Silent) agwrite(subg, stdout); } } return min; } static int label(Agnode_t * n, int nodecnt, int *edgecnt) { Agedge_t *e; setval(n, 1); nodecnt++; #ifdef USE_CGRAPH for (e = agfstedge(n->root, n); e; e = agnxtedge(n->root, e, n)) { #else for (e = agfstedge(n); e; e = agnxtedge(e, n)) { #endif (*edgecnt) += 1; if (e->node == n) e = agopp(e); if (!getval(e->node)) nodecnt = label(e->node, nodecnt, edgecnt); } return nodecnt; } static int countComponents(Agraph_t * g, int *max_degree, float *nontree_frac) { int nc = 0; int sum_edges = 0; int sum_nontree = 0; int deg; int n_edges; int n_nodes; Agnode_t *n; #ifdef USE_CGRAPH for (n = agfstnode(g); n; n = agnxtnode(g, n)) { #else for (n = agfstnode(g); n; n = agnxtnode(n)) { #endif if (!getval(n)) { nc++; n_edges = 0; n_nodes = label(n, 0, &n_edges); sum_edges += n_edges; sum_nontree += (n_edges - n_nodes + 1); } } if (max_degree) { int maxd = 0; #ifdef USE_CGRAPH for (n = agfstnode(g); n; n = agnxtnode(g, n)) { deg = agdegree(g, n, TRUE, TRUE); #else for (n = agfstnode(g); n; n = agnxtnode(n)) { deg = agdegree(n, TRUE, TRUE); #endif if (maxd < deg) maxd = deg; setval(n, 0); } *max_degree = maxd; } if (nontree_frac) { if (sum_edges > 0) *nontree_frac = (float) sum_nontree / (float) sum_edges; else *nontree_frac = 0.0; } return nc; } static void process(Agraph_t * G) { Agnode_t *n; Agraph_t *map; int nc = 0; float nontree_frac = 0; int Maxdegree = 0; Stack stack; sccstate state; aginit(G, AGRAPH, "scc_graph", sizeof(Agraphinfo_t), TRUE); aginit(G, AGNODE, "scc_node", sizeof(Agnodeinfo_t), TRUE); state.Comp = state.ID = 0; state.N_nodes_in_nontriv_SCC = 0; if (Verbose) nc = countComponents(G, &Maxdegree, &nontree_frac); initStack(&stack, agnnodes(G) + 1); map = agopen("scc_map", Agdirected, (Agdisc_t *) 0); #ifdef USE_CGRAPH for (n = agfstnode(G); n; n = agnxtnode(G, n)) #else for (n = agfstnode(G); n; n = agnxtnode(n)) #endif if (getval(n) == 0) visit(n, map, &stack, &state); freeStack(&stack); if (!Silent) agwrite(map, stdout); agclose(map); if (Verbose) fprintf(stderr, "%d %d %d %d %.4f %d %.4f\n", agnnodes(G), agnedges(G), nc, state.Comp, state.N_nodes_in_nontriv_SCC / (double) agnnodes(G), Maxdegree, nontree_frac); else fprintf(stderr, "%d nodes, %d edges, %d strong components\n", agnnodes(G), agnedges(G), state.Comp); } static char *useString = "Usage: %s [-sdv?] <files>\n\ -s - silent\n\ -d - allow degenerate components\n\ -v - verbose\n\ -? - print usage\n\ If no files are specified, stdin is used\n"; static void usage(int v) { printf(useString, CmdName); exit(v); }
/* 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); }
void sfdp_layout(graph_t * g) { int doAdjust; adjust_data am; int hops = -1; sfdp_init_graph(g); doAdjust = (Ndim == 2); 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 || HAVE_TRIANGLE) graphAdjustMode(g, &am, "prism0"); #else graphAdjustMode(g, &am, 0); #endif if ((am.mode == AM_PRISM) && doAdjust) { doAdjust = 0; /* overlap removal done in sfpd */ ctrl->overlap = am.value; ctrl->initial_scaling = am.scaling; 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); } } else { /* Turn off overlap removal in sfdp if prism not used */ ctrl->overlap = -1; } ccs = ccomps(g, &ncc, 0); if (ncc == 1) { sfdpLayout(g, ctrl, hops, pad); if (doAdjust) removeOverlapWith(g, &am); spline_edges(g); } else { pack_info pinfo; getPackInfo(g, l_node, CL_OFFSET, &pinfo); pinfo.doSplines = 1; for (i = 0; i < ncc; i++) { sg = ccs[i]; nodeInduce(sg); sfdpLayout(sg, ctrl, hops, pad); if (doAdjust) removeOverlapWith(sg, &am); setEdgeType(sg, ET_LINE); spline_edges(sg); } 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); }