tg_geometry 0.3.2 → 0.3.3
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 +12 -0
- data/README.md +81 -291
- data/ext/tg_geometry/tg_geometry_ext.c +3 -4
- data/ext/tg_geometry/vendor/.vendored +8 -8
- data/ext/tg_geometry/vendor/json/VERSION +1 -1
- data/ext/tg_geometry/vendor/json/json.c +20 -20
- data/ext/tg_geometry/vendor/json/json.h +20 -20
- data/ext/tg_geometry/vendor/rtree/VERSION +2 -2
- data/ext/tg_geometry/vendor/rtree/rtree.c +121 -148
- data/ext/tg_geometry/vendor/rtree/rtree.h +14 -11
- data/ext/tg_geometry/vendor/tg/VERSION +1 -1
- data/ext/tg_geometry/vendor/tg/tg.c +1854 -1339
- data/ext/tg_geometry/vendor/tg/tg.h +18 -17
- data/lib/tg/geometry/version.rb +1 -1
- data/script/vendor_libs.rb +11 -7
- metadata +3 -6
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#include <string.h>
|
|
6
6
|
#include <math.h>
|
|
7
7
|
#include <stdbool.h>
|
|
8
|
-
#include
|
|
8
|
+
#include <stdlib.h>
|
|
9
9
|
|
|
10
10
|
////////////////////////////////
|
|
11
11
|
|
|
@@ -16,12 +16,28 @@
|
|
|
16
16
|
|
|
17
17
|
////////////////////////////////
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
#define
|
|
21
|
-
#
|
|
19
|
+
#ifdef RTREE_USEPATHHINT
|
|
20
|
+
#define USEPATHHINT
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#ifdef RTREE_MAXITEMS
|
|
24
|
+
#undef MAXITEMS
|
|
25
|
+
#define MAXITEMS RTREE_MAXITEMS
|
|
26
|
+
#endif
|
|
22
27
|
|
|
23
|
-
#
|
|
24
|
-
#
|
|
28
|
+
#ifdef RTREE_DATATYPE
|
|
29
|
+
#undef DATATYPE
|
|
30
|
+
#define DATATYPE RTREE_DATATYPE
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#ifdef RTREE_DIMS
|
|
34
|
+
#undef DIMS
|
|
35
|
+
#define DIMS RTREE_DIMS
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#ifdef RTREE_NUMTYPE
|
|
39
|
+
#undef NUMTYPE
|
|
40
|
+
#define NUMTYPE RTREE_NUMTYPE
|
|
25
41
|
#endif
|
|
26
42
|
|
|
27
43
|
#ifdef RTREE_MAXITEMS
|
|
@@ -31,35 +47,32 @@
|
|
|
31
47
|
|
|
32
48
|
#ifdef RTREE_NOATOMICS
|
|
33
49
|
typedef int rc_t;
|
|
34
|
-
static
|
|
35
|
-
|
|
36
|
-
|
|
50
|
+
static void rc_init(rc_t *rc) {
|
|
51
|
+
*rc = 0;
|
|
52
|
+
}
|
|
53
|
+
static void rc_retain(rc_t *rc) {
|
|
54
|
+
(*rc)++;
|
|
37
55
|
}
|
|
38
|
-
static int
|
|
39
|
-
|
|
40
|
-
*ptr -= val;
|
|
41
|
-
return rc;
|
|
56
|
+
static int rc_release(rc_t *rc) {
|
|
57
|
+
return ((*rc)--) == 1;
|
|
42
58
|
}
|
|
43
|
-
static int
|
|
44
|
-
|
|
45
|
-
*ptr += val;
|
|
46
|
-
return rc;
|
|
59
|
+
static int rc_shared(rc_t *rc) {
|
|
60
|
+
return (*rc) > 1;
|
|
47
61
|
}
|
|
48
|
-
#else
|
|
62
|
+
#else
|
|
49
63
|
#include <stdatomic.h>
|
|
50
64
|
typedef atomic_int rc_t;
|
|
51
|
-
static
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
65
|
+
static void rc_init(rc_t *rc) {
|
|
66
|
+
atomic_init(rc, 0);
|
|
67
|
+
}
|
|
68
|
+
static void rc_retain(rc_t *rc) {
|
|
69
|
+
atomic_fetch_add_explicit(rc, 1, __ATOMIC_RELAXED);
|
|
57
70
|
}
|
|
58
|
-
static int
|
|
59
|
-
return
|
|
71
|
+
static int rc_release(rc_t *rc) {
|
|
72
|
+
return atomic_fetch_sub_explicit(rc, 1, __ATOMIC_ACQ_REL) == 1;
|
|
60
73
|
}
|
|
61
|
-
static int
|
|
62
|
-
return
|
|
74
|
+
static int rc_shared(rc_t *rc) {
|
|
75
|
+
return atomic_load_explicit(rc, __ATOMIC_ACQUIRE) > 1;
|
|
63
76
|
}
|
|
64
77
|
#endif
|
|
65
78
|
|
|
@@ -93,10 +106,9 @@ struct rtree {
|
|
|
93
106
|
struct node *root;
|
|
94
107
|
size_t count;
|
|
95
108
|
size_t height;
|
|
96
|
-
#ifdef
|
|
109
|
+
#ifdef USEPATHHINT
|
|
97
110
|
int path_hint[16];
|
|
98
111
|
#endif
|
|
99
|
-
bool relaxed;
|
|
100
112
|
void *(*malloc)(size_t);
|
|
101
113
|
void (*free)(void *);
|
|
102
114
|
void *udata;
|
|
@@ -116,7 +128,6 @@ static bool feq(NUMTYPE a, NUMTYPE b) {
|
|
|
116
128
|
return !(a < b || a > b);
|
|
117
129
|
}
|
|
118
130
|
|
|
119
|
-
|
|
120
131
|
void rtree_set_udata(struct rtree *tr, void *udata) {
|
|
121
132
|
tr->udata = udata;
|
|
122
133
|
}
|
|
@@ -124,8 +135,10 @@ void rtree_set_udata(struct rtree *tr, void *udata) {
|
|
|
124
135
|
static struct node *node_new(struct rtree *tr, enum kind kind) {
|
|
125
136
|
struct node *node = (struct node *)tr->malloc(sizeof(struct node));
|
|
126
137
|
if (!node) return NULL;
|
|
127
|
-
|
|
138
|
+
rc_init(&node->rc);
|
|
139
|
+
rc_retain(&node->rc);
|
|
128
140
|
node->kind = kind;
|
|
141
|
+
node->count = 0;
|
|
129
142
|
return node;
|
|
130
143
|
}
|
|
131
144
|
|
|
@@ -133,17 +146,18 @@ static struct node *node_copy(struct rtree *tr, struct node *node) {
|
|
|
133
146
|
struct node *node2 = (struct node *)tr->malloc(sizeof(struct node));
|
|
134
147
|
if (!node2) return NULL;
|
|
135
148
|
memcpy(node2, node, sizeof(struct node));
|
|
136
|
-
node2->rc
|
|
149
|
+
rc_init(&node2->rc);
|
|
150
|
+
rc_retain(&node2->rc);
|
|
137
151
|
if (node2->kind == BRANCH) {
|
|
138
152
|
for (int i = 0; i < node2->count; i++) {
|
|
139
|
-
|
|
153
|
+
rc_retain(&node2->nodes[i]->rc);
|
|
140
154
|
}
|
|
141
155
|
} else {
|
|
142
156
|
if (tr->item_clone) {
|
|
143
157
|
int n = 0;
|
|
144
158
|
bool oom = false;
|
|
145
159
|
for (int i = 0; i < node2->count; i++) {
|
|
146
|
-
if (!tr->item_clone(node->datas[i].data,
|
|
160
|
+
if (!tr->item_clone(node->datas[i].data,
|
|
147
161
|
(DATATYPE*)&node2->datas[i].data, tr->udata))
|
|
148
162
|
{
|
|
149
163
|
oom = true;
|
|
@@ -166,7 +180,9 @@ static struct node *node_copy(struct rtree *tr, struct node *node) {
|
|
|
166
180
|
}
|
|
167
181
|
|
|
168
182
|
static void node_free(struct rtree *tr, struct node *node) {
|
|
169
|
-
if (
|
|
183
|
+
if (!rc_release(&node->rc)) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
170
186
|
if (node->kind == BRANCH) {
|
|
171
187
|
for (int i = 0; i < node->count; i++) {
|
|
172
188
|
node_free(tr, node->nodes[i]);
|
|
@@ -182,7 +198,7 @@ static void node_free(struct rtree *tr, struct node *node) {
|
|
|
182
198
|
}
|
|
183
199
|
|
|
184
200
|
#define cow_node_or(rnode, code) { \
|
|
185
|
-
if (
|
|
201
|
+
if (rc_shared(&(rnode)->rc)) { \
|
|
186
202
|
struct node *node2 = node_copy(tr, (rnode)); \
|
|
187
203
|
if (!node2) { code; } \
|
|
188
204
|
node_free(tr, rnode); \
|
|
@@ -206,12 +222,12 @@ static NUMTYPE rect_area(const struct rect *rect) {
|
|
|
206
222
|
}
|
|
207
223
|
|
|
208
224
|
// return the area of two rects expanded
|
|
209
|
-
static NUMTYPE rect_unioned_area(const struct rect *rect,
|
|
225
|
+
static NUMTYPE rect_unioned_area(const struct rect *rect,
|
|
210
226
|
const struct rect *other)
|
|
211
227
|
{
|
|
212
228
|
NUMTYPE result = 1;
|
|
213
229
|
for (int i = 0; i < DIMS; i++) {
|
|
214
|
-
result *= (max0(rect->max[i], other->max[i]) -
|
|
230
|
+
result *= (max0(rect->max[i], other->max[i]) -
|
|
215
231
|
min0(rect->min[i], other->min[i]));
|
|
216
232
|
}
|
|
217
233
|
return result;
|
|
@@ -237,7 +253,7 @@ static bool rect_intersects(const struct rect *rect, const struct rect *other) {
|
|
|
237
253
|
|
|
238
254
|
static bool rect_onedge(const struct rect *rect, const struct rect *other) {
|
|
239
255
|
for (int i = 0; i < DIMS; i++) {
|
|
240
|
-
if (feq(rect->min[i], other->min[i]) ||
|
|
256
|
+
if (feq(rect->min[i], other->min[i]) ||
|
|
241
257
|
feq(rect->max[i], other->max[i]))
|
|
242
258
|
{
|
|
243
259
|
return true;
|
|
@@ -248,7 +264,7 @@ static bool rect_onedge(const struct rect *rect, const struct rect *other) {
|
|
|
248
264
|
|
|
249
265
|
static bool rect_equals(const struct rect *rect, const struct rect *other) {
|
|
250
266
|
for (int i = 0; i < DIMS; i++) {
|
|
251
|
-
if (!feq(rect->min[i], other->min[i]) ||
|
|
267
|
+
if (!feq(rect->min[i], other->min[i]) ||
|
|
252
268
|
!feq(rect->max[i], other->max[i]))
|
|
253
269
|
{
|
|
254
270
|
return false;
|
|
@@ -281,54 +297,7 @@ static int rect_largest_axis(const struct rect *rect) {
|
|
|
281
297
|
return axis;
|
|
282
298
|
}
|
|
283
299
|
|
|
284
|
-
|
|
285
|
-
static void node_swap(struct node *node, int i, int j) {
|
|
286
|
-
struct rect tmp = node->rects[i];
|
|
287
|
-
node->rects[i] = node->rects[j];
|
|
288
|
-
node->rects[j] = tmp;
|
|
289
|
-
if (node->kind == LEAF) {
|
|
290
|
-
struct item tmp = node->datas[i];
|
|
291
|
-
node->datas[i] = node->datas[j];
|
|
292
|
-
node->datas[j] = tmp;
|
|
293
|
-
} else {
|
|
294
|
-
struct node *tmp = node->nodes[i];
|
|
295
|
-
node->nodes[i] = node->nodes[j];
|
|
296
|
-
node->nodes[j] = tmp;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
struct rect4 {
|
|
301
|
-
NUMTYPE all[DIMS*2];
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
static void node_qsort(struct node *node, int s, int e, int index) {
|
|
305
|
-
int nrects = e - s;
|
|
306
|
-
if (nrects < 2) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
int left = 0;
|
|
310
|
-
int right = nrects-1;
|
|
311
|
-
int pivot = nrects / 2;
|
|
312
|
-
node_swap(node, s+pivot, s+right);
|
|
313
|
-
struct rect4 *rects = (struct rect4 *)&node->rects[s];
|
|
314
|
-
for (int i = 0; i < nrects; i++) {
|
|
315
|
-
if (rects[right].all[index] < rects[i].all[index]) {
|
|
316
|
-
node_swap(node, s+i, s+left);
|
|
317
|
-
left++;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
node_swap(node, s+left, s+right);
|
|
321
|
-
node_qsort(node, s, s+left, index);
|
|
322
|
-
node_qsort(node, s+left+1, e, index);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// sort the node rectangles by the axis. used during splits
|
|
326
|
-
static void node_sort_by_axis(struct node *node, int axis, bool max) {
|
|
327
|
-
int by_index = max ? DIMS+axis : axis;
|
|
328
|
-
node_qsort(node, 0, node->count, by_index);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
static void node_move_rect_at_index_into(struct node *from, int index,
|
|
300
|
+
static void node_move_rect_at_index_into(struct node *from, int index,
|
|
332
301
|
struct node *into)
|
|
333
302
|
{
|
|
334
303
|
into->rects[into->count] = from->rects[index];
|
|
@@ -344,8 +313,8 @@ static void node_move_rect_at_index_into(struct node *from, int index,
|
|
|
344
313
|
into->count++;
|
|
345
314
|
}
|
|
346
315
|
|
|
347
|
-
static bool node_split_largest_axis_edge_snap(struct rtree *tr,
|
|
348
|
-
struct rect *rect, struct node *node, struct node **right_out)
|
|
316
|
+
static bool node_split_largest_axis_edge_snap(struct rtree *tr,
|
|
317
|
+
struct rect *rect, struct node *node, struct node **right_out)
|
|
349
318
|
{
|
|
350
319
|
int axis = rect_largest_axis(rect);
|
|
351
320
|
struct node *right = node_new(tr, node->kind);
|
|
@@ -361,36 +330,31 @@ static bool node_split_largest_axis_edge_snap(struct rtree *tr,
|
|
|
361
330
|
i--;
|
|
362
331
|
}
|
|
363
332
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
} while (right->count < MINITEMS);
|
|
378
|
-
}
|
|
379
|
-
if (node->kind == BRANCH) {
|
|
380
|
-
node_sort_by_axis(node, 0, false);
|
|
381
|
-
node_sort_by_axis(right, 0, false);
|
|
333
|
+
if (right->count == 0) {
|
|
334
|
+
// There must be at least one item in a node.
|
|
335
|
+
// Choose the one closest to the right (max) edge
|
|
336
|
+
int j = 0;
|
|
337
|
+
double jdist = INFINITY;
|
|
338
|
+
for (int i = 0; i < node->count; i++) {
|
|
339
|
+
NUMTYPE max_dist = rect->max[axis] - node->rects[i].max[axis];
|
|
340
|
+
if (max_dist < jdist) {
|
|
341
|
+
j = i;
|
|
342
|
+
jdist = max_dist;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
node_move_rect_at_index_into(node, j, right);
|
|
382
346
|
}
|
|
383
347
|
*right_out = right;
|
|
384
348
|
return true;
|
|
385
349
|
}
|
|
386
350
|
|
|
387
351
|
static bool node_split(struct rtree *tr, struct rect *rect, struct node *node,
|
|
388
|
-
struct node **right)
|
|
352
|
+
struct node **right)
|
|
389
353
|
{
|
|
390
354
|
return node_split_largest_axis_edge_snap(tr, rect, node, right);
|
|
391
355
|
}
|
|
392
356
|
|
|
393
|
-
static int node_choose_least_enlargement(const struct node *node,
|
|
357
|
+
static int node_choose_least_enlargement(const struct node *node,
|
|
394
358
|
const struct rect *ir)
|
|
395
359
|
{
|
|
396
360
|
int j = 0;
|
|
@@ -408,10 +372,11 @@ static int node_choose_least_enlargement(const struct node *node,
|
|
|
408
372
|
return j;
|
|
409
373
|
}
|
|
410
374
|
|
|
411
|
-
static int node_choose(struct rtree *tr, const struct node *node,
|
|
375
|
+
static int node_choose(struct rtree *tr, const struct node *node,
|
|
412
376
|
const struct rect *rect, int depth)
|
|
413
377
|
{
|
|
414
|
-
|
|
378
|
+
(void)tr, (void)depth;
|
|
379
|
+
#ifdef USEPATHHINT
|
|
415
380
|
int h = tr->path_hint[depth];
|
|
416
381
|
if (h < node->count) {
|
|
417
382
|
if (rect_contains(&node->rects[h], rect)) {
|
|
@@ -422,7 +387,7 @@ static int node_choose(struct rtree *tr, const struct node *node,
|
|
|
422
387
|
// Take a quick look for the first node that contain the rect.
|
|
423
388
|
for (int i = 0; i < node->count; i++) {
|
|
424
389
|
if (rect_contains(&node->rects[i], rect)) {
|
|
425
|
-
#ifdef
|
|
390
|
+
#ifdef USEPATHHINT
|
|
426
391
|
tr->path_hint[depth] = i;
|
|
427
392
|
#endif
|
|
428
393
|
return i;
|
|
@@ -430,7 +395,7 @@ static int node_choose(struct rtree *tr, const struct node *node,
|
|
|
430
395
|
}
|
|
431
396
|
// Fallback to using che "choose least enlargment" algorithm.
|
|
432
397
|
int i = node_choose_least_enlargement(node, rect);
|
|
433
|
-
#ifdef
|
|
398
|
+
#ifdef USEPATHHINT
|
|
434
399
|
tr->path_hint[depth] = i;
|
|
435
400
|
#endif
|
|
436
401
|
return i;
|
|
@@ -445,7 +410,7 @@ static struct rect node_rect_calc(const struct node *node) {
|
|
|
445
410
|
}
|
|
446
411
|
|
|
447
412
|
// node_insert returns false if out of memory
|
|
448
|
-
static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
|
|
413
|
+
static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
|
|
449
414
|
struct rect *ir, struct item item, int depth, bool *split)
|
|
450
415
|
{
|
|
451
416
|
if (node->kind == LEAF) {
|
|
@@ -463,7 +428,7 @@ static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
463
428
|
// Choose a subtree for inserting the rectangle.
|
|
464
429
|
int i = node_choose(tr, node, ir, depth);
|
|
465
430
|
cow_node_or(node->nodes[i], return false);
|
|
466
|
-
if (!node_insert(tr, &node->rects[i], node->nodes[i], ir, item, depth+1,
|
|
431
|
+
if (!node_insert(tr, &node->rects[i], node->nodes[i], ir, item, depth+1,
|
|
467
432
|
split))
|
|
468
433
|
{
|
|
469
434
|
return false;
|
|
@@ -489,7 +454,7 @@ static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
489
454
|
return node_insert(tr, nr, node, ir, item, depth, split);
|
|
490
455
|
}
|
|
491
456
|
|
|
492
|
-
struct rtree *rtree_new_with_allocator(void *(*_malloc)(size_t),
|
|
457
|
+
struct rtree *rtree_new_with_allocator(void *(*_malloc)(size_t),
|
|
493
458
|
void (*_free)(void*)
|
|
494
459
|
) {
|
|
495
460
|
_malloc = _malloc ? _malloc : malloc;
|
|
@@ -514,14 +479,14 @@ void rtree_set_item_callbacks(struct rtree *tr,
|
|
|
514
479
|
tr->item_free = free;
|
|
515
480
|
}
|
|
516
481
|
|
|
517
|
-
bool rtree_insert(struct rtree *tr, const NUMTYPE *min,
|
|
518
|
-
const NUMTYPE *max, const DATATYPE data)
|
|
482
|
+
bool rtree_insert(struct rtree *tr, const NUMTYPE *min,
|
|
483
|
+
const NUMTYPE *max, const DATATYPE data)
|
|
519
484
|
{
|
|
520
485
|
// copy input rect
|
|
521
486
|
struct rect rect;
|
|
522
487
|
memcpy(&rect.min[0], min, sizeof(NUMTYPE)*DIMS);
|
|
523
488
|
memcpy(&rect.max[0], max?max:min, sizeof(NUMTYPE)*DIMS);
|
|
524
|
-
|
|
489
|
+
|
|
525
490
|
// copy input data
|
|
526
491
|
struct item item;
|
|
527
492
|
if (tr->item_clone) {
|
|
@@ -584,14 +549,14 @@ void rtree_free(struct rtree *tr) {
|
|
|
584
549
|
}
|
|
585
550
|
|
|
586
551
|
static bool node_search(struct node *node, struct rect *rect,
|
|
587
|
-
bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
|
|
588
|
-
void *udata),
|
|
589
|
-
void *udata)
|
|
552
|
+
bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
|
|
553
|
+
void *udata),
|
|
554
|
+
void *udata)
|
|
590
555
|
{
|
|
591
556
|
if (node->kind == LEAF) {
|
|
592
557
|
for (int i = 0; i < node->count; i++) {
|
|
593
558
|
if (rect_intersects(&node->rects[i], rect)) {
|
|
594
|
-
if (!iter(node->rects[i].min, node->rects[i].max,
|
|
559
|
+
if (!iter(node->rects[i].min, node->rects[i].max,
|
|
595
560
|
node->datas[i].data, udata))
|
|
596
561
|
{
|
|
597
562
|
return false;
|
|
@@ -610,10 +575,10 @@ static bool node_search(struct node *node, struct rect *rect,
|
|
|
610
575
|
return true;
|
|
611
576
|
}
|
|
612
577
|
|
|
613
|
-
void rtree_search(const struct rtree *tr, const NUMTYPE min[],
|
|
578
|
+
void rtree_search(const struct rtree *tr, const NUMTYPE min[],
|
|
614
579
|
const NUMTYPE max[],
|
|
615
|
-
bool (*iter)(const NUMTYPE min[], const NUMTYPE max[], const DATATYPE data,
|
|
616
|
-
void *udata),
|
|
580
|
+
bool (*iter)(const NUMTYPE min[], const NUMTYPE max[], const DATATYPE data,
|
|
581
|
+
void *udata),
|
|
617
582
|
void *udata)
|
|
618
583
|
{
|
|
619
584
|
// copy input rect
|
|
@@ -627,13 +592,13 @@ void rtree_search(const struct rtree *tr, const NUMTYPE min[],
|
|
|
627
592
|
}
|
|
628
593
|
|
|
629
594
|
static bool node_scan(struct node *node,
|
|
630
|
-
bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
|
|
631
|
-
void *udata),
|
|
632
|
-
void *udata)
|
|
595
|
+
bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
|
|
596
|
+
void *udata),
|
|
597
|
+
void *udata)
|
|
633
598
|
{
|
|
634
599
|
if (node->kind == LEAF) {
|
|
635
600
|
for (int i = 0; i < node->count; i++) {
|
|
636
|
-
if (!iter(node->rects[i].min, node->rects[i].max,
|
|
601
|
+
if (!iter(node->rects[i].min, node->rects[i].max,
|
|
637
602
|
node->datas[i].data, udata))
|
|
638
603
|
{
|
|
639
604
|
return false;
|
|
@@ -649,9 +614,9 @@ static bool node_scan(struct node *node,
|
|
|
649
614
|
return true;
|
|
650
615
|
}
|
|
651
616
|
|
|
652
|
-
void rtree_scan(const struct rtree *tr,
|
|
653
|
-
bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
|
|
654
|
-
void *udata),
|
|
617
|
+
void rtree_scan(const struct rtree *tr,
|
|
618
|
+
bool (*iter)(const NUMTYPE *min, const NUMTYPE *max, const DATATYPE data,
|
|
619
|
+
void *udata),
|
|
655
620
|
void *udata)
|
|
656
621
|
{
|
|
657
622
|
if (tr->root) {
|
|
@@ -663,7 +628,7 @@ size_t rtree_count(const struct rtree *tr) {
|
|
|
663
628
|
return tr->count;
|
|
664
629
|
}
|
|
665
630
|
|
|
666
|
-
static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
631
|
+
static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
667
632
|
struct rect *ir, struct item item, int depth, bool *removed, bool *shrunk,
|
|
668
633
|
int (*compare)(const DATATYPE a, const DATATYPE b, void *udata),
|
|
669
634
|
void *udata)
|
|
@@ -694,7 +659,7 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
694
659
|
// We need to recalculate the node rect.
|
|
695
660
|
*nr = node_rect_calc(node);
|
|
696
661
|
// Notify the caller that we shrunk the rect.
|
|
697
|
-
*shrunk = true;
|
|
662
|
+
*shrunk = true;
|
|
698
663
|
}
|
|
699
664
|
*removed = true;
|
|
700
665
|
return true;
|
|
@@ -702,12 +667,12 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
702
667
|
return true;
|
|
703
668
|
}
|
|
704
669
|
int h = 0;
|
|
705
|
-
#ifdef
|
|
670
|
+
#ifdef USEPATHHINT
|
|
706
671
|
h = tr->path_hint[depth];
|
|
707
672
|
if (h < node->count) {
|
|
708
673
|
if (rect_contains(&node->rects[h], ir)) {
|
|
709
674
|
cow_node_or(node->nodes[h], return false);
|
|
710
|
-
if (!node_delete(tr, &node->rects[h], node->nodes[h], ir, item,
|
|
675
|
+
if (!node_delete(tr, &node->rects[h], node->nodes[h], ir, item,
|
|
711
676
|
depth+1,removed, shrunk, compare, udata))
|
|
712
677
|
{
|
|
713
678
|
return false;
|
|
@@ -733,7 +698,9 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
733
698
|
if (!*removed) {
|
|
734
699
|
continue;
|
|
735
700
|
}
|
|
701
|
+
#ifdef USEPATHHINT
|
|
736
702
|
removed:
|
|
703
|
+
#endif
|
|
737
704
|
if (node->nodes[h]->count == 0) {
|
|
738
705
|
// underflow
|
|
739
706
|
node_free(tr, node->nodes[h]);
|
|
@@ -744,7 +711,7 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
744
711
|
*shrunk = true;
|
|
745
712
|
return true;
|
|
746
713
|
}
|
|
747
|
-
#ifdef
|
|
714
|
+
#ifdef USEPATHHINT
|
|
748
715
|
tr->path_hint[depth] = h;
|
|
749
716
|
#endif
|
|
750
717
|
if (*shrunk) {
|
|
@@ -759,7 +726,7 @@ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
|
|
|
759
726
|
}
|
|
760
727
|
|
|
761
728
|
// returns false if out of memory
|
|
762
|
-
static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
|
|
729
|
+
static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
|
|
763
730
|
const NUMTYPE *max, const DATATYPE data,
|
|
764
731
|
int (*compare)(const DATATYPE a, const DATATYPE b, void *udata),
|
|
765
732
|
void *udata)
|
|
@@ -779,7 +746,7 @@ static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
|
|
|
779
746
|
bool removed = false;
|
|
780
747
|
bool shrunk = false;
|
|
781
748
|
cow_node_or(tr->root, return false);
|
|
782
|
-
if (!node_delete(tr, &tr->rect, tr->root, &rect, item, 0, &removed, &shrunk,
|
|
749
|
+
if (!node_delete(tr, &tr->rect, tr->root, &rect, item, 0, &removed, &shrunk,
|
|
783
750
|
compare, udata))
|
|
784
751
|
{
|
|
785
752
|
return false;
|
|
@@ -808,13 +775,13 @@ static bool rtree_delete0(struct rtree *tr, const NUMTYPE *min,
|
|
|
808
775
|
return true;
|
|
809
776
|
}
|
|
810
777
|
|
|
811
|
-
bool rtree_delete(struct rtree *tr, const NUMTYPE *min, const NUMTYPE *max,
|
|
778
|
+
bool rtree_delete(struct rtree *tr, const NUMTYPE *min, const NUMTYPE *max,
|
|
812
779
|
const DATATYPE data)
|
|
813
780
|
{
|
|
814
781
|
return rtree_delete0(tr, min, max, data, NULL, NULL);
|
|
815
782
|
}
|
|
816
783
|
|
|
817
|
-
bool rtree_delete_with_comparator(struct rtree *tr, const NUMTYPE *min,
|
|
784
|
+
bool rtree_delete_with_comparator(struct rtree *tr, const NUMTYPE *min,
|
|
818
785
|
const NUMTYPE *max, const DATATYPE data,
|
|
819
786
|
int (*compare)(const DATATYPE a, const DATATYPE b, void *udata),
|
|
820
787
|
void *udata)
|
|
@@ -827,14 +794,20 @@ struct rtree *rtree_clone(struct rtree *tr) {
|
|
|
827
794
|
struct rtree *tr2 = tr->malloc(sizeof(struct rtree));
|
|
828
795
|
if (!tr2) return NULL;
|
|
829
796
|
memcpy(tr2, tr, sizeof(struct rtree));
|
|
830
|
-
if (tr2->root)
|
|
797
|
+
if (tr2->root) rc_retain(&tr2->root->rc);
|
|
831
798
|
return tr2;
|
|
832
|
-
}
|
|
799
|
+
}
|
|
833
800
|
|
|
834
|
-
void
|
|
835
|
-
|
|
801
|
+
void rtree_rect(struct rtree *tr, NUMTYPE *min, NUMTYPE *max) {
|
|
802
|
+
for (int i = 0; i < DIMS; i++) {
|
|
803
|
+
min[i] = tr->rect.min[i];
|
|
804
|
+
max[i] = tr->rect.max[i];
|
|
805
|
+
}
|
|
836
806
|
}
|
|
837
807
|
|
|
808
|
+
// deprecated
|
|
809
|
+
void rtree_opt_relaxed_atomics(struct rtree *tr) { (void)tr; }
|
|
810
|
+
|
|
838
811
|
#ifdef TEST_PRIVATE_FUNCTIONS
|
|
839
812
|
#include "tests/priv_funcs.h"
|
|
840
813
|
#endif
|
|
@@ -36,16 +36,16 @@ struct rtree *rtree_clone(struct rtree *tr);
|
|
|
36
36
|
// The clone function should return true if the clone succeeded or false if the
|
|
37
37
|
// system is out of memory.
|
|
38
38
|
void rtree_set_item_callbacks(struct rtree *tr,
|
|
39
|
-
bool (*clone)(const void *item, void **into, void *udata),
|
|
39
|
+
bool (*clone)(const void *item, void **into, void *udata),
|
|
40
40
|
void (*free)(const void *item, void *udata));
|
|
41
41
|
|
|
42
|
-
// rtree_set_udata sets the user-defined data.
|
|
42
|
+
// rtree_set_udata sets the user-defined data.
|
|
43
43
|
//
|
|
44
|
-
// This should be called once after rtree_new() and is only used for
|
|
44
|
+
// This should be called once after rtree_new() and is only used for
|
|
45
45
|
// the item callbacks as defined in rtree_set_item_callbacks().
|
|
46
46
|
void rtree_set_udata(struct rtree *tr, void *udata);
|
|
47
47
|
|
|
48
|
-
// rtree_insert inserts an item into the rtree.
|
|
48
|
+
// rtree_insert inserts an item into the rtree.
|
|
49
49
|
//
|
|
50
50
|
// This operation performs a copy of the data that is pointed to in the second
|
|
51
51
|
// and third arguments. The R-tree expects a rectangle, which is two arrays of
|
|
@@ -64,20 +64,20 @@ bool rtree_insert(struct rtree *tr, const double *min, const double *max, const
|
|
|
64
64
|
//
|
|
65
65
|
// Returning false from the iter will stop the search.
|
|
66
66
|
void rtree_search(const struct rtree *tr, const double *min, const double *max,
|
|
67
|
-
bool (*iter)(const double *min, const double *max, const void *data, void *udata),
|
|
67
|
+
bool (*iter)(const double *min, const double *max, const void *data, void *udata),
|
|
68
68
|
void *udata);
|
|
69
69
|
|
|
70
70
|
// rtree_scan iterates over every item in the rtree.
|
|
71
71
|
//
|
|
72
72
|
// Returning false from the iter will stop the scan.
|
|
73
73
|
void rtree_scan(const struct rtree *tr,
|
|
74
|
-
bool (*iter)(const double *min, const double *max, const void *data, void *udata),
|
|
74
|
+
bool (*iter)(const double *min, const double *max, const void *data, void *udata),
|
|
75
75
|
void *udata);
|
|
76
76
|
|
|
77
77
|
// rtree_count returns the number of items in the rtree.
|
|
78
78
|
size_t rtree_count(const struct rtree *tr);
|
|
79
79
|
|
|
80
|
-
// rtree_delete deletes an item from the rtree.
|
|
80
|
+
// rtree_delete deletes an item from the rtree.
|
|
81
81
|
//
|
|
82
82
|
// This searches the tree for an item that is contained within the provided
|
|
83
83
|
// rectangle, and perform a binary comparison of its data to the provided
|
|
@@ -92,14 +92,17 @@ bool rtree_delete(struct rtree *tr, const double *min, const double *max, const
|
|
|
92
92
|
// a compare function. The first item that is found is deleted.
|
|
93
93
|
//
|
|
94
94
|
// Returns false if the system is out of memory.
|
|
95
|
-
bool rtree_delete_with_comparator(struct rtree *tr, const double *min,
|
|
95
|
+
bool rtree_delete_with_comparator(struct rtree *tr, const double *min,
|
|
96
96
|
const double *max, const void *data,
|
|
97
97
|
int (*compare)(const void *a, const void *b, void *udata),
|
|
98
98
|
void *udata);
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
//
|
|
102
|
-
|
|
100
|
+
|
|
101
|
+
// rtree_rect returns the MBR.
|
|
102
|
+
void rtree_rect(struct rtree *tr, double *min, double *max);
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
// deprecated
|
|
103
106
|
void rtree_opt_relaxed_atomics(struct rtree *tr);
|
|
104
107
|
|
|
105
108
|
#endif // RTREE_H
|