Graphviz 15.1.1~dev.20260630.1303
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 v2.0
10 * which accompanies this distribution, and is available at
11 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
12 *
13 * Contributors: Details at https://graphviz.org
14 *************************************************************************/
15
16#include "config.h"
17
18#include <cgraph/cghdr.h>
19#include <circogen/circular.h>
20#include <neatogen/adjust.h>
21#include <pack/pack.h>
22#include <neatogen/neatoprocs.h>
23#include <stddef.h>
24#include <stdbool.h>
25#include <string.h>
26#include <util/alloc.h>
27
28static void circular_init_edge(edge_t * e)
29{
30 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
32
33 ED_factor(e) = late_double(e, E_weight, 1.0, 0.0);
34}
35
36
38{
39 node_t *n;
40 edge_t *e;
41 int i = 0;
42 ndata *alg = gv_calloc(agnnodes_z(g), sizeof(ndata));
43
44 GD_neato_nlist(g) = gv_calloc(agnnodes_z(g) + 1, sizeof(node_t *));
45 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
47 ND_alg(n) = alg + i;
48 GD_neato_nlist(g)[i++] = n;
49 }
50 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
51 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
53 }
54 }
55}
56
57
59{
61 /* GD_ndim(g) = late_int(g,agfindattr(g,"dim"),2,2); */
62 Ndim = GD_ndim(agroot(g)) = 2; /* The algorithm only makes sense in 2D */
64}
65
66/* Make a node in the derived graph, with the given name.
67 * orig points to what it represents, either a real node or
68 * a cluster. Copy size info from original node; needed for
69 * adjustNodes and packSubgraphs.
70 */
71static node_t *makeDerivedNode(graph_t * dg, char *name, int isNode,
72 void *orig)
73{
74 node_t *n = agnode(dg, name,1);
75 agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), true); //node custom data
76 ND_alg(n) = gv_alloc(sizeof(cdata));
77 if (isNode) {
78 ND_pos(n) = gv_calloc(Ndim, sizeof(double));
79 ND_lw(n) = ND_lw(orig);
80 ND_rw(n) = ND_rw(orig);
81 ND_ht(n) = ND_ht(orig);
82 ORIGN(n) = orig;
83 } else
84 ORIGG(n) = orig;
85 return n;
86}
87
88/* Construct a strict, undirected graph with no loops from g.
89 * Construct the connected components with the provision that all
90 * nodes in a block subgraph are considered connected.
91 * Return array of components with number of components in cnt.
92 * Each component has its blocks as subgraphs.
93 * FIX: Check that blocks are disjoint.
94 */
95static Agraph_t **circomps(Agraph_t *g, size_t *cnt) {
96 Agraph_t **ccs;
97 Agraph_t *dg;
98 Agnode_t *n, *v, *dt, *dh;
99 Agedge_t *e;
100 Agraph_t *sg;
101 Agedge_t *ep;
102 Agnode_t *p;
103
104 dg = agopen("derived", Agstrictundirected,NULL);
105 agbindrec (dg, "info", sizeof(Agraphinfo_t), true);
106 GD_alg(g) = dg; /* store derived graph for closing later */
107
108 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
109 if (DNODE(v))
110 continue;
111 n = makeDerivedNode(dg, agnameof(v), 1, v);
112 DNODE(v) = n;
113 }
114
115 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
116 for (e = agfstout(g, v); e; e = agnxtout(g, e)) {
117 dt = DNODE(agtail(e));
118 dh = DNODE(aghead(e));
119 if (dt != dh) {
120 agbindrec(agedge(dg, dt, dh, NULL, 1), "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
121 }
122 }
123 }
124
125 size_t c_cnt;
126 ccs = ccomps(dg, &c_cnt, 0);
127
128 /* replace block nodes with block contents */
129 for (size_t i = 0; i < c_cnt; i++) {
130 sg = ccs[i];
131
132 /* add edges: since sg is a union of components, all edges
133 * of any node should be added, except loops.
134 */
135 for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
136 p = ORIGN(n);
137 for (e = agfstout(g, p); e; e = agnxtout(g, e)) {
138 /* n = DNODE(agtail(e)); by construction since agtail(e) == p */
139 dh = DNODE(aghead(e));
140 if (n != dh) {
141 ep = agedge(dg, n, dh, NULL, 1);
142 agbindrec(ep, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
143 agsubedge(sg,ep,1);
144 }
145 }
146 }
147 }
148
149 /* Finally, add edge data to edges */
150 for (n = agfstnode(dg); n; n = agnxtnode(dg, n)) {
151 for (e = agfstout(dg, n); e; e = agnxtout(dg, e)) {
152 ED_alg(e) = gv_alloc(sizeof(edata));
153 }
154 }
155
156 *cnt = c_cnt;
157 return ccs;
158}
159
161{
162 node_t *n;
163 edge_t *e;
164
165 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
166 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
167 free(ED_alg(e));
168 }
169 free(ND_alg(n));
170 free(ND_pos(n));
171 }
172 agclose(g);
173}
174
175/* Copy position of nodes in given subgraph of derived graph
176 * to corresponding node in original graph.
177 * FIX: consider assigning from n directly to ORIG(n).
178 */
179static void copyPosns(graph_t * g)
180{
181 node_t *n;
182 node_t *v;
183
184 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
185 v = ORIGN(n);
186 ND_pos(v)[0] = ND_pos(n)[0];
187 ND_pos(v)[1] = ND_pos(n)[1];
188 }
189}
190
192{
193 Agraph_t **ccs;
194 Agraph_t *sg;
195
196 if (agnnodes(g)) {
197 size_t ncc;
198 ccs = circomps(g, &ncc);
199
200 int blockCount = 0;
201 if (ncc == 1) {
202 circularLayout(ccs[0], g, &blockCount);
203 copyPosns(ccs[0]);
204 adjustNodes(g);
205 } else {
206 Agraph_t *dg = ccs[0]->root;
207 pack_info pinfo;
208 getPackInfo(g, l_node, CL_OFFSET, &pinfo);
209
210 for (size_t i = 0; i < ncc; i++) {
211 sg = ccs[i];
212 circularLayout(sg, g, &blockCount);
213 adjustNodes(sg);
214 }
215 /* FIX: splines have not been calculated for dg
216 * To use, either do splines in dg and copy to g, or
217 * construct components of g from ccs and use that in packing.
218 */
219 packSubgraphs(ncc, ccs, dg, &pinfo);
220 for (size_t i = 0; i < ncc; i++)
221 copyPosns(ccs[i]);
222 }
223 free(ccs);
224 }
225}
226
228{
229 if (agnnodes(g) == 0) return;
231 circoLayout(g);
232 /* Release ND_alg as we need to reuse it during edge routing */
233 free(ND_alg(agfstnode(g)));
234 spline_edges(g);
236}
237
240{
241 node_t *n;
242 edge_t *e;
243
244 n = agfstnode(g);
245 if (n == NULL)
246 return; /* g is empty */
247
248 closeDerivedGraph(GD_alg(g)); // delete derived graph
249
250 /* free (ND_alg(n)); */
251 for (; n; n = agnxtnode(g, n)) {
252 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
254 }
256 }
258}
259
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
static void * gv_alloc(size_t size)
Definition alloc.h:47
cgraph.h additions
size_t agnnodes_z(const Agraph_t *g)
Definition graph.c:157
void circularLayout(Agraph_t *g, Agraph_t *realg, int *blockCount)
Definition circular.c:67
#define DNODE(n)
Definition circular.h:75
#define ORIGG(n)
Definition circular.h:81
#define ORIGN(n)
Definition circular.h:82
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:1423
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:509
#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
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:200
int agnnodes(Agraph_t *g)
Definition graph.c:159
Agedge_t * agedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, char *name, int createflag)
Definition edge.c:255
Agedge_t * agsubedge(Agraph_t *g, Agedge_t *e, int createflag)
Definition edge.c:350
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:28
#define agtail(e)
Definition cgraph.h:977
#define ED_alg(e)
Definition types.h:578
#define ED_factor(e)
Definition types.h:585
#define aghead(e)
Definition cgraph.h:978
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:43
#define GD_alg(g)
Definition types.h:358
Agdesc_t Agstrictundirected
strict undirected
Definition graph.c:277
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
Definition graph.c:97
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:143
#define ND_ht(n)
Definition types.h:500
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 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:145
Agraph_t * agroot(void *obj)
Definition obj.c:170
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:61
NEATOPROCS_API void spline_edges(Agraph_t *)
int packSubgraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
Definition pack.c:1107
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
Definition pack.c:1284
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:1513
void gv_cleanup_node(Agnode_t *n)
Definition utils.c:1525
graph or subgraph
Definition cgraph.h:424
Agraph_t * root
subgraphs - ancestors
Definition cgraph.h:433