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