Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
index.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 <stdlib.h>
12
13#include <label/index.h>
14#include <stddef.h>
15#include <stdio.h>
16#include <assert.h>
17#include <stdbool.h>
18
20{
21 LeafList_t *llp;
22
23 if ((llp = calloc(1, sizeof(LeafList_t)))) {
24 llp->leaf = lp;
25 llp->next = 0;
26 }
27 return llp;
28}
29
31{
32 if (!lp)
33 return llp;
34
36 nlp->next = llp;
37 return nlp;
38}
39
41{
42 while (llp->next) {
43 LeafList_t *tlp = llp->next;
44 free(llp);
45 llp = tlp;
46 }
47 free(llp);
48 return;
49}
50
52{
53 RTree_t *rtp;
54
55 if ((rtp = calloc(1, sizeof(RTree_t))))
56 rtp->root = RTreeNewIndex();
57 return rtp;
58}
59
60/* Make a new index, empty. Consists of a single node. */
62 Node_t *x = RTreeNewNode();
63 x->level = 0; /* leaf */
64 return x;
65}
66
67static int RTreeClose2(RTree_t * rtp, Node_t * n)
68{
69 if (n->level > 0) {
70 for (int i = 0; i < NODECARD; i++) {
71 if (!n->branch[i].child)
72 continue;
73 if (!RTreeClose2(rtp, n->branch[i].child)) {
74 free(n->branch[i].child);
75 DisconBranch(n, i);
76 }
77 }
78 } else {
79 for (int i = 0; i < NODECARD; i++) {
80 if (!n->branch[i].child)
81 continue;
82 DisconBranch(n, i);
83 }
84 }
85 return 0;
86}
87
88
90{
91 RTreeClose2(rtp, rtp->root);
92 free(rtp->root);
93 free(rtp);
94 return 0;
95}
96
97#ifdef RTDEBUG
98/* Print out all the nodes in an index.
99** Prints from root downward.
100*/
101void PrintIndex(Node_t * n)
102{
103 Node_t *nn;
104 assert(n);
105 assert(n->level >= 0);
106
107 if (n->level > 0) {
108 for (size_t i = 0; i < NODECARD; i++) {
109 if ((nn = n->branch[i].child) != NULL)
110 PrintIndex(nn);
111 }
112 }
113
114 PrintNode(n);
115}
116
117/* Print out all the data rectangles in an index.
118*/
119void PrintData(Node_t * n)
120{
121 Node_t *nn;
122 assert(n);
123 assert(n->level >= 0);
124
125 if (n->level == 0)
126 PrintNode(n);
127 else {
128 for (size_t i = 0; i < NODECARD; i++) {
129 if ((nn = n->branch[i].child) != NULL)
130 PrintData(nn);
131 }
132 }
133}
134#endif
135
136/* RTreeSearch in an index tree or subtree for all data retangles that
137** overlap the argument rectangle.
138** Returns the number of qualifying data rects.
139*/
141{
142 LeafList_t *llp = 0;
143
144 assert(n);
145 assert(n->level >= 0);
146 assert(r);
147
148 if (n->level > 0) { /* this is an internal node in the tree */
149 for (size_t i = 0; i < NODECARD; i++)
150 if (n->branch[i].child && Overlap(r, &n->branch[i].rect)) {
151 LeafList_t *tlp = RTreeSearch(rtp, n->branch[i].child, r);
152 if (llp) {
153 LeafList_t *xlp = llp;
154 while (xlp->next)
155 xlp = xlp->next;
156 xlp->next = tlp;
157 } else
158 llp = tlp;
159 }
160 } else { /* this is a leaf node */
161 for (size_t i = 0; i < NODECARD; i++) {
162 if (n->branch[i].child && Overlap(r, &n->branch[i].rect)) {
163 llp = RTreeLeafListAdd(llp, (Leaf_t *) & n->branch[i]);
164# ifdef RTDEBUG
165 PrintRect(&n->branch[i].rect);
166# endif
167 }
168 }
169 }
170 return llp;
171}
172
173/* Insert a data rectangle into an index structure.
174** RTreeInsert provides for splitting the root;
175** returns 1 if root was split, 0 if it was not.
176** The level argument specifies the number of steps up from the leaf
177** level to insert; e.g. a data rectangle goes in at level = 0.
178** RTreeInsert2 does the recursion.
179*/
180static int RTreeInsert2(RTree_t *, Rect_t *, void *, Node_t *, Node_t **, int);
181
182int RTreeInsert(RTree_t * rtp, Rect_t * r, void *data, Node_t ** n, int level)
183{
184 Node_t *newnode=0;
185 Branch_t b;
186 int result = 0;
187
188
189 assert(r && n);
190 assert(level >= 0 && level <= (*n)->level);
191 for (size_t i = 0; i < NUMDIMS; i++)
192 assert(r->boundary[i] <= r->boundary[NUMDIMS + i]);
193
194# ifdef RTDEBUG
195 fprintf(stderr, "RTreeInsert level=%d\n", level);
196# endif
197
198 if (RTreeInsert2(rtp, r, data, *n, &newnode, level)) { /* root was split */
199
200 Node_t *newroot = RTreeNewNode(); /* grow a new root, make tree taller */
201 newroot->level = (*n)->level + 1;
202 b.rect = NodeCover(*n);
203 b.child = *n;
204 AddBranch(rtp, &b, newroot, NULL);
206 b.child = newnode;
207 AddBranch(rtp, &b, newroot, NULL);
208 *n = newroot;
209 result = 1;
210 }
211
212 return result;
213}
214
215/* Inserts a new data rectangle into the index structure.
216** Recursively descends tree, propagates splits back up.
217** Returns 0 if node was not split. Old node updated.
218** If node was split, returns 1 and sets the pointer pointed to by
219** new to point to the new node. Old node updated to become one of two.
220** The level argument specifies the number of steps up from the leaf
221** level to insert; e.g. a data rectangle goes in at level = 0.
222*/
223static int
224RTreeInsert2(RTree_t * rtp, Rect_t * r, void *data,
225 Node_t * n, Node_t ** new, int level)
226{
227 Branch_t b;
228 Node_t *n2=0;
229
230 assert(r && n && new);
231 assert(level >= 0 && level <= n->level);
232
233 /* Still above level for insertion, go down tree recursively */
234 if (n->level > level) {
235 int i = PickBranch(r, n);
236 if (!RTreeInsert2(rtp, r, data, n->branch[i].child, &n2, level)) { /* recurse: child was not split */
237 n->branch[i].rect = CombineRect(r, &(n->branch[i].rect));
238 return 0;
239 } else { /* child was split */
240 n->branch[i].rect = NodeCover(n->branch[i].child);
241 b.child = n2;
242 b.rect = NodeCover(n2);
243 return AddBranch(rtp, &b, n, new);
244 }
245 } else if (n->level == level) { /* at level for insertion. */
246 /*Add rect, split if necessary */
247 b.rect = *r;
248 b.child = data;
249 return AddBranch(rtp, &b, n, new);
250 } else { /* Not supposed to happen */
251 assert(false);
252 return 0;
253 }
254}
static Agnode_t * newnode(Agraph_t *g, IDTYPE id, uint64_t seq)
Definition node.c:72
void free(void *)
node NULL
Definition grammar.y:163
static int RTreeClose2(RTree_t *rtp, Node_t *n)
Definition index.c:67
LeafList_t * RTreeSearch(RTree_t *rtp, Node_t *n, Rect_t *r)
Definition index.c:140
LeafList_t * RTreeLeafListAdd(LeafList_t *llp, Leaf_t *lp)
Definition index.c:30
void RTreeLeafListFree(LeafList_t *llp)
Definition index.c:40
RTree_t * RTreeOpen(void)
Definition index.c:51
int RTreeClose(RTree_t *rtp)
Definition index.c:89
Node_t * RTreeNewIndex(void)
Definition index.c:61
LeafList_t * RTreeNewLeafList(Leaf_t *lp)
Definition index.c:19
int RTreeInsert(RTree_t *rtp, Rect_t *r, void *data, Node_t **n, int level)
Definition index.c:182
static int RTreeInsert2(RTree_t *, Rect_t *, void *, Node_t *, Node_t **, int)
Definition index.c:224
#define NUMDIMS
Definition index.h:37
#define NODECARD
Definition index.h:43
Node_t * RTreeNewNode(void)
Definition node.c:24
int AddBranch(RTree_t *rtp, Branch_t *b, Node_t *n, Node_t **new)
Definition node.c:147
Rect_t NodeCover(Node_t *n)
Definition node.c:81
int PickBranch(Rect_t *r, Node_t *n)
Definition node.c:105
void DisconBranch(Node_t *n, int i)
Definition node.c:172
bool Overlap(const Rect_t *r, const Rect_t *s)
Definition rectangle.c:108
Rect_t CombineRect(const Rect_t *r, const Rect_t *rr)
Definition rectangle.c:88
Definition node.h:19
Rect_t rect
Definition node.h:20
struct Node * child
Definition node.h:21
Leaf_t * leaf
Definition index.h:62
struct LeafList * next
Definition index.h:61
Definition index.h:55
Definition node.h:24
int level
Definition node.h:26
struct Branch branch[NODECARD]
Definition node.h:27
Definition index.h:65
Node_t * root
Definition index.h:66
int boundary[NUMSIDES]
Definition rectangle.h:21
Definition legal.c:50