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