LCOV - code coverage report
Current view: top level - src/foreign/rtree - RTree.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 204 204
Test Date: 2025-05-22 15:35:27 Functions: 72.7 % 77 56

            Line data    Source code
       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
      39              : class RTFileStream;  // File I/O helper class, look below for implementation and notes.
      40              : #endif
      41              : 
      42              : 
      43              : /// \class RTree
      44              : /// Implementation of RTree, a multidimensional bounding rectangle tree.
      45              : /// Example usage: For a 3-dimensional tree use RTree<Object*, float, 3> myTree;
      46              : ///
      47              : /// This modified, templated C++ version by Greg Douglas at Auran (http://www.auran.com)
      48              : ///
      49              : /// DATATYPE Referenced data, should be int, void*, obj* etc. no larger than sizeof<void*> and simple type
      50              : /// ELEMTYPE Type of element such as int or float
      51              : /// NUMDIMS Number of dimensions such as 2 or 3
      52              : /// ELEMTYPEREAL Type of element that allows fractional and large values such as float or double, for use in volume calcs
      53              : ///
      54              : /// NOTES: Inserting and removing data requires the knowledge of its constant Minimal Bounding Rectangle.
      55              : ///        This version uses new/delete for nodes, I recommend using a fixed size allocator for efficiency.
      56              : ///        Instead of using a callback function for returned results, I recommend and efficient pre-sized, grow-only memory
      57              : ///        array similar to MFC CArray or STL Vector for returning search query result.
      58              : ///
      59              : template<class DATATYPE, class DATATYPENP, class ELEMTYPE, int NUMDIMS, class CONTEXT,
      60              :          class ELEMTYPEREAL = ELEMTYPE, int TMAXNODES = 8, int TMINNODES = TMAXNODES / 2>
      61              : class RTree
      62              : {
      63              : protected:
      64              : 
      65              :   struct Node;  // Fwd decl.  Used by other internal structs and iterator
      66              : 
      67              : public:
      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,                         ///< Max elements in node
      74              :     MINNODES = TMINNODES                         ///< Min elements in node
      75              :   };
      76              : 
      77              : 
      78              : public:
      79              :   typedef void(DATATYPENP::* Operation)(const CONTEXT &) const;
      80              : 
      81              :   RTree(Operation operation);
      82              :   virtual ~RTree();
      83              : 
      84              :   /// Insert entry
      85              :   /// \param a_min Min of bounding rect
      86              :   /// \param a_max Max of bounding rect
      87              :   /// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
      88              :   virtual void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
      89              : 
      90              :   /// Remove entry
      91              :   /// \param a_min Min of bounding rect
      92              :   /// \param a_max Max of bounding rect
      93              :   /// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
      94              :   virtual void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE& a_dataId);
      95              : 
      96              : 
      97              :   /// DK 15.10.2008 - begin
      98              :   //typedef void(DATATYPENP::* Operation)(const CONTEXT &) const;
      99              : 
     100              :   /// Find all within search rectangle
     101              :   /// \param a_min Min of search bounding rect
     102              :   /// \param a_max Max of search bounding rect
     103              :   /// \param a_searchResult Search result array.  Caller should set grow size. Function will reset, not append to array.
     104              :   /// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
     105              :   /// \param a_context User context to pass as parameter to a_resultCallback
     106              :   /// \return Returns the number of entries found
     107              :   virtual int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const CONTEXT &c) const;
     108              : 
     109              :   /// DK 15.10.2008 - end
     110              : 
     111              :   /// Remove all entries from tree
     112              :   void RemoveAll();
     113              : 
     114              :   /// Count the data elements in this container.  This is slow as no internal counter is maintained.
     115              :   int Count();
     116              : 
     117              : #ifdef RTREE_WANTS_IO
     118              :   /// Load tree contents from file
     119              :   bool Load(const char* a_fileName);
     120              :   /// Load tree contents from stream
     121              :   bool Load(RTFileStream& a_stream);
     122              : 
     123              : 
     124              :   /// Save tree contents to file
     125              :   bool Save(const char* a_fileName);
     126              :   /// Save tree contents to stream
     127              :   bool Save(RTFileStream& a_stream);
     128              : #endif
     129              : 
     130              :   /// Iterator is not remove safe.
     131              :   class Iterator
     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              : 
     137              :     struct StackElement
     138              :     {
     139              :       Node* m_node;
     140              :       int m_branchIndex;
     141              :     };
     142              : 
     143              :   public:
     144              : 
     145              :     Iterator()                                    { Init(); }
     146              : 
     147              :     ~Iterator()                                   { }
     148              : 
     149              :     /// Is iterator invalid
     150              :     bool IsNull()                                 { return (m_tos <= 0); }
     151              : 
     152              :     /// Is iterator pointing to valid data
     153              :     bool IsNotNull()                              { return (m_tos > 0); }
     154              : 
     155              :     /// Access the current data element. Caller must be sure iterator is not NULL first.
     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              : 
     163              :     /// Access the current data element. Caller must be sure iterator is not NULL first.
     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              : 
     171              :     /// Find the next data element
     172              :     bool operator++()                             { return FindNextData(); }
     173              : 
     174              :   private:
     175              : 
     176              :     /// Reset iterator
     177              :     void Init()                                   { m_tos = 0; }
     178              : 
     179              :     /// Find the next data element in the tree (For internal use only)
     180              :     bool FindNextData()
     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              : 
     222              :     /// Push node and branch onto iteration stack (For internal use only)
     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;
     228              :       ASSERT(m_tos <= MAX_STACK);
     229              :     }
     230              : 
     231              :     /// Pop element off iteration stack (For internal use only)
     232              :     StackElement& Pop()
     233              :     {
     234              :       ASSERT(m_tos > 0);
     235              :       --m_tos;
     236              :       return m_stack[m_tos];
     237              :     }
     238              : 
     239              :     StackElement m_stack[MAX_STACK];              ///< Stack as we are doing iteration instead of recursion
     240              :     int m_tos;                                    ///< Top Of Stack index
     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              : 
     245              :   /// Get 'first' for iteration
     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              : 
     256              :   /// Get Next for iteration
     257              :   void GetNext(Iterator& a_it)                    { ++a_it; }
     258              : 
     259              :   /// Is iterator NULL, or at end?
     260              :   bool IsNull(Iterator& a_it)                     { return a_it.IsNull(); }
     261              : 
     262              :   /// Get object at iterator position
     263              :   DATATYPE& GetAt(Iterator& a_it)                 { return *a_it; }
     264              : 
     265              : protected:
     266              : 
     267              :   /// Minimal bounding rectangle (n-dimensional)
     268              :   struct Rect
     269              :   {
     270              :     ELEMTYPE m_min[NUMDIMS];                      ///< Min dimensions of bounding box
     271              :     ELEMTYPE m_max[NUMDIMS];                      ///< Max dimensions of bounding box
     272              :   };
     273              : 
     274              :   /// May be data or may be another subtree
     275              :   /// The parents level determines this.
     276              :   /// If the parents level is 0, then this is data
     277              :   struct Branch
     278              :   {
     279              :     Rect m_rect;                                  ///< Bounds
     280              :     union
     281              :     {
     282              :       Node* m_child;                              ///< Child node
     283              :       DATATYPE m_data;                            ///< Data Id or Ptr
     284              :     };
     285              :   };
     286              : 
     287              :   /// Node for each branch level
     288              :   struct Node
     289              :   {
     290      9847691 :     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              : 
     293              :     int m_count;                                  ///< Count
     294              :     int m_level;                                  ///< Leaf is zero, others positive
     295              :     Branch m_branch[MAXNODES];                    ///< Branch
     296              :   };
     297              : 
     298              :   /// A link list of nodes for reinsertion after a delete operation
     299              :   struct ListNode
     300              :   {
     301              :     ListNode* m_next;                             ///< Next in list
     302              :     Node* m_node;                                 ///< Node
     303              :   };
     304              : 
     305              :   /// Variables for finding a split partition
     306              :   struct PartitionVars
     307              :   {
     308              :     int m_partition[MAXNODES+1];
     309              :     int m_total;
     310              :     int m_minFill;
     311              :     int m_taken[MAXNODES+1];
     312              :     int m_count[2];
     313              :     Rect m_cover[2];
     314              :     ELEMTYPEREAL m_area[2];
     315              : 
     316              :     Branch m_branchBuf[MAXNODES+1];
     317              :     int m_branchCount;
     318              :     Rect m_coverSplit;
     319              :     ELEMTYPEREAL m_coverSplitArea;
     320              :   };
     321              : 
     322              :   Node* AllocNode();
     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);
     328              :   Rect NodeCover(Node* a_node);
     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);
     345              :   ListNode* AllocListNode();
     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              : 
     359              :   Node* m_root;                                    ///< Root of tree
     360              :   ELEMTYPEREAL m_unitSphereVolume;                 ///< Unit sphere constant for required number of dimensions
     361              :   Operation myOperation;
     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.
     368              : class RTFileStream
     369              : {
     370              :   FILE* m_file;
     371              : 
     372              : public:
     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              : 
     445              : RTREE_TEMPLATE
     446       218206 : RTREE_QUAL::RTree(Operation operation)
     447       218206 : : myOperation(operation)
     448              : {
     449              :   ASSERT(MAXNODES > MINNODES);
     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       218206 :   m_root = AllocNode();
     469       218206 :   m_root->m_level = 0;
     470       218206 :   m_unitSphereVolume = (ELEMTYPEREAL)UNIT_SPHERE_VOLUMES[NUMDIMS];
     471              : }
     472              : 
     473              : 
     474              : RTREE_TEMPLATE
     475          555 : RTREE_QUAL::~RTree()
     476              : {
     477              :   Reset(); // Free, or reset node memory
     478       215184 : }
     479              : 
     480              : 
     481              : RTREE_TEMPLATE
     482       741056 : void 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      2223168 :   for(int axis=0; axis<NUMDIMS; ++axis)
     494              :   {
     495      1482112 :     rect.m_min[axis] = a_min[axis];
     496      1482112 :     rect.m_max[axis] = a_max[axis];
     497              :   }
     498              : 
     499       741056 :   InsertRect(&rect, a_dataId, &m_root, 0);
     500       741056 : }
     501              : 
     502              : 
     503              : RTREE_TEMPLATE
     504        14351 : void 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        43053 :   for(int axis=0; axis<NUMDIMS; ++axis)
     516              :   {
     517        28702 :     rect.m_min[axis] = a_min[axis];
     518        28702 :     rect.m_max[axis] = a_max[axis];
     519              :   }
     520              : 
     521        14351 :   RemoveRect(&rect, a_dataId, &m_root);
     522        14351 : }
     523              : 
     524              : 
     525              : 
     526              : RTREE_TEMPLATE
     527      1843201 : int 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      5529603 :   for(int axis=0; axis<NUMDIMS; ++axis)
     539              :   {
     540      3686402 :     rect.m_min[axis] = a_min[axis];
     541      3686402 :     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      1843201 :   int foundCount = 0;
     547      1843201 :   Search(m_root, &rect, foundCount, c);
     548              : 
     549      1843200 :   return foundCount;
     550              : }
     551              : 
     552              : 
     553              : 
     554              : 
     555              : 
     556              : 
     557              : RTREE_TEMPLATE
     558              : int RTREE_QUAL::Count()
     559              : {
     560              :   int count = 0;
     561              :   CountRec(m_root, count);
     562              : 
     563              :   return count;
     564              : }
     565              : 
     566              : 
     567              : 
     568              : RTREE_TEMPLATE
     569              : void 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
     586              : RTREE_TEMPLATE
     587              : bool 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              : 
     606              : RTREE_TEMPLATE
     607              : bool 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              : 
     654              : RTREE_TEMPLATE
     655              : bool 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              : 
     690              : RTREE_TEMPLATE
     691              : bool 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              : 
     707              : RTREE_TEMPLATE
     708              : bool 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              : 
     734              : RTREE_TEMPLATE
     735              : bool 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              : 
     770              : RTREE_TEMPLATE
     771        41194 : void RTREE_QUAL::RemoveAll()
     772              : {
     773              :   // Delete all existing nodes
     774              :   Reset();
     775              : 
     776        41194 :   m_root = AllocNode();
     777        41194 :   m_root->m_level = 0;
     778        41194 : }
     779              : 
     780              : 
     781              : RTREE_TEMPLATE
     782              : void RTREE_QUAL::Reset()
     783              : {
     784              : #ifdef RTREE_DONT_USE_MEMPOOLS
     785              :   // Delete all existing nodes
     786       256378 :   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              : 
     794              : RTREE_TEMPLATE
     795       364718 : void RTREE_QUAL::RemoveAllRec(Node* a_node)
     796              : {
     797              :   ASSERT(a_node);
     798              :   ASSERT(a_node->m_level >= 0);
     799              : 
     800       364718 :   if(a_node->IsInternalNode()) // This is an internal node in the tree
     801              :   {
     802       131677 :     for(int index=0; index < a_node->m_count; ++index)
     803              :     {
     804       108340 :       RemoveAllRec(a_node->m_branch[index].m_child);
     805              :     }
     806              :   }
     807              :   FreeNode(a_node);
     808       364718 : }
     809              : 
     810              : 
     811              : RTREE_TEMPLATE
     812              : typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
     813              : {
     814              :   Node* newNode;
     815              : #ifdef RTREE_DONT_USE_MEMPOOLS
     816       371876 :   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              : 
     825              : RTREE_TEMPLATE
     826              : void RTREE_QUAL::FreeNode(Node* a_node)
     827              : {
     828              :   ASSERT(a_node);
     829              : 
     830              : #ifdef RTREE_DONT_USE_MEMPOOLS
     831       368440 :   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.
     840              : RTREE_TEMPLATE
     841              : typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
     842              : {
     843              : #ifdef RTREE_DONT_USE_MEMPOOLS
     844         3722 :   return new ListNode;
     845              : #else // RTREE_DONT_USE_MEMPOOLS
     846              :   // EXAMPLE
     847              : #endif // RTREE_DONT_USE_MEMPOOLS
     848              : }
     849              : 
     850              : 
     851              : RTREE_TEMPLATE
     852              : void RTREE_QUAL::FreeListNode(ListNode* a_listNode)
     853              : {
     854              : #ifdef RTREE_DONT_USE_MEMPOOLS
     855         3722 :   delete a_listNode;
     856              : #else // RTREE_DONT_USE_MEMPOOLS
     857              :   // EXAMPLE
     858              : #endif // RTREE_DONT_USE_MEMPOOLS
     859         3722 : }
     860              : 
     861              : 
     862              : RTREE_TEMPLATE
     863              : void RTREE_QUAL::InitNode(Node* a_node)
     864              : {
     865       243875 :   a_node->m_count = 0;
     866       112476 :   a_node->m_level = -1;
     867              : }
     868              : 
     869              : 
     870              : RTREE_TEMPLATE
     871              : void RTREE_QUAL::InitRect(Rect* a_rect)
     872              : {
     873       689553 :   for(int index = 0; index < NUMDIMS; ++index)
     874              :   {
     875       459702 :     a_rect->m_min[index] = (ELEMTYPE)0;
     876       459702 :     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.
     888              : RTREE_TEMPLATE
     889      1648339 : bool 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      1648339 :   if(a_node->m_level > a_level)
     900              :   {
     901       896117 :     index = PickBranch(a_rect, a_node);
     902       896117 :     if (!InsertRectRec(a_rect, a_id, a_node->m_branch[index].m_child, &otherNode, a_level))
     903              :     {
     904              :       // Child was not split
     905       810713 :       a_node->m_branch[index].m_rect = CombineRect(a_rect, &(a_node->m_branch[index].m_rect));
     906       810713 :       return false;
     907              :     }
     908              :     else // Child was split
     909              :     {
     910        85404 :       a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
     911        85404 :       branch.m_child = otherNode;
     912        85404 :       branch.m_rect = NodeCover(otherNode);
     913              :       return AddBranch(&branch, a_node, a_newNode);
     914              :     }
     915              :   }
     916       752222 :   else if(a_node->m_level == a_level) // Have reached level for insertion. Add rect, split if necessary
     917              :   {
     918       752222 :     branch.m_rect = *a_rect;
     919       752222 :     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              : //
     939              : RTREE_TEMPLATE
     940       752222 : bool 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       752222 :   if(InsertRectRec(a_rect, a_id, *a_root, &newNode, a_level))  // Root split
     956              :   {
     957              :     newRoot = AllocNode();  // Grow tree taller and new root
     958        13536 :     newRoot->m_level = (*a_root)->m_level + 1;
     959        13536 :     branch.m_rect = NodeCover(*a_root);
     960        13536 :     branch.m_child = *a_root;
     961              :     AddBranch(&branch, newRoot, NULL);
     962        13536 :     branch.m_rect = NodeCover(newNode);
     963        13536 :     branch.m_child = newNode;
     964              :     AddBranch(&branch, newRoot, NULL);
     965        13536 :     *a_root = newRoot;
     966        13536 :     return true;
     967              :   }
     968              : 
     969              :   return false;
     970              : }
     971              : 
     972              : 
     973              : // Find the smallest rectangle that includes all rectangles in branches of a node.
     974              : RTREE_TEMPLATE
     975       229851 : typename 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      1292190 :   for(int index = 0; index < a_node->m_count; ++index)
     984              :   {
     985      1062339 :     if(firstTime)
     986              :     {
     987       229851 :       rect = a_node->m_branch[index].m_rect;
     988              :       firstTime = false;
     989              :     }
     990              :     else
     991              :     {
     992       832488 :       rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
     993              :     }
     994              :   }
     995              : 
     996       229851 :   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.
    1004              : RTREE_TEMPLATE
    1005              : bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
    1006              : {
    1007              :   ASSERT(a_branch);
    1008              :   ASSERT(a_node);
    1009              : 
    1010       837626 :   if(a_node->m_count < MAXNODES)  // Split won't be necessary
    1011              :   {
    1012      1642682 :     a_node->m_branch[a_node->m_count] = *a_branch;
    1013        13536 :     ++a_node->m_count;
    1014              : 
    1015      1629146 :     return false;
    1016              :   }
    1017              :   else
    1018              :   {
    1019              :     ASSERT(a_newNode);
    1020              : 
    1021        98940 :     SplitNode(a_node, a_branch, a_newNode);
    1022        98940 :     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
    1029              : RTREE_TEMPLATE
    1030              : void 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        17907 :   a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
    1037              : 
    1038        17907 :   --a_node->m_count;
    1039         3722 : }
    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.
    1047              : RTREE_TEMPLATE
    1048       896117 : int 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      5318391 :   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      4422274 :     increase = CalcRectVolume(&tempRect) - area;
    1066      4422274 :     if((increase < bestIncr) || firstTime)
    1067              :     {
    1068              :       best = index;
    1069              :       bestArea = area;
    1070              :       bestIncr = increase;
    1071              :       firstTime = false;
    1072              :     }
    1073      2102012 :     else if((increase == bestIncr) && (area < bestArea))
    1074              :     {
    1075              :       best = index;
    1076              :       bestArea = area;
    1077              :       bestIncr = increase;
    1078              :     }
    1079              :   }
    1080       896117 :   return best;
    1081              : }
    1082              : 
    1083              : 
    1084              : // Combine two rectangles into larger one containing both
    1085              : RTREE_TEMPLATE
    1086              : typename 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.
    1107              : RTREE_TEMPLATE
    1108        98940 : void 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        98940 :   level = a_node->m_level;
    1120        98940 :   GetBranches(a_node, a_branch, parVars);
    1121              : 
    1122              :   // Find partition
    1123        98940 :   ChoosePartition(parVars, MINNODES);
    1124              : 
    1125              :   // Put branches from buffer into 2 nodes according to chosen partition
    1126        98940 :   *a_newNode = AllocNode();
    1127        98940 :   (*a_newNode)->m_level = a_node->m_level = level;
    1128        98940 :   LoadNodes(a_node, *a_newNode, parVars);
    1129              : 
    1130              :   ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
    1131        98940 : }
    1132              : 
    1133              : 
    1134              : // Calculate the n-dimensional volume of a rectangle
    1135              : RTREE_TEMPLATE
    1136              : ELEMTYPEREAL 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
    1154              : RTREE_TEMPLATE
    1155              : ELEMTYPEREAL 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
    1187              : RTREE_TEMPLATE
    1188              : ELEMTYPEREAL 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.
    1199              : RTREE_TEMPLATE
    1200        98940 : void 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       890460 :   for(index=0; index < MAXNODES; ++index)
    1210              :   {
    1211       791520 :     a_parVars->m_branchBuf[index] = a_node->m_branch[index];
    1212              :   }
    1213        98940 :   a_parVars->m_branchBuf[MAXNODES] = *a_branch;
    1214        98940 :   a_parVars->m_branchCount = MAXNODES + 1;
    1215              : 
    1216              :   // Calculate rect containing all in the set
    1217        98940 :   a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
    1218       890460 :   for(index=1; index < MAXNODES+1; ++index)
    1219              :   {
    1220       791520 :     a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
    1221              :   }
    1222        98940 :   a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
    1223              : 
    1224              :   InitNode(a_node);
    1225        98940 : }
    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.
    1239              : RTREE_TEMPLATE
    1240        98940 : void 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        98940 :   InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
    1248        98940 :   PickSeeds(a_parVars);
    1249              : 
    1250        98940 :   while (((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
    1251       581633 :        && (a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill))
    1252      1136614 :        && (a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill)))
    1253              :   {
    1254              :     biggestDiff = (ELEMTYPEREAL) -1;
    1255      4983960 :     for(int index=0; index<a_parVars->m_total; ++index)
    1256              :     {
    1257      4485564 :       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      2420590 :         ELEMTYPEREAL growth0 = CalcRectVolume(&rect0) - a_parVars->m_area[0];
    1263      2420590 :         ELEMTYPEREAL growth1 = CalcRectVolume(&rect1) - a_parVars->m_area[1];
    1264      2420590 :         ELEMTYPEREAL diff = growth1 - growth0;
    1265      2420590 :         if(diff >= 0)
    1266              :         {
    1267              :           group = 0;
    1268              :         }
    1269              :         else
    1270              :         {
    1271              :           group = 1;
    1272      1188162 :           diff = -diff;
    1273              :         }
    1274              : 
    1275      2420590 :         if(diff > biggestDiff)
    1276              :         {
    1277              :           biggestDiff = diff;
    1278              :           chosen = index;
    1279              :           betterGroup = group;
    1280              :         }
    1281      1367715 :         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       498396 :     Classify(chosen, betterGroup, a_parVars);
    1289              :   }
    1290              : 
    1291              :   // If one group too full, put remaining rects in the other
    1292        98940 :   if((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
    1293              :   {
    1294        83237 :     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       832370 :     for(int index=0; index<a_parVars->m_total; ++index)
    1303              :     {
    1304       749133 :       if(!a_parVars->m_taken[index])
    1305              :       {
    1306       194184 :         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        98940 : }
    1315              : 
    1316              : 
    1317              : // Copy branches from the buffer into two nodes according to the partition.
    1318              : RTREE_TEMPLATE
    1319        98940 : void 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       989400 :   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       890460 :     if(a_parVars->m_partition[index] == 0)
    1330              :     {
    1331       447521 :       AddBranch(&a_parVars->m_branchBuf[index], a_nodeA, NULL);
    1332              :     }
    1333       442939 :     else if(a_parVars->m_partition[index] == 1)
    1334              :     {
    1335       442939 :       AddBranch(&a_parVars->m_branchBuf[index], a_nodeB, NULL);
    1336              :     }
    1337              :   }
    1338        98940 : }
    1339              : 
    1340              : 
    1341              : // Initialize a PartitionVars structure.
    1342              : RTREE_TEMPLATE
    1343              : void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill)
    1344              : {
    1345              :   ASSERT(a_parVars);
    1346              : 
    1347        98940 :   a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
    1348        98940 :   a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
    1349        98940 :   a_parVars->m_total = a_maxRects;
    1350        98940 :   a_parVars->m_minFill = a_minFill;
    1351       989400 :   for(int index=0; index < a_maxRects; ++index)
    1352              :   {
    1353       890460 :     a_parVars->m_taken[index] = false;
    1354       890460 :     a_parVars->m_partition[index] = -1;
    1355              :   }
    1356              : }
    1357              : 
    1358              : 
    1359              : RTREE_TEMPLATE
    1360        98940 : void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
    1361              : {
    1362              :   int seed0=0, seed1=1;
    1363              :   ELEMTYPEREAL worst, waste;
    1364              :   ELEMTYPEREAL area[MAXNODES+1];
    1365              : 
    1366       989400 :   for(int index=0; index<a_parVars->m_total; ++index)
    1367              :   {
    1368       890460 :     area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
    1369              :   }
    1370              : 
    1371        98940 :   worst = -a_parVars->m_coverSplitArea - 1;
    1372       890460 :   for(int indexA=0; indexA < a_parVars->m_total-1; ++indexA)
    1373              :   {
    1374      4353360 :     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      3561840 :       waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
    1378      3561840 :       if(waste > worst)
    1379              :       {
    1380              :         worst = waste;
    1381              :         seed0 = indexA;
    1382              :         seed1 = indexB;
    1383              :       }
    1384              :     }
    1385              :   }
    1386        98940 :   Classify(seed0, 0, a_parVars);
    1387        98940 :   Classify(seed1, 1, a_parVars);
    1388        98940 : }
    1389              : 
    1390              : 
    1391              : // Put a branch in one of the groups.
    1392              : RTREE_TEMPLATE
    1393       890460 : void 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       890460 :   a_parVars->m_partition[a_index] = a_group;
    1399       890460 :   a_parVars->m_taken[a_index] = true;
    1400              : 
    1401       890460 :   if (a_parVars->m_count[a_group] == 0)
    1402              :   {
    1403       197880 :     a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
    1404              :   }
    1405              :   else
    1406              :   {
    1407       692580 :     a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
    1408              :   }
    1409       890460 :   a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
    1410       890460 :   ++a_parVars->m_count[a_group];
    1411       890460 : }
    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.
    1418              : RTREE_TEMPLATE
    1419        14351 : bool 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        14351 :   ListNode* reInsertList = NULL;
    1426              : 
    1427        14351 :   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        17907 :     while(reInsertList)
    1432              :     {
    1433         3722 :       tempNode = reInsertList->m_node;
    1434              : 
    1435        14888 :       for(int index = 0; index < tempNode->m_count; ++index)
    1436              :       {
    1437        11166 :         InsertRect(&(tempNode->m_branch[index].m_rect),
    1438        11166 :                    tempNode->m_branch[index].m_data,
    1439              :                    a_root,
    1440              :                    tempNode->m_level);
    1441              :       }
    1442              : 
    1443         3722 :       ListNode* remLNode = reInsertList;
    1444         3722 :       reInsertList = reInsertList->m_next;
    1445              : 
    1446         3722 :       FreeNode(remLNode->m_node);
    1447              :       FreeListNode(remLNode);
    1448              :     }
    1449              : 
    1450              :     // Check for redundant root (not leaf, 1 child) and eliminate
    1451        14185 :     if((*a_root)->m_count == 1 && (*a_root)->IsInternalNode())
    1452              :     {
    1453          178 :       tempNode = (*a_root)->m_branch[0].m_child;
    1454              : 
    1455              :       ASSERT(tempNode);
    1456              :       FreeNode(*a_root);
    1457          178 :       *a_root = tempNode;
    1458              :     }
    1459        14185 :     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.
    1472              : RTREE_TEMPLATE
    1473        59868 : bool 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        59868 :   if(a_node->IsInternalNode())  // not a leaf node
    1479              :   {
    1480       157725 :     for(int index = 0; index < a_node->m_count; ++index)
    1481              :     {
    1482       149422 :       if(Overlap(a_rect, &(a_node->m_branch[index].m_rect)))
    1483              :       {
    1484        45517 :         if(!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode))
    1485              :         {
    1486        35693 :           if(a_node->m_branch[index].m_child->m_count >= MINNODES)
    1487              :           {
    1488              :             // child removed, just resize parent rect
    1489        31971 :             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        35693 :           return false;
    1498              :         }
    1499              :       }
    1500              :     }
    1501              :     return true;
    1502              :   }
    1503              :   else // A leaf node
    1504              :   {
    1505        62322 :     for(int index = 0; index < a_node->m_count; ++index)
    1506              :     {
    1507        60635 :       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        14185 :         return false;
    1511              :       }
    1512              :     }
    1513              :     return true;
    1514              :   }
    1515              : }
    1516              : 
    1517              : 
    1518              : // Decide whether two rectangles overlap.
    1519              : RTREE_TEMPLATE
    1520              : bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB) const
    1521              : {
    1522              :   ASSERT(a_rectA && a_rectB);
    1523              : 
    1524    143682907 :   for(int index=0; index < NUMDIMS; ++index)
    1525              :   {
    1526     96197052 :     if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
    1527     95821192 :         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.
    1538              : RTREE_TEMPLATE
    1539              : void RTREE_QUAL::ReInsert(Node* a_node, ListNode** a_listNode)
    1540              : {
    1541              :   ListNode* newListNode;
    1542              : 
    1543              :   newListNode = AllocListNode();
    1544         3722 :   newListNode->m_node = a_node;
    1545         3722 :   newListNode->m_next = *a_listNode;
    1546         3722 :   *a_listNode = newListNode;
    1547              : }
    1548              : 
    1549              : 
    1550              : 
    1551              : // Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
    1552              : RTREE_TEMPLATE
    1553      9422916 : bool 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      9422916 :   if(a_node->IsInternalNode()) // This is an internal node in the tree
    1560              :   {
    1561      9646373 :     for(int index=0; index < a_node->m_count; ++index)
    1562              :     {
    1563      7800661 :       if(Overlap(a_rect, &a_node->m_branch[index].m_rect))
    1564              :       {
    1565      7579715 :         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     47958125 :     for(int index=0; index < a_node->m_count; ++index)
    1575              :     {
    1576     40380924 :       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     39860623 :           ++a_foundCount;
    1584     39860623 :           (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
        

Generated by: LCOV version 2.0-1