Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
patchworkinit.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#include <assert.h>
12#include <cgraph/list.h>
13#include <common/render.h>
14#include <common/utils.h>
15#include <patchwork/patchwork.h>
16#include <limits.h>
17#include <neatogen/adjust.h>
18#include <pack/pack.h>
19#include <neatogen/neatoprocs.h>
20#include <stdbool.h>
21
22/* the following code shamelessly copied from lib/fdpgen/layout.c
23and should be extracted and made into a common function */
24
25DEFINE_LIST(clist, graph_t*)
26
27/* mkClusters:
28 * Attach list of immediate child clusters.
29 * NB: By convention, the indexing starts at 1.
30 * If pclist is NULL, the graph is the root graph or a cluster
31 * If pclist is non-NULL, we are recursively scanning a non-cluster
32 * subgraph for cluster children.
33 */
34static void
35mkClusters (graph_t * g, clist_t* pclist, graph_t* parent)
36{
37 graph_t* subg;
38 clist_t list = {0};
39 clist_t* clist;
40
41 if (pclist == NULL) {
42 // [0] is empty. The clusters are in [1..cnt].
43 clist_append(&list, NULL);
44 clist = &list;
45 }
46 else
47 clist = pclist;
48
49 for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
50 if (is_a_cluster(subg)) {
51 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
52 clist_append(clist, subg);
53 mkClusters(subg, NULL, subg);
54 }
55 else {
56 mkClusters(subg, clist, parent);
57 }
58 }
59 if (pclist == NULL) {
60 assert(clist_size(&list) - 1 <= INT_MAX);
61 GD_n_cluster(g) = (int)(clist_size(&list) - 1);
62 if (clist_size(&list) > 1) {
63 clist_shrink_to_fit(&list);
64 GD_clust(g) = clist_detach(&list);
65 } else {
66 clist_free(&list);
67 }
68 }
69}
70
72{
73 agset(n,"shape","box");
74}
75
77{
78 agbindrec(e, "Agedgeinfo_t", sizeof(Agnodeinfo_t), true); // edge custom data
79}
80
82{
83 node_t *n;
84 edge_t *e;
85 int i = 0;
86 rdata* alg = gv_calloc(agnnodes(g), sizeof(rdata));
87
88 GD_neato_nlist(g) = gv_calloc(agnnodes(g) + 1, sizeof(node_t*));
89 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
90 agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), true); // node custom data
91 ND_alg(n) = alg + i;
92 GD_neato_nlist(g)[i++] = n;
94
95 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
97 }
98 }
99}
100
102{
103 N_shape = agattr(g, AGNODE, "shape","box");
105 Ndim = GD_ndim(g) = 2; /* The algorithm only makes sense in 2D */
106 mkClusters(g, NULL, g);
108}
109
110/* patchwork_layout:
111 * The current version makes no use of edges, neither for a notion of connectivity
112 * nor during drawing.
113 */
115{
117
118 if ((agnnodes(g) == 0) && (GD_n_cluster(g) == 0)) return;
119
120 patchworkLayout (g);
121
123}
124
126{
128 free(GD_clust(g));
129}
130
132{
133 node_t *n;
134 edge_t *e;
135
136 n = agfstnode(g);
137 if (!n) return;
138 free (ND_alg(n));
139 for (; n; n = agnxtnode(g, n)) {
140 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
142 }
144 }
146}
147
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define parent(i)
Definition closest.c:80
void setEdgeType(graph_t *g, int defaultValue)
Definition utils.c:1434
bool is_a_cluster(Agraph_t *g)
Definition utils.c:690
#define EDGETYPE_LINE
Definition const.h:249
Agsym_t * N_shape
Definition globals.h:73
unsigned short Ndim
Definition globals.h:61
void free(void *)
node NULL
Definition grammar.y:163
int agnnodes(Agraph_t *g)
Definition graph.c:169
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:338
int agset(void *obj, char *name, const char *value)
Definition attr.c:466
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
#define GD_clust(g)
Definition types.h:360
#define GD_n_cluster(g)
Definition types.h:389
#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:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
#define ND_alg(n)
Definition types.h:484
@ 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:89
Agraph_t * agfstsubg(Agraph_t *g)
Definition subg.c:78
Agraph_t * agnxtsubg(Agraph_t *subg)
Definition subg.c:83
#define DEFINE_LIST(name, type)
Definition list.h:26
support for connected components
void patchworkLayout(Agraph_t *g)
Definition patchwork.c:273
void patchwork_cleanup(graph_t *g)
static void patchwork_init_graph(graph_t *g)
static void patchwork_init_node(node_t *n)
static void patchwork_init_node_edge(graph_t *g)
static void patchwork_init_edge(edge_t *e)
static void patchwork_cleanup_graph(graph_t *g)
static void mkClusters(graph_t *g, clist_t *pclist, graph_t *parent)
void patchwork_layout(Agraph_t *g)
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
graph or subgraph
Definition cgraph.h:425