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