ACF $AcfVersion:0$
RTree.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#ifndef RTREE_H
3#define RTREE_H
4
5// NOTE This file compiles under MSVC 6 SP5 and MSVC .Net 2003 it may not work on other compilers without modification.
6
7// NOTE These next few lines may be win32 specific, you may need to modify them to compile on other platform
8#include <stdio.h>
9#include <math.h>
10#include <assert.h>
11#include <stdlib.h>
12
13#include <algorithm>
14#include <functional>
15
16//
17// RTree.h
18//
19
20#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
21#define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES>
22
23#define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one.
24#define RTREE_USE_SPHERICAL_VOLUME // Better split classification, may be slower on some systems
25
26// Fwd decl
27class RTFileStream; // File I/O helper class, look below for implementation and notes.
28
29
46template<class DATATYPE, class ELEMTYPE, int NUMDIMS,
47 class ELEMTYPEREAL = ELEMTYPE, int TMAXNODES = 8, int TMINNODES = TMAXNODES / 2>
48 class RTree
49{
50 static_assert(std::numeric_limits<ELEMTYPEREAL>::is_iec559, "'ELEMTYPEREAL' accepts floating-point types only");
51
52protected:
53
54 struct Node; // Fwd decl. Used by other internal structs and iterator
55
56public:
57
58 // These constant must be declared after Branch and before Node struct
59 // Stuck up here for MSVC 6 compiler. NSVC .NET 2003 is much happier.
60 enum
61 {
62 MAXNODES = TMAXNODES,
63 MINNODES = TMINNODES,
64 };
65
66public:
67
68 RTree();
69 RTree(const RTree& other);
70 virtual ~RTree();
71
76 void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
77
82 void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
83
90 template<typename Func>
91 int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], Func&& callback) const;
92
94 void RemoveAll();
95
97 int Count();
98
100 bool Load(const char* a_fileName);
102 bool Load(RTFileStream& a_stream);
103
104
106 bool Save(const char* a_fileName);
108 bool Save(RTFileStream& a_stream);
109
112 {
113 private:
114
115 enum { MAX_STACK = 32 }; // Max stack size. Allows almost n^32 where n is number of branches in node
116
117 struct StackElement
118 {
119 Node* m_node;
120 int m_branchIndex;
121 };
122
123 public:
124
125 Iterator() { Init(); }
126
128
130 bool IsNull() { return (m_tos <= 0); }
131
133 bool IsNotNull() { return (m_tos > 0); }
134
136 DATATYPE& operator*()
137 {
138 assert(IsNotNull());
139 StackElement& curTos = m_stack[m_tos - 1];
140 return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
141 }
142
144 const DATATYPE& operator*() const
145 {
146 assert(IsNotNull());
147 StackElement& curTos = m_stack[m_tos - 1];
148 return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
149 }
150
152 bool operator++() { return FindNextData(); }
153
155 void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
156 {
157 assert(IsNotNull());
158 StackElement& curTos = m_stack[m_tos - 1];
159 Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
160
161 for (int index = 0; index < NUMDIMS; ++index)
162 {
163 a_min[index] = curBranch.m_rect.m_min[index];
164 a_max[index] = curBranch.m_rect.m_max[index];
165 }
166 }
167
168 private:
169
171 void Init() { m_tos = 0; }
172
174 bool FindNextData()
175 {
176 for (;;)
177 {
178 if (m_tos <= 0)
179 {
180 return false;
181 }
182 StackElement curTos = Pop(); // Copy stack top cause it may change as we use it
183
184 if (curTos.m_node->IsLeaf())
185 {
186 // Keep walking through data while we can
187 if (curTos.m_branchIndex + 1 < curTos.m_node->m_count)
188 {
189 // There is more data, just point to the next one
190 Push(curTos.m_node, curTos.m_branchIndex + 1);
191 return true;
192 }
193 // No more data, so it will fall back to previous level
194 }
195 else
196 {
197 if (curTos.m_branchIndex + 1 < curTos.m_node->m_count)
198 {
199 // Push sibling on for future tree walk
200 // This is the 'fall back' node when we finish with the current level
201 Push(curTos.m_node, curTos.m_branchIndex + 1);
202 }
203 // Since cur node is not a leaf, push first of next level to get deeper into the tree
204 Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
205 Push(nextLevelnode, 0);
206
207 // If we pushed on a new leaf, exit as the data is ready at TOS
208 if (nextLevelnode->IsLeaf())
209 {
210 return true;
211 }
212 }
213 }
214 }
215
217 void Push(Node* a_node, int a_branchIndex)
218 {
219 m_stack[m_tos].m_node = a_node;
220 m_stack[m_tos].m_branchIndex = a_branchIndex;
221 ++m_tos;
222 assert(m_tos <= MAX_STACK);
223 }
224
226 StackElement& Pop()
227 {
228 assert(m_tos > 0);
229 --m_tos;
230 return m_stack[m_tos];
231 }
232
233 StackElement m_stack[MAX_STACK];
234 int m_tos;
235
236 friend class RTree; // Allow hiding of non-public functions while allowing manipulation by logical owner
237 };
238
240 void GetFirst(Iterator& a_it)
241 {
242 a_it.Init();
243 Node* first = m_root;
244 while (first)
245 {
246 if (first->IsInternalNode() && first->m_count > 1)
247 {
248 a_it.Push(first, 1); // Descend sibling branch later
249 }
250 else if (first->IsLeaf())
251 {
252 if (first->m_count)
253 {
254 a_it.Push(first, 0);
255 }
256 break;
257 }
258 first = first->m_branch[0].m_child;
259 }
260 }
261
263 void GetNext(Iterator& a_it) { ++a_it; }
264
266 bool IsNull(Iterator& a_it) { return a_it.IsNull(); }
267
269 DATATYPE& GetAt(Iterator& a_it) { return *a_it; }
270
271protected:
272
274 struct Rect
275 {
276 ELEMTYPE m_min[NUMDIMS];
277 ELEMTYPE m_max[NUMDIMS];
278 };
279
283 struct Branch
284 {
287 DATATYPE m_data;
288 };
289
291 struct Node
292 {
293 bool IsInternalNode() { return (m_level > 0); } // Not a leaf, but a internal node
294 bool IsLeaf() { return (m_level == 0); } // A leaf, contains data
295
299 };
300
302 struct ListNode
303 {
306 };
307
310 {
311 enum { NOT_TAKEN = -1 }; // indicates that position
312
316 int m_count[2];
318 ELEMTYPEREAL m_area[2];
319
323 ELEMTYPEREAL m_coverSplitArea;
324 };
325
326 Node* AllocNode();
327 void FreeNode(Node* a_node);
328 void InitNode(Node* a_node);
329 void InitRect(Rect* a_rect);
330 bool InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level);
331 bool InsertRect(const Branch& a_branch, Node** a_root, int a_level);
332 Rect NodeCover(Node* a_node);
333 bool AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode);
334 void DisconnectBranch(Node* a_node, int a_index);
335 int PickBranch(const Rect* a_rect, Node* a_node);
336 Rect CombineRect(const Rect* a_rectA, const Rect* a_rectB);
337 void SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode);
338 ELEMTYPEREAL RectSphericalVolume(Rect* a_rect);
339 ELEMTYPEREAL RectVolume(Rect* a_rect);
340 ELEMTYPEREAL CalcRectVolume(Rect* a_rect);
341 void GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars);
342 void ChoosePartition(PartitionVars* a_parVars, int a_minFill);
343 void LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars);
344 void InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill);
345 void PickSeeds(PartitionVars* a_parVars);
346 void Classify(int a_index, int a_group, PartitionVars* a_parVars);
347 bool RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root);
348 bool RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, ListNode** a_listNode);
350 void FreeListNode(ListNode* a_listNode);
351 bool Overlap(Rect* a_rectA, Rect* a_rectB) const;
352 void ReInsert(Node* a_node, ListNode** a_listNode);
353
354 template<typename Func>
355 bool Search(Node* a_node, Rect* a_rect, int& a_foundCount, Func&& callback) const;
356
357 void RemoveAllRec(Node* a_node);
358 void Reset();
359 void CountRec(Node* a_node, int& a_count);
360
361 bool SaveRec(Node* a_node, RTFileStream& a_stream);
362 bool LoadRec(Node* a_node, RTFileStream& a_stream);
363 void CopyRec(Node* current, Node* other);
364
366 ELEMTYPEREAL m_unitSphereVolume;
367};
368
369
370// Because there is not stream support, this is a quick and dirty file I/O helper.
371// Users will likely replace its usage with a Stream implementation from their favorite API.
373{
374 FILE* m_file;
375
376public:
377
378
380 {
381 m_file = NULL;
382 }
383
385 {
386 Close();
387 }
388
389 bool Open(const char* a_fileName, const char* mode)
390 {
391#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
392 return fopen_s(&m_file, a_fileName, mode) == 0;
393#else
394 m_file = fopen(a_fileName, mode);
395 return m_file != nullptr;
396#endif
397 }
398
399 bool OpenRead(const char* a_fileName)
400 {
401 return this->Open(a_fileName, "rb");
402 }
403
404 bool OpenWrite(const char* a_fileName)
405 {
406 return this->Open(a_fileName, "wb");
407 }
408
409 void Close()
410 {
411 if (m_file)
412 {
413 fclose(m_file);
414 m_file = NULL;
415 }
416 }
417
418 template< typename TYPE >
419 size_t Write(const TYPE& a_value)
420 {
421 assert(m_file);
422 return fwrite((void*)&a_value, sizeof(a_value), 1, m_file);
423 }
424
425 template< typename TYPE >
426 size_t WriteArray(const TYPE* a_array, int a_count)
427 {
428 assert(m_file);
429 return fwrite((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
430 }
431
432 template< typename TYPE >
433 size_t Read(TYPE& a_value)
434 {
435 assert(m_file);
436 return fread((void*)&a_value, sizeof(a_value), 1, m_file);
437 }
438
439 template< typename TYPE >
440 size_t ReadArray(TYPE* a_array, int a_count)
441 {
442 assert(m_file);
443 return fread((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
444 }
445};
446
447
449RTREE_QUAL::RTree()
450{
451 assert(MAXNODES > MINNODES);
452 assert(MINNODES > 0);
453
454 // Precomputed volumes of the unit spheres for the first few dimensions
455 const float UNIT_SPHERE_VOLUMES[] = {
456 0.000000f, 2.000000f, 3.141593f, // Dimension 0,1,2
457 4.188790f, 4.934802f, 5.263789f, // Dimension 3,4,5
458 5.167713f, 4.724766f, 4.058712f, // Dimension 6,7,8
459 3.298509f, 2.550164f, 1.884104f, // Dimension 9,10,11
460 1.335263f, 0.910629f, 0.599265f, // Dimension 12,13,14
461 0.381443f, 0.235331f, 0.140981f, // Dimension 15,16,17
462 0.082146f, 0.046622f, 0.025807f, // Dimension 18,19,20
463 };
464
465 m_root = AllocNode();
466 m_root->m_level = 0;
467 m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
468}
469
470
472RTREE_QUAL::RTree(const RTree& other) : RTree()
473{
474 CopyRec(m_root, other.m_root);
475}
476
477
479RTREE_QUAL::~RTree()
480{
481 Reset(); // Free, or reset node memory
482}
483
484
486void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
487{
488#ifdef _DEBUG
489 for (int index = 0; index < NUMDIMS; ++index)
490 {
491 assert(a_min[index] <= a_max[index]);
492 }
493#endif //_DEBUG
494
495 Branch branch;
496 branch.m_data = a_dataId;
497 branch.m_child = NULL;
498
499 for (int axis = 0; axis < NUMDIMS; ++axis)
500 {
501 branch.m_rect.m_min[axis] = a_min[axis];
502 branch.m_rect.m_max[axis] = a_max[axis];
503 }
504
505 InsertRect(branch, &m_root, 0);
506}
507
508
510void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId)
511{
512#ifdef _DEBUG
513 for (int index = 0; index < NUMDIMS; ++index)
514 {
515 assert(a_min[index] <= a_max[index]);
516 }
517#endif //_DEBUG
518
519 Rect rect;
520
521 for (int axis = 0; axis < NUMDIMS; ++axis)
522 {
523 rect.m_min[axis] = a_min[axis];
524 rect.m_max[axis] = a_max[axis];
525 }
526
527 RemoveRect(&rect, a_dataId, &m_root);
528}
529
530
532template<typename Func>
533int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], Func&& callback) const
534{
535#ifdef _DEBUG
536 for (int index = 0; index < NUMDIMS; ++index)
537 {
538 assert(a_min[index] <= a_max[index]);
539 }
540#endif //_DEBUG
541
542 Rect rect;
543
544 for (int axis = 0; axis < NUMDIMS; ++axis)
545 {
546 rect.m_min[axis] = a_min[axis];
547 rect.m_max[axis] = a_max[axis];
548 }
549
550 // NOTE: May want to return search result another way, perhaps returning the number of found elements here.
551
552 int foundCount = 0;
553 Search(m_root, &rect, foundCount, std::forward<Func>(callback));
554
555 return foundCount;
556}
557
558
560int RTREE_QUAL::Count()
561{
562 int count = 0;
563 CountRec(m_root, count);
564
565 return count;
566}
567
568
569
571void RTREE_QUAL::CountRec(Node* a_node, int& a_count)
572{
573 if (a_node->IsInternalNode()) // not a leaf node
574 {
575 for (int index = 0; index < a_node->m_count; ++index)
576 {
577 CountRec(a_node->m_branch[index].m_child, a_count);
578 }
579 }
580 else // A leaf node
581 {
582 a_count += a_node->m_count;
583 }
584}
585
586
588bool RTREE_QUAL::Load(const char* a_fileName)
589{
590 RemoveAll(); // Clear existing tree
591
592 RTFileStream stream;
593 if (!stream.OpenRead(a_fileName))
594 {
595 return false;
596 }
597
598 bool result = Load(stream);
599
600 stream.Close();
601
602 return result;
603}
604
605
606
608bool RTREE_QUAL::Load(RTFileStream& a_stream)
609{
610 // Write some kind of header
611 int _dataFileId = ('R' << 0) | ('T' << 8) | ('R' << 16) | ('E' << 24);
612 int _dataSize = sizeof(DATATYPE);
613 int _dataNumDims = NUMDIMS;
614 int _dataElemSize = sizeof(ELEMTYPE);
615 int _dataElemRealSize = sizeof(ELEMTYPEREAL);
616 int _dataMaxNodes = TMAXNODES;
617 int _dataMinNodes = TMINNODES;
618
619 int dataFileId = 0;
620 int dataSize = 0;
621 int dataNumDims = 0;
622 int dataElemSize = 0;
623 int dataElemRealSize = 0;
624 int dataMaxNodes = 0;
625 int dataMinNodes = 0;
626
627 a_stream.Read(dataFileId);
628 a_stream.Read(dataSize);
629 a_stream.Read(dataNumDims);
630 a_stream.Read(dataElemSize);
631 a_stream.Read(dataElemRealSize);
632 a_stream.Read(dataMaxNodes);
633 a_stream.Read(dataMinNodes);
634
635 bool result = false;
636
637 // Test if header was valid and compatible
638 if ((dataFileId == _dataFileId)
639 && (dataSize == _dataSize)
640 && (dataNumDims == _dataNumDims)
641 && (dataElemSize == _dataElemSize)
642 && (dataElemRealSize == _dataElemRealSize)
643 && (dataMaxNodes == _dataMaxNodes)
644 && (dataMinNodes == _dataMinNodes)
645 )
646 {
647 // Recursively load tree
648 result = LoadRec(m_root, a_stream);
649 }
650
651 return result;
652}
653
654
656bool RTREE_QUAL::LoadRec(Node* a_node, RTFileStream& a_stream)
657{
658 a_stream.Read(a_node->m_level);
659 a_stream.Read(a_node->m_count);
660
661 if (a_node->IsInternalNode()) // not a leaf node
662 {
663 for (int index = 0; index < a_node->m_count; ++index)
664 {
665 Branch* curBranch = &a_node->m_branch[index];
666
667 a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
668 a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
669
670 curBranch->m_child = AllocNode();
671 LoadRec(curBranch->m_child, a_stream);
672 }
673 }
674 else // A leaf node
675 {
676 for (int index = 0; index < a_node->m_count; ++index)
677 {
678 Branch* curBranch = &a_node->m_branch[index];
679
680 a_stream.ReadArray(curBranch->m_rect.m_min, NUMDIMS);
681 a_stream.ReadArray(curBranch->m_rect.m_max, NUMDIMS);
682
683 a_stream.Read(curBranch->m_data);
684 }
685 }
686
687 return true; // Should do more error checking on I/O operations
688}
689
690
692void RTREE_QUAL::CopyRec(Node* current, Node* other)
693{
694 current->m_level = other->m_level;
695 current->m_count = other->m_count;
696
697 if (current->IsInternalNode()) // not a leaf node
698 {
699 for (int index = 0; index < current->m_count; ++index)
700 {
701 Branch* currentBranch = &current->m_branch[index];
702 Branch* otherBranch = &other->m_branch[index];
703
704 std::copy(otherBranch->m_rect.m_min,
705 otherBranch->m_rect.m_min + NUMDIMS,
706 currentBranch->m_rect.m_min);
707
708 std::copy(otherBranch->m_rect.m_max,
709 otherBranch->m_rect.m_max + NUMDIMS,
710 currentBranch->m_rect.m_max);
711
712 currentBranch->m_child = AllocNode();
713 CopyRec(currentBranch->m_child, otherBranch->m_child);
714 }
715 }
716 else // A leaf node
717 {
718 for (int index = 0; index < current->m_count; ++index)
719 {
720 Branch* currentBranch = &current->m_branch[index];
721 Branch* otherBranch = &other->m_branch[index];
722
723 std::copy(otherBranch->m_rect.m_min,
724 otherBranch->m_rect.m_min + NUMDIMS,
725 currentBranch->m_rect.m_min);
726
727 std::copy(otherBranch->m_rect.m_max,
728 otherBranch->m_rect.m_max + NUMDIMS,
729 currentBranch->m_rect.m_max);
730
731 currentBranch->m_data = otherBranch->m_data;
732 }
733 }
734}
735
736
738bool RTREE_QUAL::Save(const char* a_fileName)
739{
740 RTFileStream stream;
741 if (!stream.OpenWrite(a_fileName))
742 {
743 return false;
744 }
745
746 bool result = Save(stream);
747
748 stream.Close();
749
750 return result;
751}
752
753
755bool RTREE_QUAL::Save(RTFileStream& a_stream)
756{
757 // Write some kind of header
758 int dataFileId = ('R' << 0) | ('T' << 8) | ('R' << 16) | ('E' << 24);
759 int dataSize = sizeof(DATATYPE);
760 int dataNumDims = NUMDIMS;
761 int dataElemSize = sizeof(ELEMTYPE);
762 int dataElemRealSize = sizeof(ELEMTYPEREAL);
763 int dataMaxNodes = TMAXNODES;
764 int dataMinNodes = TMINNODES;
765
766 a_stream.Write(dataFileId);
767 a_stream.Write(dataSize);
768 a_stream.Write(dataNumDims);
769 a_stream.Write(dataElemSize);
770 a_stream.Write(dataElemRealSize);
771 a_stream.Write(dataMaxNodes);
772 a_stream.Write(dataMinNodes);
773
774 // Recursively save tree
775 bool result = SaveRec(m_root, a_stream);
776
777 return result;
778}
779
780
782bool RTREE_QUAL::SaveRec(Node* a_node, RTFileStream& a_stream)
783{
784 a_stream.Write(a_node->m_level);
785 a_stream.Write(a_node->m_count);
786
787 if (a_node->IsInternalNode()) // not a leaf node
788 {
789 for (int index = 0; index < a_node->m_count; ++index)
790 {
791 Branch* curBranch = &a_node->m_branch[index];
792
793 a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
794 a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
795
796 SaveRec(curBranch->m_child, a_stream);
797 }
798 }
799 else // A leaf node
800 {
801 for (int index = 0; index < a_node->m_count; ++index)
802 {
803 Branch* curBranch = &a_node->m_branch[index];
804
805 a_stream.WriteArray(curBranch->m_rect.m_min, NUMDIMS);
806 a_stream.WriteArray(curBranch->m_rect.m_max, NUMDIMS);
807
808 a_stream.Write(curBranch->m_data);
809 }
810 }
811
812 return true; // Should do more error checking on I/O operations
813}
814
815
817void RTREE_QUAL::RemoveAll()
818{
819 // Delete all existing nodes
820 Reset();
821
822 m_root = AllocNode();
823 m_root->m_level = 0;
824}
825
826
828void RTREE_QUAL::Reset()
829{
830#ifdef RTREE_DONT_USE_MEMPOOLS
831 // Delete all existing nodes
832 RemoveAllRec(m_root);
833#else // RTREE_DONT_USE_MEMPOOLS
834 // Just reset memory pools. We are not using complex types
835 // EXAMPLE
836#endif // RTREE_DONT_USE_MEMPOOLS
837}
838
839
841void RTREE_QUAL::RemoveAllRec(Node* a_node)
842{
843 assert(a_node);
844 assert(a_node->m_level >= 0);
845
846 if (a_node->IsInternalNode()) // This is an internal node in the tree
847 {
848 for (int index = 0; index < a_node->m_count; ++index)
849 {
850 RemoveAllRec(a_node->m_branch[index].m_child);
851 }
852 }
853 FreeNode(a_node);
854}
855
856
858typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
859{
860 Node* newNode;
861#ifdef RTREE_DONT_USE_MEMPOOLS
862 newNode = new Node;
863#else // RTREE_DONT_USE_MEMPOOLS
864 // EXAMPLE
865#endif // RTREE_DONT_USE_MEMPOOLS
866 InitNode(newNode);
867 return newNode;
868}
869
870
872void RTREE_QUAL::FreeNode(Node* a_node)
873{
874 assert(a_node);
875
876#ifdef RTREE_DONT_USE_MEMPOOLS
877 delete a_node;
878#else // RTREE_DONT_USE_MEMPOOLS
879 // EXAMPLE
880#endif // RTREE_DONT_USE_MEMPOOLS
881}
882
883
884// Allocate space for a node in the list used in DeletRect to
885// store Nodes that are too empty.
887typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
888{
889#ifdef RTREE_DONT_USE_MEMPOOLS
890 return new ListNode;
891#else // RTREE_DONT_USE_MEMPOOLS
892 // EXAMPLE
893#endif // RTREE_DONT_USE_MEMPOOLS
894}
895
896
898void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
899{
900#ifdef RTREE_DONT_USE_MEMPOOLS
901 delete a_listNode;
902#else // RTREE_DONT_USE_MEMPOOLS
903 // EXAMPLE
904#endif // RTREE_DONT_USE_MEMPOOLS
905}
906
907
909void RTREE_QUAL::InitNode(Node* a_node)
910{
911 a_node->m_count = 0;
912 a_node->m_level = -1;
913}
914
915
917void RTREE_QUAL::InitRect(Rect* a_rect)
918{
919 for (int index = 0; index < NUMDIMS; ++index)
920 {
921 a_rect->m_min[index] = (ELEMTYPE)0;
922 a_rect->m_max[index] = (ELEMTYPE)0;
923 }
924}
925
926
927// Inserts a new data rectangle into the index structure.
928// Recursively descends tree, propagates splits back up.
929// Returns 0 if node was not split. Old node updated.
930// If node was split, returns 1 and sets the pointer pointed to by
931// new_node to point to the new node. Old node updated to become one of two.
932// The level argument specifies the number of steps up from the leaf
933// level to insert; e.g. a data rectangle goes in at level = 0.
935bool RTREE_QUAL::InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level)
936{
937 assert(a_node && a_newNode);
938 assert(a_level >= 0 && a_level <= a_node->m_level);
939
940 // recurse until we reach the correct level for the new record. data records
941 // will always be called with a_level == 0 (leaf)
942 if (a_node->m_level > a_level)
943 {
944 // Still above level for insertion, go down tree recursively
945 Node* otherNode;
946
947 // find the optimal branch for this record
948 int index = PickBranch(&a_branch.m_rect, a_node);
949
950 // recursively insert this record into the picked branch
951 bool childWasSplit = InsertRectRec(a_branch, a_node->m_branch[index].m_child, &otherNode, a_level);
952
953 if (!childWasSplit)
954 {
955 // Child was not split. Merge the bounding box of the new record with the
956 // existing bounding box
957 a_node->m_branch[index].m_rect = CombineRect(&a_branch.m_rect, &(a_node->m_branch[index].m_rect));
958 return false;
959 }
960 else
961 {
962 // Child was split. The old branches are now re-partitioned to two nodes
963 // so we have to re-calculate the bounding boxes of each node
964 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
965 Branch branch;
966 branch.m_child = otherNode;
967 branch.m_rect = NodeCover(otherNode);
968
969 // The old node is already a child of a_node. Now add the newly-created
970 // node to a_node as well. a_node might be split because of that.
971 return AddBranch(&branch, a_node, a_newNode);
972 }
973 }
974 else if (a_node->m_level == a_level)
975 {
976 // We have reached level for insertion. Add rect, split if necessary
977 return AddBranch(&a_branch, a_node, a_newNode);
978 }
979 else
980 {
981 // Should never occur
982 assert(0);
983 return false;
984 }
985}
986
987
988// Insert a data rectangle into an index structure.
989// InsertRect provides for splitting the root;
990// returns 1 if root was split, 0 if it was not.
991// The level argument specifies the number of steps up from the leaf
992// level to insert; e.g. a data rectangle goes in at level = 0.
993// InsertRect2 does the recursion.
994//
996bool RTREE_QUAL::InsertRect(const Branch& a_branch, Node** a_root, int a_level)
997{
998 assert(a_root);
999 assert(a_level >= 0 && a_level <= (*a_root)->m_level);
1000#ifdef _DEBUG
1001 for (int index = 0; index < NUMDIMS; ++index)
1002 {
1003 assert(a_branch.m_rect.m_min[index] <= a_branch.m_rect.m_max[index]);
1004 }
1005#endif //_DEBUG
1006
1007 Node* newNode;
1008
1009 if (InsertRectRec(a_branch, *a_root, &newNode, a_level)) // Root split
1010 {
1011 // Grow tree taller and new root
1012 Node* newRoot = AllocNode();
1013 newRoot->m_level = (*a_root)->m_level + 1;
1014
1015 Branch branch;
1016
1017 // add old root node as a child of the new root
1018 branch.m_rect = NodeCover(*a_root);
1019 branch.m_child = *a_root;
1020 AddBranch(&branch, newRoot, NULL);
1021
1022 // add the split node as a child of the new root
1023 branch.m_rect = NodeCover(newNode);
1024 branch.m_child = newNode;
1025 AddBranch(&branch, newRoot, NULL);
1026
1027 // set the new root as the root node
1028 *a_root = newRoot;
1029
1030 return true;
1031 }
1032
1033 return false;
1034}
1035
1036
1037// Find the smallest rectangle that includes all rectangles in branches of a node.
1039typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
1040{
1041 assert(a_node);
1042
1043 Rect rect = a_node->m_branch[0].m_rect;
1044 for (int index = 1; index < a_node->m_count; ++index)
1045 {
1046 rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
1047 }
1048
1049 return rect;
1050}
1051
1052
1053// Add a branch to a node. Split the node if necessary.
1054// Returns 0 if node not split. Old node updated.
1055// Returns 1 if node split, sets *new_node to address of new node.
1056// Old node updated, becomes one of two.
1058bool RTREE_QUAL::AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode)
1059{
1060 assert(a_branch);
1061 assert(a_node);
1062
1063 if (a_node->m_count < MAXNODES) // Split won't be necessary
1064 {
1065 a_node->m_branch[a_node->m_count] = *a_branch;
1066 ++a_node->m_count;
1067
1068 return false;
1069 }
1070 else
1071 {
1072 assert(a_newNode);
1073
1074 SplitNode(a_node, a_branch, a_newNode);
1075 return true;
1076 }
1077}
1078
1079
1080// Disconnect a dependent node.
1081// Caller must return (or stop using iteration index) after this as count has changed
1083void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
1084{
1085 assert(a_node && (a_index >= 0) && (a_index < MAXNODES));
1086 assert(a_node->m_count > 0);
1087
1088 // Remove element by swapping with the last element to prevent gaps in array
1089 a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
1090
1091 --a_node->m_count;
1092}
1093
1094
1095// Pick a branch. Pick the one that will need the smallest increase
1096// in area to accomodate the new rectangle. This will result in the
1097// least total area for the covering rectangles in the current node.
1098// In case of a tie, pick the one which was smaller before, to get
1099// the best resolution when searching.
1101int RTREE_QUAL::PickBranch(const Rect* a_rect, Node* a_node)
1102{
1103 assert(a_rect && a_node);
1104
1105 bool firstTime = true;
1106 ELEMTYPEREAL increase;
1107 ELEMTYPEREAL bestIncr = (ELEMTYPEREAL)-1;
1108 ELEMTYPEREAL area;
1109 ELEMTYPEREAL bestArea = 0;
1110 int best = 0;
1111 Rect tempRect;
1112
1113 for (int index = 0; index < a_node->m_count; ++index)
1114 {
1115 Rect* curRect = &a_node->m_branch[index].m_rect;
1116 area = CalcRectVolume(curRect);
1117 tempRect = CombineRect(a_rect, curRect);
1118 increase = CalcRectVolume(&tempRect) - area;
1119 if ((increase < bestIncr) || firstTime)
1120 {
1121 best = index;
1122 bestArea = area;
1123 bestIncr = increase;
1124 firstTime = false;
1125 }
1126 else if ((increase == bestIncr) && (area < bestArea))
1127 {
1128 best = index;
1129 bestArea = area;
1130 bestIncr = increase;
1131 }
1132 }
1133 return best;
1134}
1135
1136
1137// Combine two rectangles into larger one containing both
1139typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(const Rect* a_rectA, const Rect* a_rectB)
1140{
1141 assert(a_rectA && a_rectB);
1142
1143 Rect newRect;
1144
1145 for (int index = 0; index < NUMDIMS; ++index)
1146 {
1147 newRect.m_min[index] = std::min(a_rectA->m_min[index], a_rectB->m_min[index]);
1148 newRect.m_max[index] = std::max(a_rectA->m_max[index], a_rectB->m_max[index]);
1149 }
1150
1151 return newRect;
1152}
1153
1154
1155
1156// Split a node.
1157// Divides the nodes branches and the extra one between two nodes.
1158// Old node is one of the new ones, and one really new one is created.
1159// Tries more than one method for choosing a partition, uses best result.
1161void RTREE_QUAL::SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode)
1162{
1163 assert(a_node);
1164 assert(a_branch);
1165
1166 // Could just use local here, but member or external is faster since it is reused
1167 PartitionVars localVars;
1168 PartitionVars* parVars = &localVars;
1169
1170 // Load all the branches into a buffer, initialize old node
1171 GetBranches(a_node, a_branch, parVars);
1172
1173 // Find partition
1174 ChoosePartition(parVars, MINNODES);
1175
1176 // Create a new node to hold (about) half of the branches
1177 *a_newNode = AllocNode();
1178 (*a_newNode)->m_level = a_node->m_level;
1179
1180 // Put branches from buffer into 2 nodes according to the chosen partition
1181 a_node->m_count = 0;
1182 LoadNodes(a_node, *a_newNode, parVars);
1183
1184 assert((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
1185}
1186
1187
1188// Calculate the n-dimensional volume of a rectangle
1190ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
1191{
1192 assert(a_rect);
1193
1194 ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
1195
1196 for (int index = 0; index < NUMDIMS; ++index)
1197 {
1198 volume *= a_rect->m_max[index] - a_rect->m_min[index];
1199 }
1200
1201 assert(volume >= (ELEMTYPEREAL)0);
1202
1203 return volume;
1204}
1205
1206
1207// The exact volume of the bounding sphere for the given Rect
1209ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
1210{
1211 assert(a_rect);
1212
1213 ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
1214 ELEMTYPEREAL radius;
1215
1216 for (int index = 0; index < NUMDIMS; ++index)
1217 {
1218 ELEMTYPEREAL halfExtent = ((ELEMTYPEREAL)a_rect->m_max[index] - (ELEMTYPEREAL)a_rect->m_min[index]) * (ELEMTYPEREAL)0.5;
1219 sumOfSquares += halfExtent * halfExtent;
1220 }
1221
1222 radius = (ELEMTYPEREAL)sqrt(sumOfSquares);
1223
1224 // Pow maybe slow, so test for common dims like 2,3 and just use x*x, x*x*x.
1225 if (NUMDIMS == 3)
1226 {
1227 return (radius * radius * radius * m_unitSphereVolume);
1228 }
1229 else if (NUMDIMS == 2)
1230 {
1231 return (radius * radius * m_unitSphereVolume);
1232 }
1233 else
1234 {
1235 return (ELEMTYPEREAL)(pow(radius, NUMDIMS) * m_unitSphereVolume);
1236 }
1237}
1238
1239
1240// Use one of the methods to calculate retangle volume
1242ELEMTYPEREAL RTREE_QUAL::CalcRectVolume(Rect* a_rect)
1243{
1244#ifdef RTREE_USE_SPHERICAL_VOLUME
1245 return RectSphericalVolume(a_rect); // Slower but helps certain merge cases
1246#else // RTREE_USE_SPHERICAL_VOLUME
1247 return RectVolume(a_rect); // Faster but can cause poor merges
1248#endif // RTREE_USE_SPHERICAL_VOLUME
1249}
1250
1251
1252// Load branch buffer with branches from full node plus the extra branch.
1254void RTREE_QUAL::GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars)
1255{
1256 assert(a_node);
1257 assert(a_branch);
1258
1259 assert(a_node->m_count == MAXNODES);
1260
1261 // Load the branch buffer
1262 for (int index = 0; index < MAXNODES; ++index)
1263 {
1264 a_parVars->m_branchBuf[index] = a_node->m_branch[index];
1265 }
1266 a_parVars->m_branchBuf[MAXNODES] = *a_branch;
1267 a_parVars->m_branchCount = MAXNODES + 1;
1268
1269 // Calculate rect containing all in the set
1270 a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
1271 for (int index = 1; index < MAXNODES + 1; ++index)
1272 {
1273 a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
1274 }
1275 a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
1276}
1277
1278
1279// Method #0 for choosing a partition:
1280// As the seeds for the two groups, pick the two rects that would waste the
1281// most area if covered by a single rectangle, i.e. evidently the worst pair
1282// to have in the same group.
1283// Of the remaining, one at a time is chosen to be put in one of the two groups.
1284// The one chosen is the one with the greatest difference in area expansion
1285// depending on which group - the rect most strongly attracted to one group
1286// and repelled from the other.
1287// If one group gets too full (more would force other group to violate min
1288// fill requirement) then other group gets the rest.
1289// These last are the ones that can go in either group most easily.
1291void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
1292{
1293 assert(a_parVars);
1294
1295 ELEMTYPEREAL biggestDiff;
1296 int group, chosen = 0, betterGroup = 0;
1297
1298 InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
1299 PickSeeds(a_parVars);
1300
1301 while (((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1302 && (a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill))
1303 && (a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill)))
1304 {
1305 biggestDiff = (ELEMTYPEREAL)-1;
1306 for (int index = 0; index < a_parVars->m_total; ++index)
1307 {
1308 if (PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1309 {
1310 Rect* curRect = &a_parVars->m_branchBuf[index].m_rect;
1311 Rect rect0 = CombineRect(curRect, &a_parVars->m_cover[0]);
1312 Rect rect1 = CombineRect(curRect, &a_parVars->m_cover[1]);
1313 ELEMTYPEREAL growth0 = CalcRectVolume(&rect0) - a_parVars->m_area[0];
1314 ELEMTYPEREAL growth1 = CalcRectVolume(&rect1) - a_parVars->m_area[1];
1315 ELEMTYPEREAL diff = growth1 - growth0;
1316 if (diff >= 0)
1317 {
1318 group = 0;
1319 }
1320 else
1321 {
1322 group = 1;
1323 diff = -diff;
1324 }
1325
1326 if (diff > biggestDiff)
1327 {
1328 biggestDiff = diff;
1329 chosen = index;
1330 betterGroup = group;
1331 }
1332 else if ((diff == biggestDiff) && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup]))
1333 {
1334 chosen = index;
1335 betterGroup = group;
1336 }
1337 }
1338 }
1339 Classify(chosen, betterGroup, a_parVars);
1340 }
1341
1342 // If one group too full, put remaining rects in the other
1343 if ((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
1344 {
1345 if (a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill)
1346 {
1347 group = 1;
1348 }
1349 else
1350 {
1351 group = 0;
1352 }
1353 for (int index = 0; index < a_parVars->m_total; ++index)
1354 {
1355 if (PartitionVars::NOT_TAKEN == a_parVars->m_partition[index])
1356 {
1357 Classify(index, group, a_parVars);
1358 }
1359 }
1360 }
1361
1362 assert((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
1363 assert((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
1364 (a_parVars->m_count[1] >= a_parVars->m_minFill));
1365}
1366
1367
1368// Copy branches from the buffer into two nodes according to the partition.
1370void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
1371{
1372 assert(a_nodeA);
1373 assert(a_nodeB);
1374 assert(a_parVars);
1375
1376 for (int index = 0; index < a_parVars->m_total; ++index)
1377 {
1378 assert(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
1379
1380 int targetNodeIndex = a_parVars->m_partition[index];
1381 Node* targetNodes[] = { a_nodeA, a_nodeB };
1382
1383 // It is assured that AddBranch here will not cause a node split.
1384 bool nodeWasSplit = AddBranch(&a_parVars->m_branchBuf[index], targetNodes[targetNodeIndex], NULL);
1385 assert(!nodeWasSplit);
1386 }
1387}
1388
1389
1390// Initialize a PartitionVars structure.
1392void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill)
1393{
1394 assert(a_parVars);
1395
1396 a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
1397 a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
1398 a_parVars->m_total = a_maxRects;
1399 a_parVars->m_minFill = a_minFill;
1400 for (int index = 0; index < a_maxRects; ++index)
1401 {
1402 a_parVars->m_partition[index] = PartitionVars::NOT_TAKEN;
1403 }
1404}
1405
1406
1408void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
1409{
1410 int seed0 = 0, seed1 = 0;
1411 ELEMTYPEREAL worst, waste;
1412 ELEMTYPEREAL area[MAXNODES + 1];
1413
1414 for (int index = 0; index < a_parVars->m_total; ++index)
1415 {
1416 area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
1417 }
1418
1419 worst = -a_parVars->m_coverSplitArea - 1;
1420 for (int indexA = 0; indexA < a_parVars->m_total - 1; ++indexA)
1421 {
1422 for (int indexB = indexA + 1; indexB < a_parVars->m_total; ++indexB)
1423 {
1424 Rect oneRect = CombineRect(&a_parVars->m_branchBuf[indexA].m_rect, &a_parVars->m_branchBuf[indexB].m_rect);
1425 waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
1426 if (waste > worst)
1427 {
1428 worst = waste;
1429 seed0 = indexA;
1430 seed1 = indexB;
1431 }
1432 }
1433 }
1434
1435 Classify(seed0, 0, a_parVars);
1436 Classify(seed1, 1, a_parVars);
1437}
1438
1439
1440// Put a branch in one of the groups.
1442void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
1443{
1444 assert(a_parVars);
1445 assert(PartitionVars::NOT_TAKEN == a_parVars->m_partition[a_index]);
1446
1447 a_parVars->m_partition[a_index] = a_group;
1448
1449 // Calculate combined rect
1450 if (a_parVars->m_count[a_group] == 0)
1451 {
1452 a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
1453 }
1454 else
1455 {
1456 a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
1457 }
1458
1459 // Calculate volume of combined rect
1460 a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
1461
1462 ++a_parVars->m_count[a_group];
1463}
1464
1465
1466// Delete a data rectangle from an index structure.
1467// Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
1468// Returns 1 if record not found, 0 if success.
1469// RemoveRect provides for eliminating the root.
1471bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
1472{
1473 assert(a_rect && a_root);
1474 assert(*a_root);
1475
1476 ListNode* reInsertList = NULL;
1477
1478 if (!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList))
1479 {
1480 // Found and deleted a data item
1481 // Reinsert any branches from eliminated nodes
1482 while (reInsertList)
1483 {
1484 Node* tempNode = reInsertList->m_node;
1485
1486 for (int index = 0; index < tempNode->m_count; ++index)
1487 {
1488 // TODO go over this code. should I use (tempNode->m_level - 1)?
1489 InsertRect(tempNode->m_branch[index],
1490 a_root,
1491 tempNode->m_level);
1492 }
1493
1494 ListNode* remLNode = reInsertList;
1495 reInsertList = reInsertList->m_next;
1496
1497 FreeNode(remLNode->m_node);
1498 FreeListNode(remLNode);
1499 }
1500
1501 // Check for redundant root (not leaf, 1 child) and eliminate TODO replace
1502 // if with while? In case there is a whole branch of redundant roots...
1503 if ((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
1504 {
1505 Node* tempNode = (*a_root)->m_branch[0].m_child;
1506
1507 assert(tempNode);
1508 FreeNode(*a_root);
1509 *a_root = tempNode;
1510 }
1511 return false;
1512 }
1513 else
1514 {
1515 return true;
1516 }
1517}
1518
1519
1520// Delete a rectangle from non-root part of an index structure.
1521// Called by RemoveRect. Descends tree recursively,
1522// merges branches on the way back up.
1523// Returns 1 if record not found, 0 if success.
1525bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node, ListNode** a_listNode)
1526{
1527 assert(a_rect && a_node && a_listNode);
1528 assert(a_node->m_level >= 0);
1529
1530 if (a_node->IsInternalNode()) // not a leaf node
1531 {
1532 for (int index = 0; index < a_node->m_count; ++index)
1533 {
1534 if (Overlap(a_rect, &(a_node->m_branch[index].m_rect)))
1535 {
1536 if (!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode))
1537 {
1538 if (a_node->m_branch[index].m_child->m_count >= MINNODES)
1539 {
1540 // child removed, just resize parent rect
1541 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
1542 }
1543 else
1544 {
1545 // child removed, not enough entries in node, eliminate node
1546 ReInsert(a_node->m_branch[index].m_child, a_listNode);
1547 DisconnectBranch(a_node, index); // Must return after this call as count has changed
1548 }
1549 return false;
1550 }
1551 }
1552 }
1553 return true;
1554 }
1555 else // A leaf node
1556 {
1557 for (int index = 0; index < a_node->m_count; ++index)
1558 {
1559 if (a_node->m_branch[index].m_data == a_id)
1560 {
1561 DisconnectBranch(a_node, index); // Must return after this call as count has changed
1562 return false;
1563 }
1564 }
1565 return true;
1566 }
1567}
1568
1569
1570// Decide whether two rectangles overlap.
1572bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB) const
1573{
1574 assert(a_rectA && a_rectB);
1575
1576 for (int index = 0; index < NUMDIMS; ++index)
1577 {
1578 if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
1579 a_rectB->m_min[index] > a_rectA->m_max[index])
1580 {
1581 return false;
1582 }
1583 }
1584 return true;
1585}
1586
1587
1588// Add a node to the reinsertion list. All its branches will later
1589// be reinserted into the index structure.
1591void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)
1592{
1593 ListNode* newListNode;
1594
1595 newListNode = AllocListNode();
1596 newListNode->m_node = a_node;
1597 newListNode->m_next = *a_listNode;
1598 *a_listNode = newListNode;
1599}
1600
1601
1602// Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
1604template<typename Func>
1605bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, Func&& callback) const
1606{
1607 assert(a_node);
1608 assert(a_node->m_level >= 0);
1609 assert(a_rect);
1610
1611 if (a_node->IsInternalNode())
1612 {
1613 // This is an internal node in the tree
1614 for (int index = 0; index < a_node->m_count; ++index)
1615 {
1616 if (Overlap(a_rect, &a_node->m_branch[index].m_rect))
1617 {
1618 if (!Search(a_node->m_branch[index].m_child, a_rect, a_foundCount, std::forward<Func>(callback)))
1619 {
1620 // The callback indicated to stop searching
1621 return false;
1622 }
1623 }
1624 }
1625 }
1626 else
1627 {
1628 // This is a leaf node
1629 for (int index = 0; index < a_node->m_count; ++index)
1630 {
1631 if (Overlap(a_rect, &a_node->m_branch[index].m_rect))
1632 {
1633 DATATYPE& id = a_node->m_branch[index].m_data;
1634 ++a_foundCount;
1635
1636 if (!callback(id))
1637 {
1638 return false; // Don't continue searching
1639 }
1640 }
1641 }
1642 }
1643
1644 return true; // Continue searching
1645}
1646
1647
1648#undef RTREE_TEMPLATE
1649#undef RTREE_QUAL
1650
1651#endif //RTREE_H
#define RTREE_TEMPLATE
Definition RTree.h:20
size_t Read(TYPE &a_value)
Definition RTree.h:433
size_t Write(const TYPE &a_value)
Definition RTree.h:419
bool Open(const char *a_fileName, const char *mode)
Definition RTree.h:389
size_t WriteArray(const TYPE *a_array, int a_count)
Definition RTree.h:426
bool OpenWrite(const char *a_fileName)
Definition RTree.h:404
RTFileStream()
Definition RTree.h:379
bool OpenRead(const char *a_fileName)
Definition RTree.h:399
void Close()
Definition RTree.h:409
~RTFileStream()
Definition RTree.h:384
size_t ReadArray(TYPE *a_array, int a_count)
Definition RTree.h:440
Iterator is not remove safe.
Definition RTree.h:112
bool IsNull()
Is iterator invalid.
Definition RTree.h:130
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
Get the bounds for this node.
Definition RTree.h:155
const DATATYPE & operator*() const
Access the current data element. Caller must be sure iterator is not NULL first.
Definition RTree.h:144
bool IsNotNull()
Is iterator pointing to valid data.
Definition RTree.h:133
DATATYPE & operator*()
Access the current data element. Caller must be sure iterator is not NULL first.
Definition RTree.h:136
bool operator++()
Find the next data element.
Definition RTree.h:152
Implementation of RTree, a multidimensional bounding rectangle tree.
Definition RTree.h:49
@ MINNODES
Min elements in node.
Definition RTree.h:63
@ MAXNODES
Max elements in node.
Definition RTree.h:62
RTree()
Definition RTree.h:449
bool InsertRect(const Branch &a_branch, Node **a_root, int a_level)
Definition RTree.h:996
void FreeListNode(ListNode *a_listNode)
Definition RTree.h:898
bool AddBranch(const Branch *a_branch, Node *a_node, Node **a_newNode)
Definition RTree.h:1058
int PickBranch(const Rect *a_rect, Node *a_node)
Definition RTree.h:1101
void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Remove entry.
Definition RTree.h:510
void CountRec(Node *a_node, int &a_count)
Definition RTree.h:571
ELEMTYPEREAL CalcRectVolume(Rect *a_rect)
Definition RTree.h:1242
void Reset()
Definition RTree.h:828
void ChoosePartition(PartitionVars *a_parVars, int a_minFill)
Definition RTree.h:1291
void RemoveAll()
Remove all entries from tree.
Definition RTree.h:817
void GetBranches(Node *a_node, const Branch *a_branch, PartitionVars *a_parVars)
Definition RTree.h:1254
void GetNext(Iterator &a_it)
Get Next for iteration.
Definition RTree.h:263
Node * m_root
Root of tree.
Definition RTree.h:365
void RemoveAllRec(Node *a_node)
Definition RTree.h:841
bool RemoveRectRec(Rect *a_rect, const DATATYPE &a_id, Node *a_node, ListNode **a_listNode)
Definition RTree.h:1525
bool SaveRec(Node *a_node, RTFileStream &a_stream)
Definition RTree.h:782
void ReInsert(Node *a_node, ListNode **a_listNode)
Definition RTree.h:1591
void Classify(int a_index, int a_group, PartitionVars *a_parVars)
Definition RTree.h:1442
Rect NodeCover(Node *a_node)
Definition RTree.h:1039
bool RemoveRect(Rect *a_rect, const DATATYPE &a_id, Node **a_root)
Definition RTree.h:1471
bool Save(const char *a_fileName)
Save tree contents to file.
Definition RTree.h:738
void FreeNode(Node *a_node)
Definition RTree.h:872
virtual ~RTree()
Definition RTree.h:479
ELEMTYPEREAL RectSphericalVolume(Rect *a_rect)
Definition RTree.h:1209
int Count()
Count the data elements in this container. This is slow as no internal counter is maintained.
Definition RTree.h:560
void LoadNodes(Node *a_nodeA, Node *a_nodeB, PartitionVars *a_parVars)
Definition RTree.h:1370
bool IsNull(Iterator &a_it)
Is iterator NULL, or at end?
Definition RTree.h:266
DATATYPE & GetAt(Iterator &a_it)
Get object at iterator position.
Definition RTree.h:269
ListNode * AllocListNode()
Definition RTree.h:887
void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Insert entry.
Definition RTree.h:486
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], Func &&callback) const
Find all within search rectangle.
Definition RTree.h:533
Rect CombineRect(const Rect *a_rectA, const Rect *a_rectB)
Definition RTree.h:1139
void InitRect(Rect *a_rect)
Definition RTree.h:917
void InitNode(Node *a_node)
Definition RTree.h:909
void CopyRec(Node *current, Node *other)
Definition RTree.h:692
bool LoadRec(Node *a_node, RTFileStream &a_stream)
Definition RTree.h:656
void InitParVars(PartitionVars *a_parVars, int a_maxRects, int a_minFill)
Definition RTree.h:1392
bool Overlap(Rect *a_rectA, Rect *a_rectB) const
Definition RTree.h:1572
void GetFirst(Iterator &a_it)
Get 'first' for iteration.
Definition RTree.h:240
bool Load(const char *a_fileName)
Load tree contents from file.
Definition RTree.h:588
void DisconnectBranch(Node *a_node, int a_index)
Definition RTree.h:1083
Node * AllocNode()
Definition RTree.h:858
void SplitNode(Node *a_node, const Branch *a_branch, Node **a_newNode)
Definition RTree.h:1161
ELEMTYPEREAL m_unitSphereVolume
Unit sphere constant for required number of dimensions.
Definition RTree.h:366
void PickSeeds(PartitionVars *a_parVars)
Definition RTree.h:1408
bool InsertRectRec(const Branch &a_branch, Node *a_node, Node **a_newNode, int a_level)
Definition RTree.h:935
ELEMTYPEREAL RectVolume(Rect *a_rect)
Definition RTree.h:1190
#define NULL
Definition istd.h:74
May be data or may be another subtree The parents level determines this.
Definition RTree.h:284
Rect m_rect
Bounds.
Definition RTree.h:285
Node * m_child
Child node.
Definition RTree.h:286
DATATYPE m_data
Data Id.
Definition RTree.h:287
A link list of nodes for reinsertion after a delete operation.
Definition RTree.h:303
ListNode * m_next
Next in list.
Definition RTree.h:304
Node * m_node
Node.
Definition RTree.h:305
Node for each branch level.
Definition RTree.h:292
bool IsLeaf()
Definition RTree.h:294
bool IsInternalNode()
Definition RTree.h:293
int m_level
Leaf is zero, others positive.
Definition RTree.h:297
int m_count
Count.
Definition RTree.h:296
Branch m_branch[MAXNODES]
Branch.
Definition RTree.h:298
Variables for finding a split partition.
Definition RTree.h:310
int m_partition[MAXNODES+1]
Definition RTree.h:313
Branch m_branchBuf[MAXNODES+1]
Definition RTree.h:320
ELEMTYPEREAL m_area[2]
Definition RTree.h:318
ELEMTYPEREAL m_coverSplitArea
Definition RTree.h:323
Minimal bounding rectangle (n-dimensional)
Definition RTree.h:275
ELEMTYPE m_min[NUMDIMS]
Min dimensions of bounding box.
Definition RTree.h:276
ELEMTYPE m_max[NUMDIMS]
Max dimensions of bounding box.
Definition RTree.h:277