Graphviz 14.0.5~dev.20251117.1017
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
40static block_t *newBlock(int size)
41{
42 block_t *newb = gv_alloc(sizeof(block_t));
43 newb->next = 0;
44 newb->mem = gv_calloc(size, sizeof(cell));
45 newb->endp = newb->mem + size;
46 newb->cur = newb->mem;
47
48 return newb;
49}
50
51/* Free malloc'ed memory and block.
52 * Recurse to next block
53 */
54static void freeBlock(block_t * b)
55{
56 if (b) {
57 block_t *next = b->next;
58 free(b->mem);
59 free(b);
61 }
62}
63
64struct _grid {
65 Dt_t *data; /* cells indexed by (i,j) */
66 block_t *cellMem; /* list of memory blocks for cells */
67 block_t *cellCur; /* current block */
68 int listSize; /* memory of nodes */
69 node_list *listMem; /* list of memory for node items */
70 node_list *listCur; /* next node item */
71};
72
74static cell *getCell(Grid * g)
75{
76 cell *cp;
77 block_t *bp = g->cellCur; /* current block */
78
79 if (bp->cur == bp->endp) { /* current block is full */
80 if (bp->next == 0) {
81 bp->next = newBlock(2 * (bp->endp - bp->mem));
82 }
83 bp = g->cellCur = bp->next;
84 bp->cur = bp->mem;
85 }
86 cp = bp->cur++;
87 return cp;
88}
89
90static int ijcmpf(void *point1, void *point2) {
91 const gridpt *p1 = point1;
92 const gridpt *p2 = point2;
93 if (p1->i < p2->i) {
94 return -1;
95 }
96 if (p1->i > p2->i) {
97 return 1;
98 }
99 if (p1->j < p2->j) {
100 return -1;
101 }
102 if (p1->j > p2->j) {
103 return 1;
104 }
105 return 0;
106}
107
108static Grid _grid; // hack because can't attach info. to Dt_t
109
110/* Allocate a new cell from free store and initialize its indices
111 * This is used by the grid discipline to create cells.
112 */
113static void *newCell(void *obj, Dtdisc_t *disc) {
114 cell *cellp = obj;
115 cell *newp;
116
117 (void)disc;
118 newp = getCell(&_grid);
119 newp->p.i = cellp->p.i;
120 newp->p.j = cellp->p.j;
121 newp->nodes = 0;
122
123 return newp;
124}
125
126/* Allocate a new node item from free store.
127 * Set node value and hook into list.
128 * A grid assumes the memory allocated in adjustGrid
129 * will be enough more all nodes added.
130 */
131static node_list *newNode(Grid * g, Agnode_t * n, node_list * nxt)
132{
133 node_list *newp;
134
135 newp = g->listCur++;
136 newp->node = n;
137 newp->next = nxt;
138
139 return newp;
140}
141
143 offsetof(cell, p),
144 sizeof(gridpt),
145 offsetof(cell, link),
146 newCell,
147 NULL,
148 ijcmpf,
149};
150
151/* Create grid data structure.
152 * cellHint provides rough idea of how many cells
153 * may be needed.
154 */
155Grid *mkGrid(int cellHint)
156{
157 Grid *g = &_grid;
158 memset(g, 0, sizeof(*g)); // see comment above
159 g->data = dtopen(&gridDisc, Dtoset);
160 g->cellMem = newBlock(cellHint);
161 return g;
162}
163
164/* Set up node list for grid. Make sure the list
165 * can handle nnodes nodes.
166 * It is assumed no more than nnodes will be added
167 * to the grid.
168 */
169void adjustGrid(Grid * g, int nnodes)
170{
171 int nsize;
172
173 if (nnodes > g->listSize) {
174 nsize = MAX(nnodes, 2 * g->listSize);
175 if (g->listMem)
176 free(g->listMem);
177 g->listMem = gv_calloc(nsize, sizeof(node_list));
178 g->listSize = nsize;
179 }
180}
181
182/* Reset grid. This clears the dictionary,
183 * and reuses available memory.
184 */
186{
187 dtclear(g->data);
188 g->listCur = g->listMem;
189 g->cellCur = g->cellMem;
190 g->cellCur->cur = g->cellCur->mem;
191}
192
194void delGrid(Grid * g)
195{
196 dtclose(g->data);
197 freeBlock(g->cellMem);
198 free(g->listMem);
199}
200
202void addGrid(Grid * g, int i, int j, Agnode_t * n)
203{
204 cell *cellp;
205 cell key;
206
207 key.p.i = i;
208 key.p.j = j;
209 cellp = dtinsert(g->data, &key);
210 cellp->nodes = newNode(g, n, cellp->nodes);
211 if (Verbose >= 3) {
212 fprintf(stderr, "grid(%d,%d): %s\n", i, j, agnameof(n));
213 }
214}
215
216/* Apply function walkf to each cell in the grid.
217 * The first argument to walkf is the cell; the
218 * second argument is the grid. walkf must return 0.
219 */
220void walkGrid(Grid *g, int (*walkf)(void *, void *)) {
221 dtwalk(g->data, walkf, g);
222}
223
224/* Return the cell, if any, corresponding to
225 * indices i,j
226 */
227cell *findGrid(Grid * g, int i, int j)
228{
229 cell key;
230
231 key.p.i = i;
232 key.p.j = j;
233 return dtsearch(g->data, &key);
234}
235
237int gLength(cell * p)
238{
239 int len = 0;
240 node_list *nodes = p->nodes;
241
242 while (nodes) {
243 len++;
244 nodes = nodes->next;
245 }
246 return len;
247}
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
#define MAX(a, b)
Definition arith.h:33
CDT_API int dtwalk(Dt_t *, int(*)(void *, void *), void *)
Definition dtwalk.c:9
#define dtclear(d)
Definition cdt.h:189
#define dtsearch(d, o)
Definition cdt.h:184
#define dtinsert(d, o)
Definition cdt.h:186
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:136
static bool Verbose
Definition gml2gv.c:24
void free(void *)
node NULL
Definition grammar.y:181
static void freeBlock(block_t *b)
Definition grid.c:54
static void * newCell(void *obj, Dtdisc_t *disc)
Definition grid.c:113
void adjustGrid(Grid *g, int nnodes)
Definition grid.c:169
int gLength(cell *p)
return the number of nodes in a cell
Definition grid.c:237
void delGrid(Grid *g)
close and free all grid resources
Definition grid.c:194
void walkGrid(Grid *g, int(*walkf)(void *, void *))
Definition grid.c:220
struct _block block_t
static int ijcmpf(void *point1, void *point2)
Definition grid.c:90
static Dtdisc_t gridDisc
Definition grid.c:142
static cell * getCell(Grid *g)
create a new cell using memory blocks
Definition grid.c:74
static node_list * newNode(Grid *g, Agnode_t *n, node_list *nxt)
Definition grid.c:131
void addGrid(Grid *g, int i, int j, Agnode_t *n)
add node n to cell (i,j) in grid g
Definition grid.c:202
void clearGrid(Grid *g)
Definition grid.c:185
static block_t * newBlock(int size)
create new block of size cells
Definition grid.c:40
cell * findGrid(Grid *g, int i, int j)
Definition grid.c:227
Grid * mkGrid(int cellHint)
Definition grid.c:155
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:143
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:64
Dt_t * data
Definition grid.c:65
block_t * cellMem
Definition grid.c:66
block_t * cellCur
Definition grid.c:67
node_list * listCur
Definition grid.c:70
int listSize
Definition grid.c:68
node_list * listMem
Definition grid.c:69
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:98
Definition grid.h:29
int j
Definition grid.h:30
int i
Definition grid.h:30