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); }
/* makeSelfArcs: * Generate loops. We use the library routine makeSelfEdge * which also places the labels. * We have to handle port labels here. * as well as update the bbox from edge labels. */ void makeSelfArcs(path * P, edge_t * e, int stepx) { int cnt = ED_count(e); if ((cnt == 1) || Concentrate) { edge_t *edges1[1]; edges1[0] = e; makeSelfEdge(P, edges1, 0, 1, stepx, stepx, &sinfo); if (ED_label(e)) updateBB(agraphof(agtail(e)), ED_label(e)); makePortLabels(e); } else { int i; edge_t **edges = N_GNEW(cnt, edge_t *); for (i = 0; i < cnt; i++) { edges[i] = e; e = ED_to_virt(e); } makeSelfEdge(P, edges, 0, cnt, stepx, stepx, &sinfo); for (i = 0; i < cnt; i++) { e = edges[i]; if (ED_label(e)) updateBB(agraphof(agtail(e)), ED_label(e)); makePortLabels(e); } free(edges); } }
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 void dot_cleanup_edge(edge_t * e) { dot_free_splines(e); free_label(ED_label(e)); memset(&(e->u), 0, sizeof(Agedgeinfo_t)); }
/* compute_bb: * Compute bounding box of g using nodes, splines, and clusters. * Assumes bb of clusters already computed. * store in GD_bb. */ void compute_bb(graph_t * g) { node_t *n; edge_t *e; box b, bb; point pt, s2; int i, j; bb.LL = pointof(MAXINT, MAXINT); bb.UR = pointof(-MAXINT, -MAXINT); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { pt = coord(n); s2.x = ND_xsize(n) / 2 + 1; s2.y = ND_ysize(n) / 2 + 1; b.LL = sub_points(pt, s2); b.UR = add_points(pt, s2); EXPANDBB(bb,b); for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (ED_spl(e) == 0) continue; for (i = 0; i < ED_spl(e)->size; i++) { for (j = 0; j < ED_spl(e)->list[i].size; j++) { pt = ED_spl(e)->list[i].list[j]; EXPANDBP(bb,pt); } } if (ED_label(e) && ED_label(e)->set) bb = addLabelBB(bb, ED_label(e), GD_flip(g)); } } for (i = 1; i <= GD_n_cluster(g); i++) { EXPANDBB(bb,GD_clust(g)[i]->u.bb); } GD_bb(g) = bb; }
QPointF GVEdge::getGVEdgeLabelPosition(QPointF offset) { QPointF position(0,0); #ifdef USE_LIBGRAPH_NOT_LIBCGRAPH position = QPointF(this->gv_edge->u.label->pos.x, this->layout->getGVGraph()->u.bb.UR.y - this->gv_edge->u.label->pos.y); #else qreal a = 0; qreal b = 0; textlabel_t* edgelabel = ED_label(this->gv_edge); if (edgelabel != NULL) { a = edgelabel->pos.x; } else { DBG() << "Warning: edge label doesn't exist in this->gv_edge..."; } //char* l = agget (this->gv_edge, (char*)"label"); b = (GD_bb(this->layout->getGVGraph()).UR.y - ED_label(this->gv_edge)->pos.y); position = QPointF(a,b); #endif position -= offset; return position; }
static void attachOrthoEdges (Agraph_t* g, maze* mp, int n_edges, route* route_list, splineInfo *sinfo, epair_t es[], int doLbls) { int irte = 0; int i, ipt, npts; pointf* ispline = 0; int splsz = 0; pointf p, p1, q1; route rte; segment* seg; Agedge_t* e; textlabel_t* lbl; for (; irte < n_edges; irte++) { e = es[irte].e; p1 = addPoints(ND_coord(agtail(e)), ED_tail_port(e).p); q1 = addPoints(ND_coord(aghead(e)), ED_head_port(e).p); rte = route_list[irte]; npts = 1 + 3*rte.n; if (npts > splsz) { if (ispline) free (ispline); ispline = N_GNEW(npts, pointf); splsz = npts; } seg = rte.segs; if (seg->isVert) { p.x = vtrack(seg, mp); p.y = p1.y; } else { p.y = htrack(seg, mp); p.x = p1.x; } ispline[0] = ispline[1] = p; ipt = 2; for (i = 1;i<rte.n;i++) { seg = rte.segs+i; if (seg->isVert) p.x = vtrack(seg, mp); else p.y = htrack(seg, mp); ispline[ipt+2] = ispline[ipt+1] = ispline[ipt] = p; ipt += 3; } if (seg->isVert) { p.x = vtrack(seg, mp); p.y = q1.y; } else { p.y = htrack(seg, mp); p.x = q1.x; } ispline[ipt] = ispline[ipt+1] = p; if (Verbose > 1) fprintf(stderr, "ortho %s %s\n", agnameof(agtail(e)),agnameof(aghead(e))); clip_and_install(e, aghead(e), ispline, npts, sinfo); if (doLbls && (lbl = ED_label(e)) && !lbl->set) addEdgeLabels(g, e, p1, q1); } free(ispline); }
/* return TRUE if edge has label */ int common_init_edge(edge_t * e) { char *s; int html = 0, r = 0; struct fontinfo fi; struct fontinfo lfi; fi.fontname = NULL; lfi.fontname = NULL; if (E_label && (s = agxget(e, E_label->index)) && (s[0])) { r = 1; html = aghtmlstr(s); if (html) s = strdup(s); else s = strdup_and_subst_edge(s, e); initFontEdgeAttr(e, &fi); ED_label(e) = make_label(html, s, fi.fontsize, fi.fontname, fi.fontcolor, e->tail->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ED_label(e), e) == 1) edgeError(e, "label"); } #endif GD_has_labels(e->tail->graph) |= EDGE_LABEL; ED_label_ontop(e) = mapbool(late_string(e, E_label_float, "false")); } /* vladimir */ if (E_headlabel && (s = agxget(e, E_headlabel->index)) && (s[0])) { html = aghtmlstr(s); if (html) s = strdup(s); else s = strdup_and_subst_edge(s, e); initFontLabelEdgeAttr(e, &fi, &lfi); ED_head_label(e) = make_label(html, s, lfi.fontsize, lfi.fontname, lfi.fontcolor, e->tail->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ED_head_label(e), e) == 1) edgeError(e, "head label"); } #endif GD_has_labels(e->tail->graph) |= HEAD_LABEL; } if (E_taillabel && (s = agxget(e, E_taillabel->index)) && (s[0])) { html = aghtmlstr(s); if (html) s = strdup(s); else s = strdup_and_subst_edge(s, e); if (!lfi.fontname) initFontLabelEdgeAttr(e, &fi, &lfi); ED_tail_label(e) = make_label(html, s, lfi.fontsize, lfi.fontname, lfi.fontcolor, e->tail->graph); #ifdef ENABLE_HTML //maks if (html) { if (make_html_label(ED_tail_label(e), e) == 1) edgeError(e, "tail label"); } #endif GD_has_labels(e->tail->graph) |= TAIL_LABEL; } /* end vladimir */ /* We still accept ports beginning with colons but this is deprecated */ s = agget(e, TAIL_ID); if (s[0]) ND_has_port(e->tail) = TRUE; ED_tail_port(e) = chkPort (ND_shape(e->tail)->fns->portfn,e->tail, s); if (noClip(e, E_tailclip)) ED_tail_port(e).clip = FALSE; s = agget(e, HEAD_ID); if (s[0]) ND_has_port(e->head) = TRUE; ED_head_port(e) = chkPort(ND_shape(e->head)->fns->portfn,e->head, s); if (noClip(e, E_headclip)) ED_head_port(e).clip = FALSE; return r; }
static void addXLabels(Agraph_t * gp) { Agnode_t *np; Agedge_t *ep; int cnt, i, n_objs, n_lbls; int n_nlbls = 0; /* # of unset node xlabels */ int n_elbls = 0; /* # of unset edge labels or xlabels */ int n_set_lbls = 0; /* # of set xlabels and edge labels */ int n_clbls = 0; /* # of set cluster labels */ boxf bb; pointf ur; textlabel_t* lp; label_params_t params; object_t* objs; xlabel_t* lbls; object_t* objp; xlabel_t* xlp; Agsym_t* force; int et = EDGE_TYPE(gp); if (!(GD_has_labels(gp) & NODE_XLABEL) && !(GD_has_labels(gp) & EDGE_XLABEL) && !(GD_has_labels(gp) & TAIL_LABEL) && !(GD_has_labels(gp) & HEAD_LABEL) && (!(GD_has_labels(gp) & EDGE_LABEL) || EdgeLabelsDone)) return; for (np = agfstnode(gp); np; np = agnxtnode(gp, np)) { if (ND_xlabel(np)) { if (ND_xlabel(np)->set) n_set_lbls++; else n_nlbls++; } for (ep = agfstout(gp, np); ep; ep = agnxtout(gp, ep)) { if (ED_xlabel(ep)) { if (ED_xlabel(ep)->set) n_set_lbls++; else if (HAVE_EDGE(ep)) n_elbls++; } if (ED_head_label(ep)) { if (ED_head_label(ep)->set) n_set_lbls++; else if (HAVE_EDGE(ep)) n_elbls++; } if (ED_tail_label(ep)) { if (ED_tail_label(ep)->set) n_set_lbls++; else if (HAVE_EDGE(ep)) n_elbls++; } if (ED_label(ep)) { if (ED_label(ep)->set) n_set_lbls++; else if (HAVE_EDGE(ep)) n_elbls++; } } } if (GD_has_labels(gp) & GRAPH_LABEL) n_clbls = countClusterLabels (gp); /* A label for each unpositioned external label */ n_lbls = n_nlbls + n_elbls; if (n_lbls == 0) return; /* An object for each node, each positioned external label, any cluster label, * and all unset edge labels and xlabels. */ n_objs = agnnodes(gp) + n_set_lbls + n_clbls + n_elbls; objp = objs = N_NEW(n_objs, object_t); xlp = lbls = N_NEW(n_lbls, xlabel_t); bb.LL = pointfof(INT_MAX, INT_MAX); bb.UR = pointfof(-INT_MAX, -INT_MAX); for (np = agfstnode(gp); np; np = agnxtnode(gp, np)) { bb = addNodeObj (np, objp, bb); if ((lp = ND_xlabel(np))) { if (lp->set) { objp++; bb = addLabelObj (lp, objp, bb); } else { addXLabel (lp, objp, xlp, 0, ur); xlp++; } } objp++; for (ep = agfstout(gp, np); ep; ep = agnxtout(gp, ep)) { if ((lp = ED_label(ep))) { if (lp->set) { bb = addLabelObj (lp, objp, bb); } else if (HAVE_EDGE(ep)) { addXLabel (lp, objp, xlp, 1, edgeMidpoint(gp, ep)); xlp++; } else { agerr(AGWARN, "no position for edge with label %s", ED_label(ep)->text); continue; } objp++; } if ((lp = ED_tail_label(ep))) { if (lp->set) { bb = addLabelObj (lp, objp, bb); } else if (HAVE_EDGE(ep)) { addXLabel (lp, objp, xlp, 1, edgeTailpoint(ep)); xlp++; } else { agerr(AGWARN, "no position for edge with tail label %s", ED_tail_label(ep)->text); continue; } objp++; } if ((lp = ED_head_label(ep))) { if (lp->set) { bb = addLabelObj (lp, objp, bb); } else if (HAVE_EDGE(ep)) { addXLabel (lp, objp, xlp, 1, edgeHeadpoint(ep)); xlp++; } else { agerr(AGWARN, "no position for edge with head label %s", ED_head_label(ep)->text); continue; } objp++; } if ((lp = ED_xlabel(ep))) { if (lp->set) { bb = addLabelObj (lp, objp, bb); } else if (HAVE_EDGE(ep)) { addXLabel (lp, objp, xlp, 1, edgeMidpoint(gp, ep)); xlp++; } else { agerr(AGWARN, "no position for edge with xlabel %s", ED_xlabel(ep)->text); continue; } objp++; } } } if (n_clbls) { cinfo_t info; info.bb = bb; info.objp = objp; info = addClusterObj (gp, info); bb = info.bb; } force = agfindgraphattr(gp, "forcelabels"); params.force = late_bool(gp, force, TRUE); params.bb = bb; placeLabels(objs, n_objs, lbls, n_lbls, ¶ms); if (Verbose) printData(objs, n_objs, lbls, n_lbls, ¶ms); xlp = lbls; cnt = 0; for (i = 0; i < n_lbls; i++) { if (xlp->set) { cnt++; lp = (textlabel_t *) (xlp->lbl); lp->set = 1; lp->pos = centerPt(xlp); updateBB (gp, lp); } xlp++; } if (Verbose) fprintf (stderr, "%d out of %d labels positioned.\n", cnt, n_lbls); else if (cnt != n_lbls) agerr(AGWARN, "%d out of %d exterior labels positioned.\n", cnt, n_lbls); free(objs); free(lbls); }
/* return true if edge has label */ int common_init_edge(edge_t * e) { char *str; int r = 0; struct fontinfo fi; struct fontinfo lfi; graph_t *sg = agraphof(agtail(e)); fi.fontname = NULL; lfi.fontname = NULL; if (E_label && (str = agxget(e, E_label)) && (str[0])) { r = 1; initFontEdgeAttr(e, &fi); ED_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), fi.fontsize, fi.fontname, fi.fontcolor); GD_has_labels(sg) |= EDGE_LABEL; ED_label_ontop(e) = mapbool(late_string(e, E_label_float, "false")); } if (E_xlabel && (str = agxget(e, E_xlabel)) && (str[0])) { if (!fi.fontname) initFontEdgeAttr(e, &fi); ED_xlabel(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), fi.fontsize, fi.fontname, fi.fontcolor); GD_has_labels(sg) |= EDGE_XLABEL; } /* vladimir */ if (E_headlabel && (str = agxget(e, E_headlabel)) && (str[0])) { initFontLabelEdgeAttr(e, &fi, &lfi); ED_head_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), lfi.fontsize, lfi.fontname, lfi.fontcolor); GD_has_labels(sg) |= HEAD_LABEL; } if (E_taillabel && (str = agxget(e, E_taillabel)) && (str[0])) { if (!lfi.fontname) initFontLabelEdgeAttr(e, &fi, &lfi); ED_tail_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE), lfi.fontsize, lfi.fontname, lfi.fontcolor); GD_has_labels(sg) |= TAIL_LABEL; } /* end vladimir */ /* We still accept ports beginning with colons but this is deprecated * That is, we allow tailport = ":abc" as well as the preferred * tailport = "abc". */ str = agget(e, TAIL_ID); /* libgraph always defines tailport/headport; libcgraph doesn't */ if (!str) str = ""; if (str && str[0]) ND_has_port(agtail(e)) = TRUE; ED_tail_port(e) = chkPort (ND_shape(agtail(e))->fns->portfn, agtail(e), str); if (noClip(e, E_tailclip)) ED_tail_port(e).clip = FALSE; str = agget(e, HEAD_ID); /* libgraph always defines tailport/headport; libcgraph doesn't */ if (!str) str = ""; if (str && str[0]) ND_has_port(aghead(e)) = TRUE; ED_head_port(e) = chkPort(ND_shape(aghead(e))->fns->portfn, aghead(e), str); if (noClip(e, E_headclip)) ED_head_port(e).clip = FALSE; return r; }
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) { int e_arrows; /* graph has edges with end arrows */ int s_arrows; /* graph has edges with start arrows */ int i, j, sides; char buf[BUFSIZ]; /* Used only for small strings */ unsigned char xbuffer[BUFSIZ]; /* Initial buffer for xb */ agxbuf xb; node_t *n; edge_t *e; point pt; e_arrows = s_arrows = 0; setYInvert(g); agxbinit(&xb, BUFSIZ, xbuffer); safe_dcl(g, g->proto->n, "pos", "", agnodeattr); safe_dcl(g, g->proto->n, "rects", "", agnodeattr); N_width = safe_dcl(g, g->proto->n, "width", "", agnodeattr); N_height = safe_dcl(g, g->proto->n, "height", "", agnodeattr); safe_dcl(g, g->proto->e, "pos", "", agedgeattr); if (GD_has_labels(g) & EDGE_LABEL) safe_dcl(g, g->proto->e, "lp", "", agedgeattr); if (GD_has_labels(g) & HEAD_LABEL) safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr); if (GD_has_labels(g) & TAIL_LABEL) safe_dcl(g, g->proto->e, "tail_lp", "", agedgeattr); if (GD_label(g)) { safe_dcl(g, g, "lp", "", agraphattr); if (GD_label(g)->text[0]) { pt = GD_label(g)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(g, "lp", buf); } } safe_dcl(g, g, "bb", "", agraphattr); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { sprintf(buf, "%d,%d", ND_coord_i(n).x, YDIR(ND_coord_i(n).y)); agset(n, "pos", buf); sprintf(buf, "%.2f", PS2INCH(ND_ht_i(n))); agxset(n, N_height->index, buf); sprintf(buf, "%.2f", PS2INCH(ND_lw_i(n) + ND_rw_i(n))); agxset(n, N_width->index, buf); if (strcmp(ND_shape(n)->name, "record") == 0) { set_record_rects(n, ND_shape_info(n), &xb); agxbpop(&xb); /* get rid of last space */ agset(n, "rects", agxbuse(&xb)); } else { polygon_t *poly; int i; if (N_vertices && isPolygon(n)) { poly = (polygon_t *) ND_shape_info(n); sides = poly->sides; if (sides < 3) { char *p = agget(n, "samplepoints"); if (p) sides = atoi(p); else sides = 8; if (sides < 3) sides = 8; } for (i = 0; i < sides; i++) { if (i > 0) agxbputc(&xb, ' '); if (poly->sides >= 3) sprintf(buf, "%.3f %.3f", PS2INCH(poly->vertices[i].x), YFDIR(PS2INCH(poly->vertices[i].y))); else sprintf(buf, "%.3f %.3f", ND_width(n) / 2.0 * cos(i / (double) sides * PI * 2.0), YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * PI * 2.0))); agxbput(&xb, buf); } agxset(n, N_vertices->index, agxbuse(&xb)); } } if (State >= GVSPLINES) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (ED_edge_type(e) == IGNORED) continue; if (ED_spl(e) == NULL) continue; /* reported in postproc */ for (i = 0; i < ED_spl(e)->size; i++) { if (i > 0) agxbputc(&xb, ';'); if (ED_spl(e)->list[i].sflag) { s_arrows = 1; sprintf(buf, "s,%d,%d ", ED_spl(e)->list[i].sp.x, YDIR(ED_spl(e)->list[i].sp.y)); agxbput(&xb, buf); } if (ED_spl(e)->list[i].eflag) { e_arrows = 1; sprintf(buf, "e,%d,%d ", ED_spl(e)->list[i].ep.x, YDIR(ED_spl(e)->list[i].ep.y)); agxbput(&xb, buf); } for (j = 0; j < ED_spl(e)->list[i].size; j++) { if (j > 0) agxbputc(&xb, ' '); pt = ED_spl(e)->list[i].list[j]; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agxbput(&xb, buf); } } agset(e, "pos", agxbuse(&xb)); if (ED_label(e)) { pt = ED_label(e)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(e, "lp", buf); } if (ED_head_label(e)) { pt = ED_head_label(e)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(e, "head_lp", buf); } if (ED_tail_label(e)) { pt = ED_tail_label(e)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(e, "tail_lp", buf); } } } } rec_attach_bb(g); agxbfree(&xb); if (HAS_CLUST_EDGE(g)) undoClusterEdges(g); *sp = s_arrows; *ep = e_arrows; }
/* _write_plain: */ void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend) { int i, j, splinePoints; char *tport, *hport; node_t *n; edge_t *e; bezier bz; point pt; char *lbl; // setup_graph(job, g); setYInvert(g); pt = GD_bb(g).UR; fprintf(f, "graph %.3f %.3f %.3f\n", job->zoom, PS2INCH(pt.x), PS2INCH(pt.y)); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (IS_CLUST_NODE(n)) continue; fprintf(f, "node %s ", agcanonical(n->name)); printptf(f, ND_coord_i(n)); if (ND_label(n)->html) /* if html, get original text */ lbl = agxget(n, N_label->index); else lbl = ND_label(n)->text; if (lbl) lbl = agcanonical(lbl); else lbl = "\"\""; fprintf(f, " %.3f %.3f %s %s %s %s %s\n", ND_width(n), ND_height(n), lbl, late_nnstring(n, N_style, "solid"), ND_shape(n)->name, late_nnstring(n, N_color, DEFAULT_COLOR), late_nnstring(n, N_fillcolor, DEFAULT_FILL)); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (extend && e->attr) { tport = e->attr[TAILX]; hport = e->attr[HEADX]; } else tport = hport = ""; if (ED_spl(e)) { splinePoints = 0; for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; splinePoints += bz.size; } fprintf(f, "edge "); writenodeandport(f, e->tail, tport); fprintf(f, " "); writenodeandport(f, e->head, hport); fprintf(f, " %d", splinePoints); for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; for (j = 0; j < bz.size; j++) printptf(f, bz.list[j]); } } if (ED_label(e)) { fprintf(f, " %s", agcanonical(ED_label(e)->text)); printptf(f, ED_label(e)->p); } fprintf(f, " %s %s\n", late_nnstring(e, E_style, "solid"), late_nnstring(e, E_color, DEFAULT_COLOR)); } } fprintf(f, "stop\n"); }
/* compute_bb: * Compute bounding box of g using nodes, splines, and clusters. * Assumes bb of clusters already computed. * store in GD_bb. */ void compute_bb(graph_t * g) { node_t *n; edge_t *e; boxf b, bb; boxf BF; pointf ptf, s2; int i, j; if ((agnnodes(g) == 0) && (GD_n_cluster(g) ==0)) { bb.LL = pointfof(0, 0); bb.UR = pointfof(0, 0); return; } bb.LL = pointfof(INT_MAX, INT_MAX); bb.UR = pointfof(-INT_MAX, -INT_MAX); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { ptf = coord(n); s2.x = ND_xsize(n) / 2.0; s2.y = ND_ysize(n) / 2.0; b.LL = sub_pointf(ptf, s2); b.UR = add_pointf(ptf, s2); EXPANDBB(bb,b); if (ND_xlabel(n) && ND_xlabel(n)->set) { bb = addLabelBB(bb, ND_xlabel(n), GD_flip(g)); } for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (ED_spl(e) == 0) continue; for (i = 0; i < ED_spl(e)->size; i++) { for (j = 0; j < (((Agedgeinfo_t*)AGDATA(e))->spl)->list[i].size; j++) { ptf = ED_spl(e)->list[i].list[j]; EXPANDBP(bb,ptf); } } if (ED_label(e) && ED_label(e)->set) { bb = addLabelBB(bb, ED_label(e), GD_flip(g)); } if (ED_head_label(e) && ED_head_label(e)->set) { bb = addLabelBB(bb, ED_head_label(e), GD_flip(g)); } if (ED_tail_label(e) && ED_tail_label(e)->set) { bb = addLabelBB(bb, ED_tail_label(e), GD_flip(g)); } if (ED_xlabel(e) && ED_xlabel(e)->set) { bb = addLabelBB(bb, ED_xlabel(e), GD_flip(g)); } } } for (i = 1; i <= GD_n_cluster(g); i++) { B2BF(GD_bb(GD_clust(g)[i]), BF); EXPANDBB(bb,BF); } if (GD_label(g) && GD_label(g)->set) { bb = addLabelBB(bb, GD_label(g), GD_flip(g)); } GD_bb(g) = bb; }
/* strdup_and_subst_obj0: * Replace various escape sequences with the name of the associated * graph object. A double backslash \\ can be used to avoid a replacement. * If escBackslash is true, convert \\ to \; else leave alone. All other dyads * of the form \. are passed through unchanged. */ static char *strdup_and_subst_obj0 (char *str, void *obj, int escBackslash) { char c, *s, *p, *t, *newstr; char *tp_str = "", *hp_str = ""; char *g_str = "\\G", *n_str = "\\N", *e_str = "\\E", *h_str = "\\H", *t_str = "\\T", *l_str = "\\L"; int g_len = 2, n_len = 2, e_len = 2, h_len = 2, t_len = 2, l_len = 2, tp_len = 0, hp_len = 0; int newlen = 0; int isEdge = 0; textlabel_t *tl; port pt; /* prepare substitution strings */ switch (agobjkind(obj)) { case AGRAPH: g_str = agnameof((graph_t *)obj); g_len = strlen(g_str); tl = GD_label((graph_t *)obj); if (tl) { l_str = tl->text; if (str) l_len = strlen(l_str); } break; case AGNODE: g_str = agnameof(agraphof((node_t *)obj)); g_len = strlen(g_str); n_str = agnameof((node_t *)obj); n_len = strlen(n_str); tl = ND_label((node_t *)obj); if (tl) { l_str = tl->text; if (str) l_len = strlen(l_str); } break; case AGEDGE: isEdge = 1; g_str = agnameof(agroot(agraphof(agtail(((edge_t *)obj))))); g_len = strlen(g_str); t_str = agnameof(agtail(((edge_t *)obj))); t_len = strlen(t_str); pt = ED_tail_port((edge_t *)obj); if ((tp_str = pt.name)) tp_len = strlen(tp_str); h_str = agnameof(aghead(((edge_t *)obj))); h_len = strlen(h_str); pt = ED_head_port((edge_t *)obj); if ((hp_str = pt.name)) hp_len = strlen(hp_str); h_len = strlen(h_str); tl = ED_label((edge_t *)obj); if (tl) { l_str = tl->text; if (str) l_len = strlen(l_str); } if (agisdirected(agroot(agraphof(agtail(((edge_t*)obj)))))) e_str = "->"; else e_str = "--"; e_len = t_len + (tp_len?tp_len+1:0) + 2 + h_len + (hp_len?hp_len+1:0); break; } /* two passes over str. * * first pass prepares substitution strings and computes * total length for newstring required from malloc. */ for (s = str; (c = *s++);) { if (c == '\\') { switch (c = *s++) { case 'G': newlen += g_len; break; case 'N': newlen += n_len; break; case 'E': newlen += e_len; break; case 'H': newlen += h_len; break; case 'T': newlen += t_len; break; case 'L': newlen += l_len; break; case '\\': if (escBackslash) { newlen += 1; break; } /* Fall through */ default: /* leave other escape sequences unmodified, e.g. \n \l \r */ newlen += 2; } } else { newlen++; } } /* allocate new string */ newstr = gmalloc(newlen + 1); /* second pass over str assembles new string */ for (s = str, p = newstr; (c = *s++);) { if (c == '\\') { switch (c = *s++) { case 'G': for (t = g_str; (*p = *t++); p++); break; case 'N': for (t = n_str; (*p = *t++); p++); break; case 'E': if (isEdge) { for (t = t_str; (*p = *t++); p++); if (tp_len) { *p++ = ':'; for (t = tp_str; (*p = *t++); p++); } for (t = e_str; (*p = *t++); p++); for (t = h_str; (*p = *t++); p++); if (hp_len) { *p++ = ':'; for (t = hp_str; (*p = *t++); p++); } } break; case 'T': for (t = t_str; (*p = *t++); p++); break; case 'H': for (t = h_str; (*p = *t++); p++); break; case 'L': for (t = l_str; (*p = *t++); p++); break; case '\\': if (escBackslash) { *p++ = '\\'; break; } /* Fall through */ default: /* leave other escape sequences unmodified, e.g. \n \l \r */ *p++ = '\\'; *p++ = c; break; } } else { *p++ = c; } } *p++ = '\0'; return newstr; }
/* _write_plain: */ void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend) { int i, j, splinePoints; char *tport, *hport; node_t *n; edge_t *e; bezier bz; pointf pt; char *lbl; char* fillcolor; putstr = g->clos->disc.io->putstr; // setup_graph(job, g); setYInvert(g); pt = GD_bb(g).UR; printdouble(f, "graph ", job->zoom); printdouble(f, " ", PS2INCH(pt.x)); printdouble(f, " ", PS2INCH(pt.y)); agputc('\n', f); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (IS_CLUST_NODE(n)) continue; printstring(f, "node ", agcanonStr(agnameof(n))); printpoint(f, ND_coord(n)); if (ND_label(n)->html) /* if html, get original text */ lbl = agcanonStr (agxget(n, N_label)); else lbl = canon(agraphof(n),ND_label(n)->text); printdouble(f, " ", ND_width(n)); printdouble(f, " ", ND_height(n)); printstring(f, " ", lbl); printstring(f, " ", late_nnstring(n, N_style, "solid")); printstring(f, " ", ND_shape(n)->name); printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR)); fillcolor = late_nnstring(n, N_fillcolor, ""); if (fillcolor[0] == '\0') fillcolor = late_nnstring(n, N_color, DEFAULT_FILL); printstring(f, " ", fillcolor); agputc('\n', f); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (extend) { //assuming these two attrs have already been created by cgraph if (!(tport = agget(e,"tailport"))) tport = ""; if (!(hport = agget(e,"headport"))) hport = ""; } else tport = hport = ""; if (ED_spl(e)) { splinePoints = 0; for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; splinePoints += bz.size; } printstring(f, NULL, "edge"); writenodeandport(f, agtail(e), tport); writenodeandport(f, aghead(e), hport); printint(f, " ", splinePoints); for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; for (j = 0; j < bz.size; j++) printpoint(f, bz.list[j]); } } if (ED_label(e)) { printstring(f, " ", canon(agraphof(agtail(e)),ED_label(e)->text)); printpoint(f, ED_label(e)->pos); } printstring(f, " ", late_nnstring(e, E_style, "solid")); printstring(f, " ", late_nnstring(e, E_color, DEFAULT_COLOR)); agputc('\n', f); } } agputs("stop\n", f); }
SEXP getEdgeLocs(Agraph_t *g) { SEXP outList, curCP, curEP, pntList, pntSet, curXY, curLab; SEXP epClass, cpClass, xyClass, labClass; Agnode_t *node, *head; Agedge_t *edge; char *tmpString; bezier bez; int nodes; int i,k,l,pntLstEl; int curEle = 0; epClass = MAKE_CLASS("AgEdge"); cpClass = MAKE_CLASS("BezierCurve"); xyClass = MAKE_CLASS("xyPoint"); labClass = MAKE_CLASS("AgTextLabel"); /* tmpString is used to convert a char to a char* w/ labels */ tmpString = (char *)R_alloc(2, sizeof(char)); if (tmpString == NULL) error("Allocation error in getEdgeLocs"); PROTECT(outList = allocVector(VECSXP, agnedges(g))); nodes = agnnodes(g); node = agfstnode(g); for (i = 0; i < nodes; i++) { edge = agfstout(g, node); while (edge != NULL && edge->u.spl != NULL) { PROTECT(curEP = NEW_OBJECT(epClass)); bez = edge->u.spl->list[0]; PROTECT(pntList = allocVector(VECSXP, ((bez.size-1)/3))); pntLstEl = 0; /* There are really (bez.size-1)/3 sets of control */ /* points, with the first set containing teh first 4 */ /* points, and then every other set starting with the */ /* last point from the previous set and then the next 3 */ for (k = 1; k < bez.size; k += 3) { PROTECT(curCP = NEW_OBJECT(cpClass)); PROTECT(pntSet = allocVector(VECSXP, 4)); for (l = -1; l < 3; l++) { PROTECT(curXY = NEW_OBJECT(xyClass)); SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(bez.list[k+l].x)); SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(bez.list[k+l].y)); SET_ELEMENT(pntSet, l+1, curXY); UNPROTECT(1); } SET_SLOT(curCP, Rf_install("cPoints"), pntSet); SET_ELEMENT(pntList, pntLstEl++, curCP); UNPROTECT(2); } SET_SLOT(curEP, Rf_install("splines"), pntList); /* get the sp and ep */ PROTECT(curXY = NEW_OBJECT(xyClass)); SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(bez.sp.x)); SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(bez.sp.y)); SET_SLOT(curEP, Rf_install("sp"), curXY); UNPROTECT(1); PROTECT(curXY = NEW_OBJECT(xyClass)); SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(bez.ep.x)); SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(bez.ep.y)); SET_SLOT(curEP, Rf_install("ep"), curXY); UNPROTECT(1); SET_SLOT(curEP, Rf_install("tail"), Rgraphviz_ScalarStringOrNull(node->name)); head = edge->head; SET_SLOT(curEP, Rf_install("head"), Rgraphviz_ScalarStringOrNull(head->name)); /* TODO: clean up the use of attrs: dir, arrowhead, arrowtail. * the following are for interactive plotting in R-env, not needed * for output to files. The existing codes set "dir"-attr, but use * "arrowhead"/"arrowtail" instead. Quite confusing. */ SET_SLOT(curEP, Rf_install("dir"), Rgraphviz_ScalarStringOrNull(agget(edge, "dir"))); SET_SLOT(curEP, Rf_install("arrowhead"), Rgraphviz_ScalarStringOrNull(agget(edge, "arrowhead"))); SET_SLOT(curEP, Rf_install("arrowtail"), Rgraphviz_ScalarStringOrNull(agget(edge, "arrowtail"))); SET_SLOT(curEP, Rf_install("arrowsize"), Rgraphviz_ScalarStringOrNull(agget(edge, "arrowsize"))); SET_SLOT(curEP, Rf_install("color"), Rgraphviz_ScalarStringOrNull(agget(edge, "color"))); /* get lty/lwd info */ if ( agget(edge, "lty") ) SET_SLOT(curEP, Rf_install("lty"), Rgraphviz_ScalarStringOrNull(agget(edge, "lty"))); if ( agget(edge, "lwd") ) SET_SLOT(curEP, Rf_install("lwd"), Rgraphviz_ScalarStringOrNull(agget(edge, "lwd"))); /* Get the label information */ if (edge->u.label != NULL) { PROTECT(curLab = NEW_OBJECT(labClass)); SET_SLOT(curLab, Rf_install("labelText"), Rgraphviz_ScalarStringOrNull(ED_label(edge)->text)); /* Get the X/Y location of the label */ PROTECT(curXY = NEW_OBJECT(xyClass)); #if GRAPHVIZ_MAJOR == 2 && GRAPHVIZ_MINOR > 20 SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(ED_label(edge)->pos.x)); SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(ED_label(edge)->pos.y)); #else SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(edge->u.label->p.x)); SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(edge->u.label->p.y)); #endif SET_SLOT(curLab, Rf_install("labelLoc"), curXY); UNPROTECT(1); snprintf(tmpString, 2, "%c",ED_label(edge)->u.txt.para->just); SET_SLOT(curLab, Rf_install("labelJust"), Rgraphviz_ScalarStringOrNull(tmpString)); SET_SLOT(curLab, Rf_install("labelWidth"), Rf_ScalarInteger(ED_label(edge)->u.txt.para->width)); SET_SLOT(curLab, Rf_install("labelColor"), Rgraphviz_ScalarStringOrNull(edge->u.label->fontcolor)); SET_SLOT(curLab, Rf_install("labelFontsize"), Rf_ScalarReal(edge->u.label->fontsize)); SET_SLOT(curEP, Rf_install("txtLabel"), curLab); UNPROTECT(1); } SET_ELEMENT(outList, curEle++, curEP); UNPROTECT(2); edge = agnxtout(g, edge); } node = agnxtnode(g, node); } UNPROTECT(1); return(outList); }
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep) { int e_arrows; /* graph has edges with end arrows */ int s_arrows; /* graph has edges with start arrows */ int i, j, sides; char buf[BUFSIZ]; /* Used only for small strings */ unsigned char xbuffer[BUFSIZ]; /* Initial buffer for xb */ agxbuf xb; node_t *n; edge_t *e; pointf ptf; int dim3 = (GD_odim(g) >= 3); Agsym_t* bbsym; gv_fixLocale (1); e_arrows = s_arrows = 0; setYInvert(g); agxbinit(&xb, BUFSIZ, xbuffer); safe_dcl(g, AGNODE, "pos", ""); safe_dcl(g, AGNODE, "rects", ""); N_width = safe_dcl(g, AGNODE, "width", ""); N_height = safe_dcl(g, AGNODE, "height", ""); safe_dcl(g, AGEDGE, "pos", ""); if (GD_has_labels(g) & NODE_XLABEL) safe_dcl(g, AGNODE, "xlp", ""); if (GD_has_labels(g) & EDGE_LABEL) safe_dcl(g, AGEDGE, "lp", ""); if (GD_has_labels(g) & EDGE_XLABEL) safe_dcl(g, AGEDGE, "xlp", ""); if (GD_has_labels(g) & HEAD_LABEL) safe_dcl(g, AGEDGE, "head_lp", ""); if (GD_has_labels(g) & TAIL_LABEL) safe_dcl(g, AGEDGE, "tail_lp", ""); if (GD_label(g)) { safe_dcl(g, AGRAPH, "lp", ""); safe_dcl(g, AGRAPH, "lwidth", ""); safe_dcl(g, AGRAPH, "lheight", ""); if (GD_label(g)->text[0]) { ptf = GD_label(g)->pos; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agset(g, "lp", buf); ptf = GD_label(g)->dimen; sprintf(buf, "%.2f", PS2INCH(ptf.x)); agset(g, "lwidth", buf); sprintf(buf, "%.2f", PS2INCH(ptf.y)); agset(g, "lheight", buf); } } bbsym = safe_dcl(g, AGRAPH, "bb", ""); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (dim3) { int k; sprintf(buf, "%.5g,%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y), POINTS_PER_INCH*(ND_pos(n)[2])); agxbput (&xb, buf); for (k = 3; k < GD_odim(g); k++) { sprintf(buf, ",%.5g", POINTS_PER_INCH*(ND_pos(n)[k])); agxbput (&xb, buf); } agset(n, "pos", agxbuse(&xb)); } else { sprintf(buf, "%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y)); agset(n, "pos", buf); } sprintf(buf, "%.5g", PS2INCH(ND_ht(n))); agxset(n, N_height, buf); sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n))); agxset(n, N_width, buf); if (ND_xlabel(n) && ND_xlabel(n)->set) { ptf = ND_xlabel(n)->pos; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agset(n, "xlp", buf); } if (strcmp(ND_shape(n)->name, "record") == 0) { set_record_rects(n, ND_shape_info(n), &xb); agxbpop(&xb); /* get rid of last space */ agset(n, "rects", agxbuse(&xb)); } else { polygon_t *poly; int i; if (N_vertices && isPolygon(n)) { poly = (polygon_t *) ND_shape_info(n); sides = poly->sides; if (sides < 3) { char *p = agget(n, "samplepoints"); if (p) sides = atoi(p); else sides = 8; if (sides < 3) sides = 8; } for (i = 0; i < sides; i++) { if (i > 0) agxbputc(&xb, ' '); if (poly->sides >= 3) sprintf(buf, "%.5g %.5g", PS2INCH(poly->vertices[i].x), YFDIR(PS2INCH(poly->vertices[i].y))); else sprintf(buf, "%.5g %.5g", ND_width(n) / 2.0 * cos(i / (double) sides * M_PI * 2.0), YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * M_PI * 2.0))); agxbput(&xb, buf); } agxset(n, N_vertices, agxbuse(&xb)); } } if (State >= GVSPLINES) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (ED_edge_type(e) == IGNORED) continue; if (ED_spl(e) == NULL) continue; /* reported in postproc */ for (i = 0; i < ED_spl(e)->size; i++) { if (i > 0) agxbputc(&xb, ';'); if (ED_spl(e)->list[i].sflag) { s_arrows = 1; sprintf(buf, "s,%.5g,%.5g ", ED_spl(e)->list[i].sp.x, YDIR(ED_spl(e)->list[i].sp.y)); agxbput(&xb, buf); } if (ED_spl(e)->list[i].eflag) { e_arrows = 1; sprintf(buf, "e,%.5g,%.5g ", ED_spl(e)->list[i].ep.x, YDIR(ED_spl(e)->list[i].ep.y)); agxbput(&xb, buf); } for (j = 0; j < ED_spl(e)->list[i].size; j++) { if (j > 0) agxbputc(&xb, ' '); ptf = ED_spl(e)->list[i].list[j]; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agxbput(&xb, buf); } } agset(e, "pos", agxbuse(&xb)); if (ED_label(e)) { ptf = ED_label(e)->pos; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agset(e, "lp", buf); } if (ED_xlabel(e) && ED_xlabel(e)->set) { ptf = ED_xlabel(e)->pos; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agset(e, "xlp", buf); } if (ED_head_label(e)) { ptf = ED_head_label(e)->pos; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agset(e, "head_lp", buf); } if (ED_tail_label(e)) { ptf = ED_tail_label(e)->pos; sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y)); agset(e, "tail_lp", buf); } } } } rec_attach_bb(g, bbsym); agxbfree(&xb); if (HAS_CLUST_EDGE(g)) undoClusterEdges(g); *sp = s_arrows; *ep = e_arrows; gv_fixLocale (0); }
void neato_cleanup_edge(edge_t * e) { neato_free_splines(e); free_label(ED_label(e)); memset(&(e->u), 0, sizeof(Agedgeinfo_t)); }
/* orthoEdges: * For edges without position information, construct an orthogonal routing. * If doLbls is true, use edge label info when available to guide routing, * and set label pos for those edges for which this info is not available. */ void orthoEdges (Agraph_t* g, int doLbls) { sgraph* sg; maze* mp; int n_edges; route* route_list; int i, gstart; Agnode_t* n; Agedge_t* e; snode* sn; snode* dn; epair_t* es = N_GNEW(agnedges(g), epair_t); cell* start; cell* dest; PointSet* ps; textlabel_t* lbl; if (Concentrate) ps = newPS(); #ifdef DEBUG { char* s = agget(g, "odb"); char c; odb_flags = 0; if (s && (*s != '\0')) { while ((c = *s++)) { switch (c) { case 'c' : odb_flags |= ODB_CHANG; // emit channel graph break; case 'i' : odb_flags |= (ODB_SGRAPH|ODB_IGRAPH); // emit search graphs break; case 'm' : odb_flags |= ODB_MAZE; // emit maze break; case 'r' : odb_flags |= ODB_ROUTE; // emit routes in maze break; case 's' : odb_flags |= ODB_SGRAPH; // emit search graph break; } } } } #endif if (doLbls) { agerr(AGWARN, "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n"); doLbls = 0; } mp = mkMaze (g, doLbls); sg = mp->sg; #ifdef DEBUG if (odb_flags & ODB_SGRAPH) emitSearchGraph (stderr, sg); #endif /* store edges to be routed in es, along with their lengths */ n_edges = 0; for (n = agfstnode (g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g,e)) { if ((Nop == 2) && ED_spl(e)) continue; if (Concentrate) { int ti = AGID(agtail(e)); int hi = AGID(aghead(e)); if (ti <= hi) { if (isInPS (ps,ti,hi)) continue; else addPS (ps,ti,hi); } else { if (isInPS (ps,hi,ti)) continue; else addPS (ps,hi,ti); } } es[n_edges].e = e; es[n_edges].d = edgeLen (e); n_edges++; } } route_list = N_NEW (n_edges, route); qsort((char *)es, n_edges, sizeof(epair_t), (qsort_cmpf) edgecmp); gstart = sg->nnodes; PQgen (sg->nnodes+2); sn = &sg->nodes[gstart]; dn = &sg->nodes[gstart+1]; for (i = 0; i < n_edges; i++) { #ifdef DEBUG if ((i > 0) && (odb_flags & ODB_IGRAPH)) emitSearchGraph (stderr, sg); #endif e = es[i].e; start = CELL(agtail(e)); dest = CELL(aghead(e)); if (doLbls && (lbl = ED_label(e)) && lbl->set) { } else { if (start == dest) addLoop (sg, start, dn, sn); else { addNodeEdges (sg, dest, dn); addNodeEdges (sg, start, sn); } if (shortPath (sg, dn, sn)) goto orthofinish; } route_list[i] = convertSPtoRoute(sg, sn, dn); reset (sg); } PQfree (); mp->hchans = extractHChans (mp); mp->vchans = extractVChans (mp); assignSegs (n_edges, route_list, mp); if (setjmp(jbuf)) goto orthofinish; assignTracks (n_edges, route_list, mp); #ifdef DEBUG if (odb_flags & ODB_ROUTE) emitGraph (stderr, mp, n_edges, route_list, es); #endif attachOrthoEdges (g, mp, n_edges, route_list, &sinfo, es, doLbls); orthofinish: if (Concentrate) freePS (ps); for (i=0; i < n_edges; i++) free (route_list[i].segs); free (route_list); freeMaze (mp); }