#include "adjust.h"
#include "pack.h"
#include "neatoprocs.h"
-#include <string.h>
-
-void circo_nodesize(node_t * n, boolean flip)
-{
- int w;
-
- w = ND_xsize(n) = POINTS(ND_width(n));
- ND_lw_i(n) = ND_rw_i(n) = w / 2;
- ND_ht_i(n) = ND_ysize(n) = POINTS(ND_height(n));
-}
-
+#include <string.h>
static void circular_init_node(node_t * n)
{
common_init_node(n);
- circo_nodesize(n, GD_flip(n->graph));
+ neato_nodesize(n, GD_flip(n->graph));
ND_pos(n) = N_NEW(GD_ndim(n->graph), double);
ND_alg(n) = NEW(ndata);
}
circo_init_graph(g);
circoLayout(g);
spline_edges(g);
- dotneato_postprocess(g, circo_nodesize);
+ dotneato_postprocess(g);
}
static void circular_cleanup_node(node_t * n)
CL_type = maptoken(p, rankname, rankcode);
p = agget(g, "concentrate");
Concentrate = mapbool(p);
+ State = GVBEGIN;
GD_drawing(g)->dpi = 0.0;
if (((p = agget(g, "dpi")) && p[0])
translate_bb(GD_clust(g)[c], rankdir);
}
-static void translate_drawing(graph_t * g, nodesizefn_t ns)
+void dot_nodesize(node_t * n, boolean flip)
+{
+ double x, y;
+ int ps;
+
+ if (flip == FALSE) {
+ x = ND_width(n);
+ y = ND_height(n);
+ } else {
+ y = ND_width(n);
+ x = ND_height(n);
+ }
+ ps = POINTS(x) / 2;
+ if (ps < 1)
+ ps = 1;
+ ND_lw_i(n) = ND_rw_i(n) = ps;
+ ND_ht_i(n) = POINTS(y);
+}
+
+/* translate_drawing:
+ * Translate and/or rotate nodes, spline points, and bbox info if
+ * Offset is non-trivial.
+ * Also, if Rankdir, reset ND_lw, ND_rw, and ND_ht to correct value.
+ */
+static void translate_drawing(graph_t * g)
{
node_t *v;
edge_t *e;
int shift = (Offset.x || Offset.y);
+ if (!shift && !Rankdir) return;
for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
- ns(v, FALSE);
+ if (Rankdir) dot_nodesize(v, FALSE);
if (shift) {
ND_coord_i(v) = map_point(ND_coord_i(v));
- for (e = agfstout(g, v); e; e = agnxtout(g, e))
- map_edge(e);
+ if (State == GVSPLINES)
+ for (e = agfstout(g, v); e; e = agnxtout(g, e))
+ map_edge(e);
}
}
if (shift)
* 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, nodesizefn_t ns)
+void dotneato_postprocess(Agraph_t * g)
{
int diff;
pointf dimen;
Offset = pointof(GD_bb(g).LL.y, GD_bb(g).LL.x);
break;
}
- translate_drawing(g, ns);
+ translate_drawing(g);
if (GD_label(g) && !GD_label(g)->set)
place_root_label(g, d);
extern void graph_cleanup(graph_t * g);
extern void dotneato_args_initialize(GVC_t * gvc, int, char **);
extern void dotneato_usage(int);
- extern void dotneato_postprocess(Agraph_t *, nodesizefn_t);
+ extern void dotneato_postprocess(Agraph_t *);
extern void dotneato_set_margins(GVC_t * gvc, Agraph_t *);
extern void dotneato_write(GVC_t * gvc, graph_t *g);
extern void dotneato_write_one(GVC_t * gvc, graph_t *g);
#include "dot.h"
-
-void dot_nodesize(node_t * n, boolean flip)
-{
- double x, y;
- int ps;
-
- if (flip == FALSE) {
- x = ND_width(n);
- y = ND_height(n);
- } else {
- y = ND_width(n);
- x = ND_height(n);
- }
- ps = POINTS(x) / 2;
- if (ps < 1)
- ps = 1;
- ND_lw_i(n) = ND_rw_i(n) = ps;
- ND_ht_i(n) = POINTS(y);
-}
-
static void
dot_init_node(node_t * n)
{
dot_splines(g);
if (mapbool(agget(g, "compound")))
dot_compoundEdges(g);
- dotneato_postprocess(g, dot_nodesize);
+ dotneato_postprocess(g);
}
}
/* dot_splines:
+ * If the splines attribute is defined but equal to "", skip edge routing.
*/
void dot_splines(graph_t * g)
{
edge_t *e, *e0, *e1, *ea, *eb, *le0, *le1, **edges;
path *P;
spline_info_t sd;
+ char* s = agget(g, "splines");
+
+ if (s && (*s == '\0')) return;
mark_lowclusters(g);
routesplinesinit();
attrsym_t* E_weight;
attrsym_t* E_minlen;
attrsym_t* N_group;
+ int State;
} attr_state;
/* cloneGraph:
attr_state.E_weight = E_weight;
attr_state.E_minlen = E_minlen;
attr_state.N_group = N_group;
+ attr_state.State = State;
E_constr = NULL;
E_samehead = agfindattr(auxg->proto->e, "samehead");
E_sametail = agfindattr(auxg->proto->e, "sametail");
E_weight = attr_state.E_weight;
E_minlen = attr_state.E_minlen;
N_group = attr_state.N_group;
+ State = attr_state.State;
dot_cleanup(g);
agclose(g);
}
dot_sameports(auxg);
dot_splines(auxg);
- dotneato_postprocess(auxg, dot_nodesize);
+ dotneato_postprocess(auxg);
/* copy splines */
if (GD_flip(g)) {
setBB(g);
}
-void fdp_layout(graph_t * g)
+static void
+fdpSplines (graph_t * g, char* str)
{
char *str;
int trySplines = 0;
- State = 0; /* initialize state */
- fdp_init_graph(g);
- fdpLayout(g);
-
- str = agget(g, "splines");
if (str) {
if (streq(str, "compound")) {
trySplines = splineEdges(g, compoundEdges, 1);
- /* When doing the edges again, accept edges done by compoundeEdges */
+ /* When doing the edges again, accept edges done by compoundEdges */
if (trySplines)
Nop = 2;
}
}
if (State < GVSPLINES)
spline_edges1(g, 0);
- dotneato_postprocess(g, neato_nodesize);
+}
+
+void fdp_layout(graph_t * g)
+{
+ char *str;
+
+ fdp_init_graph(g);
+ fdpLayout(g);
+ neato_set_aspect(g);
+
+ str = agget(g, "splines");
+ if (!str || *str) fdpSplines (g, str);
+
+ dotneato_postprocess(g);
}
spline_edges(g);
}
}
- dotneato_postprocess(g, neato_nodesize);
+ dotneato_postprocess(g);
}
/* splineEdges:
* Main wrapper code for generating edges.
- * Gets desired separation, sets the graph's aspect ratio,
- * and coalesces equivalent edges (edges
- * with the same endpoints). This also copies the internal
- * layout coordinates (ND_pos) to the external ones (ND_coord_i).
+ * Sets desired separation.
+ * Coalesces equivalent edges (edges * with the same endpoints).
* It then calls the edge generating function, and marks the
* spline phase complete.
* Returns 0 on success.
*
- * Assumes u.bb for has been computed for g and all clusters
- * (not just top-level clusters), and that GD_bb(g).LL is at the origin.
- *
- * This last criterion is, I believe, mainly to simplify the code
- * in neato_set_aspect. It would be good to remove this constraint,
- * as this would allow nodes pinned on input to have the same coordinates
- * when output in dot or plain format.
- *
* The edge function is given the graph, the separation to be added
* around obstacles, and the type of edge. (At present, this is a boolean,
* with 1 meaning splines and 0 meaning line segments.) It must guarantee
* still overlap.
*/
SEP = 1.01;
- neato_set_aspect(g);
/* find equivalent edges */
map = dtopen(&edgeItemDisc, Dtoset);
for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
- ND_coord_i(n).x = POINTS(ND_pos(n)[0]);
- ND_coord_i(n).y = POINTS(ND_pos(n)[1]);
for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
edge_t *leader = equivEdge(map, e);
if (leader != e) {
}
/* spline_edges0:
+ * Sets the graph's aspect ratio.
* Check splines attribute and construct edges using default algorithm.
+ * If the splines attribute is defined but equal to "", skip edge routing.
+ *
+ * Assumes u.bb for has been computed for g and all clusters
+ * (not just top-level clusters), and that GD_bb(g).LL is at the origin.
+ *
+ * This last criterion is, I believe, mainly to simplify the code
+ * in neato_set_aspect. It would be good to remove this constraint,
+ * as this would allow nodes pinned on input to have the same coordinates
+ * when output in dot or plain format.
+ *
*/
void spline_edges0(graph_t * g)
{
- spline_edges1(g, mapbool(agget(g, "splines")));
+ char* s = agget(g, "splines");
+
+ neato_set_aspect(g);
+ if (s && (*s == '\0')) return;
+ spline_edges1(g, mapbool(s));
}
/* spline_edges:
scaleBB(GD_clust(g)[i], xf, yf);
}
-/* neato_set_aspect;
+/* _neato_set_aspect;
* Assume all bounding boxes are correct and
* that GD_bb(g).LL is at origin.
*/
-void neato_set_aspect(graph_t * g)
+static void _neato_set_aspect(graph_t * g)
{
/* int i; */
double xf, yf, actual, desired;
}
}
}
+
+/* neato_set_aspect:
+ * Sets aspect ration if necessary; real work done in _neato_set_aspect;
+ * This also copies the internal layout coordinates (ND_pos) to the
+ * external ones (ND_coord_i).
+ */
+void neato_set_aspect(graph_t * g)
+{
+ node_t *n;
+
+ _neato_set_aspect(g);
+ for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
+ ND_coord_i(n).x = POINTS(ND_pos(n)[0]);
+ ND_coord_i(n).y = POINTS(ND_pos(n)[1]);
+ }
+}
+