librtree 0.9.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +80 -0
- data/COPYING +21 -0
- data/README.md +87 -0
- data/ext/rtree/extconf.rb +37 -19
- data/ext/rtree/lib/README.md +9 -0
- data/ext/rtree/lib/bindex.c +157 -0
- data/ext/rtree/lib/bindex.h +31 -0
- data/ext/rtree/lib/bounds.h +21 -0
- data/ext/rtree/lib/branch.c +51 -0
- data/ext/rtree/lib/branches.c +17 -0
- data/ext/rtree/lib/bsrt.c +704 -0
- data/ext/rtree/lib/bsrt.h +16 -0
- data/ext/rtree/lib/constants.h +19 -0
- data/ext/rtree/lib/csv.c +81 -0
- data/ext/rtree/lib/csv.h +16 -0
- data/ext/rtree/lib/endianness.h +83 -0
- data/ext/rtree/lib/error.c +47 -0
- data/ext/rtree/lib/json.c +491 -0
- data/ext/rtree/lib/json.h +16 -0
- data/ext/rtree/lib/mk/Hdr.mk +3 -0
- data/ext/rtree/lib/mk/MakeDepend +25 -0
- data/ext/rtree/lib/mk/Obj.mk +3 -0
- data/ext/rtree/lib/node.c +736 -0
- data/ext/rtree/lib/package.c +11 -0
- data/ext/rtree/lib/page.c +47 -0
- data/ext/rtree/lib/page.h +13 -0
- data/ext/rtree/lib/postscript.c +543 -0
- data/ext/rtree/lib/rect.c +139 -0
- data/ext/rtree/lib/rectf.c +219 -0
- data/ext/rtree/lib/rtree/branch.h +105 -0
- data/ext/rtree/lib/rtree/branches.h +38 -0
- data/ext/rtree/lib/rtree/error.h +42 -0
- data/ext/rtree/lib/rtree/extent.h +20 -0
- data/ext/rtree/lib/rtree/node.h +96 -0
- data/ext/rtree/lib/rtree/package.h +14 -0
- data/ext/rtree/lib/rtree/postscript.h +66 -0
- data/ext/rtree/lib/rtree/rect.h +38 -0
- data/ext/rtree/lib/rtree/rectf.h +34 -0
- data/ext/rtree/lib/rtree/search.h +27 -0
- data/ext/rtree/lib/rtree/state.h +113 -0
- data/ext/rtree/lib/rtree/types.h +14 -0
- data/ext/rtree/lib/rtree-base.c +197 -0
- data/ext/rtree/lib/rtree.h +62 -0
- data/ext/rtree/lib/search.c +54 -0
- data/ext/rtree/lib/split.c +710 -0
- data/ext/rtree/lib/split.h +15 -0
- data/ext/rtree/lib/spvol.c +48 -0
- data/ext/rtree/lib/spvol.h +13 -0
- data/ext/rtree/lib/state.c +169 -0
- data/ext/rtree/rtree.c +11 -0
- data/lib/rtree.rb +4 -4
- metadata +65 -3
@@ -0,0 +1,736 @@
|
|
1
|
+
#ifdef HAVE_CONFIG_H
|
2
|
+
#include "config.h"
|
3
|
+
#endif
|
4
|
+
|
5
|
+
#include "rtree/node.h"
|
6
|
+
#include "rtree/branches.h"
|
7
|
+
#include "rtree/rect.h"
|
8
|
+
#include "rtree/error.h"
|
9
|
+
|
10
|
+
#include "split.h"
|
11
|
+
|
12
|
+
#include <stdbool.h>
|
13
|
+
#include <stddef.h>
|
14
|
+
#include <string.h>
|
15
|
+
#include <stdlib.h>
|
16
|
+
#include <assert.h>
|
17
|
+
#include <errno.h>
|
18
|
+
|
19
|
+
#ifdef HAVE_TGMATH_H
|
20
|
+
#include <tgmath.h>
|
21
|
+
#else
|
22
|
+
#include <math.h>
|
23
|
+
#endif
|
24
|
+
|
25
|
+
/*
|
26
|
+
how many branches can we fit at the end of a node of the specified
|
27
|
+
size, typically this will be a fraction of a page size. This does
|
28
|
+
not take a state_t* as argument since it is used to initialise it.
|
29
|
+
*/
|
30
|
+
|
31
|
+
size_t node_num_branch(size_t node_size, size_t branch_size)
|
32
|
+
{
|
33
|
+
return (node_size - offsetof(node_t, branches)) / branch_size;
|
34
|
+
}
|
35
|
+
|
36
|
+
static branch_t* node_get_branch(const state_t *state,
|
37
|
+
const node_t *node, size_t i)
|
38
|
+
{
|
39
|
+
return branches_get(state, (void*)node->branches, i);
|
40
|
+
}
|
41
|
+
|
42
|
+
int node_init(const state_t *state, node_t *node)
|
43
|
+
{
|
44
|
+
node->count = 0;
|
45
|
+
node->level = 0;
|
46
|
+
|
47
|
+
const size_t n = state_branching_factor(state);
|
48
|
+
|
49
|
+
for (size_t i = 0 ; i < n ; i++)
|
50
|
+
{
|
51
|
+
int err = branch_init(state, node_get_branch(state, node, i));
|
52
|
+
if (err != RTREE_OK)
|
53
|
+
return err;
|
54
|
+
}
|
55
|
+
|
56
|
+
return RTREE_OK;
|
57
|
+
}
|
58
|
+
|
59
|
+
node_t* node_new(const state_t *state)
|
60
|
+
{
|
61
|
+
node_t *node;
|
62
|
+
|
63
|
+
if ((node = malloc(state_node_size(state))) == NULL)
|
64
|
+
errno = ENOMEM;
|
65
|
+
else
|
66
|
+
{
|
67
|
+
if (node_init(state, node) == 0)
|
68
|
+
return node;
|
69
|
+
|
70
|
+
free(node);
|
71
|
+
}
|
72
|
+
|
73
|
+
return NULL;
|
74
|
+
}
|
75
|
+
|
76
|
+
/*
|
77
|
+
Rather than iterate over the branches, we here recurse: this is so
|
78
|
+
that we can do all of the work that we need to do but leave the
|
79
|
+
allocation in node_clone() until last, and only then call ourself.
|
80
|
+
In case of failure we back out with node_destroy() return error and
|
81
|
+
our recursive parents do the same, so cleaning up after ourselves.
|
82
|
+
*/
|
83
|
+
|
84
|
+
static int node_clone_children(const state_t *state,
|
85
|
+
const node_t *src, node_t *dest,
|
86
|
+
size_t i)
|
87
|
+
{
|
88
|
+
if (i >= node_count(src)) return RTREE_OK;
|
89
|
+
|
90
|
+
const branch_t *src_branch;
|
91
|
+
if ((src_branch = node_get_branch(state, src, i)) == NULL)
|
92
|
+
return RTREE_ERR_GETBRANCH;
|
93
|
+
|
94
|
+
branch_t *dest_branch;
|
95
|
+
if ((dest_branch = node_get_branch(state, dest, i)) == NULL)
|
96
|
+
return RTREE_ERR_GETBRANCH;
|
97
|
+
|
98
|
+
const node_t *src_child;
|
99
|
+
if ((src_child = branch_get_child(src_branch)) == NULL)
|
100
|
+
return RTREE_ERR_GETCHILD;
|
101
|
+
|
102
|
+
node_t *dest_child;
|
103
|
+
if ((dest_child = node_clone(state, src_child)) == NULL)
|
104
|
+
return RTREE_ERR_NODECLONE;
|
105
|
+
|
106
|
+
int err = node_clone_children(state, src, dest, i + 1);
|
107
|
+
if (err != RTREE_OK)
|
108
|
+
{
|
109
|
+
node_destroy(state, dest_child);
|
110
|
+
return err;
|
111
|
+
}
|
112
|
+
|
113
|
+
branch_set_child(dest_branch, dest_child);
|
114
|
+
|
115
|
+
return RTREE_OK;
|
116
|
+
}
|
117
|
+
|
118
|
+
/*
|
119
|
+
To clone a leaf node (and its branches), we just need to copy,
|
120
|
+
but for internal nodes we need to replace the branches' pointers
|
121
|
+
to node by the pointer to its clone; so recursion.
|
122
|
+
*/
|
123
|
+
|
124
|
+
node_t* node_clone(const state_t *state, const node_t *src)
|
125
|
+
{
|
126
|
+
const size_t node_size = state_node_size(state);
|
127
|
+
node_t *dest;
|
128
|
+
|
129
|
+
if ((dest = malloc(node_size)) == NULL)
|
130
|
+
{
|
131
|
+
errno = ENOMEM;
|
132
|
+
return NULL;
|
133
|
+
}
|
134
|
+
|
135
|
+
memcpy(dest, src, node_size);
|
136
|
+
if (node_level(src) > 0)
|
137
|
+
{
|
138
|
+
if (node_clone_children(state, src, dest, 0) != 0)
|
139
|
+
{
|
140
|
+
free(dest);
|
141
|
+
return NULL;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
return dest;
|
146
|
+
}
|
147
|
+
|
148
|
+
/*
|
149
|
+
For the destroy, we go a bit overboard checking that everything
|
150
|
+
is non-NULL, this since we expect it to be used backing out on
|
151
|
+
failure, and that failure might be a bad alloc.
|
152
|
+
*/
|
153
|
+
|
154
|
+
void node_destroy(const state_t *state, node_t *node)
|
155
|
+
{
|
156
|
+
if (node != NULL)
|
157
|
+
{
|
158
|
+
if (node_level(node) > 0)
|
159
|
+
{
|
160
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
161
|
+
{
|
162
|
+
branch_t *branch;
|
163
|
+
if ((branch = node_get_branch(state, node, i)) != NULL)
|
164
|
+
{
|
165
|
+
node_t *child;
|
166
|
+
if ((child = branch_get_child_mutable(branch)) != NULL)
|
167
|
+
node_destroy(state, child);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
free(node);
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
/*
|
176
|
+
Apply the function f to each branch of the specified node, even if
|
177
|
+
that branch is empty (i.e., has no child). The function f should
|
178
|
+
return zero to indicate success, if a non-zero value is returned
|
179
|
+
then the iteration is aborted and that value returned.
|
180
|
+
*/
|
181
|
+
|
182
|
+
int node_branch_each(const state_t *state, const node_t *node,
|
183
|
+
nbe_cb_t *f, void *arg)
|
184
|
+
{
|
185
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
186
|
+
{
|
187
|
+
int err;
|
188
|
+
if ((err = f(state, node_get_branch(state, node, i), arg)) != 0)
|
189
|
+
return err;
|
190
|
+
}
|
191
|
+
return RTREE_OK;
|
192
|
+
}
|
193
|
+
|
194
|
+
/*
|
195
|
+
a bit like node_branch each, but applied to all nodes at the specified
|
196
|
+
level; a breadth-first iterate if you will
|
197
|
+
*/
|
198
|
+
|
199
|
+
int node_branch_each_level(const state_t *state, const node_t *node,
|
200
|
+
node_level_t level, nbe_cb_t *f, void *arg)
|
201
|
+
{
|
202
|
+
const node_level_t this_level = node_level(node);
|
203
|
+
|
204
|
+
if (this_level > level)
|
205
|
+
{
|
206
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
207
|
+
{
|
208
|
+
branch_t *branch = node_get_branch(state, node, i);
|
209
|
+
const node_t *child = branch_get_child(branch);
|
210
|
+
int err = node_branch_each_level(state, child, level, f, arg);
|
211
|
+
if (err != 0) return err;
|
212
|
+
}
|
213
|
+
}
|
214
|
+
else if (this_level == level)
|
215
|
+
{
|
216
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
217
|
+
{
|
218
|
+
branch_t *branch = node_get_branch(state, node, i);
|
219
|
+
int err = f(state, branch, arg);
|
220
|
+
if (err != 0) return err;
|
221
|
+
}
|
222
|
+
}
|
223
|
+
return RTREE_OK;
|
224
|
+
}
|
225
|
+
|
226
|
+
size_t node_bytes(const state_t *state, const node_t *node)
|
227
|
+
{
|
228
|
+
if (node == NULL)
|
229
|
+
return 0;
|
230
|
+
|
231
|
+
if (node_level(node) == 0)
|
232
|
+
return state_node_size(state);
|
233
|
+
|
234
|
+
size_t bytes = state_node_size(state);
|
235
|
+
|
236
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
237
|
+
{
|
238
|
+
branch_t *branch = node_get_branch(state, node, i);
|
239
|
+
const node_t *child = branch_get_child(branch);
|
240
|
+
bytes += node_bytes(state, child);
|
241
|
+
}
|
242
|
+
|
243
|
+
return bytes;
|
244
|
+
}
|
245
|
+
|
246
|
+
/*
|
247
|
+
remove branch i from node, to maintain contiguousness, we copy the
|
248
|
+
final branch to i (we don't need to do that if it is the final branch
|
249
|
+
of course, indeed, since we use memcpy we shouldn't do that). Note
|
250
|
+
that this handles the case when there is only one branch.
|
251
|
+
*/
|
252
|
+
|
253
|
+
int node_detach_branch(const state_t *state, node_t *node, size_t i)
|
254
|
+
{
|
255
|
+
branch_t *branch;
|
256
|
+
|
257
|
+
if ((i >= node_count(node)) ||
|
258
|
+
((branch = node_get_branch(state, node, i)) == NULL))
|
259
|
+
return RTREE_ERR_GETBRANCH;
|
260
|
+
|
261
|
+
if (i + 1 != node_count(node))
|
262
|
+
{
|
263
|
+
branch_t *branch_end = node_get_branch(state, node, node_count(node) - 1);
|
264
|
+
|
265
|
+
if (branch_end == NULL)
|
266
|
+
return RTREE_ERR_GETBRANCH;
|
267
|
+
|
268
|
+
if (branch_copy(state, branch_end, branch) == NULL)
|
269
|
+
return RTREE_ERR_NOMEM;
|
270
|
+
}
|
271
|
+
|
272
|
+
node_count_decrement(node);
|
273
|
+
|
274
|
+
return RTREE_OK;
|
275
|
+
}
|
276
|
+
|
277
|
+
static node_t* node_split(const state_t *state, node_t *node, branch_t *branch)
|
278
|
+
{
|
279
|
+
return split_node(state, node, branch);
|
280
|
+
}
|
281
|
+
|
282
|
+
/*
|
283
|
+
add branch to node, which may split the node: if so the new node
|
284
|
+
argumemnt is returned, so comparing the node argument and return
|
285
|
+
value is the way to detect that splitting has occured.
|
286
|
+
*/
|
287
|
+
|
288
|
+
node_t* node_add_branch(const state_t *state, node_t *node, branch_t *branch)
|
289
|
+
{
|
290
|
+
if (node_count(node) < state_branching_factor(state))
|
291
|
+
{
|
292
|
+
branch_t *b;
|
293
|
+
|
294
|
+
if ((b = node_get_branch(state, node, node_count(node))) == NULL)
|
295
|
+
return NULL;
|
296
|
+
|
297
|
+
branch_copy(state, branch, b);
|
298
|
+
node_count_increment(node);
|
299
|
+
|
300
|
+
return node;
|
301
|
+
}
|
302
|
+
|
303
|
+
return node_split(state, node, branch);
|
304
|
+
}
|
305
|
+
|
306
|
+
/*
|
307
|
+
Pick a branch. Pick the one that will need the smallest increase
|
308
|
+
in volume to accomodate the new (hyper-)rectangle. This will result
|
309
|
+
in the least total volume for the covering rectangles in the current
|
310
|
+
node. In case of a tie, pick the one which was smaller before, to
|
311
|
+
get the best resolution when searching.
|
312
|
+
*/
|
313
|
+
|
314
|
+
static int node_pick_branch(const state_t *state,
|
315
|
+
node_t *node, const rtree_coord_t *rect,
|
316
|
+
size_t *index)
|
317
|
+
{
|
318
|
+
const size_t
|
319
|
+
dims = state_dims(state);
|
320
|
+
size_t
|
321
|
+
index_min = SIZE_MAX;
|
322
|
+
rtree_coord_t
|
323
|
+
dvol_min = INFINITY,
|
324
|
+
vol_min = INFINITY;
|
325
|
+
|
326
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
327
|
+
{
|
328
|
+
branch_t *branch;
|
329
|
+
|
330
|
+
if ((branch = node_get_branch(state, node, i)) == NULL)
|
331
|
+
return RTREE_ERR_GETBRANCH;
|
332
|
+
|
333
|
+
const rtree_coord_t *rect1 = branch_get_rect(branch);
|
334
|
+
rtree_coord_t rect2[2 * dims];
|
335
|
+
rect_combine(state, rect, rect1, rect2);
|
336
|
+
|
337
|
+
rtree_coord_t
|
338
|
+
vol1 = rect_spherical_volume(state, rect1),
|
339
|
+
vol2 = rect_spherical_volume(state, rect2),
|
340
|
+
dvol = vol2 - vol1;
|
341
|
+
|
342
|
+
if ((dvol < dvol_min) || ((dvol == dvol_min) && (vol1 < vol_min)))
|
343
|
+
{
|
344
|
+
index_min = i;
|
345
|
+
vol_min = vol1;
|
346
|
+
dvol_min = dvol;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
/*
|
351
|
+
This can only happen if no branches are assigned in the above
|
352
|
+
block, on the first call of it, dvol_min == DBL_MAX, so either
|
353
|
+
the first case is called, or dvol == DBL_MAX, but dvol is equal
|
354
|
+
to vol2 - vol1, and vol1, vol2 are non-negative, so vol2 must
|
355
|
+
be DBL_MAX and vol1 zero, in particular vol1 < vol_min (DBL_MAX),
|
356
|
+
so the second condition is met.
|
357
|
+
*/
|
358
|
+
|
359
|
+
if (index_min == SIZE_MAX)
|
360
|
+
return RTREE_ERR_PICKBRANCH;
|
361
|
+
|
362
|
+
*index = index_min;
|
363
|
+
|
364
|
+
return RTREE_OK;
|
365
|
+
}
|
366
|
+
|
367
|
+
int node_envelope(const state_t *state, const node_t *node,
|
368
|
+
rtree_coord_t *rect)
|
369
|
+
{
|
370
|
+
size_t n = node_count(node);
|
371
|
+
|
372
|
+
if (n > 0)
|
373
|
+
{
|
374
|
+
const branch_t *branch;
|
375
|
+
|
376
|
+
if ((branch = node_get_branch(state, node, 0)) == NULL)
|
377
|
+
return RTREE_ERR_GETBRANCH;
|
378
|
+
rect_copy(state, branch_get_rect(branch), rect);
|
379
|
+
|
380
|
+
for (size_t i = 1 ; i < n ; i++)
|
381
|
+
{
|
382
|
+
if ((branch = node_get_branch(state, node, i)) == NULL)
|
383
|
+
return RTREE_ERR_GETBRANCH;
|
384
|
+
rect_merge(state, branch_get_rect(branch), rect);
|
385
|
+
}
|
386
|
+
}
|
387
|
+
|
388
|
+
return RTREE_OK;
|
389
|
+
}
|
390
|
+
|
391
|
+
static node_t* node_add_rect2(const state_t *state,
|
392
|
+
rtree_id_t id, const rtree_coord_t *rect, node_t *node,
|
393
|
+
node_level_t level)
|
394
|
+
{
|
395
|
+
const size_t rect_size = state_rect_size(state);
|
396
|
+
|
397
|
+
if (node_level(node) > level)
|
398
|
+
{
|
399
|
+
/* internal node */
|
400
|
+
|
401
|
+
size_t i;
|
402
|
+
|
403
|
+
if (node_pick_branch(state, node, rect, &i) != 0)
|
404
|
+
return NULL;
|
405
|
+
|
406
|
+
branch_t *picked;
|
407
|
+
|
408
|
+
if ((picked = node_get_branch(state, node, i)) == NULL)
|
409
|
+
return NULL;
|
410
|
+
|
411
|
+
node_t
|
412
|
+
*child = branch_get_child_mutable(picked),
|
413
|
+
*node2 = node_add_rect2(state, id, rect, child, level);
|
414
|
+
|
415
|
+
if (node2 == child)
|
416
|
+
{
|
417
|
+
/* child not split */
|
418
|
+
|
419
|
+
rtree_coord_t rect_comb[rect_size];
|
420
|
+
rect_combine(state, rect, branch_get_rect(picked), rect_comb);
|
421
|
+
branch_set_rect(state, picked, rect_comb);
|
422
|
+
|
423
|
+
return node;
|
424
|
+
}
|
425
|
+
else
|
426
|
+
{
|
427
|
+
/* child split */
|
428
|
+
|
429
|
+
rtree_coord_t rect_comb[rect_size];
|
430
|
+
if (node_envelope(state, child, rect_comb) != 0)
|
431
|
+
return NULL;
|
432
|
+
branch_set_rect(state, picked, rect_comb);
|
433
|
+
|
434
|
+
char branch_bytes[state_branch_size(state)];
|
435
|
+
branch_t *branch = (branch_t*)branch_bytes;
|
436
|
+
branch_init(state, branch);
|
437
|
+
|
438
|
+
branch_set_child(branch, node2);
|
439
|
+
|
440
|
+
if (node_envelope(state, node2, rect_comb) != 0)
|
441
|
+
return NULL;
|
442
|
+
branch_set_rect(state, branch, rect_comb);
|
443
|
+
|
444
|
+
node_t *new_node = node_add_branch(state, node, branch);
|
445
|
+
|
446
|
+
return new_node;
|
447
|
+
}
|
448
|
+
}
|
449
|
+
else if (node_level(node) == level)
|
450
|
+
{
|
451
|
+
/* leaf node */
|
452
|
+
|
453
|
+
char branch_bytes[state_branch_size(state)];
|
454
|
+
branch_t *branch = (branch_t*)branch_bytes;
|
455
|
+
branch_init(state, branch);
|
456
|
+
|
457
|
+
branch_set_id(branch, id);
|
458
|
+
branch_set_rect(state, branch, rect);
|
459
|
+
|
460
|
+
node_t *new_node = node_add_branch(state, node, branch);
|
461
|
+
|
462
|
+
return new_node;
|
463
|
+
}
|
464
|
+
|
465
|
+
return NULL;
|
466
|
+
}
|
467
|
+
|
468
|
+
/*
|
469
|
+
Insert the rect (array) into the node root, the root may be split
|
470
|
+
and the sibling is returned from the function on success. On failure
|
471
|
+
NULL is returned and the root is not modified (so can be reallocated)
|
472
|
+
*/
|
473
|
+
|
474
|
+
node_t* node_add_rect(const state_t *state,
|
475
|
+
rtree_id_t id, rtree_coord_t *rect, node_t *root,
|
476
|
+
node_level_t level)
|
477
|
+
{
|
478
|
+
const size_t dims = state_dims(state);
|
479
|
+
|
480
|
+
/*
|
481
|
+
dims is never zero as that would not make sense at the application
|
482
|
+
level, and that is enforced in state_new(), but scan-build does
|
483
|
+
not look that deep and thinks that it might be so errors on a length
|
484
|
+
zero VLA below; this assert fixes that, removing it leads to spurious
|
485
|
+
CI failures.
|
486
|
+
*/
|
487
|
+
|
488
|
+
assert(dims > 0);
|
489
|
+
|
490
|
+
for (size_t i = 0 ; i < dims ; i++)
|
491
|
+
{
|
492
|
+
if (rect[i] > rect[dims + i])
|
493
|
+
{
|
494
|
+
errno = EINVAL;
|
495
|
+
return NULL;
|
496
|
+
}
|
497
|
+
}
|
498
|
+
|
499
|
+
node_t *sibling;
|
500
|
+
|
501
|
+
if ((sibling = node_add_rect2(state, id, rect, root, level)) == NULL)
|
502
|
+
return NULL;
|
503
|
+
|
504
|
+
if (sibling == root)
|
505
|
+
return root;
|
506
|
+
|
507
|
+
node_t *new_root;
|
508
|
+
|
509
|
+
if ((new_root = node_new(state)) != NULL)
|
510
|
+
{
|
511
|
+
node_set_level(new_root, node_level(root) + 1);
|
512
|
+
|
513
|
+
char branch_bytes[state_branch_size(state)];
|
514
|
+
branch_t *branch = (branch_t*)branch_bytes;
|
515
|
+
branch_init(state, branch);
|
516
|
+
|
517
|
+
rtree_coord_t envelope[2 * dims];
|
518
|
+
|
519
|
+
if (node_envelope(state, root, envelope) == 0)
|
520
|
+
{
|
521
|
+
branch_set_child(branch, root);
|
522
|
+
branch_set_rect(state, branch, envelope);
|
523
|
+
|
524
|
+
/*
|
525
|
+
node_add_branch() may return a node different to the input
|
526
|
+
node if the node splits -- that shouldn't happen, since we
|
527
|
+
have just created this node, so if it does then we error
|
528
|
+
out (making a half-hearted effort to clean up).
|
529
|
+
*/
|
530
|
+
|
531
|
+
node_t *n = node_add_branch(state, new_root, branch);
|
532
|
+
|
533
|
+
if (n != new_root)
|
534
|
+
node_destroy(state, n);
|
535
|
+
else
|
536
|
+
{
|
537
|
+
if (node_envelope(state, sibling, envelope) == 0)
|
538
|
+
{
|
539
|
+
branch_set_child(branch, sibling);
|
540
|
+
branch_set_rect(state, branch, envelope);
|
541
|
+
node_add_branch(state, new_root, branch);
|
542
|
+
|
543
|
+
return new_root;
|
544
|
+
}
|
545
|
+
}
|
546
|
+
}
|
547
|
+
|
548
|
+
node_destroy(state, new_root);
|
549
|
+
}
|
550
|
+
|
551
|
+
node_destroy(state, sibling);
|
552
|
+
|
553
|
+
return NULL;
|
554
|
+
}
|
555
|
+
|
556
|
+
int node_update(const state_t *state, const node_t *node,
|
557
|
+
rtree_update_t *f, void *context)
|
558
|
+
{
|
559
|
+
node_level_t level = node_level(node);
|
560
|
+
|
561
|
+
if (level > 0)
|
562
|
+
{
|
563
|
+
const size_t dims = state_dims(state);
|
564
|
+
|
565
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
566
|
+
{
|
567
|
+
branch_t *branch = node_get_branch(state, node, i);
|
568
|
+
if (branch == NULL) return RTREE_ERR_GETBRANCH;
|
569
|
+
|
570
|
+
const node_t *child = branch_get_child(branch);
|
571
|
+
if (child == NULL) return RTREE_ERR_GETCHILD;
|
572
|
+
|
573
|
+
/*
|
574
|
+
Note, in the case that node_update returns RTREE_ERR_USER,
|
575
|
+
we could calculate and assign the envelope, and then the
|
576
|
+
search index should be correct. but it seems unlikely that
|
577
|
+
this would ever be useful, since you're then be indexing a
|
578
|
+
half-updated set of rectangles. So we leave that until the
|
579
|
+
need arises.
|
580
|
+
*/
|
581
|
+
|
582
|
+
int err;
|
583
|
+
|
584
|
+
err = node_update(state, child, f, context);
|
585
|
+
if (err != RTREE_OK) return err;
|
586
|
+
|
587
|
+
rtree_coord_t envelope[2 * dims];
|
588
|
+
err = node_envelope(state, child, envelope);
|
589
|
+
if (err != RTREE_OK) return err;
|
590
|
+
|
591
|
+
branch_set_rect(state, branch, envelope);
|
592
|
+
}
|
593
|
+
}
|
594
|
+
else
|
595
|
+
{
|
596
|
+
for (size_t i = 0 ; i < node_count(node) ; i++)
|
597
|
+
{
|
598
|
+
branch_t *branch = node_get_branch(state, node, i);
|
599
|
+
if (branch == NULL) return RTREE_ERR_GETBRANCH;
|
600
|
+
|
601
|
+
rtree_coord_t *rect = branch_get_rect_mutable(branch);
|
602
|
+
rtree_id_t id = branch_get_id(branch);
|
603
|
+
|
604
|
+
if (f(id, rect, context) != 0) return RTREE_ERR_USER;
|
605
|
+
}
|
606
|
+
}
|
607
|
+
|
608
|
+
return RTREE_OK;
|
609
|
+
}
|
610
|
+
|
611
|
+
/*
|
612
|
+
Height is the maximal number of branches from the root to a leaf,
|
613
|
+
or zero if the tree is empty. If there have been no branch
|
614
|
+
deletions, then this is the same as the level of the root plus one,
|
615
|
+
but if there have been deletions then this is not the case. This
|
616
|
+
function iterates over all internal nodes to calculate the height,
|
617
|
+
this could probably be done more efficiently by holding some state
|
618
|
+
on branch deletions, but we don't expect this to be called that
|
619
|
+
often (and it's still pretty quick).
|
620
|
+
*/
|
621
|
+
|
622
|
+
node_level_t node_height(const state_t *state, const node_t *node)
|
623
|
+
{
|
624
|
+
node_count_t count;
|
625
|
+
|
626
|
+
if ((count = node_count(node)) == 0)
|
627
|
+
return 0;
|
628
|
+
|
629
|
+
if (node_level(node) == 0)
|
630
|
+
return 1;
|
631
|
+
|
632
|
+
node_level_t child_max_height = 0;
|
633
|
+
|
634
|
+
for (size_t i = 0 ; i < count ; i++)
|
635
|
+
{
|
636
|
+
const branch_t *branch = node_get_branch(state, node, i);
|
637
|
+
const node_t *child = branch_get_child(branch);
|
638
|
+
node_level_t child_height = node_height(state, child);
|
639
|
+
|
640
|
+
if (child_height > child_max_height)
|
641
|
+
child_max_height = child_height;
|
642
|
+
}
|
643
|
+
|
644
|
+
if (child_max_height == 0)
|
645
|
+
return 0;
|
646
|
+
else
|
647
|
+
return child_max_height + 1;
|
648
|
+
}
|
649
|
+
|
650
|
+
/*
|
651
|
+
it is assumed that the state is identical for a and b, i.e., that
|
652
|
+
state_identical() is true (so we don't need to pass the state for
|
653
|
+
both nodes).
|
654
|
+
*/
|
655
|
+
|
656
|
+
bool node_identical(const state_t *state, const node_t *a, const node_t *b)
|
657
|
+
{
|
658
|
+
if (a && b)
|
659
|
+
{
|
660
|
+
if ((node_level(a) != node_level(b)) || (node_count(a) != node_count(b)))
|
661
|
+
return false;
|
662
|
+
|
663
|
+
node_level_t level = node_level(a);
|
664
|
+
node_count_t count = node_count(a);
|
665
|
+
|
666
|
+
for (size_t i = 0 ; i < count ; i++)
|
667
|
+
{
|
668
|
+
const branch_t
|
669
|
+
*branch_a = node_get_branch(state, a, i),
|
670
|
+
*branch_b = node_get_branch(state, b, i);
|
671
|
+
const rtree_coord_t
|
672
|
+
*rect_a = branch_get_rect(branch_a),
|
673
|
+
*rect_b = branch_get_rect(branch_b);
|
674
|
+
|
675
|
+
if (! rect_identical(state, rect_a, rect_b))
|
676
|
+
return false;
|
677
|
+
|
678
|
+
if (level > 0)
|
679
|
+
{
|
680
|
+
const node_t
|
681
|
+
*child_a = branch_get_child(branch_a),
|
682
|
+
*child_b = branch_get_child(branch_b);
|
683
|
+
|
684
|
+
if (! node_identical(state, child_a, child_b))
|
685
|
+
return false;
|
686
|
+
}
|
687
|
+
else
|
688
|
+
{
|
689
|
+
rtree_id_t
|
690
|
+
id_a = branch_get_id(branch_a),
|
691
|
+
id_b = branch_get_id(branch_b);
|
692
|
+
|
693
|
+
if (id_a != id_b)
|
694
|
+
return false;
|
695
|
+
}
|
696
|
+
}
|
697
|
+
return true;
|
698
|
+
}
|
699
|
+
|
700
|
+
return ! (a || b);
|
701
|
+
}
|
702
|
+
|
703
|
+
/*
|
704
|
+
find whether the node or its descendants have a leaf, so we're
|
705
|
+
looking for a level-zero node with a non-zero count, of course
|
706
|
+
we short circuit as soon as we find one.
|
707
|
+
*/
|
708
|
+
|
709
|
+
bool node_nonempty(const state_t *state, const node_t *node)
|
710
|
+
{
|
711
|
+
node_count_t count;
|
712
|
+
|
713
|
+
if ((count = node_count(node)) == 0)
|
714
|
+
return false;
|
715
|
+
|
716
|
+
if (node_level(node) == 0)
|
717
|
+
return true;
|
718
|
+
|
719
|
+
for (size_t i = 0 ; i < count ; i++)
|
720
|
+
{
|
721
|
+
const branch_t *branch = node_get_branch(state, node, i);
|
722
|
+
const node_t *child = branch_get_child(branch);
|
723
|
+
|
724
|
+
if (node_nonempty(state, child))
|
725
|
+
return true;
|
726
|
+
}
|
727
|
+
|
728
|
+
return false;
|
729
|
+
}
|
730
|
+
|
731
|
+
extern node_count_t node_count(const node_t*);
|
732
|
+
extern void node_count_increment(node_t*);
|
733
|
+
extern void node_count_decrement(node_t*);
|
734
|
+
extern node_level_t node_level(const node_t*);
|
735
|
+
extern void node_set_level(node_t*, node_level_t);
|
736
|
+
extern void* node_get_branches(node_t*);
|