Graphviz 16.1.1~dev.20261004.1917
Loading...
Searching...
No Matches
twopiinit.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v2.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11/*
12 * Written by Emden R. Gansner
13 * Derived from Graham Wills' algorithm described in GD'97.
14 */
15
16#include "config.h"
17
18#include <cgraph/cgraph.h>
19#include <neatogen/adjust.h>
20#include <neatogen/neatoprocs.h>
21#include <pack/pack.h>
22#include <stdbool.h>
23#include <stddef.h>
24#include <twopigen/circle.h>
25#include <util/alloc.h>
26
27static void twopi_init_edge(edge_t *e) {
28 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); // edge custom data
30 ED_factor(e) = late_double(e, E_weight, 1.0, 0.0);
31}
32
34 node_t *n;
35 edge_t *e;
36 int i = 0;
37 const size_t n_nodes = agnnodes_z(g);
38
39 rdata *alg = gv_calloc(n_nodes, sizeof(rdata));
40 GD_neato_nlist(g) = gv_calloc(n_nodes + 1, sizeof(node_t *));
41 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
43 ND_alg(n) = alg + i;
44 GD_neato_nlist(g)[i++] = n;
45 }
46 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
47 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
49 }
50 }
51}
52
55 Ndim = GD_ndim(agroot(g)) = 2; /* The algorithm only makes sense in 2D */
57}
58
59static Agnode_t *findRootNode(Agraph_t *sg, Agsym_t *rootattr) {
60 Agnode_t *n;
61
62 for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
63 if (mapbool(agxget(n, rootattr)))
64 return n;
65 }
66 return NULL;
67}
68
70 Agnode_t *ctr = 0;
71 char *s;
72 bool setRoot = false;
73 bool setLocalRoot = false;
74 Agsym_t *rootattr;
75
76 if (agnnodes(g) == 0)
77 return;
78
80 if ((s = agget(g, "root"))) {
81 if (*s) {
82 ctr = agfindnode(g, s);
83 if (!ctr) {
84 agwarningf("specified root node \"%s\" was not found.", s);
85 agerr(AGPREV, "Using default calculation for root node\n");
86 setRoot = true;
87 }
88 } else {
89 setRoot = true;
90 }
91 }
92 if ((rootattr = agattr_text(g, AGNODE, "root", 0))) {
93 setLocalRoot = true;
94 }
95
96 if (agnnodes(g)) {
97 Agnode_t *lctr;
98
99 size_t ncc;
100 Agraph_t **const ccs = ccomps(g, &ncc, 0);
101 if (ncc == 1) {
102 if (ctr)
103 lctr = ctr;
104 else if (!rootattr || !(lctr = findRootNode(g, rootattr)))
105 lctr = 0;
106 Agnode_t *const c = circleLayout(g, lctr);
107 if (setRoot && !ctr)
108 ctr = c;
109 if (setLocalRoot && !lctr)
110 agxset(c, rootattr, "1");
111 Agnode_t *const n = agfstnode(g);
112 free(ND_alg(n));
113 ND_alg(n) = NULL;
114 adjustNodes(g);
115 spline_edges(g);
116 } else {
117 pack_info pinfo;
118 getPackInfo(g, l_node, CL_OFFSET, &pinfo);
119 pinfo.doSplines = false;
120
121 for (size_t i = 0; i < ncc; i++) {
122 Agraph_t *const sg = ccs[i];
123 if (ctr && agcontains(sg, ctr))
124 lctr = ctr;
125 else if (!rootattr || !(lctr = findRootNode(sg, rootattr)))
126 lctr = 0;
127 (void)graphviz_node_induce(sg, NULL);
128 Agnode_t *const c = circleLayout(sg, lctr);
129 if (setRoot && !ctr)
130 ctr = c;
131 if (setLocalRoot && (!lctr || (lctr == ctr)))
132 agxset(c, rootattr, "1");
133 adjustNodes(sg);
134 }
135 Agnode_t *const n = agfstnode(g);
136 if (n != NULL) {
137 free(ND_alg(n));
138 ND_alg(n) = NULL;
139 }
140 packSubgraphs(ncc, ccs, g, &pinfo);
141 spline_edges(g);
142 }
143 for (size_t i = 0; i < ncc; i++) {
144 agdelete(g, ccs[i]);
145 }
146 free(ccs);
147 }
148 if (setRoot)
149 agset(g, "root", agnameof(ctr));
151}
152
154
155/* The ND_alg data used by twopi is freed in twopi_layout
156 * before edge routing as edge routing may use this field.
157 */
159 node_t *n;
160 edge_t *e;
161
162 n = agfstnode(g);
163 if (!n)
164 return; /* empty graph */
165 for (; n; n = agnxtnode(g, n)) {
166 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
168 }
170 }
172}
173
int adjustNodes(graph_t *G)
Definition adjust.c:999
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
abstract graph C library, Cgraph API
Agnode_t * circleLayout(Agraph_t *sg, Agnode_t *center)
Definition circle.c:311
bool mapbool(const char *p)
Definition utils.c:341
void setEdgeType(graph_t *g, int defaultValue)
Definition utils.c:1412
double late_double(void *obj, attrsym_t *attr, double defaultValue, double minimum)
Definition utils.c:55
void common_init_edge(edge_t *e)
Definition utils.c:498
#define CL_OFFSET
Definition const.h:142
#define EDGETYPE_LINE
Definition const.h:235
Agsym_t * E_weight
Definition globals.h:83
unsigned short Ndim
Definition globals.h:65
void free(void *)
node NULL
Definition grammar.y:181
int agnnodes(Agraph_t *g)
Definition graph.c:163
size_t agnnodes_z(const Agraph_t *g)
Definition graph.c:161
size_t graphviz_node_induce(Agraph_t *g, Agraph_t *edgeset)
Definition node_induce.c:12
Agsym_t * agattr_text(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up text attributes of a graph
Definition attr.c:333
int agset(void *obj, char *name, const char *value)
Definition attr.c:474
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:521
char * agget(void *obj, char *name)
Definition attr.c:447
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:457
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:28
#define ED_factor(e)
Definition types.h:585
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:43
void agwarningf(const char *fmt,...)
Definition agerror.c:175
int agerr(agerrlevel_t level, const char *fmt,...)
Definition agerror.c:157
@ AGPREV
Definition cgraph.h:951
#define GD_ndim(g)
Definition types.h:390
#define GD_neato_nlist(g)
Definition types.h:392
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:50
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:43
#define ND_alg(n)
Definition types.h:484
#define agfindnode(g, n)
Definition types.h:611
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:145
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Definition obj.c:22
int agcontains(Agraph_t *, void *obj)
returns non-zero if obj is a member of (sub)graph
Definition obj.c:235
Agraph_t * agroot(void *obj)
Definition obj.c:170
@ AGNODE
Definition cgraph.h:207
void * agbindrec(void *obj, const char *name, unsigned int recsize, int move_to_front)
attaches a new record of the given size to the object
Definition rec.c:91
Agraph_t ** ccomps(Agraph_t *g, size_t *ncc, char *pfx)
Definition ccomps.c:185
void neato_init_node(node_t *n)
Definition neatoinit.c:60
NEATOPROCS_API void spline_edges(Agraph_t *)
int packSubgraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
Definition pack.c:1108
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
Definition pack.c:1285
support for connected components
@ l_node
Definition pack.h:55
void dotneato_postprocess(Agraph_t *g)
Definition postproc.c:691
void gv_cleanup_edge(Agedge_t *e)
Definition utils.c:1502
void gv_cleanup_node(Agnode_t *n)
Definition utils.c:1514
graph or subgraph
Definition cgraph.h:424
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:641
bool doSplines
use splines in constructing graph shape
Definition pack.h:71
static void twopi_init_edge(edge_t *e)
Definition twopiinit.c:27
static Agnode_t * findRootNode(Agraph_t *sg, Agsym_t *rootattr)
Definition twopiinit.c:59
static void twopi_init_node_edge(graph_t *g)
Definition twopiinit.c:33
void twopi_layout(Agraph_t *g)
Definition twopiinit.c:69
static void twopi_cleanup_graph(graph_t *g)
Definition twopiinit.c:153
void twopi_cleanup(graph_t *g)
Definition twopiinit.c:158
void twopi_init_graph(graph_t *g)
Definition twopiinit.c:53
Definition grammar.c:90