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