Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
grid.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/*
13 * grid.c
14 * Written by Emden R. Gansner
15 *
16 * Support for grid to speed up layout. On each pass, nodes are
17 * put into grid cells. Given a node, repulsion is only computed
18 * for nodes in one of that nodes 9 adjacent grids.
19 */
20
21/* uses PRIVATE interface for NOTUSED */
22#define FDP_PRIVATE 1
23
24#include <fdpgen/fdp.h>
25#include <fdpgen/grid.h>
26#include <common/macros.h>
27#include <stddef.h>
28#include <string.h>
29#include <util/alloc.h>
30
31 /* structure for maintaining a free list of cells */
32typedef struct _block {
33 cell *mem; /* block of cells */
34 cell *cur; /* next available cell */
35 cell *endp; /* after last cell */
36 struct _block *next; /* next memory block */
38
39/* newBlock:
40 * Create new block of size cells
41 */
42static block_t *newBlock(int size)
43{
44 block_t *newb = gv_alloc(sizeof(block_t));
45 newb->next = 0;
46 newb->mem = gv_calloc(size, sizeof(cell));
47 newb->endp = newb->mem + size;
48 newb->cur = newb->mem;
49
50 return newb;
51}
52
53/* freeBlock:
54 * Free malloc'ed memory and block.
55 * Recurse to next block
56 */
57static void freeBlock(block_t * b)
58{
59 if (b) {
60 block_t *next = b->next;
61 free(b->mem);
62 free(b);
64 }
65}
66
67struct _grid {
68 Dt_t *data; /* cells indexed by (i,j) */
69 block_t *cellMem; /* list of memory blocks for cells */
70 block_t *cellCur; /* current block */
71 int listSize; /* memory of nodes */
72 node_list *listMem; /* list of memory for node items */
73 node_list *listCur; /* next node item */
74};
75
76/* getCell:
77 * Create a new cell using memory blocks.
78 */
79static cell *getCell(Grid * g)
80{
81 cell *cp;
82 block_t *bp = g->cellCur; /* current block */
83
84 if (bp->cur == bp->endp) { /* current block is full */
85 if (bp->next == 0) {
86 bp->next = newBlock(2 * (bp->endp - bp->mem));
87 }
88 bp = g->cellCur = bp->next;
89 bp->cur = bp->mem;
90 }
91 cp = bp->cur++;
92 return cp;
93}
94
95static int ijcmpf(void *point1, void *point2) {
96 const gridpt *p1 = point1;
97 const gridpt *p2 = point2;
98 if (p1->i < p2->i) {
99 return -1;
100 }
101 if (p1->i > p2->i) {
102 return 1;
103 }
104 if (p1->j < p2->j) {
105 return -1;
106 }
107 if (p1->j > p2->j) {
108 return 1;
109 }
110 return 0;
111}
112
113static Grid _grid; // hack because can't attach info. to Dt_t
114
115/* newCell:
116 * Allocate a new cell from free store and initialize its indices
117 * This is used by the grid discipline to create cells.
118 */
119static void *newCell(void *obj, Dtdisc_t *disc) {
120 cell *cellp = obj;
121 cell *newp;
122
123 (void)disc;
124 newp = getCell(&_grid);
125 newp->p.i = cellp->p.i;
126 newp->p.j = cellp->p.j;
127 newp->nodes = 0;
128
129 return newp;
130}
131
132/* newNode:
133 * Allocate a new node item from free store.
134 * Set node value and hook into list.
135 * A grid assumes the memory allocated in adjustGrid
136 * will be enough more all nodes added.
137 */
138static node_list *newNode(Grid * g, Agnode_t * n, node_list * nxt)
139{
140 node_list *newp;
141
142 newp = g->listCur++;
143 newp->node = n;
144 newp->next = nxt;
145
146 return newp;
147}
148
150 offsetof(cell, p),
151 sizeof(gridpt),
152 offsetof(cell, link),
153 newCell,
154 NULL,
155 ijcmpf,
156};
157
158/* mkGrid:
159 * Create grid data structure.
160 * cellHint provides rough idea of how many cells
161 * may be needed.
162 */
163Grid *mkGrid(int cellHint)
164{
165 Grid *g = &_grid;
166 memset(g, 0, sizeof(*g)); // see comment above
167 g->data = dtopen(&gridDisc, Dtoset);
168 g->cellMem = newBlock(cellHint);
169 return g;
170}
171
172/* adjustGrid:
173 * Set up node list for grid. Make sure the list
174 * can handle nnodes nodes.
175 * It is assumed no more than nnodes will be added
176 * to the grid.
177 */
178void adjustGrid(Grid * g, int nnodes)
179{
180 int nsize;
181
182 if (nnodes > g->listSize) {
183 nsize = MAX(nnodes, 2 * g->listSize);
184 if (g->listMem)
185 free(g->listMem);
186 g->listMem = gv_calloc(nsize, sizeof(node_list));
187 g->listSize = nsize;
188 }
189}
190
191/* clearGrid:
192 * Reset grid. This clears the dictionary,
193 * and reuses available memory.
194 */
196{
197 dtclear(g->data);
198 g->listCur = g->listMem;
199 g->cellCur = g->cellMem;
200 g->cellCur->cur = g->cellCur->mem;
201}
202
203/* delGrid:
204 * Close and free all grid resources.
205 */
206void delGrid(Grid * g)
207{
208 dtclose(g->data);
209 freeBlock(g->cellMem);
210 free(g->listMem);
211}
212
213/* addGrid:
214 * Add node n to cell (i,j) in grid g.
215 */
216void addGrid(Grid * g, int i, int j, Agnode_t * n)
217{
218 cell *cellp;
219 cell key;
220
221 key.p.i = i;
222 key.p.j = j;
223 cellp = dtinsert(g->data, &key);
224 cellp->nodes = newNode(g, n, cellp->nodes);
225 if (Verbose >= 3) {
226 fprintf(stderr, "grid(%d,%d): %s\n", i, j, agnameof(n));
227 }
228}
229
230typedef int (*walkfn_t)(void*, void*);
231
232/* walkGrid:
233 * Apply function walkf to each cell in the grid.
234 * The second argument to walkf is the cell; the
235 * third argument is the grid. (The first argument
236 * is the dictionary.) walkf must return 0.
237 */
238void walkGrid(Grid *g, int (*walkf)(cell*, Grid*))
239{
240 dtwalk(g->data, (walkfn_t) walkf, g);
241}
242
243/* findGrid;
244 * Return the cell, if any, corresponding to
245 * indices i,j
246 */
247cell *findGrid(Grid * g, int i, int j)
248{
249 cell key;
250
251 key.p.i = i;
252 key.p.j = j;
253 return dtsearch(g->data, &key);
254}
255
256/* gLength:
257 * Return the number of nodes in a cell.
258 */
259int gLength(cell * p)
260{
261 int len = 0;
262 node_list *nodes = p->nodes;
263
264 while (nodes) {
265 len++;
266 nodes = nodes->next;
267 }
268 return len;
269}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
static void * gv_alloc(size_t size)
Definition alloc.h:47
CDT_API int dtwalk(Dt_t *, int(*)(void *, void *), void *)
Definition dtwalk.c:9
#define dtclear(d)
Definition cdt.h:188
#define dtsearch(d, o)
Definition cdt.h:183
#define dtinsert(d, o)
Definition cdt.h:185
CDT_API int dtclose(Dt_t *)
Definition dtclose.c:8
CDT_API Dtmethod_t * Dtoset
ordered set (self-adjusting tree)
Definition dttree.c:304
CDT_API Dt_t * dtopen(Dtdisc_t *, Dtmethod_t *)
Definition dtopen.c:9
static Dtdisc_t disc
Definition exparse.y:209
static double len(glCompPoint p)
Definition glutils.c:150
static bool Verbose
Definition gml2gv.c:23
void free(void *)
node NULL
Definition grammar.y:163
static void freeBlock(block_t *b)
Definition grid.c:57
static void * newCell(void *obj, Dtdisc_t *disc)
Definition grid.c:119
void walkGrid(Grid *g, int(*walkf)(cell *, Grid *))
Definition grid.c:238
void adjustGrid(Grid *g, int nnodes)
Definition grid.c:178
int gLength(cell *p)
Definition grid.c:259
void delGrid(Grid *g)
Definition grid.c:206
struct _block block_t
static int ijcmpf(void *point1, void *point2)
Definition grid.c:95
int(* walkfn_t)(void *, void *)
Definition grid.c:230
static Dtdisc_t gridDisc
Definition grid.c:149
static cell * getCell(Grid *g)
Definition grid.c:79
static node_list * newNode(Grid *g, Agnode_t *n, node_list *nxt)
Definition grid.c:138
void addGrid(Grid *g, int i, int j, Agnode_t *n)
Definition grid.c:216
void clearGrid(Grid *g)
Definition grid.c:195
static block_t * newBlock(int size)
Definition grid.c:42
cell * findGrid(Grid *g, int i, int j)
Definition grid.c:247
Grid * mkGrid(int cellHint)
Definition grid.c:163
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
Definition grid.c:32
struct _block * next
Definition grid.c:36
cell * endp
Definition grid.c:35
cell * mem
Definition grid.c:33
cell * cur
Definition grid.c:34
Definition grid.c:67
Dt_t * data
Definition grid.c:68
block_t * cellMem
Definition grid.c:69
block_t * cellCur
Definition grid.c:70
node_list * listCur
Definition grid.c:73
int listSize
Definition grid.c:71
node_list * listMem
Definition grid.c:72
Agnode_t * node
Definition grid.h:25
struct _node_list * next
Definition grid.h:26
Definition block.h:26
block_t * next
Definition block.h:28
result of partitioning available space, part of maze
Definition grid.h:33
node_list * nodes
Definition grid.h:35
gridpt p
Definition grid.h:34
Definition cdt.h:100
Definition grid.h:29
int j
Definition grid.h:30
int i
Definition grid.h:30
#define MAX(a, b)
Definition write.c:31