spatial-graph 0.0.1__py3-none-any.whl

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.
@@ -0,0 +1,1021 @@
1
+ // Copyright 2023 Joshua J Baker. All rights reserved.
2
+ // Use of this source code is governed by an MIT-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ #include <string.h>
6
+ #include <math.h>
7
+ #include "config.h"
8
+ #include "rtree.h"
9
+
10
+ // used for splits
11
+ #define MINITEMS_PERCENTAGE 10
12
+ #define MINITEMS ((MAXITEMS) * (MINITEMS_PERCENTAGE) / 100 + 1)
13
+
14
+ #ifndef RTREE_NOPATHHINT
15
+ #define USE_PATHHINT
16
+ #endif
17
+
18
+ #ifdef RTREE_MAXITEMS
19
+ #undef MAXITEMS
20
+ #define MAXITEMS RTREE_MAXITEMS
21
+ #endif
22
+
23
+ #ifdef RTREE_NOATOMICS
24
+ typedef int rc_t;
25
+ static int rc_load(rc_t *ptr, bool relaxed) {
26
+ (void)relaxed; // nothing to do
27
+ return *ptr;
28
+ }
29
+ static int rc_fetch_sub(rc_t *ptr, int val) {
30
+ int rc = *ptr;
31
+ *ptr -= val;
32
+ return rc;
33
+ }
34
+ static int rc_fetch_add(rc_t *ptr, int val) {
35
+ int rc = *ptr;
36
+ *ptr += val;
37
+ return rc;
38
+ }
39
+ #else
40
+ #include <stdatomic.h>
41
+ typedef atomic_int rc_t;
42
+ static int rc_load(rc_t *ptr, bool relaxed) {
43
+ if (relaxed) {
44
+ return atomic_load_explicit(ptr, memory_order_relaxed);
45
+ } else {
46
+ return atomic_load(ptr);
47
+ }
48
+ }
49
+ static int rc_fetch_sub(rc_t *ptr, int delta) {
50
+ return atomic_fetch_sub(ptr, delta);
51
+ }
52
+ static int rc_fetch_add(rc_t *ptr, int delta) {
53
+ return atomic_fetch_add(ptr, delta);
54
+ }
55
+ #endif
56
+
57
+ #define abs(x) ((x) >= 0 ? (x) : -(x))
58
+
59
+ enum kind {
60
+ LEAF = 1,
61
+ BRANCH = 2,
62
+ ITEM_BY_BB = 3, // for priority queue, item enqueued by bb distance
63
+ ITEM = 4 // for priority queue, item enqueued with exact distance
64
+ };
65
+
66
+ struct rect {
67
+ coord_t min[DIMS];
68
+ coord_t max[DIMS];
69
+ };
70
+
71
+ struct node {
72
+ rc_t rc; // reference counter for copy-on-write
73
+ enum kind kind; // LEAF or BRANCH
74
+ int count; // number of rects
75
+ struct rect rects[MAXITEMS];
76
+ union {
77
+ struct node *nodes[MAXITEMS];
78
+ item_t items[MAXITEMS];
79
+ };
80
+ };
81
+
82
+ // priority queue
83
+ struct element {
84
+ coord_t distance;
85
+ enum kind kind;
86
+ union {
87
+ struct node* node; // if kind == LEAF or BRANCH
88
+ struct { // if kind == ITEM_BY_BB or ITEM
89
+ item_t item;
90
+ struct rect *rect;
91
+ };
92
+ };
93
+ };
94
+
95
+ struct priority_queue {
96
+ size_t size;
97
+ size_t capacity;
98
+ struct element *elements;
99
+ };
100
+
101
+ struct priority_queue* priority_queue_new() {
102
+ struct priority_queue *queue = (struct priority_queue*)malloc(sizeof(struct priority_queue));
103
+ if (!queue)
104
+ return NULL;
105
+ queue->size = 0;
106
+ queue->capacity = INITIAL_QUEUE_SIZE;
107
+ queue->elements = (struct element*)malloc(sizeof(struct element) * queue->capacity);
108
+ if (!queue->elements) {
109
+ free(queue);
110
+ return NULL;
111
+ }
112
+ return queue;
113
+ }
114
+
115
+ void priority_queue_free(struct priority_queue* queue) {
116
+ if (queue->elements)
117
+ free(queue->elements);
118
+ free(queue);
119
+ }
120
+
121
+ void swap(struct element* a, struct element* b) {
122
+ struct element tmp = *a;
123
+ *a = *b;
124
+ *b = tmp;
125
+ }
126
+
127
+ void heapify_up(struct priority_queue* queue, size_t index) {
128
+ if (index == 0) return;
129
+ size_t midpoint = (index - 1)/2;
130
+ if (queue->elements[midpoint].distance > queue->elements[index].distance) {
131
+ swap(&queue->elements[midpoint], &queue->elements[index]);
132
+ heapify_up(queue, midpoint);
133
+ }
134
+ }
135
+
136
+ void heapify_down(struct priority_queue* queue, size_t index) {
137
+ size_t smallest = index;
138
+ size_t left = 2*index + 1;
139
+ size_t right = 2*index + 2;
140
+
141
+ if (left < queue->size) {
142
+ if (queue->elements[left].distance < queue->elements[smallest].distance) {
143
+ smallest = left;
144
+ }
145
+ }
146
+ if (right < queue->size) {
147
+ if (queue->elements[right].distance < queue->elements[smallest].distance) {
148
+ smallest = right;
149
+ }
150
+ }
151
+ if (smallest != index) {
152
+ swap(&queue->elements[index], &queue->elements[smallest]);
153
+ heapify_down(queue, smallest);
154
+ }
155
+ }
156
+
157
+ bool enqueue(struct priority_queue* queue, struct element element) {
158
+ if (queue->size == queue->capacity) {
159
+ queue->capacity *= 2;
160
+ queue->elements = realloc(queue->elements, sizeof(struct element) * queue->capacity);
161
+ if (!queue->elements)
162
+ return false;
163
+ }
164
+ queue->elements[queue->size] = element;
165
+ queue->size++;
166
+ heapify_up(queue, queue->size - 1);
167
+ return true;
168
+ }
169
+
170
+ struct element dequeue(struct priority_queue* queue) {
171
+
172
+ struct element top = queue->elements[0];
173
+ queue->elements[0] = queue->elements[--queue->size];
174
+ heapify_down(queue, 0);
175
+ // reclaim some memory when the queue is shrinking
176
+ if (queue->size < queue->capacity/4) {
177
+ queue->capacity /= 2;
178
+ struct element *elements = realloc(queue->elements, sizeof(struct element) * queue->capacity);
179
+ if (!elements) {
180
+ queue->capacity *= 2;
181
+ } else {
182
+ queue->elements = elements;
183
+ }
184
+ }
185
+ return top;
186
+ }
187
+
188
+ struct element peek(struct priority_queue* queue) {
189
+ return queue->elements[0];
190
+ }
191
+ // end priority queue
192
+
193
+ struct rtree {
194
+ struct rect rect;
195
+ struct node *root;
196
+ struct priority_queue *queue;
197
+ size_t count;
198
+ size_t height;
199
+ #ifdef USE_PATHHINT
200
+ int path_hint[16];
201
+ #endif
202
+ bool relaxed;
203
+ void *(*malloc)(size_t);
204
+ void (*free)(void *);
205
+ };
206
+
207
+ static inline coord_t min0(coord_t x, coord_t y) {
208
+ return x < y ? x : y;
209
+ }
210
+
211
+ static inline coord_t max0(coord_t x, coord_t y) {
212
+ return x > y ? x : y;
213
+ }
214
+
215
+ static bool feq(coord_t a, coord_t b) {
216
+ return !(a < b || a > b);
217
+ }
218
+
219
+ #ifdef KNN_USE_EXACT_DISTANCE
220
+ inline coord_t distance(const coord_t point[], const struct rect *rect, const struct item_t item);
221
+ #endif
222
+
223
+ static struct node *node_new(struct rtree *tr, enum kind kind) {
224
+ struct node *node = (struct node *)tr->malloc(sizeof(struct node));
225
+ if (!node) return NULL;
226
+ memset(node, 0, sizeof(struct node));
227
+ node->kind = kind;
228
+ return node;
229
+ }
230
+
231
+ static struct node *node_copy(struct rtree *tr, struct node *node) {
232
+ struct node *node2 = (struct node *)tr->malloc(sizeof(struct node));
233
+ if (!node2) return NULL;
234
+ memcpy(node2, node, sizeof(struct node));
235
+ node2->rc = 0;
236
+ if (node2->kind == BRANCH) {
237
+ for (int i = 0; i < node2->count; i++) {
238
+ rc_fetch_add(&node2->nodes[i]->rc, 1);
239
+ }
240
+ }
241
+ return node2;
242
+ }
243
+
244
+ static void node_free(struct rtree *tr, struct node *node) {
245
+ if (rc_fetch_sub(&node->rc, 1) > 0) return;
246
+ if (node->kind == BRANCH) {
247
+ for (int i = 0; i < node->count; i++) {
248
+ node_free(tr, node->nodes[i]);
249
+ }
250
+ } else {
251
+ }
252
+ tr->free(node);
253
+ }
254
+
255
+ #define cow_node_or(rnode, code) { \
256
+ if (rc_load(&(rnode)->rc, tr->relaxed) > 0) { \
257
+ struct node *node2 = node_copy(tr, (rnode)); \
258
+ if (!node2) { code; } \
259
+ rc_fetch_sub(&(rnode)->rc, 1); \
260
+ (rnode) = node2; \
261
+ } \
262
+ }
263
+
264
+ static void rect_expand(struct rect *rect, const struct rect *other) {
265
+ for (int i = 0; i < DIMS; i++) {
266
+ rect->min[i] = min0(rect->min[i], other->min[i]);
267
+ rect->max[i] = max0(rect->max[i], other->max[i]);
268
+ }
269
+ }
270
+
271
+ static coord_t rect_area(const struct rect *rect) {
272
+ coord_t result = 1;
273
+ for (int i = 0; i < DIMS; i++) {
274
+ result *= (rect->max[i] - rect->min[i]);
275
+ }
276
+ return result;
277
+ }
278
+
279
+ // return the area of two rects expanded
280
+ static coord_t rect_unioned_area(const struct rect *rect,
281
+ const struct rect *other)
282
+ {
283
+ coord_t result = 1;
284
+ for (int i = 0; i < DIMS; i++) {
285
+ result *= (max0(rect->max[i], other->max[i]) -
286
+ min0(rect->min[i], other->min[i]));
287
+ }
288
+ return result;
289
+ }
290
+
291
+ static bool rect_contains(const struct rect *rect, const struct rect *other) {
292
+ int bits = 0;
293
+ for (int i = 0; i < DIMS; i++) {
294
+ bits |= other->min[i] < rect->min[i];
295
+ bits |= other->max[i] > rect->max[i];
296
+ }
297
+ return bits == 0;
298
+ }
299
+
300
+ static bool rect_contains_point(const struct rect *rect, const coord_t point[]) {
301
+ int bits = 0;
302
+ for (int i = 0; i < DIMS; i++) {
303
+ bits |= point[i] < rect->min[i];
304
+ bits |= point[i] > rect->max[i];
305
+ }
306
+ return bits == 0;
307
+ }
308
+
309
+ static bool rect_intersects(const struct rect *rect, const struct rect *other) {
310
+ int bits = 0;
311
+ for (int i = 0; i < DIMS; i++) {
312
+ bits |= other->min[i] > rect->max[i];
313
+ bits |= other->max[i] < rect->min[i];
314
+ }
315
+ return bits == 0;
316
+ }
317
+
318
+ static bool rect_onedge(const struct rect *rect, const struct rect *other) {
319
+ for (int i = 0; i < DIMS; i++) {
320
+ if (feq(rect->min[i], other->min[i]) ||
321
+ feq(rect->max[i], other->max[i]))
322
+ {
323
+ return true;
324
+ }
325
+ }
326
+ return false;
327
+ }
328
+
329
+ static bool rect_equals(const struct rect *rect, const struct rect *other) {
330
+ for (int i = 0; i < DIMS; i++) {
331
+ if (!feq(rect->min[i], other->min[i]) ||
332
+ !feq(rect->max[i], other->max[i]))
333
+ {
334
+ return false;
335
+ }
336
+ }
337
+ return true;
338
+ }
339
+
340
+ static bool rect_equals_bin(const struct rect *rect, const struct rect *other) {
341
+ for (int i = 0; i < DIMS; i++) {
342
+ if (rect->min[i] != other->min[i] ||
343
+ rect->max[i] != other->max[i])
344
+ {
345
+ return false;
346
+ }
347
+ }
348
+ return true;
349
+ }
350
+
351
+ static int rect_largest_axis(const struct rect *rect) {
352
+ int axis = 0;
353
+ coord_t nlength = rect->max[0] - rect->min[0];
354
+ for (int i = 1; i < DIMS; i++) {
355
+ coord_t length = rect->max[i] - rect->min[i];
356
+ if (length > nlength) {
357
+ nlength = length;
358
+ axis = i;
359
+ }
360
+ }
361
+ return axis;
362
+ }
363
+
364
+ // swap two rectangles
365
+ static void node_swap(struct node *node, int i, int j) {
366
+ struct rect tmp = node->rects[i];
367
+ node->rects[i] = node->rects[j];
368
+ node->rects[j] = tmp;
369
+ if (node->kind == LEAF) {
370
+ item_t tmp = node->items[i];
371
+ node->items[i] = node->items[j];
372
+ node->items[j] = tmp;
373
+ } else {
374
+ struct node *tmp = node->nodes[i];
375
+ node->nodes[i] = node->nodes[j];
376
+ node->nodes[j] = tmp;
377
+ }
378
+ }
379
+
380
+ struct rect4 {
381
+ coord_t all[DIMS*2];
382
+ };
383
+
384
+ static void node_qsort(struct node *node, int s, int e, int index, bool rev) {
385
+ int nrects = e - s;
386
+ if (nrects < 2) {
387
+ return;
388
+ }
389
+ int left = 0;
390
+ int right = nrects-1;
391
+ int pivot = nrects / 2;
392
+ node_swap(node, s+pivot, s+right);
393
+ struct rect4 *rects = (struct rect4 *)&node->rects[s];
394
+ if (!rev) {
395
+ for (int i = 0; i < nrects; i++) {
396
+ if (rects[i].all[index] < rects[right].all[index]) {
397
+ node_swap(node, s+i, s+left);
398
+ left++;
399
+ }
400
+ }
401
+ } else {
402
+ for (int i = 0; i < nrects; i++) {
403
+ if (rects[right].all[index] < rects[i].all[index]) {
404
+ node_swap(node, s+i, s+left);
405
+ left++;
406
+ }
407
+ }
408
+ }
409
+ node_swap(node, s+left, s+right);
410
+ node_qsort(node, s, s+left, index, rev);
411
+ node_qsort(node, s+left+1, e, index, rev);
412
+ }
413
+
414
+ // sort the node rectangles by the axis. used during splits
415
+ static void node_sort_by_axis(struct node *node, int axis, bool rev, bool max) {
416
+ int by_index = max ? DIMS+axis : axis;
417
+ node_qsort(node, 0, node->count, by_index, rev);
418
+ }
419
+
420
+ static void node_move_rect_at_index_into(struct node *from, int index,
421
+ struct node *into)
422
+ {
423
+ into->rects[into->count] = from->rects[index];
424
+ from->rects[index] = from->rects[from->count-1];
425
+ if (from->kind == LEAF) {
426
+ into->items[into->count] = from->items[index];
427
+ from->items[index] = from->items[from->count-1];
428
+ } else {
429
+ into->nodes[into->count] = from->nodes[index];
430
+ from->nodes[index] = from->nodes[from->count-1];
431
+ }
432
+ from->count--;
433
+ into->count++;
434
+ }
435
+
436
+ static bool node_split_largest_axis_edge_snap(struct rtree *tr,
437
+ struct rect *rect, struct node *node, struct node **right_out)
438
+ {
439
+ int axis = rect_largest_axis(rect);
440
+ struct node *right = node_new(tr, node->kind);
441
+ if (!right) {
442
+ return false;
443
+ }
444
+ for (int i = 0; i < node->count; i++) {
445
+ coord_t min_dist = node->rects[i].min[axis] - rect->min[axis];
446
+ coord_t max_dist = rect->max[axis] - node->rects[i].max[axis];
447
+ if (max_dist < min_dist) {
448
+ // move to right
449
+ node_move_rect_at_index_into(node, i, right);
450
+ i--;
451
+ }
452
+ }
453
+ // Make sure that both left and right nodes have at least
454
+ // MINITEMS by moving items into underflowed nodes.
455
+ if (node->count < MINITEMS) {
456
+ // reverse sort by min axis
457
+ node_sort_by_axis(right, axis, true, false);
458
+ do {
459
+ node_move_rect_at_index_into(right, right->count-1, node);
460
+ } while (node->count < MINITEMS);
461
+ } else if (right->count < MINITEMS) {
462
+ // reverse sort by max axis
463
+ node_sort_by_axis(node, axis, true, true);
464
+ do {
465
+ node_move_rect_at_index_into(node, node->count-1, right);
466
+ } while (right->count < MINITEMS);
467
+ }
468
+ *right_out = right;
469
+ return true;
470
+ }
471
+
472
+ static bool node_split(struct rtree *tr, struct rect *rect, struct node *node,
473
+ struct node **right)
474
+ {
475
+ return node_split_largest_axis_edge_snap(tr, rect, node, right);
476
+ }
477
+
478
+ static int node_choose_least_enlargement(const struct node *node,
479
+ const struct rect *ir)
480
+ {
481
+ int j = 0;
482
+ coord_t jenlarge = INFINITY;
483
+ for (int i = 0; i < node->count; i++) {
484
+ // calculate the enlarged area
485
+ coord_t uarea = rect_unioned_area(&node->rects[i], ir);
486
+ coord_t area = rect_area(&node->rects[i]);
487
+ coord_t enlarge = uarea - area;
488
+ if (enlarge < jenlarge) {
489
+ j = i;
490
+ jenlarge = enlarge;
491
+ }
492
+ }
493
+ return j;
494
+ }
495
+
496
+ static int node_choose(struct rtree *tr, const struct node *node,
497
+ const struct rect *rect, int depth)
498
+ {
499
+ #ifdef USE_PATHHINT
500
+ int h = tr->path_hint[depth];
501
+ if (h < node->count) {
502
+ if (rect_contains(&node->rects[h], rect)) {
503
+ return h;
504
+ }
505
+ }
506
+ #endif
507
+ // Take a quick look for the first node that contain the rect.
508
+ for (int i = 0; i < node->count; i++) {
509
+ if (rect_contains(&node->rects[i], rect)) {
510
+ #ifdef USE_PATHHINT
511
+ tr->path_hint[depth] = i;
512
+ #endif
513
+ return i;
514
+ }
515
+ }
516
+ // Fallback to using che "choose least enlargment" algorithm.
517
+ int i = node_choose_least_enlargement(node, rect);
518
+ #ifdef USE_PATHHINT
519
+ tr->path_hint[depth] = i;
520
+ #endif
521
+ return i;
522
+ }
523
+
524
+ static struct rect node_rect_calc(const struct node *node) {
525
+ struct rect rect = node->rects[0];
526
+ for (int i = 1; i < node->count; i++) {
527
+ rect_expand(&rect, &node->rects[i]);
528
+ }
529
+ return rect;
530
+ }
531
+
532
+ // node_insert returns false if out of memory
533
+ static bool node_insert(struct rtree *tr, struct rect *nr, struct node *node,
534
+ struct rect *ir, item_t item, int depth, bool *split)
535
+ {
536
+ if (node->kind == LEAF) {
537
+ if (node->count == MAXITEMS) {
538
+ *split = true;
539
+ return true;
540
+ }
541
+ int index = node->count;
542
+ node->rects[index] = *ir;
543
+ node->items[index] = item;
544
+ node->count++;
545
+ *split = false;
546
+ return true;
547
+ }
548
+ // Choose a subtree for inserting the rectangle.
549
+ int i = node_choose(tr, node, ir, depth);
550
+ cow_node_or(node->nodes[i], return false);
551
+ if (!node_insert(tr, &node->rects[i], node->nodes[i], ir, item, depth+1,
552
+ split))
553
+ {
554
+ return false;
555
+ }
556
+ if (!*split) {
557
+ rect_expand(&node->rects[i], ir);
558
+ *split = false;
559
+ return true;
560
+ }
561
+ // split the child node
562
+ if (node->count == MAXITEMS) {
563
+ *split = true;
564
+ return true;
565
+ }
566
+ struct node *right;
567
+ if (!node_split(tr, &node->rects[i], node->nodes[i], &right)) {
568
+ return false;
569
+ }
570
+ node->rects[i] = node_rect_calc(node->nodes[i]);
571
+ node->rects[node->count] = node_rect_calc(right);
572
+ node->nodes[node->count] = right;
573
+ node->count++;
574
+ return node_insert(tr, nr, node, ir, item, depth, split);
575
+ }
576
+
577
+ struct rtree *rtree_new_with_allocator(void *(*_malloc)(size_t),
578
+ void (*_free)(void*)
579
+ ) {
580
+ _malloc = _malloc ? _malloc : malloc;
581
+ _free = _free ? _free : free;
582
+ struct rtree *tr = (struct rtree *)_malloc(sizeof(struct rtree));
583
+ if (!tr) return NULL;
584
+ memset(tr, 0, sizeof(struct rtree));
585
+ tr->malloc = _malloc;
586
+ tr->free = _free;
587
+ return tr;
588
+ }
589
+
590
+ struct rtree *rtree_new(void) {
591
+ return rtree_new_with_allocator(NULL, NULL);
592
+ }
593
+
594
+ bool rtree_insert(struct rtree *tr, const coord_t *min,
595
+ const coord_t *max, const item_t item)
596
+ {
597
+ // copy input rect
598
+ struct rect rect;
599
+ memcpy(&rect.min[0], min, sizeof(coord_t)*DIMS);
600
+ memcpy(&rect.max[0], max?max:min, sizeof(coord_t)*DIMS);
601
+
602
+ while (1) {
603
+ if (!tr->root) {
604
+ struct node *new_root = node_new(tr, LEAF);
605
+ if (!new_root) {
606
+ break;
607
+ }
608
+ tr->root = new_root;
609
+ tr->rect = rect;
610
+ tr->height = 1;
611
+ }
612
+ bool split = false;
613
+ cow_node_or(tr->root, break);
614
+ if (!node_insert(tr, &tr->rect, tr->root, &rect, item, 0, &split)) {
615
+ break;
616
+ }
617
+ if (!split) {
618
+ rect_expand(&tr->rect, &rect);
619
+ tr->count++;
620
+ return true;
621
+ }
622
+ struct node *new_root = node_new(tr, BRANCH);
623
+ if (!new_root) {
624
+ break;
625
+ }
626
+ struct node *right;
627
+ if (!node_split(tr, &tr->rect, tr->root, &right)) {
628
+ tr->free(new_root);
629
+ break;
630
+ }
631
+ new_root->rects[0] = node_rect_calc(tr->root);
632
+ new_root->rects[1] = node_rect_calc(right);
633
+ new_root->nodes[0] = tr->root;
634
+ new_root->nodes[1] = right;
635
+ tr->root = new_root;
636
+ tr->root->count = 2;
637
+ tr->height++;
638
+ }
639
+ // out of memory
640
+ return false;
641
+ }
642
+
643
+ void rtree_free(struct rtree *tr) {
644
+ if (tr->root) {
645
+ node_free(tr, tr->root);
646
+ }
647
+ if (tr->queue) {
648
+ priority_queue_free(tr->queue);
649
+ }
650
+ tr->free(tr);
651
+ }
652
+
653
+ static bool node_search(struct node *node, struct rect *rect,
654
+ bool (*iter)(const coord_t *min, const coord_t *max, const item_t item,
655
+ void *udata),
656
+ void *udata)
657
+ {
658
+ if (node->kind == LEAF) {
659
+ for (int i = 0; i < node->count; i++) {
660
+ if (rect_intersects(&node->rects[i], rect)) {
661
+ if (!iter(node->rects[i].min, node->rects[i].max,
662
+ node->items[i], udata))
663
+ {
664
+ return false;
665
+ }
666
+ }
667
+ }
668
+ return true;
669
+ }
670
+ for (int i = 0; i < node->count; i++) {
671
+ if (rect_intersects(&node->rects[i], rect)) {
672
+ if (!node_search(node->nodes[i], rect, iter, udata)) {
673
+ return false;
674
+ }
675
+ }
676
+ }
677
+ return true;
678
+ }
679
+
680
+ void rtree_search(const struct rtree *tr, const coord_t min[],
681
+ const coord_t max[],
682
+ bool (*iter)(const coord_t min[], const coord_t max[], const item_t item,
683
+ void *udata),
684
+ void *udata)
685
+ {
686
+ // copy input rect
687
+ struct rect rect;
688
+ memcpy(&rect.min[0], min, sizeof(coord_t)*DIMS);
689
+ memcpy(&rect.max[0], max?max:min, sizeof(coord_t)*DIMS);
690
+
691
+ if (tr->root) {
692
+ node_search(tr->root, &rect, iter, udata);
693
+ }
694
+ }
695
+
696
+ coord_t distance_bb(const coord_t point[], struct rect *rect) {
697
+
698
+ coord_t dist2 = 0;
699
+
700
+ for (int i = 0; i < DIMS; i++) {
701
+ if (point[i] < rect->min[i]) {
702
+ dist2 += pow(rect->min[i] - point[i], 2);
703
+ } else if (point[i] > rect->max[i]) {
704
+ dist2 += pow(point[i] - rect->max[i], 2);
705
+ }
706
+ // else: coordinate is within min and max, does not contribute to
707
+ // distance
708
+ }
709
+
710
+ return dist2;
711
+ }
712
+
713
+ bool rtree_nearest(struct rtree *tr, const coord_t point[],
714
+ bool (*iter)(const item_t item, coord_t distance, void *udata),
715
+ void *udata) {
716
+
717
+ if (!tr->root)
718
+ return true;
719
+
720
+ if (!tr->queue)
721
+ tr->queue = priority_queue_new();
722
+ else
723
+ tr->queue->size = 0;
724
+
725
+ struct element root = { .distance = 0.0, .kind = tr->root->kind, .node = tr->root };
726
+ if (!enqueue(tr->queue, root)) {
727
+ return false;
728
+ }
729
+
730
+ while (tr->queue->size > 0) {
731
+
732
+ struct element next_element = dequeue(tr->queue);
733
+
734
+ if (next_element.kind == ITEM) {
735
+ // We found an ITEM with an exact distance that is the next closest
736
+ // to the query point.
737
+
738
+ // Report the item and stop searching if the user function returns
739
+ // false:
740
+ bool keep_going = iter(next_element.item, next_element.distance, udata);
741
+ if (!keep_going) {
742
+ return true;
743
+ }
744
+
745
+ } else if (next_element.kind == ITEM_BY_BB) {
746
+ // We found an ITEM_BY_BB in the queue, whose bounding box is next
747
+ // closest to the query point.
748
+
749
+ // Here, we can calculate a more accurate distance than the one
750
+ // used in the queue (e.g., distance to a line is poorly
751
+ // approximated by distance to bounding box of line). If that
752
+ // distance is larger than the next element on the queue, enqueue
753
+ // the item again with kind ITEM and continue the while-loop.
754
+
755
+ #ifdef KNN_USE_EXACT_DISTANCE
756
+ next_element.distance = distance(point, next_element.rect, next_element.item);
757
+ if (next_element.distance > peek(tr->queue).distance) {
758
+ next_element.kind = ITEM;
759
+ if (!enqueue(tr->queue, next_element)) {
760
+ return false;
761
+ }
762
+ continue;
763
+ }
764
+ #endif
765
+
766
+ // Report the item and stop searching if the user function returns
767
+ // false:
768
+ bool keep_going = iter(next_element.item, next_element.distance, udata);
769
+ if (!keep_going) {
770
+ return true;
771
+ }
772
+
773
+ } else if (next_element.kind == LEAF) {
774
+ // We found a LEAF node in the queue, whose bounding box is next
775
+ // closest to the query point. Add each item contained in that leaf
776
+ // to the queue.
777
+
778
+ struct node *leaf = next_element.node;
779
+ for (int i = 0; i < leaf->count; i++) {
780
+
781
+ struct element item_element = {
782
+ .distance = distance_bb(point, &leaf->rects[i]),
783
+ .kind = ITEM_BY_BB,
784
+ .item = leaf->items[i],
785
+ .rect = &leaf->rects[i]
786
+ };
787
+ if (!enqueue(tr->queue, item_element)) {
788
+ return false;
789
+ }
790
+ }
791
+
792
+ } else { // next_element.kind == BRANCH
793
+ // We found a BRANCH node in the queue, whose bounding box is next
794
+ // closest to the query point. Add each child node (BRANCH or LEAF)
795
+ // to the queue.
796
+
797
+ struct node *branch = next_element.node;
798
+ for (int i = 0; i < branch->count; i++) {
799
+
800
+ struct element node_element = {
801
+ .distance = distance_bb(point, &branch->rects[i]),
802
+ .kind = branch->nodes[i]->kind, // BRANCH or LEAF
803
+ .node = branch->nodes[i]
804
+ };
805
+ if (!enqueue(tr->queue, node_element)) {
806
+ return false;
807
+ }
808
+ }
809
+ }
810
+ }
811
+ return true;
812
+ }
813
+
814
+ static bool node_scan(struct node *node,
815
+ bool (*iter)(const coord_t *min, const coord_t *max, const item_t item,
816
+ void *udata),
817
+ void *udata)
818
+ {
819
+ if (node->kind == LEAF) {
820
+ for (int i = 0; i < node->count; i++) {
821
+ if (!iter(node->rects[i].min, node->rects[i].max,
822
+ node->items[i], udata))
823
+ {
824
+ return false;
825
+ }
826
+ }
827
+ return true;
828
+ }
829
+ for (int i = 0; i < node->count; i++) {
830
+ if (!node_scan(node->nodes[i], iter, udata)) {
831
+ return false;
832
+ }
833
+ }
834
+ return true;
835
+ }
836
+
837
+ void rtree_scan(const struct rtree *tr,
838
+ bool (*iter)(const coord_t *min, const coord_t *max, const item_t item,
839
+ void *udata),
840
+ void *udata)
841
+ {
842
+ if (tr->root) {
843
+ node_scan(tr->root, iter, udata);
844
+ }
845
+ }
846
+
847
+ size_t rtree_count(const struct rtree *tr) {
848
+ return tr->count;
849
+ }
850
+
851
+ void rtree_bb(const struct rtree *tr, coord_t* min, coord_t* max) {
852
+ memcpy(min, tr->rect.min, sizeof(coord_t)*DIMS);
853
+ memcpy(max, tr->rect.max, sizeof(coord_t)*DIMS);
854
+ }
855
+
856
+ static bool node_delete(struct rtree *tr, struct rect *nr, struct node *node,
857
+ struct rect *ir, item_t item, int depth, bool *removed, bool *shrunk,
858
+ int (*compare)(const item_t a, const item_t b, void *udata),
859
+ void *udata)
860
+ {
861
+ *removed = false;
862
+ *shrunk = false;
863
+ if (node->kind == LEAF) {
864
+ for (int i = 0; i < node->count; i++) {
865
+ if (!rect_equals_bin(ir, &node->rects[i])) {
866
+ // different bounding box, keep going
867
+ continue;
868
+ }
869
+ if (!equal(node->items[i], item)) {
870
+ // different content, keep going
871
+ continue;
872
+ }
873
+ // Found the target item to delete.
874
+ node->rects[i] = node->rects[node->count-1];
875
+ node->items[i] = node->items[node->count-1];
876
+ node->count--;
877
+ if (rect_onedge(ir, nr)) {
878
+ // The item rect was on the edge of the node rect.
879
+ // We need to recalculate the node rect.
880
+ *nr = node_rect_calc(node);
881
+ // Notify the caller that we shrunk the rect.
882
+ *shrunk = true;
883
+ }
884
+ *removed = true;
885
+ return true;
886
+ }
887
+ return true;
888
+ }
889
+ int h = 0;
890
+ #ifdef USE_PATHHINT
891
+ h = tr->path_hint[depth];
892
+ if (h < node->count) {
893
+ if (rect_contains(&node->rects[h], ir)) {
894
+ cow_node_or(node->nodes[h], return false);
895
+ if (!node_delete(tr, &node->rects[h], node->nodes[h], ir, item,
896
+ depth+1,removed, shrunk, compare, udata))
897
+ {
898
+ return false;
899
+ }
900
+ if (*removed) {
901
+ goto removed;
902
+ }
903
+ }
904
+ }
905
+ h = 0;
906
+ #endif
907
+ for (; h < node->count; h++) {
908
+ if (!rect_contains(&node->rects[h], ir)) {
909
+ continue;
910
+ }
911
+ struct rect crect = node->rects[h];
912
+ cow_node_or(node->nodes[h], return false);
913
+ if (!node_delete(tr, &node->rects[h], node->nodes[h], ir, item, depth+1,
914
+ removed, shrunk, compare, udata))
915
+ {
916
+ return false;
917
+ }
918
+ if (!*removed) {
919
+ continue;
920
+ }
921
+ removed:
922
+ if (node->nodes[h]->count == 0) {
923
+ // underflow
924
+ node_free(tr, node->nodes[h]);
925
+ node->rects[h] = node->rects[node->count-1];
926
+ node->nodes[h] = node->nodes[node->count-1];
927
+ node->count--;
928
+ *nr = node_rect_calc(node);
929
+ *shrunk = true;
930
+ return true;
931
+ }
932
+ #ifdef USE_PATHHINT
933
+ tr->path_hint[depth] = h;
934
+ #endif
935
+ if (*shrunk) {
936
+ *shrunk = !rect_equals(&node->rects[h], &crect);
937
+ if (*shrunk) {
938
+ *nr = node_rect_calc(node);
939
+ }
940
+ }
941
+ return true;
942
+ }
943
+ return true;
944
+ }
945
+
946
+ // returns false if out of memory
947
+ static int rtree_delete0(struct rtree *tr, const coord_t *min,
948
+ const coord_t *max, const item_t item,
949
+ int (*compare)(const item_t a, const item_t b, void *udata),
950
+ void *udata)
951
+ {
952
+ // copy input rect
953
+ struct rect rect;
954
+ memcpy(&rect.min[0], min, sizeof(coord_t)*DIMS);
955
+ memcpy(&rect.max[0], max?max:min, sizeof(coord_t)*DIMS);
956
+
957
+ if (!tr->root) {
958
+ return 0;
959
+ }
960
+ bool removed = false;
961
+ bool shrunk = false;
962
+ cow_node_or(tr->root, return false);
963
+ if (!node_delete(tr, &tr->rect, tr->root, &rect, item, 0, &removed, &shrunk,
964
+ compare, udata))
965
+ {
966
+ return -1; // OOM
967
+ }
968
+ if (!removed) {
969
+ return 0;
970
+ }
971
+ tr->count--;
972
+ if (tr->count == 0) {
973
+ node_free(tr, tr->root);
974
+ tr->root = NULL;
975
+ memset(&tr->rect, 0, sizeof(struct rect));
976
+ tr->height = 0;
977
+ } else {
978
+ while (tr->root->kind == BRANCH && tr->root->count == 1) {
979
+ struct node *prev = tr->root;
980
+ tr->root = tr->root->nodes[0];
981
+ prev->count = 0;
982
+ node_free(tr, prev);
983
+ tr->height--;
984
+ }
985
+ if (shrunk) {
986
+ tr->rect = node_rect_calc(tr->root);
987
+ }
988
+ }
989
+ return 1;
990
+ }
991
+
992
+ int rtree_delete(struct rtree *tr, const coord_t *min, const coord_t *max,
993
+ const item_t item)
994
+ {
995
+ return rtree_delete0(tr, min, max, item, NULL, NULL);
996
+ }
997
+
998
+ int rtree_delete_with_comparator(struct rtree *tr, const coord_t *min,
999
+ const coord_t *max, const item_t item,
1000
+ int (*compare)(const item_t a, const item_t b, void *udata),
1001
+ void *udata)
1002
+ {
1003
+ return rtree_delete0(tr, min, max, item, compare, udata);
1004
+ }
1005
+
1006
+ struct rtree *rtree_clone(struct rtree *tr) {
1007
+ if (!tr) return NULL;
1008
+ struct rtree *tr2 = tr->malloc(sizeof(struct rtree));
1009
+ if (!tr2) return NULL;
1010
+ memcpy(tr2, tr, sizeof(struct rtree));
1011
+ if (tr2->root) rc_fetch_add(&tr2->root->rc, 1);
1012
+ return tr2;
1013
+ }
1014
+
1015
+ void rtree_opt_relaxed_atomics(struct rtree *tr) {
1016
+ tr->relaxed = true;
1017
+ }
1018
+
1019
+ #ifdef TEST_PRIVATE_FUNCTIONS
1020
+ #include "tests/priv_funcs.h"
1021
+ #endif