Graphviz 14.1.5~dev.20260409.0840
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 <assert.h>
19#include <cgraph/cgraph.h>
20#include <neatogen/adjust.h>
21#include <neatogen/neatoprocs.h>
22#include <pack/pack.h>
23#include <stdbool.h>
24#include <stddef.h>
25#include <twopigen/circle.h>
26#include <util/alloc.h>
27
28static void twopi_init_edge(edge_t *e) {
29 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), true); // edge custom data
31 ED_factor(e) = late_double(e, E_weight, 1.0, 0.0);
32}
33
35 node_t *n;
36 edge_t *e;
37 int i = 0;
38 int n_nodes = agnnodes(g);
39
40 assert(n_nodes >= 0);
41 rdata *alg = gv_calloc((size_t)n_nodes, sizeof(rdata));
42 GD_neato_nlist(g) = gv_calloc((size_t)n_nodes + 1, sizeof(node_t *));
43 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
45 ND_alg(n) = alg + i;
46 GD_neato_nlist(g)[i++] = n;
47 }
48 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
49 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
51 }
52 }
53}
54
57 Ndim = GD_ndim(agroot(g)) = 2; /* The algorithm only makes sense in 2D */
59}
60
61static Agnode_t *findRootNode(Agraph_t *sg, Agsym_t *rootattr) {
62 Agnode_t *n;
63
64 for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
65 if (mapbool(agxget(n, rootattr)))
66 return n;
67 }
68 return NULL;
69}
70
72 Agnode_t *ctr = 0;
73 char *s;
74 bool setRoot = false;
75 bool setLocalRoot = false;
76 Agsym_t *rootattr;
77
78 if (agnnodes(g) == 0)
79 return;
80
82 if ((s = agget(g, "root"))) {
83 if (*s) {
84 ctr = agfindnode(g, s);
85 if (!ctr) {
86 agwarningf("specified root node \"%s\" was not found.", s);
87 agerr(AGPREV, "Using default calculation for root node\n");
88 setRoot = true;
89 }
90 } else {
91 setRoot = true;
92 }
93 }
94 if ((rootattr = agattr_text(g, AGNODE, "root", 0))) {
95 setLocalRoot = true;
96 }
97
98 if (agnnodes(g)) {
99 Agnode_t *lctr;
100
101 size_t ncc;
102 Agraph_t **const ccs = ccomps(g, &ncc, 0);
103 if (ncc == 1) {
104 if (ctr)
105 lctr = ctr;
106 else if (!rootattr || !(lctr = findRootNode(g, rootattr)))
107 lctr = 0;
108 Agnode_t *const c = circleLayout(g, lctr);
109 if (setRoot && !ctr)
110 ctr = c;
111 if (setLocalRoot && !lctr)
112 agxset(c, rootattr, "1");
113 Agnode_t *const n = agfstnode(g);
114 free(ND_alg(n));
115 ND_alg(n) = NULL;
116 adjustNodes(g);
117 spline_edges(g);
118 } else {
119 pack_info pinfo;
120 getPackInfo(g, l_node, CL_OFFSET, &pinfo);
121 pinfo.doSplines = false;
122
123 for (size_t i = 0; i < ncc; i++) {
124 Agraph_t *const sg = ccs[i];
125 if (ctr && agcontains(sg, ctr))
126 lctr = ctr;
127 else if (!rootattr || !(lctr = findRootNode(sg, rootattr)))
128 lctr = 0;
129 (void)graphviz_node_induce(sg, NULL);
130 Agnode_t *const c = circleLayout(sg, lctr);
131 if (setRoot && !ctr)
132 ctr = c;
133 if (setLocalRoot && (!lctr || (lctr == ctr)))
134 agxset(c, rootattr, "1");
135 adjustNodes(sg);
136 }
137 Agnode_t *const n = agfstnode(g);
138 if (n != NULL) {
139 free(ND_alg(n));
140 ND_alg(n) = NULL;
141 }
142 packSubgraphs(ncc, ccs, g, &pinfo);
143 spline_edges(g);
144 }
145 for (size_t i = 0; i < ncc; i++) {
146 agdelete(g, ccs[i]);
147 }
148 free(ccs);
149 }
150 if (setRoot)
151 agset(g, "root", agnameof(ctr));
153}
154
156
157/* The ND_alg data used by twopi is freed in twopi_layout
158 * before edge routing as edge routing may use this field.
159 */
161 node_t *n;
162 edge_t *e;
163
164 n = agfstnode(g);
165 if (!n)
166 return; /* empty graph */
167 for (; n; n = agnxtnode(g, n)) {
168 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
170 }
172 }
174}
175
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:312
bool mapbool(const char *p)
Definition utils.c:341
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:82
unsigned short Ndim
Definition globals.h:62
void free(void *)
node NULL
Definition grammar.y:181
int agnnodes(Agraph_t *g)
Definition graph.c:159
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:946
#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: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
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:640
bool doSplines
use splines in constructing graph shape
Definition pack.h:71
static void twopi_init_edge(edge_t *e)
Definition twopiinit.c:28
static Agnode_t * findRootNode(Agraph_t *sg, Agsym_t *rootattr)
Definition twopiinit.c:61
static void twopi_init_node_edge(graph_t *g)
Definition twopiinit.c:34
void twopi_layout(Agraph_t *g)
Definition twopiinit.c:71
static void twopi_cleanup_graph(graph_t *g)
Definition twopiinit.c:155
void twopi_cleanup(graph_t *g)
Definition twopiinit.c:160
void twopi_init_graph(graph_t *g)
Definition twopiinit.c:55
Definition grammar.c:90