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