librtree 0.9.1 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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*);
|