LCOV - code coverage report
Current view: top level - home/lbartoletti/qgis_coverage_src/external/rtree/include - RTree.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 408 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : //
       2                 :            : // RTree.h
       3                 :            : //
       4                 :            : #ifndef RTREE_H
       5                 :            : #define RTREE_H
       6                 :            : 
       7                 :            : #include <cassert>
       8                 :            : #include <algorithm>
       9                 :            : #include <functional>
      10                 :            : #include <type_traits>
      11                 :            : #include <cmath>
      12                 :            : 
      13                 :            : #define RTreeAssert assert // RTree uses RTreeAssert( condition )
      14                 :            : 
      15                 :            : 
      16                 :            : #define RTREE_DONT_USE_MEMPOOLS         // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one.
      17                 :            : #define RTREE_USE_SPHERICAL_VOLUME      // Better split classification, may be slower on some systems
      18                 :            : 
      19                 :            : 
      20                 :            : // Because there is not stream support, this is a quick and dirty file I/O helper.
      21                 :            : // Users will likely replace its usage with a Stream implementation from their favorite API.
      22                 :            : class RTFileStream {
      23                 :            : public:
      24                 :            :     RTFileStream() = default;
      25                 :            : 
      26                 :            :     ~RTFileStream() {
      27                 :            :         Close();
      28                 :            :     }
      29                 :            : 
      30                 :            :     bool OpenRead(const char* a_fileName) {
      31                 :            :         m_file = fopen(a_fileName, "rb");
      32                 :            :         if (!m_file) {
      33                 :            :             return false;
      34                 :            :         }
      35                 :            :         return true;
      36                 :            :     }
      37                 :            : 
      38                 :            :     bool OpenWrite(const char* a_fileName) {
      39                 :            :         m_file = fopen(a_fileName, "wb");
      40                 :            :         if (!m_file) {
      41                 :            :             return false;
      42                 :            :         }
      43                 :            :         return true;
      44                 :            :     }
      45                 :            : 
      46                 :            :     void Close() {
      47                 :            :         if (m_file) {
      48                 :            :             fclose(m_file);
      49                 :            :             m_file = nullptr;
      50                 :            :         }
      51                 :            :     }
      52                 :            : 
      53                 :            :     template< typename TYPE >
      54                 :            :     size_t Write(const TYPE& a_value) {
      55                 :            :         RTreeAssert(m_file);
      56                 :            :         return fwrite((void*)&a_value, sizeof(a_value), 1, m_file);
      57                 :            :     }
      58                 :            : 
      59                 :            :     template< typename TYPE >
      60                 :            :     size_t WriteArray(const TYPE* a_array, int a_count) {
      61                 :            :         RTreeAssert(m_file);
      62                 :            :         return fwrite((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
      63                 :            :     }
      64                 :            : 
      65                 :            :     template< typename TYPE >
      66                 :            :     size_t Read(TYPE& a_value) {
      67                 :            :         RTreeAssert(m_file);
      68                 :            :         return fread((void*)&a_value, sizeof(a_value), 1, m_file);
      69                 :            :     }
      70                 :            : 
      71                 :            :     template< typename TYPE >
      72                 :            :     size_t ReadArray(TYPE* a_array, int a_count) {
      73                 :            :         RTreeAssert(m_file);
      74                 :            :         return fread((void*)a_array, sizeof(TYPE) * a_count, 1, m_file);
      75                 :            :     }
      76                 :            : 
      77                 :            : private:
      78                 :            :     FILE* m_file = nullptr;
      79                 :            : };
      80                 :            : 
      81                 :            : 
      82                 :            : /// \class RTree
      83                 :            : /// Implementation of RTree, a multidimensional bounding rectangle tree.
      84                 :            : /// Example usage: For a 3-dimensional tree use RTree<Object*, float, 3> myTree;
      85                 :            : ///
      86                 :            : /// This modified, templated C++ version by Greg Douglas at Auran (http://www.auran.com)
      87                 :            : ///
      88                 :            : /// _DataType Referenced data, should be int, void*, obj* etc. no larger than sizeof<void*> and simple type
      89                 :            : /// _ElementType Type of element such as int or float
      90                 :            : /// _NumDimensions Number of dimensions such as 2 or 3
      91                 :            : /// _ElementTypeReal Type of element that allows fractional and large values such as float or double, for use in volume calcs
      92                 :            : ///
      93                 :            : /// NOTES: Inserting and removing data requires the knowledge of its constant Minimal Bounding Rectangle.
      94                 :            : ///        This version uses new/delete for nodes, I recommend using a fixed size allocator for efficiency.
      95                 :            : ///        Instead of using a callback function for returned results, I recommend and efficient pre-sized, grow-only memory
      96                 :            : ///        array similar to MFC CArray or STL Vector for returning search query result.
      97                 :            : ///
      98                 :            : template<class _DataType, class _ElementType, int _NumDimensions, 
      99                 :            :     class _ElementTypeReal = _ElementType, int _MaxNodeCount = 8, int _MinNodeCount = _MaxNodeCount / 2>
     100                 :            : class RTree
     101                 :            : {
     102                 :            :     static_assert(1 < _NumDimensions, "_NumDimensions must be larger than 1");
     103                 :            :     static_assert(0 < _MinNodeCount, "_MinNodeCount must be larger than 0");
     104                 :            :     static_assert(_MinNodeCount < _MaxNodeCount, "_MaxNodeCount must be larger than _MinNodeCount");
     105                 :            :     static_assert(std::is_floating_point<_ElementTypeReal>::value, "_ElementTypeReal must be floating point type");
     106                 :            : protected:
     107                 :            : 
     108                 :            :     struct Node;  // Fwd decl.  Used by other internal structs and iterator
     109                 :            : 
     110                 :            : public:
     111                 :            :     using DataType = _DataType;
     112                 :            :     using ElementType = _ElementType;
     113                 :            :     using ElementTypeReal = _ElementTypeReal;
     114                 :            :     using Element = ElementType[_NumDimensions];
     115                 :            : 
     116                 :            :     constexpr static const int kNumDimensions = _NumDimensions;
     117                 :            :     constexpr static const int kMaxNodeCount = _MaxNodeCount;
     118                 :            :     constexpr static const int kMinNodeCount = _MinNodeCount;
     119                 :            : 
     120                 :            :     template<typename ValueType>
     121                 :            :     constexpr static ElementType CastElementType(const ValueType val) noexcept {
     122                 :            :         return static_cast<ElementType>(val);
     123                 :            :     }
     124                 :            :     template<typename ValueType>
     125                 :          0 :     constexpr static ElementTypeReal CastElementTypeReal(const ValueType val) noexcept {
     126                 :          0 :         return static_cast<ElementTypeReal>(val);
     127                 :            :     }
     128                 :            :     constexpr static const ElementTypeReal kElementTypeRealOne = CastElementTypeReal(1.0);
     129                 :            :     constexpr static const ElementTypeReal kElementTypeRealZero = CastElementTypeReal(0.0);
     130                 :            : 
     131                 :          0 :     RTree() {
     132                 :            :         // Precomputed volumes of the unit spheres for the first few dimensions
     133                 :          0 :         constexpr const ElementTypeReal kUnitSphereVolumes[] = {
     134                 :            :           CastElementTypeReal(0.000000), CastElementTypeReal(2.000000), CastElementTypeReal(3.141593), // Dimension  0,1,2
     135                 :            :           CastElementTypeReal(4.188790), CastElementTypeReal(4.934802), CastElementTypeReal(5.263789), // Dimension  3,4,5
     136                 :            :           CastElementTypeReal(5.167713), CastElementTypeReal(4.724766), CastElementTypeReal(4.058712), // Dimension  6,7,8
     137                 :            :           CastElementTypeReal(3.298509), CastElementTypeReal(2.550164), CastElementTypeReal(1.884104), // Dimension  9,10,11
     138                 :            :           CastElementTypeReal(1.335263), CastElementTypeReal(0.910629), CastElementTypeReal(0.599265), // Dimension  12,13,14
     139                 :            :           CastElementTypeReal(0.381443), CastElementTypeReal(0.235331), CastElementTypeReal(0.140981), // Dimension  15,16,17
     140                 :            :           CastElementTypeReal(0.082146), CastElementTypeReal(0.046622), CastElementTypeReal(0.025807), // Dimension  18,19,20 
     141                 :            :         };
     142                 :            : 
     143                 :          0 :         this->m_root = this->AllocNode();
     144                 :          0 :         this->m_root->m_level = 0;
     145                 :          0 :         this->m_unitSphereVolume = kUnitSphereVolumes[kNumDimensions];
     146                 :          0 :     }
     147                 :            : 
     148                 :            :     RTree(const RTree& other) : RTree() {
     149                 :            :         this->CopyRec(this->m_root, other.m_root);
     150                 :            :     }
     151                 :            : 
     152                 :          0 :     ~RTree() {
     153                 :          0 :         this->Reset();
     154                 :          0 :     }
     155                 :            : 
     156                 :            :     /// Insert entry
     157                 :            :     /// \param a_min Min of bounding rect
     158                 :            :     /// \param a_max Max of bounding rect
     159                 :            :     /// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
     160                 :          0 :     void Insert(const Element& a_min, const Element& a_max, const DataType& a_dataId) {
     161                 :            : #ifdef _DEBUG
     162                 :            :         for (int index = 0; index < kNumDimensions; ++index) {
     163                 :            :             RTreeAssert(a_min[index] <= a_max[index]);
     164                 :            :         }
     165                 :            : #endif //_DEBUG
     166                 :            : 
     167                 :          0 :         Branch branch;
     168                 :          0 :         branch.m_data = a_dataId;
     169                 :          0 :         branch.m_child = nullptr;
     170                 :            : 
     171                 :          0 :         for (int axis = 0; axis < kNumDimensions; ++axis) {
     172                 :          0 :             branch.m_rect.m_min[axis] = a_min[axis];
     173                 :          0 :             branch.m_rect.m_max[axis] = a_max[axis];
     174                 :          0 :         }
     175                 :            : 
     176                 :          0 :         InsertRect(branch, &m_root, 0);
     177                 :          0 :     }
     178                 :            : 
     179                 :            :     /// Remove entry
     180                 :            :     /// \param a_min Min of bounding rect
     181                 :            :     /// \param a_max Max of bounding rect
     182                 :            :     /// \param a_dataId Positive Id of data.  Maybe zero, but negative numbers not allowed.
     183                 :          0 :     void Remove(const Element& a_min, const Element& a_max, const DataType& a_dataId) {
     184                 :            : #ifdef _DEBUG
     185                 :            :         for (int index = 0; index < kNumDimensions; ++index) {
     186                 :            :             RTreeAssert(a_min[index] <= a_max[index]);
     187                 :            :         }
     188                 :            : #endif //_DEBUG
     189                 :            : 
     190                 :          0 :         Rect rect;
     191                 :            : 
     192                 :          0 :         for (int axis = 0; axis < kNumDimensions; ++axis) {
     193                 :          0 :             rect.m_min[axis] = a_min[axis];
     194                 :          0 :             rect.m_max[axis] = a_max[axis];
     195                 :          0 :         }
     196                 :            : 
     197                 :          0 :         RemoveRect(&rect, a_dataId, &m_root);
     198                 :          0 :     }
     199                 :            : 
     200                 :            :     /// Find all within search rectangle
     201                 :            :     /// \param a_min Min of search bounding rect
     202                 :            :     /// \param a_max Max of search bounding rect
     203                 :            :     /// \param a_searchResult Search result array.  Caller should set grow size. Function will reset, not append to array.
     204                 :            :     /// \param a_resultCallback Callback function to return result.  Callback should return 'true' to continue searching
     205                 :            :     /// \param a_context User context to pass as parameter to a_resultCallback
     206                 :            :     /// \return Returns the number of entries found
     207                 :          0 :     int Search(const Element& a_min, const Element& a_max, std::function<bool(const DataType&)> callback) const {
     208                 :            : #ifdef _DEBUG
     209                 :            :         for (int index = 0; index < kNumDimensions; ++index) {
     210                 :            :             RTreeAssert(a_min[index] <= a_max[index]);
     211                 :            :         }
     212                 :            : #endif //_DEBUG
     213                 :            : 
     214                 :          0 :         Rect rect;
     215                 :            : 
     216                 :          0 :         for (int axis = 0; axis < kNumDimensions; ++axis) {
     217                 :          0 :             rect.m_min[axis] = a_min[axis];
     218                 :          0 :             rect.m_max[axis] = a_max[axis];
     219                 :          0 :         }
     220                 :            : 
     221                 :            :         // NOTE: May want to return search result another way, perhaps returning the number of found elements here.
     222                 :            : 
     223                 :          0 :         int foundCount = 0;
     224                 :          0 :         Search(m_root, &rect, foundCount, callback);
     225                 :            : 
     226                 :          0 :         return foundCount;
     227                 :          0 :     }
     228                 :            : 
     229                 :            :     /// Remove all entries from tree
     230                 :            :     void RemoveAll() {
     231                 :            : 
     232                 :            :         // Delete all existing nodes
     233                 :            :         Reset();
     234                 :            : 
     235                 :            :         m_root = AllocNode();
     236                 :            :         m_root->m_level = 0;
     237                 :            :     }
     238                 :            : 
     239                 :            :     /// Count the data elements in this container.  This is slow as no internal counter is maintained.
     240                 :            :     int Count() const {
     241                 :            : 
     242                 :            :         int count = 0;
     243                 :            :         CountRec(m_root, count);
     244                 :            : 
     245                 :            :         return count;
     246                 :            :     }
     247                 :            : 
     248                 :            :     /// Load tree contents from file
     249                 :            :     bool Load(const char* a_fileName) {
     250                 :            :         RemoveAll(); // Clear existing tree
     251                 :            : 
     252                 :            :         RTFileStream stream;
     253                 :            :         if (!stream.OpenRead(a_fileName)) {
     254                 :            :             return false;
     255                 :            :         }
     256                 :            : 
     257                 :            :         bool result = Load(stream);
     258                 :            : 
     259                 :            :         stream.Close();
     260                 :            : 
     261                 :            :         return result;
     262                 :            :     }
     263                 :            :     /// Load tree contents from stream
     264                 :            :     bool Load(RTFileStream& a_stream) {
     265                 :            :         // Write some kind of header
     266                 :            :         int _dataFileId = ('R' << 0) | ('T' << 8) | ('R' << 16) | ('E' << 24);
     267                 :            :         int _dataSize = sizeof(DataType);
     268                 :            :         int _dataNumDims = kNumDimensions;
     269                 :            :         int _dataElemSize = sizeof(ElementType);
     270                 :            :         int _dataElemRealSize = sizeof(ElementTypeReal);
     271                 :            :         int _dataMaxNodes = kMaxNodeCount;
     272                 :            :         int _dataMinNodes = kMinNodeCount;
     273                 :            : 
     274                 :            :         int dataFileId = 0;
     275                 :            :         int dataSize = 0;
     276                 :            :         int dataNumDims = 0;
     277                 :            :         int dataElemSize = 0;
     278                 :            :         int dataElemRealSize = 0;
     279                 :            :         int dataMaxNodes = 0;
     280                 :            :         int dataMinNodes = 0;
     281                 :            : 
     282                 :            :         a_stream.Read(dataFileId);
     283                 :            :         a_stream.Read(dataSize);
     284                 :            :         a_stream.Read(dataNumDims);
     285                 :            :         a_stream.Read(dataElemSize);
     286                 :            :         a_stream.Read(dataElemRealSize);
     287                 :            :         a_stream.Read(dataMaxNodes);
     288                 :            :         a_stream.Read(dataMinNodes);
     289                 :            : 
     290                 :            :         bool result = false;
     291                 :            : 
     292                 :            :         // Test if header was valid and compatible
     293                 :            :         if ((dataFileId == _dataFileId)
     294                 :            :             && (dataSize == _dataSize)
     295                 :            :             && (dataNumDims == _dataNumDims)
     296                 :            :             && (dataElemSize == _dataElemSize)
     297                 :            :             && (dataElemRealSize == _dataElemRealSize)
     298                 :            :             && (dataMaxNodes == _dataMaxNodes)
     299                 :            :             && (dataMinNodes == _dataMinNodes)
     300                 :            :             ) {
     301                 :            :             // Recursively load tree
     302                 :            :             result = LoadRec(m_root, a_stream);
     303                 :            :         }
     304                 :            : 
     305                 :            :         return result;
     306                 :            :     }
     307                 :            : 
     308                 :            : 
     309                 :            :     /// Save tree contents to file
     310                 :            :     bool Save(const char* a_fileName) {
     311                 :            : 
     312                 :            :         RTFileStream stream;
     313                 :            :         if (!stream.OpenWrite(a_fileName)) {
     314                 :            :             return false;
     315                 :            :         }
     316                 :            : 
     317                 :            :         bool result = Save(stream);
     318                 :            : 
     319                 :            :         stream.Close();
     320                 :            : 
     321                 :            :         return result;
     322                 :            :     }
     323                 :            :     /// Save tree contents to stream
     324                 :            :     bool Save(RTFileStream& a_stream) {
     325                 :            : 
     326                 :            :         // Write some kind of header
     327                 :            :         int dataFileId = ('R' << 0) | ('T' << 8) | ('R' << 16) | ('E' << 24);
     328                 :            :         int dataSize = sizeof(DataType);
     329                 :            :         int dataNumDims = kNumDimensions;
     330                 :            :         int dataElemSize = sizeof(ElementType);
     331                 :            :         int dataElemRealSize = sizeof(ElementTypeReal);
     332                 :            :         int dataMaxNodes = kMaxNodeCount;
     333                 :            :         int dataMinNodes = kMinNodeCount;
     334                 :            : 
     335                 :            :         a_stream.Write(dataFileId);
     336                 :            :         a_stream.Write(dataSize);
     337                 :            :         a_stream.Write(dataNumDims);
     338                 :            :         a_stream.Write(dataElemSize);
     339                 :            :         a_stream.Write(dataElemRealSize);
     340                 :            :         a_stream.Write(dataMaxNodes);
     341                 :            :         a_stream.Write(dataMinNodes);
     342                 :            : 
     343                 :            :         // Recursively save tree
     344                 :            :         bool result = SaveRec(m_root, a_stream);
     345                 :            : 
     346                 :            :         return result;
     347                 :            :     }
     348                 :            : 
     349                 :            :     /// Iterator is not remove safe.
     350                 :            :     class Iterator
     351                 :            :     {
     352                 :            :     private:
     353                 :            : 
     354                 :            :         constexpr static const int kMaxStackSize = 32;  //  Max stack size. Allows almost n^32 where n is number of branches in node
     355                 :            : 
     356                 :            :         struct StackElement
     357                 :            :         {
     358                 :            :             Node* m_node = nullptr;
     359                 :            :             int m_branchIndex = 0;
     360                 :            :         };
     361                 :            : 
     362                 :            :     public:
     363                 :            : 
     364                 :            :         Iterator() { Init(); }
     365                 :            : 
     366                 :            :         ~Iterator() = default;
     367                 :            : 
     368                 :            :         /// Is iterator invalid
     369                 :            :         bool IsNull() const noexcept { return (m_tos <= 0); }
     370                 :            : 
     371                 :            :         /// Is iterator pointing to valid data
     372                 :            :         bool IsNotNull() const noexcept { return (m_tos > 0); }
     373                 :            : 
     374                 :            :         /// Access the current data element. Caller must be sure iterator is not NULL first.
     375                 :            :         DataType& operator*()
     376                 :            :         {
     377                 :            :             RTreeAssert(IsNotNull());
     378                 :            :             auto& curTos = m_stack[m_tos - 1];
     379                 :            :             return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
     380                 :            :         }
     381                 :            : 
     382                 :            :         /// Access the current data element. Caller must be sure iterator is not NULL first.
     383                 :            :         const DataType& operator*() const
     384                 :            :         {
     385                 :            :             RTreeAssert(IsNotNull());
     386                 :            :             auto& curTos = m_stack[m_tos - 1];
     387                 :            :             return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
     388                 :            :         }
     389                 :            : 
     390                 :            :         /// Find the next data element
     391                 :            :         bool operator++() { return FindNextData(); }
     392                 :            : 
     393                 :            :         /// Get the bounds for this node
     394                 :            :         void GetBounds(Element& a_min, Element& a_max)
     395                 :            :         {
     396                 :            :             RTreeAssert(IsNotNull());
     397                 :            :             auto& curTos = m_stack[m_tos - 1];
     398                 :            :             auto& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
     399                 :            : 
     400                 :            :             for (int index = 0; index < kNumDimensions; ++index)
     401                 :            :             {
     402                 :            :                 a_min[index] = curBranch.m_rect.m_min[index];
     403                 :            :                 a_max[index] = curBranch.m_rect.m_max[index];
     404                 :            :             }
     405                 :            :         }
     406                 :            : 
     407                 :            :     private:
     408                 :            : 
     409                 :            :         /// Reset iterator
     410                 :            :         void Init() { m_tos = 0; }
     411                 :            : 
     412                 :            :         /// Find the next data element in the tree (For internal use only)
     413                 :            :         bool FindNextData()
     414                 :            :         {
     415                 :            :             for (;;)
     416                 :            :             {
     417                 :            :                 if (m_tos <= 0)
     418                 :            :                 {
     419                 :            :                     return false;
     420                 :            :                 }
     421                 :            :                 auto curTos = Pop(); // Copy stack top cause it may change as we use it
     422                 :            : 
     423                 :            :                 if (curTos.m_node->IsLeaf())
     424                 :            :                 {
     425                 :            :                     // Keep walking through data while we can
     426                 :            :                     if (curTos.m_branchIndex + 1 < curTos.m_node->m_count)
     427                 :            :                     {
     428                 :            :                         // There is more data, just point to the next one
     429                 :            :                         Push(curTos.m_node, curTos.m_branchIndex + 1);
     430                 :            :                         return true;
     431                 :            :                     }
     432                 :            :                     // No more data, so it will fall back to previous level
     433                 :            :                 }
     434                 :            :                 else
     435                 :            :                 {
     436                 :            :                     if (curTos.m_branchIndex + 1 < curTos.m_node->m_count)
     437                 :            :                     {
     438                 :            :                         // Push sibling on for future tree walk
     439                 :            :                         // This is the 'fall back' node when we finish with the current level
     440                 :            :                         Push(curTos.m_node, curTos.m_branchIndex + 1);
     441                 :            :                     }
     442                 :            :                     // Since cur node is not a leaf, push first of next level to get deeper into the tree
     443                 :            :                     auto nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
     444                 :            :                     Push(nextLevelnode, 0);
     445                 :            : 
     446                 :            :                     // If we pushed on a new leaf, exit as the data is ready at TOS
     447                 :            :                     if (nextLevelnode->IsLeaf())
     448                 :            :                     {
     449                 :            :                         return true;
     450                 :            :                     }
     451                 :            :                 }
     452                 :            :             }
     453                 :            :         }
     454                 :            : 
     455                 :            :         /// Push node and branch onto iteration stack (For internal use only)
     456                 :            :         void Push(Node* a_node, int a_branchIndex)
     457                 :            :         {
     458                 :            :             m_stack[m_tos].m_node = a_node;
     459                 :            :             m_stack[m_tos].m_branchIndex = a_branchIndex;
     460                 :            :             ++m_tos;
     461                 :            :             RTreeAssert(m_tos <= kMaxStackSize);
     462                 :            :         }
     463                 :            : 
     464                 :            :         /// Pop element off iteration stack (For internal use only)
     465                 :            :         StackElement& Pop()
     466                 :            :         {
     467                 :            :             RTreeAssert(m_tos > 0);
     468                 :            :             --m_tos;
     469                 :            :             return m_stack[m_tos];
     470                 :            :         }
     471                 :            : 
     472                 :            :         StackElement m_stack[kMaxStackSize];          ///< Stack as we are doing iteration instead of recursion
     473                 :            :         int m_tos = 0;                                ///< Top Of Stack index
     474                 :            : 
     475                 :            :         friend class RTree; // Allow hiding of non-public functions while allowing manipulation by logical owner
     476                 :            :     };
     477                 :            : 
     478                 :            :     /// Get 'first' for iteration
     479                 :            :     void GetFirst(Iterator& a_it) const
     480                 :            :     {
     481                 :            :         a_it.Init();
     482                 :            :         auto first = m_root;
     483                 :            :         while (first)
     484                 :            :         {
     485                 :            :             if (first->IsInternalNode() && first->m_count > 1)
     486                 :            :             {
     487                 :            :                 a_it.Push(first, 1); // Descend sibling branch later
     488                 :            :             }
     489                 :            :             else if (first->IsLeaf())
     490                 :            :             {
     491                 :            :                 if (first->m_count)
     492                 :            :                 {
     493                 :            :                     a_it.Push(first, 0);
     494                 :            :                 }
     495                 :            :                 break;
     496                 :            :             }
     497                 :            :             first = first->m_branch[0].m_child;
     498                 :            :         }
     499                 :            :     }
     500                 :            : 
     501                 :            :     /// Get Next for iteration
     502                 :            :     void GetNext(Iterator& a_it) const { ++a_it; }
     503                 :            : 
     504                 :            :     /// Is iterator NULL, or at end?
     505                 :            :     bool IsNull(const Iterator& a_it) const { return a_it.IsNull(); }
     506                 :            : 
     507                 :            :     /// Get object at iterator position
     508                 :            :     DataType& GetAt(Iterator& a_it) { return *a_it; }
     509                 :            : 
     510                 :            : protected:
     511                 :            : 
     512                 :            :     /// Minimal bounding rectangle (n-dimensional)
     513                 :          0 :     struct Rect
     514                 :            :     {
     515                 :          0 :         ElementType m_min[kNumDimensions] = { 0, };                      ///< Min dimensions of bounding box 
     516                 :          0 :         ElementType m_max[kNumDimensions] = { 0, };                      ///< Max dimensions of bounding box 
     517                 :            :     };
     518                 :            : 
     519                 :            :     /// May be data or may be another subtree
     520                 :            :     /// The parents level determines this.
     521                 :            :     /// If the parents level is 0, then this is data
     522                 :          0 :     struct Branch
     523                 :            :     {
     524                 :            :         Rect m_rect;                                  ///< Bounds
     525                 :          0 :         Node* m_child = nullptr;                      ///< Child node
     526                 :            :         DataType m_data;                             ///< Data Id
     527                 :            :     };
     528                 :            : 
     529                 :            :     /// Node for each branch level
     530                 :          0 :     struct Node
     531                 :            :     {
     532                 :          0 :         bool IsInternalNode() const noexcept { return (m_level > 0); } // Not a leaf, but a internal node
     533                 :            :         bool IsLeaf() const noexcept { return (m_level == 0); }        // A leaf, contains data
     534                 :            : 
     535                 :          0 :         int m_count = 0;                              ///< Count
     536                 :          0 :         int m_level = 0;                              ///< Leaf is zero, others positive
     537                 :            :         Branch m_branch[_MaxNodeCount];               ///< Branch
     538                 :            :     };
     539                 :            : 
     540                 :            :     /// A link list of nodes for reinsertion after a delete operation
     541                 :          0 :     struct ListNode
     542                 :            :     {
     543                 :          0 :         ListNode* m_next = nullptr;                   ///< Next in list
     544                 :          0 :         Node* m_node = nullptr;                       ///< Node
     545                 :            :     };
     546                 :            : 
     547                 :            :     /// Variables for finding a split partition
     548                 :          0 :     struct PartitionVars
     549                 :            :     {
     550                 :            :         constexpr static const int kNotTaken = -1; // indicates that position
     551                 :            : 
     552                 :          0 :         int m_partition[_MaxNodeCount + 1] = { 0, };
     553                 :          0 :         int m_total = 0;
     554                 :          0 :         int m_minFill = 0;
     555                 :          0 :         int m_count[2] = { 0, };
     556                 :            :         Rect m_cover[2];
     557                 :          0 :         ElementTypeReal m_area[2] = { kElementTypeRealZero, };
     558                 :            : 
     559                 :            :         Branch m_branchBuf[_MaxNodeCount + 1];
     560                 :          0 :         int m_branchCount = 0;
     561                 :            :         Rect m_coverSplit;
     562                 :          0 :         ElementTypeReal m_coverSplitArea = kElementTypeRealZero;
     563                 :            :     };
     564                 :            : 
     565                 :          0 :     Node* AllocNode() {
     566                 :            :         Node* newNode;
     567                 :            : #ifdef RTREE_DONT_USE_MEMPOOLS
     568                 :          0 :         newNode = new Node;
     569                 :            : #else // RTREE_DONT_USE_MEMPOOLS
     570                 :            :         // EXAMPLE
     571                 :            : #endif // RTREE_DONT_USE_MEMPOOLS
     572                 :          0 :         InitNode(newNode);
     573                 :          0 :         return newNode;
     574                 :            :     }
     575                 :            : 
     576                 :          0 :     void FreeNode(Node* a_node) {
     577                 :          0 :         RTreeAssert(a_node);
     578                 :            : 
     579                 :            : #ifdef RTREE_DONT_USE_MEMPOOLS
     580                 :          0 :         delete a_node;
     581                 :            : #else // RTREE_DONT_USE_MEMPOOLS
     582                 :            :         // EXAMPLE
     583                 :            : #endif // RTREE_DONT_USE_MEMPOOLS
     584                 :          0 :     }
     585                 :            : 
     586                 :          0 :     void InitNode(Node* a_node) {
     587                 :          0 :         a_node->m_count = 0;
     588                 :          0 :         a_node->m_level = -1;
     589                 :          0 :     }
     590                 :            : 
     591                 :            :     void InitRect(Rect* a_rect) {
     592                 :            :         for (int index = 0; index < kNumDimensions; ++index) {
     593                 :            :             a_rect->m_min[index] = CastElementType(0);
     594                 :            :             a_rect->m_max[index] = CastElementType(0);
     595                 :            :         }
     596                 :            :     }
     597                 :            : 
     598                 :            :     // Inserts a new data rectangle into the index structure.
     599                 :            :     // Recursively descends tree, propagates splits back up.
     600                 :            :     // Returns 0 if node was not split.  Old node updated.
     601                 :            :     // If node was split, returns 1 and sets the pointer pointed to by
     602                 :            :     // new_node to point to the new node.  Old node updated to become one of two.
     603                 :            :     // The level argument specifies the number of steps up from the leaf
     604                 :            :     // level to insert; e.g. a data rectangle goes in at level = 0.
     605                 :          0 :     bool InsertRectRec(const Branch& a_branch, Node* a_node, Node** a_newNode, int a_level) {
     606                 :          0 :         RTreeAssert(a_node && a_newNode);
     607                 :          0 :         RTreeAssert(a_level >= 0 && a_level <= a_node->m_level);
     608                 :            : 
     609                 :            :         // recurse until we reach the correct level for the new record. data records
     610                 :            :         // will always be called with a_level == 0 (leaf)
     611                 :          0 :         if (a_node->m_level > a_level) {
     612                 :            :             // Still above level for insertion, go down tree recursively
     613                 :            :             Node* otherNode;
     614                 :            : 
     615                 :            :             // find the optimal branch for this record
     616                 :          0 :             int index = PickBranch(&a_branch.m_rect, a_node);
     617                 :            : 
     618                 :            :             // recursively insert this record into the picked branch
     619                 :          0 :             bool childWasSplit = InsertRectRec(a_branch, a_node->m_branch[index].m_child, &otherNode, a_level);
     620                 :            : 
     621                 :          0 :             if (!childWasSplit) {
     622                 :            :                 // Child was not split. Merge the bounding box of the new record with the
     623                 :            :                 // existing bounding box
     624                 :          0 :                 a_node->m_branch[index].m_rect = CombineRect(&a_branch.m_rect, &(a_node->m_branch[index].m_rect));
     625                 :          0 :                 return false;
     626                 :            :             } else {
     627                 :            :                 // Child was split. The old branches are now re-partitioned to two nodes
     628                 :            :                 // so we have to re-calculate the bounding boxes of each node
     629                 :          0 :                 a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
     630                 :          0 :                 Branch branch;
     631                 :          0 :                 branch.m_child = otherNode;
     632                 :          0 :                 branch.m_rect = NodeCover(otherNode);
     633                 :            : 
     634                 :            :                 // The old node is already a child of a_node. Now add the newly-created
     635                 :            :                 // node to a_node as well. a_node might be split because of that.
     636                 :          0 :                 return AddBranch(&branch, a_node, a_newNode);
     637                 :            :             }
     638                 :          0 :         } else if (a_node->m_level == a_level) {
     639                 :            :             // We have reached level for insertion. Add rect, split if necessary
     640                 :          0 :             return AddBranch(&a_branch, a_node, a_newNode);
     641                 :            :         } else {
     642                 :            :             // Should never occur
     643                 :          0 :             RTreeAssert(0);
     644                 :            :             return false;
     645                 :            :         }
     646                 :          0 :     }
     647                 :            : 
     648                 :            :     // Insert a data rectangle into an index structure.
     649                 :            :     // InsertRect provides for splitting the root;
     650                 :            :     // returns 1 if root was split, 0 if it was not.
     651                 :            :     // The level argument specifies the number of steps up from the leaf
     652                 :            :     // level to insert; e.g. a data rectangle goes in at level = 0.
     653                 :            :     // InsertRect2 does the recursion.
     654                 :          0 :     bool InsertRect(const Branch& a_branch, Node** a_root, int a_level) {
     655                 :            : 
     656                 :          0 :         RTreeAssert(a_root);
     657                 :          0 :         RTreeAssert(a_level >= 0 && a_level <= (*a_root)->m_level);
     658                 :            : #ifdef _DEBUG
     659                 :            :         for (int index = 0; index < kNumDimensions; ++index) {
     660                 :            :             RTreeAssert(a_branch.m_rect.m_min[index] <= a_branch.m_rect.m_max[index]);
     661                 :            :         }
     662                 :            : #endif //_DEBUG  
     663                 :            : 
     664                 :            :         Node* newNode;
     665                 :            : 
     666                 :          0 :         if (InsertRectRec(a_branch, *a_root, &newNode, a_level))  // Root split
     667                 :            :         {
     668                 :            :             // Grow tree taller and new root
     669                 :          0 :             Node* newRoot = AllocNode();
     670                 :          0 :             newRoot->m_level = (*a_root)->m_level + 1;
     671                 :            : 
     672                 :          0 :             Branch branch;
     673                 :            : 
     674                 :            :             // add old root node as a child of the new root
     675                 :          0 :             branch.m_rect = NodeCover(*a_root);
     676                 :          0 :             branch.m_child = *a_root;
     677                 :          0 :             AddBranch(&branch, newRoot, nullptr);
     678                 :            : 
     679                 :            :             // add the split node as a child of the new root
     680                 :          0 :             branch.m_rect = NodeCover(newNode);
     681                 :          0 :             branch.m_child = newNode;
     682                 :          0 :             AddBranch(&branch, newRoot, nullptr);
     683                 :            : 
     684                 :            :             // set the new root as the root node
     685                 :          0 :             *a_root = newRoot;
     686                 :            : 
     687                 :          0 :             return true;
     688                 :            :         }
     689                 :            : 
     690                 :          0 :         return false;
     691                 :          0 :     }
     692                 :            : 
     693                 :            :     // Find the smallest rectangle that includes all rectangles in branches of a node.
     694                 :          0 :     Rect NodeCover(Node* a_node) {
     695                 :          0 :         RTreeAssert(a_node);
     696                 :            : 
     697                 :          0 :         Rect rect = a_node->m_branch[0].m_rect;
     698                 :          0 :         for (int index = 1; index < a_node->m_count; ++index) {
     699                 :          0 :             rect = CombineRect(&rect, &(a_node->m_branch[index].m_rect));
     700                 :          0 :         }
     701                 :            : 
     702                 :          0 :         return rect;
     703                 :            :     }
     704                 :            : 
     705                 :            :     // Add a branch to a node.  Split the node if necessary.
     706                 :            :     // Returns 0 if node not split.  Old node updated.
     707                 :            :     // Returns 1 if node split, sets *new_node to address of new node.
     708                 :            :     // Old node updated, becomes one of two.
     709                 :          0 :     bool AddBranch(const Branch* a_branch, Node* a_node, Node** a_newNode) {
     710                 :            : 
     711                 :          0 :         RTreeAssert(a_branch);
     712                 :          0 :         RTreeAssert(a_node);
     713                 :            : 
     714                 :          0 :         if (a_node->m_count < _MaxNodeCount)  // Split won't be necessary
     715                 :            :         {
     716                 :          0 :             a_node->m_branch[a_node->m_count] = *a_branch;
     717                 :          0 :             ++a_node->m_count;
     718                 :            : 
     719                 :          0 :             return false;
     720                 :            :         } else {
     721                 :          0 :             RTreeAssert(a_newNode);
     722                 :            : 
     723                 :          0 :             SplitNode(a_node, a_branch, a_newNode);
     724                 :          0 :             return true;
     725                 :            :         }
     726                 :          0 :     }
     727                 :            : 
     728                 :            :     // Disconnect a dependent node.
     729                 :            :     // Caller must return (or stop using iteration index) after this as count has changed
     730                 :          0 :     void DisconnectBranch(Node* a_node, int a_index) {
     731                 :          0 :         RTreeAssert(a_node && (a_index >= 0) && (a_index < _MaxNodeCount));
     732                 :          0 :         RTreeAssert(a_node->m_count > 0);
     733                 :            : 
     734                 :            :         // Remove element by swapping with the last element to prevent gaps in array
     735                 :          0 :         a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
     736                 :            : 
     737                 :          0 :         --a_node->m_count;
     738                 :          0 :     }
     739                 :            : 
     740                 :            :     // Pick a branch.  Pick the one that will need the smallest increase
     741                 :            :     // in area to accomodate the new rectangle.  This will result in the
     742                 :            :     // least total area for the covering rectangles in the current node.
     743                 :            :     // In case of a tie, pick the one which was smaller before, to get
     744                 :            :     // the best resolution when searching.
     745                 :          0 :     int PickBranch(const Rect* a_rect, Node* a_node) {
     746                 :          0 :         RTreeAssert(a_rect && a_node);
     747                 :            : 
     748                 :          0 :         bool firstTime = true;
     749                 :            :         ElementTypeReal increase;
     750                 :          0 :         ElementTypeReal bestIncr = CastElementTypeReal(-1);
     751                 :            :         ElementTypeReal area;
     752                 :          0 :         ElementTypeReal bestArea = CastElementTypeReal(-1);
     753                 :          0 :         int best = 0;
     754                 :          0 :         Rect tempRect;
     755                 :            : 
     756                 :          0 :         for (int index = 0; index < a_node->m_count; ++index) {
     757                 :          0 :             Rect* curRect = &a_node->m_branch[index].m_rect;
     758                 :          0 :             area = CalcRectVolume(curRect);
     759                 :          0 :             tempRect = CombineRect(a_rect, curRect);
     760                 :          0 :             increase = CalcRectVolume(&tempRect) - area;
     761                 :          0 :             if ((increase < bestIncr) || firstTime) {
     762                 :          0 :                 best = index;
     763                 :          0 :                 bestArea = area;
     764                 :          0 :                 bestIncr = increase;
     765                 :          0 :                 firstTime = false;
     766                 :          0 :             } else if ((increase == bestIncr) && (area < bestArea)) {
     767                 :          0 :                 best = index;
     768                 :          0 :                 bestArea = area;
     769                 :          0 :                 bestIncr = increase;
     770                 :          0 :             }
     771                 :          0 :         }
     772                 :          0 :         return best;
     773                 :            :     }
     774                 :            : 
     775                 :            :     // Combine two rectangles into larger one containing both
     776                 :          0 :     Rect CombineRect(const Rect* a_rectA, const Rect* a_rectB) {
     777                 :          0 :         RTreeAssert(a_rectA && a_rectB);
     778                 :            : 
     779                 :          0 :         Rect newRect;
     780                 :            : 
     781                 :          0 :         for (int index = 0; index < kNumDimensions; ++index) {
     782                 :          0 :             newRect.m_min[index] = (std::min)(a_rectA->m_min[index], a_rectB->m_min[index]);
     783                 :          0 :             newRect.m_max[index] = (std::max)(a_rectA->m_max[index], a_rectB->m_max[index]);
     784                 :          0 :         }
     785                 :            : 
     786                 :          0 :         return newRect;
     787                 :            :     }
     788                 :            : 
     789                 :            :     // Split a node.
     790                 :            :     // Divides the nodes branches and the extra one between two nodes.
     791                 :            :     // Old node is one of the new ones, and one really new one is created.
     792                 :            :     // Tries more than one method for choosing a partition, uses best result.
     793                 :          0 :     void SplitNode(Node* a_node, const Branch* a_branch, Node** a_newNode) {
     794                 :          0 :         RTreeAssert(a_node);
     795                 :          0 :         RTreeAssert(a_branch);
     796                 :            : 
     797                 :            :         // Could just use local here, but member or external is faster since it is reused
     798                 :          0 :         PartitionVars localVars;
     799                 :          0 :         PartitionVars* parVars = &localVars;
     800                 :            : 
     801                 :            :         // Load all the branches into a buffer, initialize old node
     802                 :          0 :         GetBranches(a_node, a_branch, parVars);
     803                 :            : 
     804                 :            :         // Find partition
     805                 :          0 :         ChoosePartition(parVars, _MinNodeCount);
     806                 :            : 
     807                 :            :         // Create a new node to hold (about) half of the branches
     808                 :          0 :         *a_newNode = AllocNode();
     809                 :          0 :         (*a_newNode)->m_level = a_node->m_level;
     810                 :            : 
     811                 :            :         // Put branches from buffer into 2 nodes according to the chosen partition
     812                 :          0 :         a_node->m_count = 0;
     813                 :          0 :         LoadNodes(a_node, *a_newNode, parVars);
     814                 :            : 
     815                 :          0 :         RTreeAssert((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
     816                 :          0 :     }
     817                 :            : 
     818                 :            :     // The exact volume of the bounding sphere for the given Rect
     819                 :          0 :     ElementTypeReal RectSphericalVolume(Rect* a_rect) {
     820                 :          0 :         RTreeAssert(a_rect);
     821                 :            : 
     822                 :          0 :         ElementTypeReal sumOfSquares = kElementTypeRealZero;
     823                 :            : 
     824                 :          0 :         for (int index = 0; index < kNumDimensions; ++index) {
     825                 :          0 :             const auto halfExtent = ((ElementTypeReal)a_rect->m_max[index] - (ElementTypeReal)a_rect->m_min[index]) * 0.5f;
     826                 :          0 :             sumOfSquares += halfExtent * halfExtent;
     827                 :          0 :         }
     828                 :            : 
     829                 :          0 :         const auto radius = CastElementTypeReal(sqrt(sumOfSquares));
     830                 :            : 
     831                 :            :         // Pow maybe slow, so test for common dims like 2,3 and just use x*x, x*x*x.
     832                 :            :         if (kNumDimensions == 3) {
     833                 :            :             return (radius * radius * radius * m_unitSphereVolume);
     834                 :            :         } else if (kNumDimensions == 2) {
     835                 :          0 :             return (radius * radius * m_unitSphereVolume);
     836                 :            :         } else {
     837                 :            :             return CastElementTypeReal(pow(radius, kNumDimensions) * m_unitSphereVolume);
     838                 :            :         }
     839                 :            :     }
     840                 :            : 
     841                 :            :     // Calculate the n-dimensional volume of a rectangle
     842                 :            :     ElementTypeReal RectVolume(Rect* a_rect) {
     843                 :            :         RTreeAssert(a_rect);
     844                 :            : 
     845                 :            :         auto volume = kElementTypeRealOne;
     846                 :            : 
     847                 :            :         for (int index = 0; index < kNumDimensions; ++index) {
     848                 :            :             volume *= a_rect->m_max[index] - a_rect->m_min[index];
     849                 :            :         }
     850                 :            : 
     851                 :            :         RTreeAssert(volume >= kElementTypeRealZero);
     852                 :            : 
     853                 :            :         return volume;
     854                 :            :     }
     855                 :            : 
     856                 :            :     // Use one of the methods to calculate retangle volume
     857                 :          0 :     ElementTypeReal CalcRectVolume(Rect* a_rect) {
     858                 :            : #ifdef RTREE_USE_SPHERICAL_VOLUME
     859                 :          0 :         return RectSphericalVolume(a_rect); // Slower but helps certain merge cases
     860                 :            : #else // RTREE_USE_SPHERICAL_VOLUME
     861                 :            :         return RectVolume(a_rect); // Faster but can cause poor merges
     862                 :            : #endif // RTREE_USE_SPHERICAL_VOLUME  
     863                 :            :     }
     864                 :            : 
     865                 :            :     // Load branch buffer with branches from full node plus the extra branch.
     866                 :          0 :     void GetBranches(Node* a_node, const Branch* a_branch, PartitionVars* a_parVars) {
     867                 :          0 :         RTreeAssert(a_node);
     868                 :          0 :         RTreeAssert(a_branch);
     869                 :            : 
     870                 :          0 :         RTreeAssert(a_node->m_count == _MaxNodeCount);
     871                 :            : 
     872                 :            :         // Load the branch buffer
     873                 :          0 :         for (int index = 0; index < _MaxNodeCount; ++index) {
     874                 :          0 :             a_parVars->m_branchBuf[index] = a_node->m_branch[index];
     875                 :          0 :         }
     876                 :          0 :         a_parVars->m_branchBuf[_MaxNodeCount] = *a_branch;
     877                 :          0 :         a_parVars->m_branchCount = _MaxNodeCount + 1;
     878                 :            : 
     879                 :            :         // Calculate rect containing all in the set
     880                 :          0 :         a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
     881                 :          0 :         for (int index = 1; index < _MaxNodeCount + 1; ++index) {
     882                 :          0 :             a_parVars->m_coverSplit = CombineRect(&a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect);
     883                 :          0 :         }
     884                 :          0 :         a_parVars->m_coverSplitArea = CalcRectVolume(&a_parVars->m_coverSplit);
     885                 :          0 :     }
     886                 :            : 
     887                 :            :     // Method #0 for choosing a partition:
     888                 :            :     // As the seeds for the two groups, pick the two rects that would waste the
     889                 :            :     // most area if covered by a single rectangle, i.e. evidently the worst pair
     890                 :            :     // to have in the same group.
     891                 :            :     // Of the remaining, one at a time is chosen to be put in one of the two groups.
     892                 :            :     // The one chosen is the one with the greatest difference in area expansion
     893                 :            :     // depending on which group - the rect most strongly attracted to one group
     894                 :            :     // and repelled from the other.
     895                 :            :     // If one group gets too full (more would force other group to violate min
     896                 :            :     // fill requirement) then other group gets the rest.
     897                 :            :     // These last are the ones that can go in either group most easily.
     898                 :          0 :     void ChoosePartition(PartitionVars* a_parVars, int a_minFill) {
     899                 :          0 :         RTreeAssert(a_parVars);
     900                 :            : 
     901                 :            :         ElementTypeReal biggestDiff;
     902                 :          0 :         int group, chosen = 0, betterGroup = 0;
     903                 :            : 
     904                 :          0 :         InitParVars(a_parVars, a_parVars->m_branchCount, a_minFill);
     905                 :          0 :         PickSeeds(a_parVars);
     906                 :            : 
     907                 :          0 :         while (((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total)
     908                 :          0 :             && (a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill))
     909                 :          0 :             && (a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill))) {
     910                 :          0 :             biggestDiff = CastElementTypeReal(-1);
     911                 :          0 :             for (int index = 0; index < a_parVars->m_total; ++index) {
     912                 :          0 :                 if (PartitionVars::kNotTaken == a_parVars->m_partition[index]) {
     913                 :          0 :                     Rect* curRect = &a_parVars->m_branchBuf[index].m_rect;
     914                 :          0 :                     Rect rect0 = CombineRect(curRect, &a_parVars->m_cover[0]);
     915                 :          0 :                     Rect rect1 = CombineRect(curRect, &a_parVars->m_cover[1]);
     916                 :          0 :                     ElementTypeReal growth0 = CalcRectVolume(&rect0) - a_parVars->m_area[0];
     917                 :          0 :                     ElementTypeReal growth1 = CalcRectVolume(&rect1) - a_parVars->m_area[1];
     918                 :          0 :                     ElementTypeReal diff = growth1 - growth0;
     919                 :          0 :                     if (diff >= 0) {
     920                 :          0 :                         group = 0;
     921                 :          0 :                     } else {
     922                 :          0 :                         group = 1;
     923                 :          0 :                         diff = -diff;
     924                 :            :                     }
     925                 :            : 
     926                 :          0 :                     if (diff > biggestDiff) {
     927                 :          0 :                         biggestDiff = diff;
     928                 :          0 :                         chosen = index;
     929                 :          0 :                         betterGroup = group;
     930                 :          0 :                     } else if ((diff == biggestDiff) && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup])) {
     931                 :          0 :                         chosen = index;
     932                 :          0 :                         betterGroup = group;
     933                 :          0 :                     }
     934                 :          0 :                 }
     935                 :          0 :             }
     936                 :          0 :             Classify(chosen, betterGroup, a_parVars);
     937                 :            :         }
     938                 :            : 
     939                 :            :         // If one group too full, put remaining rects in the other
     940                 :          0 :         if ((a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total) {
     941                 :          0 :             if (a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill) {
     942                 :          0 :                 group = 1;
     943                 :          0 :             } else {
     944                 :          0 :                 group = 0;
     945                 :            :             }
     946                 :          0 :             for (int index = 0; index < a_parVars->m_total; ++index) {
     947                 :          0 :                 if (PartitionVars::kNotTaken == a_parVars->m_partition[index]) {
     948                 :          0 :                     Classify(index, group, a_parVars);
     949                 :          0 :                 }
     950                 :          0 :             }
     951                 :          0 :         }
     952                 :            : 
     953                 :          0 :         RTreeAssert((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
     954                 :          0 :         RTreeAssert((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
     955                 :            :             (a_parVars->m_count[1] >= a_parVars->m_minFill));
     956                 :          0 :     }
     957                 :            : 
     958                 :            :     // Copy branches from the buffer into two nodes according to the partition.
     959                 :          0 :     void LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars) {
     960                 :          0 :         RTreeAssert(a_nodeA);
     961                 :          0 :         RTreeAssert(a_nodeB);
     962                 :          0 :         RTreeAssert(a_parVars);
     963                 :            : 
     964                 :          0 :         for (int index = 0; index < a_parVars->m_total; ++index) {
     965                 :          0 :             RTreeAssert(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
     966                 :            : 
     967                 :          0 :             int targetNodeIndex = a_parVars->m_partition[index];
     968                 :          0 :             Node* targetNodes[] = { a_nodeA, a_nodeB };
     969                 :            : 
     970                 :            :             // It is assured that AddBranch here will not cause a node split. 
     971                 :          0 :             bool nodeWasSplit = AddBranch(&a_parVars->m_branchBuf[index], targetNodes[targetNodeIndex], nullptr);
     972                 :            :             (void)nodeWasSplit;
     973                 :          0 :             RTreeAssert(!nodeWasSplit);
     974                 :          0 :         }
     975                 :          0 :     }
     976                 :            : 
     977                 :            :     // Initialize a PartitionVars structure.
     978                 :          0 :     void InitParVars(PartitionVars* a_parVars, int a_maxRects, int a_minFill) {
     979                 :          0 :         RTreeAssert(a_parVars);
     980                 :            : 
     981                 :          0 :         a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
     982                 :          0 :         a_parVars->m_area[0] = a_parVars->m_area[1] = kElementTypeRealZero;
     983                 :          0 :         a_parVars->m_total = a_maxRects;
     984                 :          0 :         a_parVars->m_minFill = a_minFill;
     985                 :          0 :         for (int index = 0; index < a_maxRects; ++index) {
     986                 :          0 :             a_parVars->m_partition[index] = PartitionVars::kNotTaken;
     987                 :          0 :         }
     988                 :          0 :     }
     989                 :            : 
     990                 :          0 :     void PickSeeds(PartitionVars* a_parVars) {
     991                 :          0 :         int seed0 = 0, seed1 = 0;
     992                 :          0 :         _ElementTypeReal worst{ 0.0 }, waste{ 0.0 };
     993                 :          0 :         _ElementTypeReal area[_MaxNodeCount + 1] = { 0.0, };
     994                 :            : 
     995                 :          0 :         for (int index = 0; index < a_parVars->m_total; ++index) {
     996                 :          0 :             area[index] = CalcRectVolume(&a_parVars->m_branchBuf[index].m_rect);
     997                 :          0 :         }
     998                 :            : 
     999                 :          0 :         worst = -a_parVars->m_coverSplitArea - 1;
    1000                 :          0 :         for (int indexA = 0; indexA < a_parVars->m_total - 1; ++indexA) {
    1001                 :          0 :             for (int indexB = indexA + 1; indexB < a_parVars->m_total; ++indexB) {
    1002                 :          0 :                 auto oneRect = CombineRect(&a_parVars->m_branchBuf[indexA].m_rect, &a_parVars->m_branchBuf[indexB].m_rect);
    1003                 :          0 :                 waste = CalcRectVolume(&oneRect) - area[indexA] - area[indexB];
    1004                 :          0 :                 if (waste > worst) {
    1005                 :          0 :                     worst = waste;
    1006                 :          0 :                     seed0 = indexA;
    1007                 :          0 :                     seed1 = indexB;
    1008                 :          0 :                 }
    1009                 :          0 :             }
    1010                 :          0 :         }
    1011                 :            : 
    1012                 :          0 :         Classify(seed0, 0, a_parVars);
    1013                 :          0 :         Classify(seed1, 1, a_parVars);
    1014                 :          0 :     }
    1015                 :            : 
    1016                 :            :     // Put a branch in one of the groups.
    1017                 :          0 :     void Classify(int a_index, int a_group, PartitionVars* a_parVars) {
    1018                 :          0 :         RTreeAssert(a_parVars);
    1019                 :          0 :         RTreeAssert(PartitionVars::kNotTaken == a_parVars->m_partition[a_index]);
    1020                 :            : 
    1021                 :          0 :         a_parVars->m_partition[a_index] = a_group;
    1022                 :            : 
    1023                 :            :         // Calculate combined rect
    1024                 :          0 :         if (a_parVars->m_count[a_group] == 0) {
    1025                 :          0 :             a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
    1026                 :          0 :         } else {
    1027                 :          0 :             a_parVars->m_cover[a_group] = CombineRect(&a_parVars->m_branchBuf[a_index].m_rect, &a_parVars->m_cover[a_group]);
    1028                 :            :         }
    1029                 :            : 
    1030                 :            :         // Calculate volume of combined rect
    1031                 :          0 :         a_parVars->m_area[a_group] = CalcRectVolume(&a_parVars->m_cover[a_group]);
    1032                 :            : 
    1033                 :          0 :         ++a_parVars->m_count[a_group];
    1034                 :          0 :     }
    1035                 :            : 
    1036                 :            :     // Delete a data rectangle from an index structure.
    1037                 :            :     // Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
    1038                 :            :     // Returns 1 if record not found, 0 if success.
    1039                 :            :     // RemoveRect provides for eliminating the root.
    1040                 :          0 :     bool RemoveRect(Rect* a_rect, const DataType& a_id, Node** a_root) {
    1041                 :          0 :         RTreeAssert(a_rect && a_root);
    1042                 :          0 :         RTreeAssert(*a_root);
    1043                 :            : 
    1044                 :          0 :         ListNode* reInsertList{ nullptr };
    1045                 :            : 
    1046                 :          0 :         if (!RemoveRectRec(a_rect, a_id, *a_root, &reInsertList)) {
    1047                 :            :             // Found and deleted a data item
    1048                 :            :             // Reinsert any branches from eliminated nodes
    1049                 :          0 :             while (reInsertList) {
    1050                 :          0 :                 Node* tempNode = reInsertList->m_node;
    1051                 :            : 
    1052                 :          0 :                 for (int index = 0; index < tempNode->m_count; ++index) {
    1053                 :            :                     // TODO go over this code. should I use (tempNode->m_level - 1)?
    1054                 :          0 :                     InsertRect(tempNode->m_branch[index],
    1055                 :          0 :                         a_root,
    1056                 :          0 :                         tempNode->m_level);
    1057                 :          0 :                 }
    1058                 :            : 
    1059                 :          0 :                 ListNode* remLNode = reInsertList;
    1060                 :          0 :                 reInsertList = reInsertList->m_next;
    1061                 :            : 
    1062                 :          0 :                 FreeNode(remLNode->m_node);
    1063                 :          0 :                 FreeListNode(remLNode);
    1064                 :            :             }
    1065                 :            : 
    1066                 :            :             // Check for redundant root (not leaf, 1 child) and eliminate TODO replace
    1067                 :            :             // if with while? In case there is a whole branch of redundant roots...
    1068                 :          0 :             if ((*a_root)->m_count == 1 && (*a_root)->IsInternalNode()) {
    1069                 :          0 :                 auto tempNode = (*a_root)->m_branch[0].m_child;
    1070                 :            : 
    1071                 :          0 :                 RTreeAssert(tempNode);
    1072                 :          0 :                 FreeNode(*a_root);
    1073                 :          0 :                 *a_root = tempNode;
    1074                 :          0 :             }
    1075                 :          0 :             return false;
    1076                 :            :         } else {
    1077                 :          0 :             return true;
    1078                 :            :         }
    1079                 :          0 :     }
    1080                 :            : 
    1081                 :            :     // Delete a rectangle from non-root part of an index structure.
    1082                 :            :     // Called by RemoveRect.  Descends tree recursively,
    1083                 :            :     // merges branches on the way back up.
    1084                 :            :     // Returns 1 if record not found, 0 if success.
    1085                 :          0 :     bool RemoveRectRec(Rect* a_rect, const DataType& a_id, Node* a_node, ListNode** a_listNode) {
    1086                 :          0 :         RTreeAssert(a_rect && a_node && a_listNode);
    1087                 :          0 :         RTreeAssert(a_node->m_level >= 0);
    1088                 :            : 
    1089                 :          0 :         if (a_node->IsInternalNode())  // not a leaf node
    1090                 :            :         {
    1091                 :          0 :             for (int index = 0; index < a_node->m_count; ++index) {
    1092                 :          0 :                 if (Overlap(a_rect, &(a_node->m_branch[index].m_rect))) {
    1093                 :          0 :                     if (!RemoveRectRec(a_rect, a_id, a_node->m_branch[index].m_child, a_listNode)) {
    1094                 :          0 :                         if (a_node->m_branch[index].m_child->m_count >= _MinNodeCount) {
    1095                 :            :                             // child removed, just resize parent rect
    1096                 :          0 :                             a_node->m_branch[index].m_rect = NodeCover(a_node->m_branch[index].m_child);
    1097                 :          0 :                         } else {
    1098                 :            :                             // child removed, not enough entries in node, eliminate node
    1099                 :          0 :                             ReInsert(a_node->m_branch[index].m_child, a_listNode);
    1100                 :          0 :                             DisconnectBranch(a_node, index); // Must return after this call as count has changed
    1101                 :            :                         }
    1102                 :          0 :                         return false;
    1103                 :            :                     }
    1104                 :          0 :                 }
    1105                 :          0 :             }
    1106                 :          0 :             return true;
    1107                 :            :         } else // A leaf node
    1108                 :            :         {
    1109                 :          0 :             for (int index = 0; index < a_node->m_count; ++index) {
    1110                 :          0 :                 if (a_node->m_branch[index].m_data == a_id) {
    1111                 :          0 :                     DisconnectBranch(a_node, index); // Must return after this call as count has changed
    1112                 :          0 :                     return false;
    1113                 :            :                 }
    1114                 :          0 :             }
    1115                 :          0 :             return true;
    1116                 :            :         }
    1117                 :          0 :     }
    1118                 :            : 
    1119                 :            :     // Allocate space for a node in the list used in DeletRect to
    1120                 :            :     // store Nodes that are too empty.
    1121                 :          0 :     ListNode* AllocListNode() {
    1122                 :            : #ifdef RTREE_DONT_USE_MEMPOOLS
    1123                 :          0 :         return new ListNode;
    1124                 :            : #else // RTREE_DONT_USE_MEMPOOLS
    1125                 :            :         // EXAMPLE
    1126                 :            : #endif // RTREE_DONT_USE_MEMPOOLS
    1127                 :            :     }
    1128                 :            : 
    1129                 :          0 :     void FreeListNode(ListNode* a_listNode) {
    1130                 :            : #ifdef RTREE_DONT_USE_MEMPOOLS
    1131                 :          0 :         delete a_listNode;
    1132                 :            : #else // RTREE_DONT_USE_MEMPOOLS
    1133                 :            :         // EXAMPLE
    1134                 :            : #endif // RTREE_DONT_USE_MEMPOOLS
    1135                 :          0 :     }
    1136                 :            : 
    1137                 :            :     // Decide whether two rectangles overlap.
    1138                 :          0 :     bool Overlap(Rect* a_rectA, Rect* a_rectB) const {
    1139                 :          0 :         RTreeAssert(a_rectA && a_rectB);
    1140                 :            : 
    1141                 :          0 :         for (int index = 0; index < kNumDimensions; ++index) {
    1142                 :          0 :             if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
    1143                 :          0 :                 a_rectB->m_min[index] > a_rectA->m_max[index]) {
    1144                 :          0 :                 return false;
    1145                 :            :             }
    1146                 :          0 :         }
    1147                 :          0 :         return true;
    1148                 :          0 :     }
    1149                 :            : 
    1150                 :            :     // Add a node to the reinsertion list.  All its branches will later
    1151                 :            :     // be reinserted into the index structure.
    1152                 :          0 :     void ReInsert(Node* a_node, ListNode** a_listNode) {
    1153                 :            :         ListNode* newListNode;
    1154                 :            : 
    1155                 :          0 :         newListNode = AllocListNode();
    1156                 :          0 :         newListNode->m_node = a_node;
    1157                 :          0 :         newListNode->m_next = *a_listNode;
    1158                 :          0 :         *a_listNode = newListNode;
    1159                 :          0 :     }
    1160                 :            : 
    1161                 :            :     // Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
    1162                 :          0 :     bool Search(Node* a_node, Rect* a_rect, int& a_foundCount, std::function<bool(const DataType&)> callback) const {
    1163                 :          0 :         RTreeAssert(a_node);
    1164                 :          0 :         RTreeAssert(a_node->m_level >= 0);
    1165                 :          0 :         RTreeAssert(a_rect);
    1166                 :            : 
    1167                 :          0 :         if (a_node->IsInternalNode()) {
    1168                 :            :             // This is an internal node in the tree
    1169                 :          0 :             for (int index = 0; index < a_node->m_count; ++index) {
    1170                 :          0 :                 if (Overlap(a_rect, &a_node->m_branch[index].m_rect)) {
    1171                 :          0 :                     if (!Search(a_node->m_branch[index].m_child, a_rect, a_foundCount, callback)) {
    1172                 :            :                         // The callback indicated to stop searching
    1173                 :          0 :                         return false;
    1174                 :            :                     }
    1175                 :          0 :                 }
    1176                 :          0 :             }
    1177                 :          0 :         } else {
    1178                 :            :             // This is a leaf node
    1179                 :          0 :             for (int index = 0; index < a_node->m_count; ++index) {
    1180                 :          0 :                 if (Overlap(a_rect, &a_node->m_branch[index].m_rect)) {
    1181                 :          0 :                     const auto& id = a_node->m_branch[index].m_data;
    1182                 :          0 :                     ++a_foundCount;
    1183                 :            : 
    1184                 :          0 :                     if (callback && !callback(id)) {
    1185                 :          0 :                         return false; // Don't continue searching
    1186                 :            :                     }
    1187                 :          0 :                 }
    1188                 :          0 :             }
    1189                 :            :         }
    1190                 :            : 
    1191                 :          0 :         return true; // Continue searching
    1192                 :          0 :     }
    1193                 :            : 
    1194                 :          0 :     void RemoveAllRec(Node* a_node) {
    1195                 :          0 :         RTreeAssert(a_node);
    1196                 :          0 :         RTreeAssert(a_node->m_level >= 0);
    1197                 :            : 
    1198                 :          0 :         if (a_node->IsInternalNode()) // This is an internal node in the tree
    1199                 :            :         {
    1200                 :          0 :             for (int index = 0; index < a_node->m_count; ++index) {
    1201                 :          0 :                 RemoveAllRec(a_node->m_branch[index].m_child);
    1202                 :          0 :             }
    1203                 :          0 :         }
    1204                 :          0 :         FreeNode(a_node);
    1205                 :          0 :     }
    1206                 :            : 
    1207                 :          0 :     void Reset() {
    1208                 :            : #ifdef RTREE_DONT_USE_MEMPOOLS
    1209                 :            :         // Delete all existing nodes
    1210                 :          0 :         RemoveAllRec(m_root);
    1211                 :            : #else // RTREE_DONT_USE_MEMPOOLS
    1212                 :            :         // Just reset memory pools.  We are not using complex types
    1213                 :            :         // EXAMPLE
    1214                 :            : #endif // RTREE_DONT_USE_MEMPOOLS
    1215                 :          0 :     }
    1216                 :            : 
    1217                 :            :     void CountRec(Node* a_node, int& a_count) const {
    1218                 :            :         if (a_node->IsInternalNode())  // not a leaf node
    1219                 :            :         {
    1220                 :            :             for (int index = 0; index < a_node->m_count; ++index) {
    1221                 :            :                 CountRec(a_node->m_branch[index].m_child, a_count);
    1222                 :            :             }
    1223                 :            :         } else // A leaf node
    1224                 :            :         {
    1225                 :            :             a_count += a_node->m_count;
    1226                 :            :         }
    1227                 :            :     }
    1228                 :            : 
    1229                 :            :     bool SaveRec(Node* a_node, RTFileStream& a_stream) {
    1230                 :            :         a_stream.Write(a_node->m_level);
    1231                 :            :         a_stream.Write(a_node->m_count);
    1232                 :            : 
    1233                 :            :         if (a_node->IsInternalNode())  // not a leaf node
    1234                 :            :         {
    1235                 :            :             for (int index = 0; index < a_node->m_count; ++index) {
    1236                 :            :                 const auto& curBranch = a_node->m_branch[index];
    1237                 :            : 
    1238                 :            :                 a_stream.WriteArray(curBranch->m_rect.m_min, kNumDimensions);
    1239                 :            :                 a_stream.WriteArray(curBranch->m_rect.m_max, kNumDimensions);
    1240                 :            : 
    1241                 :            :                 SaveRec(curBranch->m_child, a_stream);
    1242                 :            :             }
    1243                 :            :         } else // A leaf node
    1244                 :            :         {
    1245                 :            :             for (int index = 0; index < a_node->m_count; ++index) {
    1246                 :            :                 const auto& curBranch = &a_node->m_branch[index];
    1247                 :            : 
    1248                 :            :                 a_stream.WriteArray(curBranch->m_rect.m_min, kNumDimensions);
    1249                 :            :                 a_stream.WriteArray(curBranch->m_rect.m_max, kNumDimensions);
    1250                 :            : 
    1251                 :            :                 a_stream.Write(curBranch->m_data);
    1252                 :            :             }
    1253                 :            :         }
    1254                 :            : 
    1255                 :            :         return true; // Should do more error checking on I/O operations
    1256                 :            :     }
    1257                 :            : 
    1258                 :            :     bool LoadRec(Node* a_node, RTFileStream& a_stream) {
    1259                 :            :         a_stream.Read(a_node->m_level);
    1260                 :            :         a_stream.Read(a_node->m_count);
    1261                 :            : 
    1262                 :            :         if (a_node->IsInternalNode())  // not a leaf node
    1263                 :            :         {
    1264                 :            :             for (int index = 0; index < a_node->m_count; ++index) {
    1265                 :            :                 Branch* curBranch = &a_node->m_branch[index];
    1266                 :            : 
    1267                 :            :                 a_stream.ReadArray(curBranch->m_rect.m_min, kNumDimensions);
    1268                 :            :                 a_stream.ReadArray(curBranch->m_rect.m_max, kNumDimensions);
    1269                 :            : 
    1270                 :            :                 curBranch->m_child = AllocNode();
    1271                 :            :                 LoadRec(curBranch->m_child, a_stream);
    1272                 :            :             }
    1273                 :            :         } else // A leaf node
    1274                 :            :         {
    1275                 :            :             for (int index = 0; index < a_node->m_count; ++index) {
    1276                 :            :                 Branch* curBranch = &a_node->m_branch[index];
    1277                 :            : 
    1278                 :            :                 a_stream.ReadArray(curBranch->m_rect.m_min, kNumDimensions);
    1279                 :            :                 a_stream.ReadArray(curBranch->m_rect.m_max, kNumDimensions);
    1280                 :            : 
    1281                 :            :                 a_stream.Read(curBranch->m_data);
    1282                 :            :             }
    1283                 :            :         }
    1284                 :            : 
    1285                 :            :         return true; // Should do more error checking on I/O operations
    1286                 :            :     }
    1287                 :            : 
    1288                 :            :     void CopyRec(Node* current, Node* other) {
    1289                 :            :         current->m_level = other->m_level;
    1290                 :            :         current->m_count = other->m_count;
    1291                 :            : 
    1292                 :            :         if (current->IsInternalNode())  // not a leaf node
    1293                 :            :         {
    1294                 :            :             for (int index = 0; index < current->m_count; ++index) {
    1295                 :            :                 auto& currentBranch = current->m_branch[index];
    1296                 :            :                 const auto& otherBranch = other->m_branch[index];
    1297                 :            : 
    1298                 :            :                 std::copy(otherBranch.m_rect.m_min,
    1299                 :            :                     otherBranch.m_rect.m_min + kNumDimensions,
    1300                 :            :                     currentBranch.m_rect.m_min);
    1301                 :            : 
    1302                 :            :                 std::copy(otherBranch.m_rect.m_max,
    1303                 :            :                     otherBranch.m_rect.m_max + kNumDimensions,
    1304                 :            :                     currentBranch.m_rect.m_max);
    1305                 :            : 
    1306                 :            :                 currentBranch.m_child = AllocNode();
    1307                 :            :                 CopyRec(currentBranch.m_child, otherBranch.m_child);
    1308                 :            :             }
    1309                 :            :         } else // A leaf node
    1310                 :            :         {
    1311                 :            :             for (int index = 0; index < current->m_count; ++index) {
    1312                 :            :                 auto& currentBranch = current->m_branch[index];
    1313                 :            :                 const auto& otherBranch = other->m_branch[index];
    1314                 :            : 
    1315                 :            :                 std::copy(otherBranch.m_rect.m_min,
    1316                 :            :                     otherBranch.m_rect.m_min + kNumDimensions,
    1317                 :            :                     currentBranch.m_rect.m_min);
    1318                 :            : 
    1319                 :            :                 std::copy(otherBranch.m_rect.m_max,
    1320                 :            :                     otherBranch.m_rect.m_max + kNumDimensions,
    1321                 :            :                     currentBranch.m_rect.m_max);
    1322                 :            : 
    1323                 :            :                 currentBranch.m_data = otherBranch.m_data;
    1324                 :            :             }
    1325                 :            :         }
    1326                 :            :     }
    1327                 :            : 
    1328                 :          0 :     Node* m_root = nullptr;                                         ///< Root of tree
    1329                 :          0 :     ElementTypeReal m_unitSphereVolume = kElementTypeRealZero;      ///< Unit sphere constant for required number of dimensions
    1330                 :            : };
    1331                 :            : 
    1332                 :            : #endif //RTREE_H

Generated by: LCOV version 1.14