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