Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
sfdpinit.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 v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11
12#include "config.h"
13#include <float.h>
14#include <limits.h>
15#include <sfdpgen/sfdp.h>
16#include <neatogen/neato.h>
17#include <neatogen/adjust.h>
18#include <pack/pack.h>
19#include <assert.h>
21#include <neatogen/overlap.h>
23#include <cgraph/cgraph.h>
24#include <stdbool.h>
25#include <stddef.h>
26#include <util/alloc.h>
27#include <util/gv_ctype.h>
28#include <util/strcasecmp.h>
29
30static void sfdp_init_edge(edge_t * e)
31{
32 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); //node custom data
34}
35
37{
38 node_t *n;
39 edge_t *e;
40
41 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
43 }
44 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
45 for (e = agfstout(g, n); e; e = agnxtout(g, e))
47 }
48}
49
50static void sfdp_init_graph(Agraph_t * g)
51{
52 int outdim;
53
55 outdim = late_int(g, agfindgraphattr(g, "dimen"), 2, 2);
56 GD_ndim(agroot(g)) = late_int(g, agfindgraphattr(g, "dim"), outdim, 2);
58 GD_odim(agroot(g)) = MIN(outdim, Ndim);
60}
61
62/* getPos:
63 */
64static double *getPos(Agraph_t * g)
65{
66 Agnode_t *n;
67 double *pos = gv_calloc(Ndim * agnnodes(g), sizeof(double));
68 int ix, i;
69
70 if (agfindnodeattr(g, "pos") == NULL)
71 return pos;
72
73 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
74 i = ND_id(n);
75 if (hasPos(n)) {
76 for (ix = 0; ix < Ndim; ix++) {
77 pos[i * Ndim + ix] = ND_pos(n)[ix];
78 }
79 }
80 }
81
82 return pos;
83}
84
86 pointf pad) {
87 double *sizes;
88 double *pos;
89 Agnode_t *n;
90 int flag, i;
91 int n_edge_label_nodes = 0, *edge_label_nodes = NULL;
93
94 if (ctrl->overlap >= 0) {
95 if (ctrl->edge_labeling_scheme > 0)
96 sizes = getSizes(g, pad, &n_edge_label_nodes, &edge_label_nodes);
97 else
98 sizes = getSizes(g, pad, NULL, NULL);
99 }
100 else
101 sizes = NULL;
102 pos = getPos(g);
103
104 multilevel_spring_electrical_embedding(Ndim, A, ctrl, sizes, pos, n_edge_label_nodes, edge_label_nodes, &flag);
105
106 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
107 double *npos = pos + (Ndim * ND_id(n));
108 for (i = 0; i < Ndim; i++) {
109 ND_pos(n)[i] = npos[i];
110 }
111 }
112
113 free(sizes);
114 free(pos);
116 free(edge_label_nodes);
117}
118
119static int
120late_smooth (graph_t* g, Agsym_t* sym, int dflt)
121{
122 char* s;
123 int v;
124 int rv;
125
126 if (!sym) return dflt;
127 s = agxget (g, sym);
128 if (gv_isdigit(*s)) {
129#if (defined(HAVE_GTS) || defined(HAVE_TRIANGLE))
130 if ((v = atoi (s)) <= SMOOTHING_RNG)
131#else
132 if ((v = atoi (s)) <= SMOOTHING_SPRING)
133#endif
134 rv = v;
135 else
136 rv = dflt;
137 }
138 else if (gv_isalpha(*s)) {
139 if (!strcasecmp(s, "avg_dist"))
141 else if (!strcasecmp(s, "graph_dist"))
143 else if (!strcasecmp(s, "none"))
144 rv = SMOOTHING_NONE;
145 else if (!strcasecmp(s, "power_dist"))
147#if (defined(HAVE_GTS) || defined(HAVE_TRIANGLE))
148 else if (!strcasecmp(s, "rng"))
149 rv = SMOOTHING_RNG;
150#endif
151 else if (!strcasecmp(s, "spring"))
152 rv = SMOOTHING_SPRING;
153#if (defined(HAVE_GTS) || defined(HAVE_TRIANGLE))
154 else if (!strcasecmp(s, "triangle"))
156#endif
157 else
158 rv = dflt;
159 }
160 else
161 rv = dflt;
162 return rv;
163}
164
165static int
167{
168 char* s;
169 int v;
170 int rv;
171
172 if (!sym) return dflt;
173 s = agxget (g, sym);
174 if (gv_isdigit(*s)) {
175 if ((v = atoi (s)) <= QUAD_TREE_FAST && v >= QUAD_TREE_NONE){
176 rv = v;
177 } else {
178 rv = dflt;
179 }
180 } else if (gv_isalpha(*s)) {
181 if (!strcasecmp(s, "none") || !strcasecmp(s, "false") ){
182 rv = QUAD_TREE_NONE;
183 } else if (!strcasecmp(s, "normal") || !strcasecmp(s, "true") || !strcasecmp(s, "yes")){
184 rv = QUAD_TREE_NORMAL;
185 } else if (!strcasecmp(s, "fast")){
186 rv = QUAD_TREE_FAST;
187 } else {
188 rv = dflt;
189 }
190 } else {
191 rv = dflt;
192 }
193 return rv;
194}
195
196
197/* tuneControl:
198 * Use user values to reset control
199 */
200static void
202{
203 long seed;
204 int init;
205
206 seed = ctrl->random_seed;
207 init = setSeed (g, INIT_RANDOM, &seed);
208 if (init != INIT_RANDOM) {
209 agwarningf("sfdp only supports start=random\n");
210 }
211 ctrl->random_seed = seed;
212
213 ctrl->K = late_double(g, agfindgraphattr(g, "K"), -1.0, 0.0);
214 ctrl->p = -1.0*late_double(g, agfindgraphattr(g, "repulsiveforce"), -AUTOP, 0.0);
215 ctrl->multilevels = late_int(g, agfindgraphattr(g, "levels"), INT_MAX, 0);
216 ctrl->smoothing = late_smooth(g, agfindgraphattr(g, "smoothing"), SMOOTHING_NONE);
218 ctrl->beautify_leaves = mapbool(agget(g, "beautify"));
219 ctrl->do_shrinking = mapBool(agget(g, "overlap_shrink"), true);
220 ctrl->rotation = late_double(g, agfindgraphattr(g, "rotation"), 0.0, -DBL_MAX);
221 ctrl->edge_labeling_scheme = late_int(g, agfindgraphattr(g, "label_scheme"), 0, 0);
222 if (ctrl->edge_labeling_scheme > 4) {
223 agwarningf("label_scheme = %d > 4 : ignoring\n", ctrl->edge_labeling_scheme);
224 ctrl->edge_labeling_scheme = 0;
225 }
226}
227
229{
230 int doAdjust;
231 adjust_data am;
233 doAdjust = (Ndim == 2);
234
235 if (agnnodes(g)) {
236 Agraph_t **ccs;
237 Agraph_t *sg;
238 expand_t sep;
239 pointf pad;
241
242 tuneControl (g, ctrl);
243#if (defined(HAVE_GTS) || defined(HAVE_TRIANGLE))
244 graphAdjustMode(g, &am, "prism0");
245#else
246 graphAdjustMode(g, &am, 0);
247#endif
248
249 pad.x = PS2INCH(DFLT_MARGIN);
250 pad.y = PS2INCH(DFLT_MARGIN);
251
252 if ((am.mode == AM_PRISM) && doAdjust) {
253 doAdjust = 0; /* overlap removal done in sfdp */
254 ctrl->overlap = am.value;
255 ctrl->initial_scaling = am.scaling;
256 sep = sepFactor(g);
257 if (sep.doAdd) {
258 pad.x = PS2INCH(sep.x);
259 pad.y = PS2INCH(sep.y);
260 }
261 }
262 else {
263 /* Turn off overlap removal in sfdp if prism not used */
264 ctrl->overlap = -1;
265 }
266
267 if (Verbose)
269
270 size_t ncc;
271 ccs = ccomps(g, &ncc, 0);
272 if (ncc == 1) {
273 sfdpLayout(g, ctrl, pad);
274 if (doAdjust) removeOverlapWith(g, &am);
275 spline_edges(g);
276 } else {
277 pack_info pinfo;
278 getPackInfo(g, l_node, CL_OFFSET, &pinfo);
279 pinfo.doSplines = true;
280
281 for (size_t i = 0; i < ncc; i++) {
282 sg = ccs[i];
283 (void)graphviz_node_induce(sg, NULL);
284 sfdpLayout(sg, ctrl, pad);
285 if (doAdjust) removeOverlapWith(sg, &am);
287 spline_edges(sg);
288 }
289 packSubgraphs(ncc, ccs, g, &pinfo);
290 }
291 for (size_t i = 0; i < ncc; i++) {
292 agdelete(g, ccs[i]);
293 }
294 free(ccs);
296 }
297
299}
300
302{
303 node_t *n;
304 edge_t *e;
305
306 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
307 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
309 }
311 }
312}
313
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix makeMatrix(Agraph_t *g)
Definition adjust.c:559
expand_t sepFactor(graph_t *g)
Definition adjust.c:1069
double * getSizes(Agraph_t *g, pointf pad, int *n_elabels, int **elabels)
Set up array of half sizes in inches.
Definition adjust.c:529
void graphAdjustMode(graph_t *G, adjust_data *dp, char *dflt)
Definition adjust.c:880
int removeOverlapWith(graph_t *G, adjust_data *am)
Definition adjust.c:916
#define DFLT_MARGIN
Definition adjust.h:21
@ AM_PRISM
Definition adjust.h:28
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define MIN(a, b)
Definition arith.h:28
abstract graph C library, Cgraph API
bool mapbool(const char *p)
Definition utils.c:335
void setEdgeType(graph_t *g, int defaultValue)
Definition utils.c:1434
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
Definition utils.c:33
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:504
bool mapBool(const char *p, bool defaultValue)
Definition utils.c:319
#define CL_OFFSET
Definition const.h:151
#define MAXDIM
Definition const.h:169
#define EDGETYPE_LINE
Definition const.h:249
static void init(int argc, char *argv[], double *angle, double *accuracy, int *check_edges_with_same_endpoint, int *seed, const char **color_scheme, int *lightness)
static long seed
Definition exeval.c:1035
#define A(n, t)
Definition expr.h:76
#define PS2INCH(a_points)
Definition geom.h:70
unsigned short Ndim
Definition globals.h:61
static bool Verbose
Definition gml2gv.c:23
void free(void *)
node NULL
Definition grammar.y:163
int agnnodes(Agraph_t *g)
Definition graph.c:169
size_t graphviz_node_induce(Agraph_t *g, Agraph_t *edgeset)
Definition node_induce.c:9
char * agget(void *obj, char *name)
Definition attr.c:439
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:455
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:24
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:39
void agwarningf(const char *fmt,...)
Definition agerror.c:173
#define agfindgraphattr(g, a)
Definition types.h:613
#define GD_ndim(g)
Definition types.h:390
#define GD_odim(g)
Definition types.h:391
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
#define agfindnodeattr(g, a)
Definition types.h:615
#define ND_pos(n)
Definition types.h:520
int agdelete(Agraph_t *g, void *obj)
deletes object. Equivalent to agclose, agdelnode, and agdeledge for obj being a graph,...
Definition obj.c:20
Agraph_t * agroot(void *obj)
Definition obj.c:168
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:89
replacements for ctype.h functions
static bool gv_isdigit(int c)
Definition gv_ctype.h:41
static bool gv_isalpha(int c)
Definition gv_ctype.h:29
Agraph_t ** ccomps(Agraph_t *g, size_t *ncc, char *pfx)
Definition ccomps.c:187
#define hasPos(n)
Definition macros.h:18
#define ND_id(n)
Definition mm2gv.c:39
#define INIT_RANDOM
Definition neato.h:29
int setSeed(graph_t *G, int dflt, long *seedp)
Definition neatoinit.c:954
void neato_init_node(node_t *n)
Definition neatoinit.c:59
NEATOPROCS_API void spline_edges(Agraph_t *)
int packSubgraphs(size_t ng, Agraph_t **gs, Agraph_t *root, pack_info *info)
Definition pack.c:1104
pack_mode getPackInfo(Agraph_t *g, pack_mode dflt, int dfltMargin, pack_info *pinfo)
Definition pack.c:1281
support for connected components
@ l_node
Definition pack.h:55
void dotneato_postprocess(Agraph_t *g)
Definition postproc.c:689
void gv_cleanup_edge(Agedge_t *e)
Definition utils.c:1524
void gv_cleanup_node(Agnode_t *n)
Definition utils.c:1536
static void sfdp_init_node_edge(graph_t *g)
Definition sfdpinit.c:36
static void sfdp_init_graph(Agraph_t *g)
Definition sfdpinit.c:50
void sfdp_cleanup(graph_t *g)
Definition sfdpinit.c:301
static void sfdp_init_edge(edge_t *e)
Definition sfdpinit.c:30
static int late_smooth(graph_t *g, Agsym_t *sym, int dflt)
Definition sfdpinit.c:120
void sfdp_layout(graph_t *g)
Definition sfdpinit.c:228
static double * getPos(Agraph_t *g)
Definition sfdpinit.c:64
static void sfdpLayout(graph_t *g, spring_electrical_control ctrl, pointf pad)
Definition sfdpinit.c:85
static void tuneControl(graph_t *g, spring_electrical_control ctrl)
Definition sfdpinit.c:201
static int late_quadtree_scheme(graph_t *g, Agsym_t *sym, int dflt)
Definition sfdpinit.c:166
void spring_electrical_control_print(spring_electrical_control ctrl)
spring_electrical_control spring_electrical_control_new(void)
void multilevel_spring_electrical_embedding(int dim, SparseMatrix A0, spring_electrical_control ctrl, double *label_sizes, double *x, int n_edge_label_nodes, int *edge_label_nodes, int *flag)
void spring_electrical_control_delete(spring_electrical_control ctrl)
@ QUAD_TREE_NORMAL
@ QUAD_TREE_FAST
@ QUAD_TREE_NONE
@ SMOOTHING_NONE
@ SMOOTHING_SPRING
@ SMOOTHING_RNG
@ SMOOTHING_STRESS_MAJORIZATION_GRAPH_DIST
@ SMOOTHING_STRESS_MAJORIZATION_POWER_DIST
@ SMOOTHING_TRIANGLE
@ SMOOTHING_STRESS_MAJORIZATION_AVG_DIST
#define AUTOP
platform abstraction for case-insensitive string functions
graph or subgraph
Definition cgraph.h:425
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:637
int value
Definition adjust.h:34
double scaling
Definition adjust.h:35
adjust_mode mode
Definition adjust.h:32
double x
Definition adjust.h:39
double y
Definition adjust.h:39
bool doAdd
Definition adjust.h:40
bool doSplines
use splines in constructing graph shape
Definition pack.h:71
double x
Definition geom.h:29
double y
Definition geom.h:29
Definition grammar.c:93