Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
circularinit.c
Go to the documentation of this file.
1
6/*************************************************************************
7 * Copyright (c) 2011 AT&T Intellectual Property
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the Eclipse Public License v1.0
10 * which accompanies this distribution, and is available at
11 * https://www.eclipse.org/legal/epl-v10.html
12 *
13 * Contributors: Details at https://graphviz.org
14 *************************************************************************/
15
16#include <cgraph/alloc.h>
17#include <circogen/circular.h>
18#include <neatogen/adjust.h>
19#include <pack/pack.h>
20#include <neatogen/neatoprocs.h>
21#include <stddef.h>
22#include <stdbool.h>
23#include <string.h>
24
25static void circular_init_edge(edge_t * e)
26{
27 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
29
30 ED_factor(e) = late_double(e, E_weight, 1.0, 0.0);
31}
32
33
35{
36 node_t *n;
37 edge_t *e;
38 int i = 0;
39 ndata* alg = gv_calloc(agnnodes(g), sizeof(ndata));
40
41 GD_neato_nlist(g) = gv_calloc(agnnodes(g) + 1, sizeof(node_t*));
42 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
44 ND_alg(n) = alg + i;
45 GD_neato_nlist(g)[i++] = n;
46 }
47 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
48 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
50 }
51 }
52}
53
54
56{
58 /* GD_ndim(g) = late_int(g,agfindattr(g,"dim"),2,2); */
59 Ndim = GD_ndim(agroot(g)) = 2; /* The algorithm only makes sense in 2D */
61}
62
63/* Make a node in the derived graph, with the given name.
64 * orig points to what it represents, either a real node or
65 * a cluster. Copy size info from original node; needed for
66 * adjustNodes and packSubgraphs.
67 */
68static node_t *makeDerivedNode(graph_t * dg, char *name, int isNode,
69 void *orig)
70{
71 node_t *n = agnode(dg, name,1);
72 agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), true); //node custom data
73 ND_alg(n) = gv_alloc(sizeof(cdata));
74 if (isNode) {
75 ND_pos(n) = gv_calloc(Ndim, sizeof(double));
76 ND_lw(n) = ND_lw(orig);
77 ND_rw(n) = ND_rw(orig);
78 ND_ht(n) = ND_ht(orig);
79 ORIGN(n) = orig;
80 } else
81 ORIGG(n) = orig;
82 return n;
83}
84
85/* Construct a strict, undirected graph with no loops from g.
86 * Construct the connected components with the provision that all
87 * nodes in a block subgraph are considered connected.
88 * Return array of components with number of components in cnt.
89 * Each component has its blocks as subgraphs.
90 * FIX: Check that blocks are disjoint.
91 */
92static Agraph_t **circomps(Agraph_t *g, size_t *cnt) {
93 Agraph_t **ccs;
94 Agraph_t *dg;
95 Agnode_t *n, *v, *dt, *dh;
96 Agedge_t *e;
97 Agraph_t *sg;
98 Agedge_t *ep;
99 Agnode_t *p;
100
101 dg = agopen("derived", Agstrictundirected,NULL);
102 agbindrec (dg, "info", sizeof(Agraphinfo_t), true);
103 GD_alg(g) = dg; /* store derived graph for closing later */
104
105 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
106 if (DNODE(v))
107 continue;
108 n = makeDerivedNode(dg, agnameof(v), 1, v);
109 DNODE(v) = n;
110 }
111
112 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
113 for (e = agfstout(g, v); e; e = agnxtout(g, e)) {
114 dt = DNODE(agtail(e));
115 dh = DNODE(aghead(e));
116 if (dt != dh) {
117 agbindrec(agedge(dg, dt, dh, NULL, 1), "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
118 }
119 }
120 }
121
122 size_t c_cnt;
123 ccs = ccomps(dg, &c_cnt, 0);
124
125 /* replace block nodes with block contents */
126 for (size_t i = 0; i < c_cnt; i++) {
127 sg = ccs[i];
128
129 /* add edges: since sg is a union of components, all edges
130 * of any node should be added, except loops.
131 */
132 for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
133 p = ORIGN(n);
134 for (e = agfstout(g, p); e; e = agnxtout(g, e)) {
135 /* n = DNODE(agtail(e)); by construction since agtail(e) == p */
136 dh = DNODE(aghead(e));
137 if (n != dh) {
138 ep = agedge(dg, n, dh, NULL, 1);
139 agbindrec(ep, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
140 agsubedge(sg,ep,1);
141 }
142 }
143 }
144 }
145
146 /* Finally, add edge data to edges */
147 for (n = agfstnode(dg); n; n = agnxtnode(dg, n)) {
148 for (e = agfstout(dg, n); e; e = agnxtout(dg, e)) {
149 ED_alg(e) = gv_alloc(sizeof(edata));
150 }
151 }
152
153 *cnt = c_cnt;
154 return ccs;
155}
156
158{
159 node_t *n;
160 edge_t *e;
161
162 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
163 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
164 free(ED_alg(e));
165 }
166 free(ND_alg(n));
167 free(ND_pos(n));
168 }
169 agclose(g);
170}
171
172/* Copy position of nodes in given subgraph of derived graph
173 * to corresponding node in original graph.
174 * FIX: consider assigning from n directly to ORIG(n).
175 */
176static void copyPosns(graph_t * g)
177{
178 node_t *n;
179 node_t *v;
180
181 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
182 v = ORIGN(n);
183 ND_pos(v)[0] = ND_pos(n)[0];
184 ND_pos(v)[1] = ND_pos(n)[1];
185 }
186}
187
189{
190 Agraph_t **ccs;
191 Agraph_t *sg;
192
193 if (agnnodes(g)) {
194 size_t ncc;
195 ccs = circomps(g, &ncc);
196
197 int blockCount = 0;
198 if (ncc == 1) {
199 circularLayout(ccs[0], g, &blockCount);
200 copyPosns(ccs[0]);
201 adjustNodes(g);
202 } else {
203 Agraph_t *dg = ccs[0]->root;
204 pack_info pinfo;
205 getPackInfo(g, l_node, CL_OFFSET, &pinfo);
206
207 for (size_t i = 0; i < ncc; i++) {
208 sg = ccs[i];
209 circularLayout(sg, g, &blockCount);
210 adjustNodes(sg);
211 }
212 /* FIX: splines have not been calculated for dg
213 * To use, either do splines in dg and copy to g, or
214 * construct components of g from ccs and use that in packing.
215 */
216 packSubgraphs(ncc, ccs, dg, &pinfo);
217 for (size_t i = 0; i < ncc; i++)
218 copyPosns(ccs[i]);
219 }
220 free(ccs);
221 }
222}
223
225{
226 if (agnnodes(g) == 0) return;
228 circoLayout(g);
229 /* Release ND_alg as we need to reuse it during edge routing */
230 free(ND_alg(agfstnode(g)));
231 spline_edges(g);
233}
234
237{
238 node_t *n;
239 edge_t *e;
240
241 n = agfstnode(g);
242 if (n == NULL)
243 return; /* g is empty */
244
245 closeDerivedGraph(GD_alg(g)); // delete derived graph
246
247 /* free (ND_alg(n)); */
248 for (; n; n = agnxtnode(g, n)) {
249 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
251 }
253 }
255}
256
int adjustNodes(graph_t *G)
Definition adjust.c:1027
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static void * gv_alloc(size_t size)
Definition alloc.h:47
void circularLayout(Agraph_t *g, Agraph_t *realg, int *blockCount)
Definition circular.c:65
#define DNODE(n)
Definition circular.h:74
#define ORIGG(n)
Definition circular.h:80
#define ORIGN(n)
Definition circular.h:81
static node_t * makeDerivedNode(graph_t *dg, char *name, int isNode, void *orig)
static void closeDerivedGraph(graph_t *g)
static void circular_init_node_edge(graph_t *g)
void circoLayout(Agraph_t *g)
static void copyPosns(graph_t *g)
void circo_init_graph(graph_t *g)
void circo_layout(Agraph_t *g)
static Agraph_t ** circomps(Agraph_t *g, size_t *cnt)
void circo_cleanup(graph_t *g)
ND_alg is freed in circo_layout.
static void circular_init_edge(edge_t *e)
void setEdgeType(graph_t *g, int defaultValue)
Definition utils.c:1443
double late_double(void *obj, attrsym_t *attr, double defaultValue, double minimum)
Definition utils.c:48
void common_init_edge(edge_t *e)
Definition utils.c:505
#define CL_OFFSET
Definition const.h:151
#define EDGETYPE_LINE
Definition const.h:249
Agsym_t * E_weight
Definition globals.h:91
unsigned short Ndim
Definition globals.h:64
void free(void *)
node NULL
Definition grammar.y:149
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:199
int agnnodes(Agraph_t *g)
Definition graph.c:158
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:260
Agedge_t * agsubedge(Agraph_t *g, Agedge_t *e, int createflag)
Definition edge.c:355
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:23
#define agtail(e)
Definition cgraph.h:889
#define ED_alg(e)
Definition types.h:578
#define ED_factor(e)
Definition types.h:585
#define aghead(e)
Definition cgraph.h:890
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:38
#define GD_alg(g)
Definition types.h:358
Agdesc_t Agstrictundirected
strict undirected
Definition graph.c:276
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Definition graph.c:96
Agraph_t * agopen(char *name, Agdesc_t desc, Agdisc_t *disc)
creates a new graph with the given name and kind
Definition graph.c:44
#define GD_ndim(g)
Definition types.h:390
#define GD_neato_nlist(g)
Definition types.h:392
Agnode_t * agnode(Agraph_t *g, char *name, int createflag)
Definition node.c:147
#define ND_ht(n)
Definition types.h:500
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
#define ND_alg(n)
Definition types.h:484
#define ND_rw(n)
Definition types.h:525
#define ND_lw(n)
Definition types.h:506
#define ND_pos(n)
Definition types.h:520
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
Agraph_t * agroot(void *obj)
Definition obj.c:167
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:88
Agraph_t ** ccomps(Agraph_t *g, size_t *ncc, char *pfx)
Definition ccomps.c:205
void neato_init_node(node_t *n)
Definition neatoinit.c:56
NEATOPROCS_API void spline_edges(Agraph_t *)
int packSubgraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
Definition pack.c:1070
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
Definition pack.c:1253
support for connected components
@ l_node
Definition pack.h:55
void dotneato_postprocess(Agraph_t *g)
Definition postproc.c:693
void gv_cleanup_edge(Agedge_t *e)
Definition utils.c:1533
void gv_cleanup_node(Agnode_t *n)
Definition utils.c:1545
graph or subgraph
Definition cgraph.h:425
Agraph_t * root
subgraphs - ancestors
Definition cgraph.h:434