/* setYInvert: * Set parameters used to flip coordinate system (y=0 at top). * Values do not need to be unset, since if Y_invert is set, it's * set for * all graphs during current run, so each will * reinitialize the values for its bbox. */ static void setYInvert(graph_t * g) { if (Y_invert) { Y_off = GD_bb(g).UR.y + GD_bb(g).LL.y; YF_off = PS2INCH(Y_off); } }
static void init1_gd(GVC_t * gvc, graph_t * g, box bb, point pb) { Dpi = GD_drawing(g)->dpi; if (Dpi < 1.0) Dpi = DEFAULT_DPI; DevScale = Dpi / POINTS_PER_INCH; Viewport.x = gvc->job->width; Viewport.y = gvc->job->height; #if 0 if (Viewport.x) { Zoom = gvc->job->zoom; GraphFocus = gvc->job->focus; } else { Viewport.x = (bb.UR.x - bb.LL.x + 2 * GD_drawing(g)->margin.x) * DevScale + 2; Viewport.y = (bb.UR.y - bb.LL.y + 2 * GD_drawing(g)->margin.y) * DevScale + 2; GraphFocus.x = (GD_bb(g).UR.x - GD_bb(g).LL.x) / 2.; GraphFocus.y = (GD_bb(g).UR.y - GD_bb(g).LL.y) / 2.; Zoom = 1.0; } #else Zoom = gvc->job->zoom; GraphFocus = gvc->job->focus; #endif CompScale = Zoom * DevScale; }
/* gvLayout: * Selects layout based on engine and binds it to gvc; * does the layout and sets the graph's bbox. * Return 0 on success. */ int gvLayout(GVC_t *gvc, graph_t *g, const char *engine) { char buf[256]; int rc; rc = gvlayout_select(gvc, engine); if (rc == NO_SUPPORT) { agerr (AGERR, "Layout type: \"%s\" not recognized. Use one of:%s\n", engine, gvplugin_list(gvc, API_layout, engine)); return -1; } if (gvLayoutJobs(gvc, g) == -1) return -1; /* set bb attribute for basic layout. * doesn't yet include margins, scaling or page sizes because * those depend on the renderer being used. */ if (GD_drawing(g)->landscape) sprintf(buf, "%d %d %d %d", ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).UR.y), ROUND(GD_bb(g).UR.x)); else sprintf(buf, "%d %d %d %d", ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y)); agsafeset(g, "bb", buf, ""); return 0; }
static void gd_begin_graph(graph_t* g, box bb, point pb) { Viewport = GD_drawing(g)->viewport.size; if (Viewport.x) { GraphFocus = GD_drawing(g)->viewport.focus; Zoom = GD_drawing(g)->viewport.zoom; } else { Viewport.x = (bb.UR.x - bb.LL.x + 2*GD_drawing(g)->margin.x) * SCALE + 1; Viewport.y = (bb.UR.y - bb.LL.y + 2*GD_drawing(g)->margin.y) * SCALE + 1; GraphFocus.x = (GD_bb(g).UR.x - GD_bb(g).LL.x) / 2.; GraphFocus.y = (GD_bb(g).UR.y - GD_bb(g).LL.y) / 2.; Zoom = SCALE; } }
void QGVSubGraph::updateLayout() { prepareGeometryChange(); //SubGraph box boxf box = GD_bb(_sgraph->graph()); pointf p1 = box.UR; pointf p2 = box.LL; _width = p1.x - p2.x; _height = p1.y - p2.y; qreal gheight = QGVCore::graphHeight(_scene->_graph->graph()); setPos(p2.x, gheight - p1.y); _pen.setWidth(1); _brush.setStyle(QGVCore::toBrushStyle(getAttribute("style"))); _brush.setColor(QGVCore::toColor(getAttribute("fillcolor"))); _pen.setColor(QGVCore::toColor(getAttribute("color"))); //SubGraph label textlabel_t *xlabel = GD_label(_sgraph->graph()); if(xlabel) { _label = xlabel->text; _label_rect.setSize(QSize(xlabel->dimen.x, xlabel->dimen.y)); _label_rect.moveCenter(QGVCore::toPoint(xlabel->pos, QGVCore::graphHeight(_scene->_graph->graph())) - pos()); } }
/** Get position of a state in the graph. * @param state_name name of state to get position of * @param px upon successful return contains X position value * @param py upon succesful return contains Y position value * Positions px/py are decimal percentages of * graph width/height from left/top. * @return true if node has been found and px/py have been set, false otherwise */ bool SkillGuiGraphDrawingArea::get_state_position(std::string state_name, double &px, double &py) { if (! __graph) { return false; } for (node_t *n = agfstnode(__graph); n; n = agnxtnode(__graph, n)) { const char *name = agnameof(n); pointf nodepos = ND_coord(n); if (state_name == name) { boxf bb = GD_bb(__graph); double bb_width = bb.UR.x - bb.LL.x; double bb_height = bb.UR.y - bb.LL.y; px = nodepos.x / bb_width; py = 1. - (nodepos.y / bb_height); return true; } } return false; }
static void rec_attach_bb(graph_t * g) { int c; char buf[BUFSIZ]; point pt; sprintf(buf, "%d,%d,%d,%d", GD_bb(g).LL.x, GD_bb(g).LL.y, GD_bb(g).UR.x, GD_bb(g).UR.y); agset(g, "bb", buf); if (GD_label(g) && GD_label(g)->text[0]) { pt = GD_label(g)->p; sprintf(buf, "%d,%d", pt.x, YDIR(pt.y)); agset(g, "lp", buf); } for (c = 1; c <= GD_n_cluster(g); c++) rec_attach_bb(GD_clust(g)[c]); }
void translate_bb(graph_t * g, int rankdir) { int c; boxf bb, new_bb; bb = GD_bb(g); if (rankdir == RANKDIR_LR || rankdir == RANKDIR_BT) { new_bb.LL = map_point(pointfof(bb.LL.x, bb.UR.y)); new_bb.UR = map_point(pointfof(bb.UR.x, bb.LL.y)); } else { new_bb.LL = map_point(pointfof(bb.LL.x, bb.LL.y)); new_bb.UR = map_point(pointfof(bb.UR.x, bb.UR.y)); } GD_bb(g) = new_bb; if (GD_label(g)) { GD_label(g)->pos = map_point(GD_label(g)->pos); } for (c = 1; c <= GD_n_cluster(g); c++) translate_bb(GD_clust(g)[c], rankdir); }
/* place_graph_label: * Put cluster labels recursively in the non-flip case. * The adjustments to the bounding boxes should no longer * be necessary, since we now guarantee the label fits in * the cluster. */ void place_graph_label(graph_t * g) { int c; pointf p, d; if ((g != agroot(g)) && (GD_label(g)) && !GD_label(g)->set) { if (GD_label_pos(g) & LABEL_AT_TOP) { d = GD_border(g)[TOP_IX]; p.y = GD_bb(g).UR.y - d.y / 2; } else { d = GD_border(g)[BOTTOM_IX]; p.y = GD_bb(g).LL.y + d.y / 2; } if (GD_label_pos(g) & LABEL_AT_RIGHT) { p.x = GD_bb(g).UR.x - d.x / 2; } else if (GD_label_pos(g) & LABEL_AT_LEFT) { p.x = GD_bb(g).LL.x + d.x / 2; } else { p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2; } GD_label(g)->pos = p; GD_label(g)->set = TRUE; } for (c = 1; c <= GD_n_cluster(g); c++) place_graph_label(GD_clust(g)[c]); }
static void rec_attach_bb(graph_t * g, Agsym_t* bbsym) { int c; char buf[BUFSIZ]; pointf pt; sprintf(buf, "%.5g,%.5g,%.5g,%.5g", GD_bb(g).LL.x, YDIR(GD_bb(g).LL.y), GD_bb(g).UR.x, YDIR(GD_bb(g).UR.y)); agxset(g, bbsym, buf); if (GD_label(g) && GD_label(g)->text[0]) { pt = GD_label(g)->pos; sprintf(buf, "%.5g,%.5g", pt.x, YDIR(pt.y)); agset(g, "lp", buf); pt = GD_label(g)->dimen; sprintf(buf, "%.2f", PS2INCH(pt.x)); agset (g, "lwidth", buf); sprintf(buf, "%.2f", PS2INCH(pt.y)); agset (g, "lheight", buf); } for (c = 1; c <= GD_n_cluster(g); c++) rec_attach_bb(GD_clust(g)[c], bbsym); }
static pointf get_centroid(Agraph_t *g) { int cnt = 0; static pointf sum = {0.0, 0.0}; static Agraph_t *save; Agnode_t *n; sum.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2.0; sum.y = (GD_bb(g).LL.y + GD_bb(g).UR.y) / 2.0; return sum; if (save == g) return sum; save = g; for (n = agfstnode(g); n; n = agnxtnode(g,n)) { sum.x += ND_pos(n)[0]; sum.y += ND_pos(n)[1]; cnt++; } sum.x = sum.x / cnt; sum.y = sum.y / cnt; return sum; }
void tcldot_layout(GVC_t *gvc, Agraph_t * g, char *engine) { char buf[256]; Agsym_t *a; int rc; gvFreeLayout(gvc, g); /* in case previously drawn */ /* support old behaviors if engine isn't specified*/ if (!engine || *engine == '\0') { if (agisdirected(g)) rc = gvlayout_select(gvc, "dot"); else rc = gvlayout_select(gvc, "neato"); } else { if (strcasecmp(engine, "nop") == 0) { Nop = 2; PSinputscale = POINTS_PER_INCH; rc = gvlayout_select(gvc, "neato"); } else { rc = gvlayout_select(gvc, engine); } if (rc == NO_SUPPORT) rc = gvlayout_select(gvc, "dot"); } if (rc == NO_SUPPORT) { fprintf(stderr, "Layout type: \"%s\" not recognized. Use one of:%s\n", engine, gvplugin_list(gvc, API_layout, engine)); return; } gvLayoutJobs(gvc, g); /* set bb attribute for basic layout. * doesn't yet include margins, scaling or page sizes because * those depend on the renderer being used. */ if (GD_drawing(g)->landscape) sprintf(buf, "%d %d %d %d", ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).UR.y), ROUND(GD_bb(g).UR.x)); else sprintf(buf, "%d %d %d %d", ROUND(GD_bb(g).LL.x), ROUND(GD_bb(g).LL.y), ROUND(GD_bb(g).UR.x), ROUND(GD_bb(g).UR.y)); if (!(a = agattr(g, AGRAPH, "bb", NULL))) a = agattr(g, AGRAPH, "bb", ""); agxset(g, a, buf); }
// used in nineml_graphicsitems.cpp:122 or thereabouts. This method // is a bit bizarre; I would apply the offset in the client code to // make this a pure position accessor. QPointF GVNode::getGVNodePosition(QPointF offset) { QPointF position; #ifdef USE_LIBGRAPH_NOT_LIBCGRAPH position = QPointF((gv_node->u.coord.x), (layout->getGVGraph()->u.bb.UR.y - gv_node->u.coord.y)); #else position = QPointF(ND_coord(this->gv_node).x, (GD_bb(this->layout->getGVGraph()).UR.y - ND_coord(this->gv_node).y)); #endif //DBG() << "getGVNodePosition: actual position: " << position // << " for node ID " << ND_id(this->gv_node); position -= offset; return position; }
static void dumpBB(graph_t * g) { boxf bb; box b; bb = BB(g); b = GD_bb(g); prIndent(); fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", bb.LL.x, bb.LL.y, bb.UR.x, bb.UR.y); prIndent(); fprintf(stderr, " LL (%d,%d) UR (%d,%d)\n", b.LL.x, b.LL.y, b.UR.x, b.UR.y); }
/* computeStep: * Compute grid step size. This is a root of the * quadratic equation al^2 +bl + c, where a, b and * c are defined below. */ static int computeStep(int ng, Agraph_t ** gs, int margin) { double l1, l2; double a, b, c, d, r; double W, H; /* width and height of graph, with margin */ Agraph_t *g; int i; a = C * ng - 1; c = 0; b = 0; for (i = 0; i < ng; i++) { g = gs[i]; W = GD_bb(g).UR.x - GD_bb(g).LL.x + 2 * margin; H = GD_bb(g).UR.y - GD_bb(g).LL.y + 2 * margin; b -= (W + H); c -= (W * H); } d = b * b - 4.0 * a * c; if (d < 0) { agerr(AGERR, "libpack: disc = %f ( < 0)\n", d); return -1; } r = sqrt(d); l1 = (-b + r) / (2 * a); l2 = (-b - r) / (2 * a); if (Verbose > 2) { fprintf(stderr, "Packing: compute grid size\n"); fprintf(stderr, "a %f b %f c %f d %f r %f\n", a, b, c, d, r); fprintf(stderr, "root %d (%f) %d (%f)\n", (int) l1, l1, (int) l2, l2); fprintf(stderr, " r1 %f r2 %f\n", a * l1 * l1 + b * l1 + c, a * l2 * l2 + b * l2 + c); } return (int) l1; }
/* _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; #ifdef WITH_CGRAPH putstr = g->clos->disc.io->putstr; #endif // 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 */ #ifndef WITH_CGRAPH lbl = agcanonStr (agxget(n, N_label->index)); #else lbl = agcanonStr (agxget(n, N_label)); #endif 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); }
/* 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; }
/* place_root_label: * Set position of root graph label. * Note that at this point, after translate_drawing, a * flipped drawing has been transposed, so we don't have * to worry about switching x and y. */ static void place_root_label(graph_t * g, pointf d) { pointf p; if (GD_label_pos(g) & LABEL_AT_RIGHT) { p.x = GD_bb(g).UR.x - d.x / 2; } else if (GD_label_pos(g) & LABEL_AT_LEFT) { p.x = GD_bb(g).LL.x + d.x / 2; } else { p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2; } if (GD_label_pos(g) & LABEL_AT_TOP) { p.y = GD_bb(g).UR.y - d.y / 2; } else { p.y = GD_bb(g).LL.y + d.y / 2; } GD_label(g)->pos = p; GD_label(g)->set = TRUE; }
/* updateBB: * Reset graph's bounding box to include bounding box of the given label. * Assume the label's position has been set. */ void updateBB(graph_t * g, textlabel_t * lp) { GD_bb(g) = addLabelBB(GD_bb(g), lp, GD_flip(g)); }
/* dotneato_postprocess: * Set graph and cluster label positions. * Add space for root graph label and translate graph accordingly. * Set final nodesize using ns. * Assumes the boxes of all clusters have been computed. * When done, the bounding box of g has LL at origin. */ void dotneato_postprocess(Agraph_t * g) { int diff; pointf dimen; point d = { 0, 0 }; Rankdir = GD_rankdir(g); Flip = GD_flip(g); if (Flip) place_flip_graph_label(g); else place_graph_label(g); if (GD_label(g) && !GD_label(g)->set) { dimen = GD_label(g)->dimen; PAD(dimen); PF2P(dimen, d); if (Flip) { if (GD_label_pos(g) & LABEL_AT_TOP) { GD_bb(g).UR.x += d.y; } else { GD_bb(g).LL.x -= d.y; } if (d.x > GD_bb(g).UR.y - GD_bb(g).LL.y) { diff = d.x - (GD_bb(g).UR.y - GD_bb(g).LL.y); diff = diff / 2; GD_bb(g).LL.y -= diff; GD_bb(g).UR.y += diff; } } else { if (GD_label_pos(g) & LABEL_AT_TOP) { if (Rankdir == RANKDIR_TB) GD_bb(g).UR.y += d.y; else GD_bb(g).LL.y -= d.y; } else { if (Rankdir == RANKDIR_TB) GD_bb(g).LL.y -= d.y; else GD_bb(g).UR.y += d.y; } if (d.x > GD_bb(g).UR.x - GD_bb(g).LL.x) { diff = d.x - (GD_bb(g).UR.x - GD_bb(g).LL.x); diff = diff / 2; GD_bb(g).LL.x -= diff; GD_bb(g).UR.x += diff; } } } switch (Rankdir) { case RANKDIR_TB: Offset = GD_bb(g).LL; break; case RANKDIR_LR: Offset = pointof(-GD_bb(g).UR.y, GD_bb(g).LL.x); break; case RANKDIR_BT: Offset = pointof(GD_bb(g).LL.x, -GD_bb(g).UR.y); break; case RANKDIR_RL: Offset = pointof(GD_bb(g).LL.y, GD_bb(g).LL.x); break; } translate_drawing(g); if (GD_label(g) && !GD_label(g)->set) place_root_label(g, d); if (Show_boxes) { char buf[BUFSIZ]; if (Flip) sprintf(buf, M2, Offset.x, Offset.y, Offset.x, Offset.y); else sprintf(buf, M1, Offset.y, Offset.x, Offset.y, Offset.x, -Offset.x, -Offset.y); Show_boxes[0] = strdup(buf); } }
QPointF GVEdge::getGVEdgeSplinesEndPoint() { QPointF spline = QPointF(ED_spl(this->gv_edge)->list->ep.x, GD_bb(this->layout->getGVGraph()).UR.y - ED_spl(this->gv_edge)->list->ep.y); return spline; }
/* place_flip_graph_label: * Put cluster labels recursively in the flip case. */ static void place_flip_graph_label(graph_t * g) { int c; point p, d; #ifdef OLD int maxx, minx; int maxy, miny; pointf dimen; #endif if ((g != g->root) && (GD_label(g)) && !GD_label(g)->set) { if (GD_label_pos(g) & LABEL_AT_TOP) { d = GD_border(g)[RIGHT_IX]; p.x = GD_bb(g).UR.x - d.x / 2; #ifdef OLD maxx = GD_bb(g).UR.x + d.y; GD_bb(g).UR.x = maxx; if (GD_bb(g->root).UR.x < maxx) GD_bb(g->root).UR.x = maxx; #endif } else { d = GD_border(g)[LEFT_IX]; p.x = GD_bb(g).LL.x + d.x / 2; #ifdef OLD minx = GD_bb(g).LL.x - d.y; GD_bb(g).LL.x = minx; if (GD_bb(g->root).LL.x > minx) GD_bb(g->root).LL.x = minx; #endif } if (GD_label_pos(g) & LABEL_AT_RIGHT) { p.y = GD_bb(g).LL.y + d.y / 2; #ifdef OLD maxy = p.y + d.x / 2; if (GD_bb(g->root).UR.y < maxy) GD_bb(g->root).UR.y = maxy; #endif } else if (GD_label_pos(g) & LABEL_AT_LEFT) { p.y = GD_bb(g).UR.y - d.y / 2; #ifdef OLD miny = p.y - d.x / 2; if (GD_bb(g->root).LL.y > miny) GD_bb(g->root).LL.y = miny; #endif } else { p.y = (GD_bb(g).LL.y + GD_bb(g).UR.y) / 2; #ifdef OLD maxy = p.y + d.x / 2; miny = p.y - d.x / 2; #endif } GD_label(g)->p = p; GD_label(g)->set = TRUE; } for (c = 1; c <= GD_n_cluster(g); c++) place_flip_graph_label(GD_clust(g)[c]); }
/* place_graph_label: * Put cluster labels recursively in the non-flip case. * The adjustments to the bounding boxes should no longer * be necessary, since we now guarantee the label fits in * the cluster. */ void place_graph_label(graph_t * g) { int c; #ifdef OLD int minx, maxx; #endif point p, d; if ((g != g->root) && (GD_label(g)) && !GD_label(g)->set) { if (GD_label_pos(g) & LABEL_AT_TOP) { d = GD_border(g)[TOP_IX]; p.y = GD_bb(g).UR.y - d.y / 2; } else { d = GD_border(g)[BOTTOM_IX]; p.y = GD_bb(g).LL.y + d.y / 2; } if (GD_label_pos(g) & LABEL_AT_RIGHT) { p.x = GD_bb(g).UR.x - d.x / 2; #ifdef OLD minx = p.x - d.x / 2; if (GD_bb(g).LL.x > minx) GD_bb(g).LL.x = minx; if (GD_bb(g->root).LL.x > minx) GD_bb(g->root).LL.x = minx; #endif } else if (GD_label_pos(g) & LABEL_AT_LEFT) { p.x = GD_bb(g).LL.x + d.x / 2; #ifdef OLD maxx = p.x + d.x / 2; if (GD_bb(g).UR.x < maxx) GD_bb(g).UR.x = maxx; if (GD_bb(g->root).UR.x < maxx) GD_bb(g->root).UR.x = maxx; #endif } else { p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2; #ifdef OLD maxx = p.x + d.x / 2; minx = p.x - d.x / 2; if (GD_bb(g).UR.x < maxx) GD_bb(g).UR.x = maxx; if (GD_bb(g).LL.x > minx) GD_bb(g).LL.x = minx; if (GD_bb(g->root).UR.x < maxx) GD_bb(g->root).UR.x = maxx; if (GD_bb(g->root).LL.x > minx) GD_bb(g->root).LL.x = minx; #endif } GD_label(g)->p = p; GD_label(g)->set = TRUE; } for (c = 1; c <= GD_n_cluster(g); c++) place_graph_label(GD_clust(g)[c]); }
/* _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); }
qreal QGVCore::graphHeight(Agraph_t *graph) { return GD_bb(graph).UR.y; }
/* gv_postprocess: * Set graph and cluster label positions. * Add space for root graph label and translate graph accordingly. * Set final nodesize using ns. * Assumes the boxes of all clusters have been computed. * When done, the bounding box of g has LL at origin. */ void gv_postprocess(Agraph_t * g, int allowTranslation) { double diff; pointf dimen = { 0., 0. }; Rankdir = GD_rankdir(g); Flip = GD_flip(g); /* Handle cluster labels */ if (Flip) place_flip_graph_label(g); else place_graph_label(g); /* Everything has been placed except the root graph label, if any. * The graph positions have not yet been rotated back if necessary. */ addXLabels(g); /* Add space for graph label if necessary */ if (GD_label(g) && !GD_label(g)->set) { dimen = GD_label(g)->dimen; PAD(dimen); if (Flip) { if (GD_label_pos(g) & LABEL_AT_TOP) { GD_bb(g).UR.x += dimen.y; } else { GD_bb(g).LL.x -= dimen.y; } if (dimen.x > (GD_bb(g).UR.y - GD_bb(g).LL.y)) { diff = dimen.x - (GD_bb(g).UR.y - GD_bb(g).LL.y); diff = diff / 2.; GD_bb(g).LL.y -= diff; GD_bb(g).UR.y += diff; } } else { if (GD_label_pos(g) & LABEL_AT_TOP) { if (Rankdir == RANKDIR_TB) GD_bb(g).UR.y += dimen.y; else GD_bb(g).LL.y -= dimen.y; } else { if (Rankdir == RANKDIR_TB) GD_bb(g).LL.y -= dimen.y; else GD_bb(g).UR.y += dimen.y; } if (dimen.x > (GD_bb(g).UR.x - GD_bb(g).LL.x)) { diff = dimen.x - (GD_bb(g).UR.x - GD_bb(g).LL.x); diff = diff / 2.; GD_bb(g).LL.x -= diff; GD_bb(g).UR.x += diff; } } } if (allowTranslation) { switch (Rankdir) { case RANKDIR_TB: Offset = GD_bb(g).LL; break; case RANKDIR_LR: Offset = pointfof(-GD_bb(g).UR.y, GD_bb(g).LL.x); break; case RANKDIR_BT: Offset = pointfof(GD_bb(g).LL.x, -GD_bb(g).UR.y); break; case RANKDIR_RL: Offset = pointfof(GD_bb(g).LL.y, GD_bb(g).LL.x); break; } translate_drawing(g); } if (GD_label(g) && !GD_label(g)->set) place_root_label(g, dimen); if (Show_boxes) { char buf[BUFSIZ]; if (Flip) sprintf(buf, M2, Offset.x, Offset.y, Offset.x, Offset.y); else sprintf(buf, M1, Offset.y, Offset.x, Offset.y, Offset.x, -Offset.x, -Offset.y); Show_boxes[0] = strdup(buf); } }
qreal QGVCore::graphHeight(Agraph_t *graph) { //Hauteur totale du graphique (permet d'effectuer le calcul inverse des coordonnées) return GD_bb(graph).UR.y; }
/* _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"); }
static void makeCompoundEdge(graph_t * g, edge_t * e) #endif { graph_t *lh; /* cluster containing head */ graph_t *lt; /* cluster containing tail */ bezier *bez; /* original Bezier for e */ bezier *nbez; /* new Bezier for e */ int starti = 0, endi = 0; /* index of first and last control point */ node_t *head; node_t *tail; boxf *bb; int i, j; int size; pointf pts[4]; pointf p; int fixed; /* find head and tail target clusters, if defined */ #ifdef WITH_CGRAPH lh = getCluster(g, agget(e, "lhead"), clustMap); lt = getCluster(g, agget(e, "ltail"), clustMap); #else lh = getCluster(g, agget(e, "lhead")); lt = getCluster(g, agget(e, "ltail")); #endif if (!lt && !lh) return; if (!ED_spl(e)) return; /* at present, we only handle single spline case */ if (ED_spl(e)->size > 1) { agerr(AGWARN, "%s -> %s: spline size > 1 not supported\n", agnameof(agtail(e)), agnameof(aghead(e))); return; } bez = ED_spl(e)->list; size = bez->size; head = aghead(e); tail = agtail(e); /* allocate new Bezier */ nbez = GNEW(bezier); nbez->eflag = bez->eflag; nbez->sflag = bez->sflag; /* if Bezier has four points, almost collinear, * make line - unimplemented optimization? */ /* If head cluster defined, find first Bezier * crossing head cluster, and truncate spline to * box edge. * Otherwise, leave end alone. */ fixed = 0; if (lh) { bb = &(GD_bb(lh)); if (!inBoxf(ND_coord(head), bb)) { agerr(AGWARN, "%s -> %s: head not inside head cluster %s\n", agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "lhead")); } else { /* If first control point is in bb, degenerate case. Spline * reduces to four points between the arrow head and the point * where the segment between the first control point and arrow head * crosses box. */ if (inBoxf(bez->list[0], bb)) { if (inBoxf(ND_coord(tail), bb)) { agerr(AGWARN, "%s -> %s: tail is inside head cluster %s\n", agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "lhead")); } else { assert(bez->sflag); /* must be arrowhead on tail */ p = boxIntersectf(bez->list[0], bez->sp, bb); bez->list[3] = p; bez->list[1] = mid_pointf(p, bez->sp); bez->list[0] = mid_pointf(bez->list[1], bez->sp); bez->list[2] = mid_pointf(bez->list[1], p); if (bez->eflag) endi = arrowEndClip(e, bez->list, starti, 0, nbez, bez->eflag); endi += 3; fixed = 1; } } else { for (endi = 0; endi < size - 1; endi += 3) { if (splineIntersectf(&(bez->list[endi]), bb)) break; } if (endi == size - 1) { /* no intersection */ assert(bez->eflag); nbez->ep = boxIntersectf(bez->ep, bez->list[endi], bb); } else { if (bez->eflag) endi = arrowEndClip(e, bez->list, starti, endi, nbez, bez->eflag); endi += 3; } fixed = 1; } } } if (fixed == 0) { /* if no lh, or something went wrong, use original head */ endi = size - 1; if (bez->eflag) nbez->ep = bez->ep; } /* If tail cluster defined, find last Bezier * crossing tail cluster, and truncate spline to * box edge. * Otherwise, leave end alone. */ fixed = 0; if (lt) { bb = &(GD_bb(lt)); if (!inBoxf(ND_coord(tail), bb)) { agerr(AGWARN, "%s -> %s: tail not inside tail cluster %s\n", agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "ltail")); } else { /* If last control point is in bb, degenerate case. Spline * reduces to four points between arrow head, and the point * where the segment between the last control point and the * arrow head crosses box. */ if (inBoxf(bez->list[endi], bb)) { if (inBoxf(ND_coord(head), bb)) { agerr(AGWARN, "%s -> %s: head is inside tail cluster %s\n", agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "ltail")); } else { assert(bez->eflag); /* must be arrowhead on head */ p = boxIntersectf(bez->list[endi], nbez->ep, bb); starti = endi - 3; bez->list[starti] = p; bez->list[starti + 2] = mid_pointf(p, nbez->ep); bez->list[starti + 3] = mid_pointf(bez->list[starti + 2], nbez->ep); bez->list[starti + 1] = mid_pointf(bez->list[starti + 2], p); if (bez->sflag) starti = arrowStartClip(e, bez->list, starti, endi - 3, nbez, bez->sflag); fixed = 1; } } else { for (starti = endi; starti > 0; starti -= 3) { for (i = 0; i < 4; i++) pts[i] = bez->list[starti - i]; if (splineIntersectf(pts, bb)) { for (i = 0; i < 4; i++) bez->list[starti - i] = pts[i]; break; } } if (starti == 0) { assert(bez->sflag); nbez->sp = boxIntersectf(bez->sp, bez->list[starti], bb); } else { starti -= 3; if (bez->sflag) starti = arrowStartClip(e, bez->list, starti, endi - 3, nbez, bez->sflag); } fixed = 1; } } } if (fixed == 0) { /* if no lt, or something went wrong, use original tail */ /* Note: starti == 0 */ if (bez->sflag) nbez->sp = bez->sp; } /* complete Bezier, free garbage and attach new Bezier to edge */ nbez->size = endi - starti + 1; nbez->list = N_GNEW(nbez->size, pointf); for (i = 0, j = starti; i < nbez->size; i++, j++) nbez->list[i] = bez->list[j]; free(bez->list); free(bez); ED_spl(e)->list = nbez; }