Graphviz 14.1.2~dev.20251230.0621
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 <common/render.h>
13#include <common/utils.h>
14#include <patchwork/patchwork.h>
15#include <limits.h>
16#include <neatogen/adjust.h>
17#include <pack/pack.h>
18#include <neatogen/neatoprocs.h>
19#include <stdbool.h>
20#include <stddef.h>
21#include <util/list.h>
22
23/* the following code shamelessly copied from lib/fdpgen/layout.c
24and should be extracted and made into a common function */
25
26typedef LIST(graph_t *) clist_t;
27
28/* mkClusters:
29 * Attach list of immediate child clusters.
30 * NB: By convention, the indexing starts at 1.
31 * If pclist is NULL, the graph is the root graph or a cluster
32 * If pclist is non-NULL, we are recursively scanning a non-cluster
33 * subgraph for cluster children.
34 */
35static void
36mkClusters (graph_t * g, clist_t* pclist, graph_t* parent)
37{
38 graph_t* subg;
39 clist_t list = {0};
40 clist_t* clist;
41
42 if (pclist == NULL) {
43 // [0] is empty. The clusters are in [1..cnt].
44 LIST_APPEND(&list, NULL);
45 clist = &list;
46 }
47 else
48 clist = pclist;
49
50 for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
51 if (is_a_cluster(subg)) {
52 agbindrec(subg, "Agraphinfo_t", sizeof(Agraphinfo_t), true);
53 LIST_APPEND(clist, subg);
54 mkClusters(subg, NULL, subg);
55 }
56 else {
57 mkClusters(subg, clist, parent);
58 }
59 }
60 if (pclist == NULL) {
61 assert(LIST_SIZE(&list) - 1 <= INT_MAX);
62 GD_n_cluster(g) = (int)(LIST_SIZE(&list) - 1);
63 if (LIST_SIZE(&list) > 1) {
64 LIST_SHRINK_TO_FIT(&list);
65 LIST_DETACH(&list, &GD_clust(g), NULL);
66 } else {
67 LIST_FREE(&list);
68 }
69 }
70}
71
73{
74 agset(n,"shape","box");
75}
76
78{
79 agbindrec(e, "Agedgeinfo_t", sizeof(Agnodeinfo_t), true); // edge custom data
80}
81
83{
84 node_t *n;
85 edge_t *e;
86 int i = 0;
87 assert(agnnodes(g) >= 0);
88 const size_t nnodes = (size_t)agnnodes(g);
89 rdata* alg = gv_calloc(nnodes, sizeof(rdata));
90
91 GD_neato_nlist(g) = gv_calloc(nnodes + 1, sizeof(node_t*));
92 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
93 agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), true); // node custom data
94 ND_alg(n) = alg + i;
95 GD_neato_nlist(g)[i++] = n;
97
98 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
100 }
101 }
102}
103
105{
106 N_shape = agattr_text(g, AGNODE, "shape","box");
108 Ndim = GD_ndim(g) = 2; /* The algorithm only makes sense in 2D */
109 mkClusters(g, NULL, g);
111}
112
113/* patchwork_layout:
114 * The current version makes no use of edges, neither for a notion of connectivity
115 * nor during drawing.
116 */
118{
120
121 if ((agnnodes(g) == 0) && (GD_n_cluster(g) == 0)) return;
122
123 patchworkLayout (g);
124
126}
127
129{
131 free(GD_clust(g));
132}
133
135{
136 node_t *n;
137 edge_t *e;
138
139 n = agfstnode(g);
140 if (!n) return;
141 free (ND_alg(n));
142 for (; n; n = agnxtnode(g, n)) {
143 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
145 }
147 }
149}
150
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define parent(i)
Definition closest.c:73
void setEdgeType(graph_t *g, int defaultValue)
Definition utils.c:1420
bool is_a_cluster(Agraph_t *g)
Definition utils.c:693
#define EDGETYPE_LINE
Definition const.h:235
Agsym_t * N_shape
Definition globals.h:74
unsigned short Ndim
Definition globals.h:62
void free(void *)
node NULL
Definition grammar.y:181
int agnnodes(Agraph_t *g)
Definition graph.c:155
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:334
int agset(void *obj, char *name, const char *value)
Definition attr.c:475
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:26
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:41
#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:48
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:41
#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:73
Agraph_t * agnxtsubg(Agraph_t *subg)
Definition subg.c:78
static void mkClusters(graph_t *g, clist_t *pclist, graph_t *parent)
Definition layout.c:983
type-generic dynamically expanding list
#define LIST_DETACH(list, datap, sizep)
Definition list.h:443
#define LIST(type)
Definition list.h:55
#define LIST_SIZE(list)
Definition list.h:80
#define LIST_APPEND(list, item)
Definition list.h:120
#define LIST_FREE(list)
Definition list.h:370
#define LIST_SHRINK_TO_FIT(list)
Definition list.h:358
support for connected components
void patchworkLayout(Agraph_t *g)
Definition patchwork.c:266
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)
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:1510
void gv_cleanup_node(Agnode_t *n)
Definition utils.c:1522
graph or subgraph
Definition cgraph.h:424