/* dfs: * Return the number of reversed edges for this component. */ static int dfs(Agraph_t * g, Agnode_t * t, int hasCycle) { Agedge_t *e; Agedge_t *f; Agnode_t *h; ND_mark(t) = 1; ND_onstack(t) = 1; for (e = agfstout(g, t); e; e = f) { f = agnxtout(g, e); if (agtail(e) == aghead(e)) continue; h = aghead(e); if (ND_onstack(h)) { if (agisstrict(g)) { if (agedge(g, h, t, 0, 0) == 0) addRevEdge(g, e); } else { char* key = agnameof (e); if (!key || (agedge(g, h, t, key, 0) == 0)) addRevEdge(g, e); } agdelete(g, e); hasCycle = 1; } else if (ND_mark(h) == 0) hasCycle |= dfs(g, h, hasCycle); } ND_onstack(t) = 0; return hasCycle; }
/* To ensure that min and max rank nodes always have the intended rank * assignment, reverse any incompatible edges. */ static point minmax_edges(graph_t * g) { node_t *n; edge_t *e; point slen; slen.x = slen.y = 0; if ((GD_maxset(g) == NULL) && (GD_minset(g) == NULL)) return slen; if (GD_minset(g) != NULL) GD_minset(g) = UF_find(GD_minset(g)); if (GD_maxset(g) != NULL) GD_maxset(g) = UF_find(GD_maxset(g)); if ((n = GD_maxset(g))) { slen.y = (ND_ranktype(GD_maxset(g)) == SINKRANK); while ((e = ND_out(n).list[0])) { assert(aghead(e) == UF_find(aghead(e))); reverse_edge(e); } } if ((n = GD_minset(g))) { slen.x = (ND_ranktype(GD_minset(g)) == SOURCERANK); while ((e = ND_in(n).list[0])) { assert(agtail(e) == UF_find(agtail(e))); reverse_edge(e); } } return slen; }
void remove_child(Agraph_t * graph, Agnode_t * node) { Agedge_t *edge; Agedge_t *nexte; /* Avoid cycles */ if MARKED (node) return; MARK(node); /* Skip nodes with more than one parent */ edge = agfstin(node); if (edge && (agnxtin(edge) != NULL)) { UNMARK(node); return; } /* recursively remove children */ for (edge = agfstout(node); edge; edge = nexte) { nexte = agnxtout(edge); if (aghead(edge) != node) { if (verbose) fprintf(stderr, "Processing descendant: %s\n", agnameof(aghead(edge))); remove_child(graph, aghead(edge)); agdeledge(edge); } } agdelnode(node); return; }
static int dfs(Agnode_t * n, Agedge_t * link, int warn) { Agedge_t *e; Agedge_t *f; Agraph_t *g = agrootof(n); MARK(n) = 1; for (e = agfstin(g, n); e; e = f) { f = agnxtin(g, e); if (e == link) continue; if (MARK(agtail(e))) agdelete(g, e); } for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (MARK(aghead(e))) { if (!warn) { warn++; fprintf(stderr, "warning: %s has cycle(s), transitive reduction not unique\n", agnameof(g)); fprintf(stderr, "cycle involves edge %s -> %s\n", agnameof(agtail(e)), agnameof(aghead(e))); } } else warn = dfs(aghead(e), AGOUT2IN(e), warn); } MARK(n) = 0; return warn; }
static void dfs(Agraph_t * g, Agnode_t * u, bcstate * stp, Agnode_t * parent) { Agnode_t *v; Agedge_t *e; Agedge_t *ep; Agraph_t *sg; stp->count++; Low(u) = N(u) = stp->count; for (e = agfstedge(g, u); e; e = agnxtedge(g, e, u)) { if ((v = aghead(e)) == u) v = agtail(e); if (v == u) continue; if (N(v) == 0) { push(&stp->stk, e); dfs(g, v, stp, u); Low(u) = min(Low(u), Low(v)); if (Low(v) >= N(u)) { /* u is an articulation point */ Cut(u) = 1; sg = mkBlock(g, stp); do { ep = pop(&stp->stk); agsubnode(sg, aghead(ep), 1); agsubnode(sg, agtail(ep), 1); } while (ep != e); } } else if (parent != v) { Low(u) = min(Low(u), N(v)); if (N(v) < N(u)) push(&stp->stk, e); } } }
aresta_t add_aresta(grafo g, vertice_t v, Agnode_t *v_cgraph, Agedge_t *a){ aresta_t nova_aresta; Agnode_t * vertice_dest; char *peso; // aloca aresta nova_aresta = (aresta_t) malloc(sizeof(struct aresta_t)); // insere aresta na fila nova_aresta->next = v->aresta; v->aresta = nova_aresta; // seta peso peso = agget(a, (char *)"peso"); if ( peso && *peso ) { nova_aresta->peso = atof(peso); g->peso = 1; } else nova_aresta->peso = PESO_DEFAULT; // seta ponteiro da aresta para vertice if (!strcmp(agnameof(v_cgraph), agnameof(aghead(a))) ) vertice_dest = agtail(a); else vertice_dest = aghead(a); nova_aresta->vertice = get_vertice(vertice_dest); return nova_aresta; }
static char *nameOf(void *obj, agxbuf * xb) { Agedge_t *ep; switch (agobjkind(obj)) { #ifndef WITH_CGRAPH case AGGRAPH: #else case AGRAPH: #endif agxbput(xb, agnameof(((Agraph_t *) obj))); break; case AGNODE: agxbput(xb, agnameof(((Agnode_t *) obj))); break; case AGEDGE: ep = (Agedge_t *) obj; agxbput(xb, agnameof(agtail(ep))); agxbput(xb, agnameof(aghead(ep))); if (agisdirected(agraphof(aghead(ep)))) agxbput(xb, "->"); else agxbput(xb, "--"); break; } return agxbuse(xb); }
/* finishEdge: * Finish edge generation, clipping to nodes and adding arrowhead * if necessary, and adding edge labels */ static void finishEdge (graph_t* g, edge_t* e, Ppoly_t spl, int flip, pointf p, pointf q) { int j; pointf *spline = N_GNEW(spl.pn, pointf); pointf p1, q1; if (flip) { for (j = 0; j < spl.pn; j++) { spline[spl.pn - 1 - j] = spl.ps[j]; } p1 = q; q1 = p; } else { for (j = 0; j < spl.pn; j++) { spline[j] = spl.ps[j]; } p1 = p; q1 = q; } if (Verbose > 1) fprintf(stderr, "spline %s %s\n", agnameof(agtail(e)), agnameof(aghead(e))); clip_and_install(e, aghead(e), spline, spl.pn, &sinfo); free(spline); addEdgeLabels(g, e, p1, q1); }
/* getPath * Construct the shortest path from one endpoint of e to the other. * The obstacles and their number are given by obs and npoly. * vconfig is a precomputed data structure to help in the computation. * If chkPts is true, the function finds the polygons, if any, containing * the endpoints and tells the shortest path computation to ignore them. * Assumes this info is set in ND_lim, usually from _spline_edges. * Returns the shortest path. */ Ppolyline_t getPath(edge_t * e, vconfig_t * vconfig, int chkPts, Ppoly_t ** obs, int npoly) { Ppolyline_t line; int pp, qp; Ppoint_t p, q; p = add_pointf(ND_coord(agtail(e)), ED_tail_port(e).p); q = add_pointf(ND_coord(aghead(e)), ED_head_port(e).p); /* determine the polygons (if any) that contain the endpoints */ pp = qp = POLYID_NONE; if (chkPts) { pp = ND_lim(agtail(e)); qp = ND_lim(aghead(e)); /* for (i = 0; i < npoly; i++) { if ((pp == POLYID_NONE) && in_poly(*obs[i], p)) pp = i; if ((qp == POLYID_NONE) && in_poly(*obs[i], q)) qp = i; } */ } Pobspath(vconfig, p, pp, q, qp, &line); return line; }
static void adjust_anchors(Agraph_t* g, int* anchors, int k, mat z) { int i, j; double* centroid = (double*) malloc(sizeof(double)*z->c); for(i = 0; i < k; i++) { Agnode_t* n = get_node(anchors[i]); Agedge_t* e; int degree = 0; for(j = 0; j < z->c; j++) { centroid[j] = 0; } for(e = agfstedge(g,n); e; e = agnxtedge(g,e,n)) { int v = (n == aghead(e)) ? getid(agtail(e)) : getid(aghead(e)); for(j = 0; j < z->c; j++) { centroid[j] += z->m[mindex(v,j,z)]; } degree++; } for(j = 0; j < z->c; j++) { if(degree != 0) centroid[j] /= degree; z->m[mindex(anchors[i],j,z)] = centroid[j]; } } free(centroid); }
static int debugleveln(edge_t* realedge, int i) { return (GD_showboxes(agraphof(aghead(realedge))) == i || GD_showboxes(agraphof(agtail(realedge))) == i || ED_showboxes(realedge) == i || ND_showboxes(aghead(realedge)) == i || ND_showboxes(agtail(realedge)) == i); }
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 mark_lowclusters(Agraph_t * root) { Agnode_t *n, *vn; Agedge_t *orig, *e; /* first, zap any previous cluster labelings */ for (n = agfstnode(root); n; n = agnxtnode(root, n)) { ND_clust(n) = NULL; for (orig = agfstout(root, n); orig; orig = agnxtout(root, orig)) { if ((e = ED_to_virt(orig))) { #ifndef WITH_CGRAPH while (e && (vn = e->head)->u.node_type == VIRTUAL) { #else /* WITH_CGRAPH */ while (e && (ND_node_type(vn = aghead(e))) == VIRTUAL) { #endif /* WITH_CGRAPH */ ND_clust(vn) = NULL; e = ND_out(aghead(e)).list[0]; } } } } /* do the recursion */ mark_lowcluster_basic(root); } static void mark_lowcluster_basic(Agraph_t * g) { Agraph_t *clust; Agnode_t *n, *vn; Agedge_t *orig, *e; int c; for (c = 1; c <= GD_n_cluster(g); c++) { clust = GD_clust(g)[c]; mark_lowcluster_basic(clust); } /* see what belongs to this graph that wasn't already marked */ for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (ND_clust(n) == NULL) ND_clust(n) = g; for (orig = agfstout(g, n); orig; orig = agnxtout(g, orig)) { if ((e = ED_to_virt(orig))) { #ifndef WITH_CGRAPH while (e && (vn = e->head)->u.node_type == VIRTUAL) { #else /* WITH_CGRAPH */ while (e && (ND_node_type(vn = aghead(e))) == VIRTUAL) { #endif /* WITH_CGRAPH */ if (ND_clust(vn) == NULL) ND_clust(vn) = g; e = ND_out(aghead(e)).list[0]; } } } } }
bool rm(Agedge_t *e) { if (!e) return false; // removal of the protoedge is not permitted if ((agnameof(aghead(e))[0] == '\001' && strcmp (agnameof(aghead(e)), "\001proto") == 0) || (agnameof(agtail(e))[0] == '\001' && strcmp (agnameof(agtail(e)), "\001proto") == 0)) return false; agdelete(agroot(agraphof(aghead(e))), e); return true; }
/* cloneSubg: * Clone subgraph sg in tgt. */ static Agraph_t *cloneSubg(Agraph_t * tgt, Agraph_t * g, Dt_t* emap) { Agraph_t *ng; Agraph_t *sg; Agnode_t *t; Agnode_t *newt; Agedge_t *e; Agedge_t *newe; char* name; ng = (Agraph_t *) (copy(tgt, OBJ(g))); if (!ng) return 0; for (t = agfstnode(g); t; t = agnxtnode(g, t)) { newt = agnode(tgt, agnameof(t), 0); if (!newt) { exerror("node %s not found in cloned graph %s", agnameof(t), agnameof(tgt)); return 0; } else agsubnode(ng, newt, 1); } for (t = agfstnode(g); t; t = agnxtnode(g, t)) { for (e = agfstout(g, t); e; e = agnxtout(g, e)) { newe = mapEdge (emap, e); if (!newe) { name = agnameof(AGMKOUT(e)); if (name) exerror("edge (%s,%s)[%s] not found in cloned graph %s", agnameof(agtail(e)), agnameof(aghead(e)), name, agnameof(tgt)); else exerror("edge (%s,%s) not found in cloned graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(tgt)); return 0; } else agsubedge(ng, newe, 1); } } for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(ng, sg, emap)) { exerror("error cloning subgraph %s from graph %s", agnameof(sg), agnameof(g)); return 0; } } return ng; }
/* makePolyline: */ static void makePolyline(graph_t* g, edge_t * e) { Ppolyline_t spl, line = ED_path(e); Ppoint_t p0, q0; p0 = line.ps[0]; q0 = line.ps[line.pn - 1]; make_polyline (line, &spl); if (Verbose > 1) fprintf(stderr, "polyline %s %s\n", agnameof(agtail(e)), agnameof(aghead(e))); clip_and_install(e, aghead(e), spl.ps, spl.pn, &sinfo); addEdgeLabels(g, e, p0, q0); }
static void undoCompound(edge_t * e, graph_t * clg) { node_t *t = agtail(e); node_t *h = aghead(e); node_t *ntail; node_t *nhead; edge_t* ce; if (!(IS_CLUST_NODE(t) || IS_CLUST_NODE(h))) return; ntail = mapN(t, clg); nhead = mapN(h, clg); ce = cloneEdge(e, ntail, nhead); /* transfer drawing information */ ED_spl(ce) = ED_spl(e); ED_spl(e) = NULL; ED_label(ce) = ED_label(e); ED_label(e) = NULL; ED_xlabel(ce) = ED_xlabel(e); ED_xlabel(e) = NULL; ED_head_label(ce) = ED_head_label(e); ED_head_label(e) = NULL; ED_tail_label(ce) = ED_tail_label(e); ED_tail_label(e) = NULL; gv_cleanup_edge(e); }
static void dot_init_edge(edge_t * e) { char *tailgroup, *headgroup; #ifdef WITH_CGRAPH agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); //graph custom data #endif /* WITH_CGRAPH */ common_init_edge(e); ED_weight(e) = late_double(e, E_weight, 1.0, 0.0); tailgroup = late_string(agtail(e), N_group, ""); headgroup = late_string(aghead(e), N_group, ""); ED_count(e) = ED_xpenalty(e) = 1; if (tailgroup[0] && (tailgroup == headgroup)) { ED_xpenalty(e) = CL_CROSS; ED_weight(e) *= 100; } if (nonconstraint_edge(e)) { ED_xpenalty(e) = 0; ED_weight(e) = 0; } ED_showboxes(e) = late_int(e, E_showboxes, 0, 0); ED_minlen(e) = late_int(e, E_minlen, 1, 0); }
/* 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; } } } }
/* insertEdge: */ static void insertEdge(Dt_t * map, void *t, void *h, edge_t * e) { item dummy; dummy.p[0] = t; dummy.p[1] = h; dummy.t = agtail(e); dummy.h = aghead(e); dtinsert(map, &dummy); dummy.p[0] = h; dummy.p[1] = t; dummy.t = aghead(e); dummy.h = agtail(e); dtinsert(map, &dummy); }
grafo le_grafo(FILE *input){ if (!input) return NULL; Agraph_t *Ag = agread(input, NULL); if(!Ag) return NULL; grafo g = cria_grafo(agnameof(Ag), agisdirected(Ag), contem_pesos(Ag), agnnodes(Ag)); for (Agnode_t *Av=agfstnode(Ag); Av; Av=agnxtnode(Ag,Av)) { cria_vertice(g, agnameof(Av)); } for (Agnode_t *Av=agfstnode(Ag); Av; Av=agnxtnode(Ag,Av)) { for (Agedge_t *Ae=agfstout(Ag,Av); Ae; Ae=agnxtout(Ag,Ae)) { vertice u = v_busca(g, agnameof(agtail(Ae))); vertice v = v_busca(g, agnameof(aghead(Ae))); cria_vizinhanca(g, u, v, get_peso(Ae)); } } agclose(Ag); agfree(Ag, NULL); return g; }
/* cloneGraph: * Clone node, edge and subgraph structure from src to tgt. */ static void cloneGraph(Agraph_t * tgt, Agraph_t * src) { Agedge_t *e; Agnode_t *t; Agraph_t *sg; for (t = agfstnode(src); t; t = agnxtnode(t)) { if (!copy(tgt, OBJ(t))) { error(ERROR_FATAL, "error cloning node %s from graph %s", agnameof(t), agnameof(src)); } } for (t = agfstnode(src); t; t = agnxtnode(t)) { for (e = agfstout(t); e; e = agnxtout(e)) { if (!copy(tgt, OBJ(e))) { error(ERROR_FATAL, "error cloning edge (%s,%s)[%s] from graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(e), agnameof(src)); } } } for (sg = agfstsubg(src); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(tgt, sg)) { error(ERROR_FATAL, "error cloning subgraph %s from graph %s", agnameof(sg), agnameof(src)); } } }
static void node_induce(graph_t * par, graph_t * g) { node_t *n, *nn; edge_t *e; int i; /* enforce that a node is in at most one cluster at this level */ for (n = agfstnode(g); n; n = nn) { nn = agnxtnode(g, n); if (ND_ranktype(n)) { agdelete(g, n); continue; } for (i = 1; i < GD_n_cluster(par); i++) if (agcontains(GD_clust(par)[i], n)) break; if (i < GD_n_cluster(par)) agdelete(g, n); ND_clust(n) = NULL; } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(dot_root(g), n); e; e = agnxtout(dot_root(g), e)) { if (agcontains(g, aghead(e))) agsubedge(g,e,1); } } }
static void map_edge(edge_t * e) { int j, k; bezier bz; if (ED_spl(e) == NULL) { if ((Concentrate == FALSE) && (ED_edge_type(e) != IGNORED)) agerr(AGERR, "lost %s %s edge\n", agnameof(agtail(e)), agnameof(aghead(e))); return; } for (j = 0; j < ED_spl(e)->size; j++) { bz = ED_spl(e)->list[j]; for (k = 0; k < bz.size; k++) bz.list[k] = map_point(bz.list[k]); if (bz.sflag) ED_spl(e)->list[j].sp = map_point(ED_spl(e)->list[j].sp); if (bz.eflag) ED_spl(e)->list[j].ep = map_point(ED_spl(e)->list[j].ep); } if (ED_label(e)) ED_label(e)->pos = map_point(ED_label(e)->pos); if (ED_xlabel(e)) ED_xlabel(e)->pos = map_point(ED_xlabel(e)->pos); /* vladimir */ if (ED_head_label(e)) ED_head_label(e)->pos = map_point(ED_head_label(e)->pos); if (ED_tail_label(e)) ED_tail_label(e)->pos = map_point(ED_tail_label(e)->pos); }
static int edgeLen (Agedge_t* e) { pointf p = ND_coord(agtail(e)); pointf q = ND_coord(aghead(e)); return (int)DIST2(p,q); }
int nonconstraint_edge(edge_t * e) { char *constr; #ifndef WITH_CGRAPH if (E_constr && (constr = agxget(e, E_constr->index))) { #else /* WITH_CGRAPH */ if (E_constr && (constr = agxget(e, E_constr))) { #endif /* WITH_CGRAPH */ if (constr[0] && mapbool(constr) == FALSE) return TRUE; } return FALSE; } static void interclust1(graph_t * g, node_t * t, node_t * h, edge_t * e) { node_t *v, *t0, *h0; int offset, t_len, h_len, t_rank, h_rank; edge_t *rt, *rh; if (ND_clust(agtail(e))) t_rank = ND_rank(agtail(e)) - ND_rank(GD_leader(ND_clust(agtail(e)))); else t_rank = 0; if (ND_clust(aghead(e))) h_rank = ND_rank(aghead(e)) - ND_rank(GD_leader(ND_clust(aghead(e)))); else h_rank = 0; offset = ED_minlen(e) + t_rank - h_rank; if (offset > 0) { t_len = 0; h_len = offset; } else { t_len = -offset; h_len = 0; } v = virtual_node(g); ND_node_type(v) = SLACKNODE; t0 = UF_find(t); h0 = UF_find(h); rt = make_aux_edge(v, t0, t_len, CL_BACK * ED_weight(e)); rh = make_aux_edge(v, h0, h_len, ED_weight(e)); ED_to_orig(rt) = ED_to_orig(rh) = e; }
/* nearTail: * Given a point a and edge e, return true if a is closer to the * tail of e than the head. */ static int nearTail (GVJ_t* job, pointf a, Agedge_t* e) { pointf tp = gvrender_ptf(job, ND_coord(agtail(e))); pointf hp = gvrender_ptf(job, ND_coord(aghead(e))); return (DIST2(a, tp) < DIST2(a, hp)); }
/* cloneGraph: * Clone node, edge and subgraph structure from src to tgt. */ static void cloneGraph(Agraph_t * tgt, Agraph_t * src) { Agedge_t *e; Agedge_t *ne; Agnode_t *t; Agraph_t *sg; char* name; Dt_t* emap = dtopen (&edgepair, Dtoset); edgepair_t* data = (edgepair_t*)malloc(sizeof(edgepair_t)*agnedges(src)); edgepair_t* ep = data; for (t = agfstnode(src); t; t = agnxtnode(src, t)) { if (!copy(tgt, OBJ(t))) { exerror("error cloning node %s from graph %s", agnameof(t), agnameof(src)); } } for (t = agfstnode(src); t; t = agnxtnode(src, t)) { for (e = agfstout(src, t); e; e = agnxtout(src, e)) { if (!(ne = (Agedge_t*)copy(tgt, OBJ(e)))) { name = agnameof(AGMKOUT(e)); if (name) exerror("error cloning edge (%s,%s)[%s] from graph %s", agnameof(agtail(e)), agnameof(aghead(e)), name, agnameof(src)); else exerror("error cloning edge (%s,%s) from graph %s", agnameof(agtail(e)), agnameof(aghead(e)), agnameof(src)); return; } ep->key = e; ep->val = ne; dtinsert (emap, ep++); } } for (sg = agfstsubg(src); sg; sg = agnxtsubg(sg)) { if (!cloneSubg(tgt, sg, emap)) { exerror("error cloning subgraph %s from graph %s", agnameof(sg), agnameof(src)); } } dtclose (emap); free (data); }
Agnode_t *headof(Agedge_t *e) { if (!e) return NULL; if (AGTYPE(e) == AGRAPH) return NULL; return aghead(e); }
/* mapEdge: * Check if we already have cluster edge corresponding to t->h, * and return it. */ static item *mapEdge(Dt_t * map, edge_t * e) { void *key[2]; key[0] = agtail(e); key[1] = aghead(e); return (item *) dtmatch(map, &key); }