KiCad PCB EDA Suite
rtree.h
Go to the documentation of this file.
1 //TITLE
2 //
3 // R-TREES: A DYNAMIC INDEX STRUCTURE FOR SPATIAL SEARCHING
4 //
5 //DESCRIPTION
6 //
7 // A C++ templated version of the RTree algorithm.
8 // For more information please read the comments in RTree.h
9 //
10 //AUTHORS
11 //
12 // * 1983 Original algorithm and test code by Antonin Guttman and Michael Stonebraker, UC Berkely
13 // * 1994 ANCI C ported from original test code by Melinda Green - melinda@superliminal.com
14 // * 1995 Sphere volume fix for degeneracy problem submitted by Paul Brook
15 // * 2004 Templated C++ port by Greg Douglas
16 // * 2013 CERN (www.cern.ch)
17 //
18 //LICENSE:
19 //
20 // Entirely free for all uses. Enjoy!
21 
22 #ifndef RTREE_H
23 #define RTREE_H
24 
25 // NOTE This file compiles under MSVC 6 SP5 and MSVC .Net 2003 it may not work on other compilers without modification.
26 
27 // NOTE These next few lines may be win32 specific, you may need to modify them to compile on other platform
28 #include <stdio.h>
29 #include <math.h>
30 #include <assert.h>
31 #include <stdlib.h>
32 
33 #define ASSERT assert // RTree uses ASSERT( condition )
34 #ifndef rMin
35  #define rMin std::min
36 #endif // rMin
37 #ifndef rMax
38  #define rMax std::max
39 #endif // rMax
40 
41 //
42 // RTree.h
43 //
44 
45 #define RTREE_TEMPLATE template <class DATATYPE, class ELEMTYPE, int NUMDIMS, \
46  class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
47 #define RTREE_SEARCH_TEMPLATE template <class DATATYPE, class ELEMTYPE, int NUMDIMS, \
48  class ELEMTYPEREAL, int TMAXNODES, int TMINNODES, class VISITOR>
49 #define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, \
50  TMINNODES>
51 #define RTREE_SEARCH_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, \
52  TMINNODES, VISITOR>
53 
54 #define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one.
55 #define RTREE_USE_SPHERICAL_VOLUME // Better split classification, may be slower on some systems
56 
57 // Fwd decl
58 class RTFileStream; // File I/O helper class, look below for implementation and notes.
59 
60 
77 template <class DATATYPE, class ELEMTYPE, int NUMDIMS,
78  class ELEMTYPEREAL = ELEMTYPE, int TMAXNODES = 8, int TMINNODES = TMAXNODES / 2>
79 class RTree
80 {
81 protected:
82 
83  struct Node; // Fwd decl. Used by other internal structs and iterator
84 public:
85 
86  // These constant must be declared after Branch and before Node struct
87  // Stuck up here for MSVC 6 compiler. NSVC .NET 2003 is much happier.
88  enum {
89  MAXNODES = TMAXNODES,
90  MINNODES = TMINNODES,
91  };
92 
93  struct Statistics {
94  int maxDepth;
95  int avgDepth;
96 
100  };
101 
102 public:
103 
104  RTree();
105  virtual ~RTree();
106 
111  void Insert( const ELEMTYPE a_min[NUMDIMS],
112  const ELEMTYPE a_max[NUMDIMS],
113  const DATATYPE& a_dataId );
114 
119  void Remove( const ELEMTYPE a_min[NUMDIMS],
120  const ELEMTYPE a_max[NUMDIMS],
121  const DATATYPE& a_dataId );
122 
129  int Search( const ELEMTYPE a_min[NUMDIMS],
130  const ELEMTYPE a_max[NUMDIMS],
131  bool a_resultCallback( DATATYPE a_data, void* a_context ),
132  void* a_context );
133 
134  template <class VISITOR>
135  int Search( const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], VISITOR& a_visitor )
136  {
137  #ifdef _DEBUG
138 
139  for( int index = 0; index<NUMDIMS; ++index )
140  {
141  ASSERT( a_min[index] <= a_max[index] );
142  }
143 
144  #endif // _DEBUG
145 
146  Rect rect;
147 
148  for( int axis = 0; axis<NUMDIMS; ++axis )
149  {
150  rect.m_min[axis] = a_min[axis];
151  rect.m_max[axis] = a_max[axis];
152  }
153 
154 
155  // NOTE: May want to return search result another way, perhaps returning the number of found elements here.
156  int cnt = 0;
157 
158  Search( m_root, &rect, a_visitor, cnt );
159 
160  return cnt;
161  }
162 
164 
165  Statistics CalcStats();
166 
168  void RemoveAll();
169 
171  int Count();
172 
174  bool Load( const char* a_fileName );
175 
177  bool Load( RTFileStream& a_stream );
178 
179 
181  bool Save( const char* a_fileName );
182 
184  bool Save( RTFileStream& a_stream );
185 
191  DATATYPE NearestNeighbor( const ELEMTYPE a_point[NUMDIMS] );
192 
200  DATATYPE NearestNeighbor( const ELEMTYPE a_point[NUMDIMS],
201  ELEMTYPE a_squareDistanceCallback( const ELEMTYPE a_point[NUMDIMS], DATATYPE a_data ),
202  ELEMTYPE* a_squareDistance );
203 
205  class Iterator
206  {
207  private:
208 
209  enum { MAX_STACK = 32 }; // Max stack size. Allows almost n^32 where n is number of branches in node
210 
212  {
215  };
216  public:
217 
218  Iterator() { Init(); }
219 
220  ~Iterator() { }
221 
223  bool IsNull() { return m_tos <= 0; }
224 
226  bool IsNotNull() { return m_tos > 0; }
227 
229  DATATYPE& operator*()
230  {
231  ASSERT( IsNotNull() );
232  StackElement& curTos = m_stack[m_tos - 1];
233  return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
234  }
235 
237  const DATATYPE& operator*() const
238  {
239  ASSERT( IsNotNull() );
240  StackElement& curTos = m_stack[m_tos - 1];
241  return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
242  }
243 
245  bool operator++() { return FindNextData(); }
246 
248  void GetBounds( ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS] )
249  {
250  ASSERT( IsNotNull() );
251  StackElement& curTos = m_stack[m_tos - 1];
252  Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
253 
254  for( int index = 0; index < NUMDIMS; ++index )
255  {
256  a_min[index] = curBranch.m_rect.m_min[index];
257  a_max[index] = curBranch.m_rect.m_max[index];
258  }
259  }
260 
261  private:
262 
264  void Init() { m_tos = 0; }
265 
268  {
269  for( ; ; )
270  {
271  if( m_tos <= 0 )
272  {
273  return false;
274  }
275 
276  StackElement curTos = Pop(); // Copy stack top cause it may change as we use it
277 
278  if( curTos.m_node->IsLeaf() )
279  {
280  // Keep walking through data while we can
281  if( curTos.m_branchIndex + 1 < curTos.m_node->m_count )
282  {
283  // There is more data, just point to the next one
284  Push( curTos.m_node, curTos.m_branchIndex + 1 );
285  return true;
286  }
287 
288  // No more data, so it will fall back to previous level
289  }
290  else
291  {
292  if( curTos.m_branchIndex + 1 < curTos.m_node->m_count )
293  {
294  // Push sibling on for future tree walk
295  // This is the 'fall back' node when we finish with the current level
296  Push( curTos.m_node, curTos.m_branchIndex + 1 );
297  }
298 
299  // Since cur node is not a leaf, push first of next level to get deeper into the tree
300  Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
301  Push( nextLevelnode, 0 );
302 
303  // If we pushed on a new leaf, exit as the data is ready at TOS
304  if( nextLevelnode->IsLeaf() )
305  {
306  return true;
307  }
308  }
309  }
310  }
311 
313  void Push( Node* a_node, int a_branchIndex )
314  {
315  m_stack[m_tos].m_node = a_node;
316  m_stack[m_tos].m_branchIndex = a_branchIndex;
317  ++m_tos;
318  ASSERT( m_tos <= MAX_STACK );
319  }
320 
323  {
324  ASSERT( m_tos > 0 );
325  --m_tos;
326  return m_stack[m_tos];
327  }
328 
329  StackElement m_stack[MAX_STACK];
330  int m_tos;
331 
332  friend class RTree; // Allow hiding of non-public functions while allowing manipulation by logical owner
333  };
334 
335 
337  void GetFirst( Iterator& a_it )
338  {
339  a_it.Init();
340  Node* first = m_root;
341 
342  while( first )
343  {
344  if( first->IsInternalNode() && first->m_count > 1 )
345  {
346  a_it.Push( first, 1 ); // Descend sibling branch later
347  }
348  else if( first->IsLeaf() )
349  {
350  if( first->m_count )
351  {
352  a_it.Push( first, 0 );
353  }
354 
355  break;
356  }
357 
358  first = first->m_branch[0].m_child;
359  }
360  }
361 
363  void GetNext( Iterator& a_it ) { ++a_it; }
364 
366  bool IsNull( Iterator& a_it ) { return a_it.IsNull(); }
367 
369  DATATYPE& GetAt( Iterator& a_it ) { return *a_it; }
370 protected:
371 
373  struct Rect
374  {
375  ELEMTYPE m_min[NUMDIMS];
376  ELEMTYPE m_max[NUMDIMS];
377  };
378 
382  struct Branch
383  {
385  union
386  {
388  DATATYPE m_data;
389  };
390  };
391 
393  struct Node
394  {
395  bool IsInternalNode() { return m_level > 0; } // Not a leaf, but a internal node
396  bool IsLeaf() { return m_level == 0; } // A leaf, contains data
397 
398  int m_count;
399  int m_level;
400  Branch m_branch[MAXNODES];
401  };
402 
404  struct ListNode
405  {
408  };
409 
412  {
413  int m_partition[MAXNODES + 1];
414  int m_total;
416  int m_taken[MAXNODES + 1];
417  int m_count[2];
418  Rect m_cover[2];
419  ELEMTYPEREAL m_area[2];
420 
421  Branch m_branchBuf[MAXNODES + 1];
424  ELEMTYPEREAL m_coverSplitArea;
425  };
426 
428  struct NNNode
429  {
431  ELEMTYPE minDist;
432  bool isLeaf;
433  };
434 
435  Node* AllocNode();
436  void FreeNode( Node* a_node );
437  void InitNode( Node* a_node );
438  void InitRect( Rect* a_rect );
439  bool InsertRectRec( Rect* a_rect,
440  const DATATYPE& a_id,
441  Node* a_node,
442  Node** a_newNode,
443  int a_level );
444  bool InsertRect( Rect* a_rect, const DATATYPE& a_id, Node** a_root, int a_level );
445  Rect NodeCover( Node* a_node );
446  bool AddBranch( Branch* a_branch, Node* a_node, Node** a_newNode );
447  void DisconnectBranch( Node* a_node, int a_index );
448  int PickBranch( Rect* a_rect, Node* a_node );
449  Rect CombineRect( Rect* a_rectA, Rect* a_rectB );
450  void SplitNode( Node* a_node, Branch* a_branch, Node** a_newNode );
451  ELEMTYPEREAL RectSphericalVolume( Rect* a_rect );
452  ELEMTYPEREAL RectVolume( Rect* a_rect );
453  ELEMTYPEREAL CalcRectVolume( Rect* a_rect );
454  void GetBranches( Node* a_node, Branch* a_branch, PartitionVars* a_parVars );
455  void ChoosePartition( PartitionVars* a_parVars, int a_minFill );
456  void LoadNodes( Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars );
457  void InitParVars( PartitionVars* a_parVars, int a_maxRects, int a_minFill );
458  void PickSeeds( PartitionVars* a_parVars );
459  void Classify( int a_index, int a_group, PartitionVars* a_parVars );
460  bool RemoveRect( Rect* a_rect, const DATATYPE& a_id, Node** a_root );
461  bool RemoveRectRec( Rect* a_rect,
462  const DATATYPE& a_id,
463  Node* a_node,
464  ListNode** a_listNode );
466  void FreeListNode( ListNode* a_listNode );
467  bool Overlap( Rect* a_rectA, Rect* a_rectB );
468  void ReInsert( Node* a_node, ListNode** a_listNode );
469  ELEMTYPE MinDist( const ELEMTYPE a_point[NUMDIMS], Rect* a_rect );
470  void InsertNNListSorted( std::vector<NNNode*>* nodeList, NNNode* newNode );
471 
472  bool Search( Node * a_node, Rect * a_rect, int& a_foundCount, bool a_resultCallback(
473  DATATYPE a_data,
474  void* a_context ), void* a_context );
475 
476  template <class VISITOR>
477  bool Search( Node* a_node, Rect* a_rect, VISITOR& a_visitor, int& a_foundCount )
478  {
479  ASSERT( a_node );
480  ASSERT( a_node->m_level >= 0 );
481  ASSERT( a_rect );
482 
483  if( a_node->IsInternalNode() ) // This is an internal node in the tree
484  {
485  for( int index = 0; index < a_node->m_count; ++index )
486  {
487  if( Overlap( a_rect, &a_node->m_branch[index].m_rect ) )
488  {
489  if( !Search( a_node->m_branch[index].m_child, a_rect, a_visitor, a_foundCount ) )
490  {
491  return false; // Don't continue searching
492  }
493  }
494  }
495  }
496  else // This is a leaf node
497  {
498  for( int index = 0; index < a_node->m_count; ++index )
499  {
500  if( Overlap( a_rect, &a_node->m_branch[index].m_rect ) )
501  {
502  DATATYPE& id = a_node->m_branch[index].m_data;
503 
504  if( !a_visitor( id ) )
505  return false;
506 
507  a_foundCount++;
508  }
509  }
510  }
511 
512  return true; // Continue searching
513  }
514 
515  void RemoveAllRec( Node* a_node );
516  void Reset();
517  void CountRec( Node* a_node, int& a_count );
518 
519  bool SaveRec( Node* a_node, RTFileStream& a_stream );
520  bool LoadRec( Node* a_node, RTFileStream& a_stream );
521 
522  Node* m_root;
523  ELEMTYPEREAL m_unitSphereVolume;
524 };
525 
526 
527 // Because there is not stream support, this is a quick and dirty file I/O helper.
528 // Users will likely replace its usage with a Stream implementation from their favorite API.
530 {
531  FILE* m_file;
532 public:
533 
534 
536  {
537  m_file = NULL;
538  }
539 
541  {
542  Close();
543  }
544 
545  bool OpenRead( const char* a_fileName )
546  {
547  m_file = fopen( a_fileName, "rb" );
548 
549  if( !m_file )
550  {
551  return false;
552  }
553 
554  return true;
555  }
556 
557  bool OpenWrite( const char* a_fileName )
558  {
559  m_file = fopen( a_fileName, "wb" );
560 
561  if( !m_file )
562  {
563  return false;
564  }
565 
566  return true;
567  }
568 
569  void Close()
570  {
571  if( m_file )
572  {
573  fclose( m_file );
574  m_file = NULL;
575  }
576  }
577 
578  template <typename TYPE>
579  size_t Write( const TYPE& a_value )
580  {
581  ASSERT( m_file );
582  return fwrite( (void*) &a_value, sizeof(a_value), 1, m_file );
583  }
584 
585  template <typename TYPE>
586  size_t WriteArray( const TYPE* a_array, int a_count )
587  {
588  ASSERT( m_file );
589  return fwrite( (void*) a_array, sizeof(TYPE) * a_count, 1, m_file );
590  }
591 
592  template <typename TYPE>
593  size_t Read( TYPE& a_value )
594  {
595  ASSERT( m_file );
596  return fread( (void*) &a_value, sizeof(a_value), 1, m_file );
597  }
598 
599  template <typename TYPE>
600  size_t ReadArray( TYPE* a_array, int a_count )
601  {
602  ASSERT( m_file );
603  return fread( (void*) a_array, sizeof(TYPE) * a_count, 1, m_file );
604  }
605 };
606 
607 
608 RTREE_TEMPLATE RTREE_QUAL::RTree()
609 {
610  ASSERT( MAXNODES > MINNODES );
611  ASSERT( MINNODES > 0 );
612 
613 
614  // We only support machine word size simple data type eg. integer index or object pointer.
615  // Since we are storing as union with non data branch
616  ASSERT( sizeof(DATATYPE) == sizeof(void*) || sizeof(DATATYPE) == sizeof(int) );
617 
618  // Precomputed volumes of the unit spheres for the first few dimensions
619  const float UNIT_SPHERE_VOLUMES[] =
620  {
621  0.000000f, 2.000000f, 3.141593f, // Dimension 0,1,2
622  4.188790f, 4.934802f, 5.263789f, // Dimension 3,4,5
623  5.167713f, 4.724766f, 4.058712f, // Dimension 6,7,8
624  3.298509f, 2.550164f, 1.884104f, // Dimension 9,10,11
625  1.335263f, 0.910629f, 0.599265f, // Dimension 12,13,14
626  0.381443f, 0.235331f, 0.140981f, // Dimension 15,16,17
627  0.082146f, 0.046622f, 0.025807f, // Dimension 18,19,20
628  };
629 
630  m_root = AllocNode();
631  m_root->m_level = 0;
632  m_unitSphereVolume = (ELEMTYPEREAL) UNIT_SPHERE_VOLUMES[NUMDIMS];
633 }
634 
635 
637 RTREE_QUAL::~RTree() {
638  Reset(); // Free, or reset node memory
639 }
640 
641 
643 void RTREE_QUAL::Insert( const ELEMTYPE a_min[NUMDIMS],
644  const ELEMTYPE a_max[NUMDIMS],
645  const DATATYPE& a_dataId )
646 {
647 #ifdef _DEBUG
648 
649  for( int index = 0; index<NUMDIMS; ++index )
650  {
651  ASSERT( a_min[index] <= a_max[index] );
652  }
653 
654 #endif // _DEBUG
655 
656  Rect rect;
657 
658  for( int axis = 0; axis<NUMDIMS; ++axis )
659  {
660  rect.m_min[axis] = a_min[axis];
661  rect.m_max[axis] = a_max[axis];
662  }
663 
664  InsertRect( &rect, a_dataId, &m_root, 0 );
665 }
666 
667 
669 void RTREE_QUAL::Remove( const ELEMTYPE a_min[NUMDIMS],
670  const ELEMTYPE a_max[NUMDIMS],
671  const DATATYPE& a_dataId )
672 {
673 #ifdef _DEBUG
674 
675  for( int index = 0; index<NUMDIMS; ++index )
676  {
677  ASSERT( a_min[index] <= a_max[index] );
678  }
679 
680 #endif // _DEBUG
681 
682  Rect rect;
683 
684  for( int axis = 0; axis<NUMDIMS; ++axis )
685  {
686  rect.m_min[axis] = a_min[axis];
687  rect.m_max[axis] = a_max[axis];
688  }
689 
690  RemoveRect( &rect, a_dataId, &m_root );
691 }
692 
693 
695 int RTREE_QUAL::Search( const ELEMTYPE a_min[NUMDIMS],
696  const ELEMTYPE a_max[NUMDIMS],
697  bool a_resultCallback( DATATYPE a_data, void* a_context ),
698  void* a_context )
699 {
700 #ifdef _DEBUG
701 
702  for( int index = 0; index<NUMDIMS; ++index )
703  {
704  ASSERT( a_min[index] <= a_max[index] );
705  }
706 
707 #endif // _DEBUG
708 
709  Rect rect;
710 
711  for( int axis = 0; axis<NUMDIMS; ++axis )
712  {
713  rect.m_min[axis] = a_min[axis];
714  rect.m_max[axis] = a_max[axis];
715  }
716 
717  // NOTE: May want to return search result another way, perhaps returning the number of found elements here.
718 
719  int foundCount = 0;
720  Search( m_root, &rect, foundCount, a_resultCallback, a_context );
721  return foundCount;
722 }
723 
724 
726 DATATYPE RTREE_QUAL::NearestNeighbor( const ELEMTYPE a_point[NUMDIMS] )
727 {
728  return this->NearestNeighbor( a_point, 0, 0 );
729 }
730 
731 
733 DATATYPE RTREE_QUAL::NearestNeighbor( const ELEMTYPE a_point[NUMDIMS],
734  ELEMTYPE a_squareDistanceCallback( const ELEMTYPE a_point[NUMDIMS], DATATYPE a_data ),
735  ELEMTYPE* a_squareDistance )
736 {
737  typedef typename std::vector<NNNode*>::iterator iterator;
738  std::vector<NNNode*> nodeList;
739  Node* node = m_root;
740  NNNode* closestNode = 0;
741  while( !closestNode || !closestNode->isLeaf )
742  {
743  //check every node on this level
744  for( int index = 0; index < node->m_count; ++index )
745  {
746  NNNode* newNode = new NNNode;
747  newNode->isLeaf = node->IsLeaf();
748  newNode->m_branch = node->m_branch[index];
749  if( newNode->isLeaf && a_squareDistanceCallback )
750  newNode->minDist = a_squareDistanceCallback( a_point, newNode->m_branch.m_data );
751  else
752  newNode->minDist = this->MinDist( a_point, &(node->m_branch[index].m_rect) );
753 
754  //TODO: a custom list could be more efficient than a vector
755  this->InsertNNListSorted( &nodeList, newNode );
756  }
757  if( nodeList.size() == 0 )
758  {
759  return 0;
760  }
761  closestNode = nodeList.back();
762  node = closestNode->m_branch.m_child;
763  nodeList.pop_back();
764  free(closestNode);
765  }
766 
767  // free memory used for remaining NNNodes in nodeList
768  for( iterator iter = nodeList.begin(); iter != nodeList.end(); ++iter )
769  {
770  NNNode* nnode = *iter;
771  free(nnode);
772  }
773 
774  *a_squareDistance = closestNode->minDist;
775  return closestNode->m_branch.m_data;
776 }
777 
778 
780 int RTREE_QUAL::Count()
781 {
782  int count = 0;
783 
784  CountRec( m_root, count );
785 
786  return count;
787 }
788 
789 
791 void RTREE_QUAL::CountRec( Node* a_node, int& a_count )
792 {
793  if( a_node->IsInternalNode() ) // not a leaf node
794  {
795  for( int index = 0; index < a_node->m_count; ++index )
796  {
797  CountRec( a_node->m_branch[index].m_child, a_count );
798  }
799  }
800  else // A leaf node
801  {
802  a_count += a_node->m_count;
803  }
804 }
805 
806 
808 bool RTREE_QUAL::Load( const char* a_fileName )
809 {
810  RemoveAll(); // Clear existing tree
811 
812  RTFileStream stream;
813 
814  if( !stream.OpenRead( a_fileName ) )
815  {
816  return false;
817  }
818 
819  bool result = Load( stream );
820 
821  stream.Close();
822 
823  return result;
824 }
825 
826 
828 bool RTREE_QUAL::Load( RTFileStream& a_stream )
829 {
830  // Write some kind of header
831  int _dataFileId = ('R' << 0) | ('T' << 8) | ('R' << 16) | ('E' << 24);
832  int _dataSize = sizeof(DATATYPE);
833  int _dataNumDims = NUMDIMS;
834  int _dataElemSize = sizeof(ELEMTYPE);
835  int _dataElemRealSize = sizeof(ELEMTYPEREAL);
836  int _dataMaxNodes = TMAXNODES;
837  int _dataMinNodes = TMINNODES;
838 
839  int dataFileId = 0;
840  int dataSize = 0;
841  int dataNumDims = 0;
842  int dataElemSize = 0;
843  int dataElemRealSize = 0;
844  int dataMaxNodes = 0;
845  int dataMinNodes = 0;
846 
847  a_stream.Read( dataFileId );
848  a_stream.Read( dataSize );
849  a_stream.Read( dataNumDims );
850  a_stream.Read( dataElemSize );
851  a_stream.Read( dataElemRealSize );
852  a_stream.Read( dataMaxNodes );
853  a_stream.Read( dataMinNodes );
854 
855  bool result = false;
856 
857  // Test if header was valid and compatible
858  if( (dataFileId == _dataFileId)
859  && (dataSize == _dataSize)
860  && (dataNumDims == _dataNumDims)
861  && (dataElemSize == _dataElemSize)
862  && (dataElemRealSize == _dataElemRealSize)
863  && (dataMaxNodes == _dataMaxNodes)
864  && (dataMinNodes == _dataMinNodes)
865  )
866  {
867  // Recursively load tree
868  result = LoadRec( m_root, a_stream );
869  }
870 
871  return result;
872 }
873 
874 
876 bool RTREE_QUAL::LoadRec( Node* a_node, RTFileStream& a_stream )
877 {
878  a_stream.Read( a_node->m_level );
879  a_stream.Read( a_node->m_count );
880 
881  if( a_node->IsInternalNode() ) // not a leaf node
882  {
883  for( int index = 0; index < a_node->m_count; ++index )
884  {
885  Branch* curBranch = &a_node->m_branch[index];
886 
887  a_stream.ReadArray( curBranch->m_rect.m_min, NUMDIMS );
888  a_stream.ReadArray( curBranch->m_rect.m_max, NUMDIMS );
889 
890  curBranch->m_child = AllocNode();
891  LoadRec( curBranch->m_child, a_stream );
892  }
893  }
894  else // A leaf node
895  {
896  for( int index = 0; index < a_node->m_count; ++index )
897  {
898  Branch* curBranch = &a_node->m_branch[index];
899 
900  a_stream.ReadArray( curBranch->m_rect.m_min, NUMDIMS );
901  a_stream.ReadArray( curBranch->m_rect.m_max, NUMDIMS );
902 
903  a_stream.Read( curBranch->m_data );
904  }
905  }
906 
907  return true; // Should do more error checking on I/O operations
908 }
909 
910 
912 bool RTREE_QUAL::Save( const char* a_fileName )
913 {
914  RTFileStream stream;
915 
916  if( !stream.OpenWrite( a_fileName ) )
917  {
918  return false;
919  }
920 
921  bool result = Save( stream );
922 
923  stream.Close();
924 
925  return result;
926 }
927 
928 
930 bool RTREE_QUAL::Save( RTFileStream& a_stream )
931 {
932  // Write some kind of header
933  int dataFileId = ('R' << 0) | ('T' << 8) | ('R' << 16) | ('E' << 24);
934  int dataSize = sizeof(DATATYPE);
935  int dataNumDims = NUMDIMS;
936  int dataElemSize = sizeof(ELEMTYPE);
937  int dataElemRealSize = sizeof(ELEMTYPEREAL);
938  int dataMaxNodes = TMAXNODES;
939  int dataMinNodes = TMINNODES;
940 
941  a_stream.Write( dataFileId );
942  a_stream.Write( dataSize );
943  a_stream.Write( dataNumDims );
944  a_stream.Write( dataElemSize );
945  a_stream.Write( dataElemRealSize );
946  a_stream.Write( dataMaxNodes );
947  a_stream.Write( dataMinNodes );
948 
949  // Recursively save tree
950  bool result = SaveRec( m_root, a_stream );
951 
952  return result;
953 }
954 
955 
957 bool RTREE_QUAL::SaveRec( Node* a_node, RTFileStream& a_stream )
958 {
959  a_stream.Write( a_node->m_level );
960  a_stream.Write( a_node->m_count );
961 
962  if( a_node->IsInternalNode() ) // not a leaf node
963  {
964  for( int index = 0; index < a_node->m_count; ++index )
965  {
966  Branch* curBranch = &a_node->m_branch[index];
967 
968  a_stream.WriteArray( curBranch->m_rect.m_min, NUMDIMS );
969  a_stream.WriteArray( curBranch->m_rect.m_max, NUMDIMS );
970 
971  SaveRec( curBranch->m_child, a_stream );
972  }
973  }
974  else // A leaf node
975  {
976  for( int index = 0; index < a_node->m_count; ++index )
977  {
978  Branch* curBranch = &a_node->m_branch[index];
979 
980  a_stream.WriteArray( curBranch->m_rect.m_min, NUMDIMS );
981  a_stream.WriteArray( curBranch->m_rect.m_max, NUMDIMS );
982 
983  a_stream.Write( curBranch->m_data );
984  }
985  }
986 
987  return true; // Should do more error checking on I/O operations
988 }
989 
990 
992 void RTREE_QUAL::RemoveAll()
993 {
994  // Delete all existing nodes
995  Reset();
996 
997  m_root = AllocNode();
998  m_root->m_level = 0;
999 }
1000 
1001 
1003 void RTREE_QUAL::Reset()
1004 {
1005 #ifdef RTREE_DONT_USE_MEMPOOLS
1006  // Delete all existing nodes
1007  RemoveAllRec( m_root );
1008 #else // RTREE_DONT_USE_MEMPOOLS
1009  // Just reset memory pools. We are not using complex types
1010  // EXAMPLE
1011 #endif // RTREE_DONT_USE_MEMPOOLS
1012 }
1013 
1014 
1016 void RTREE_QUAL::RemoveAllRec( Node* a_node )
1017 {
1018  ASSERT( a_node );
1019  ASSERT( a_node->m_level >= 0 );
1020 
1021  if( a_node->IsInternalNode() ) // This is an internal node in the tree
1022  {
1023  for( int index = 0; index < a_node->m_count; ++index )
1024  {
1025  RemoveAllRec( a_node->m_branch[index].m_child );
1026  }
1027  }
1028 
1029  FreeNode( a_node );
1030 }
1031 
1032 
1034 typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
1035 {
1036  Node* newNode;
1037 
1038 #ifdef RTREE_DONT_USE_MEMPOOLS
1039  newNode = new Node;
1040 #else // RTREE_DONT_USE_MEMPOOLS
1041  // EXAMPLE
1042 #endif // RTREE_DONT_USE_MEMPOOLS
1043  InitNode( newNode );
1044  return newNode;
1045 }
1046 
1047 
1049 void RTREE_QUAL::FreeNode( Node* a_node )
1050 {
1051  ASSERT( a_node );
1052 
1053 #ifdef RTREE_DONT_USE_MEMPOOLS
1054  delete a_node;
1055 #else // RTREE_DONT_USE_MEMPOOLS
1056  // EXAMPLE
1057 #endif // RTREE_DONT_USE_MEMPOOLS
1058 }
1059 
1060 
1061 // Allocate space for a node in the list used in DeletRect to
1062 // store Nodes that are too empty.
1064 typename RTREE_QUAL::ListNode* RTREE_QUAL::AllocListNode()
1065 {
1066 #ifdef RTREE_DONT_USE_MEMPOOLS
1067  return new ListNode;
1068 #else // RTREE_DONT_USE_MEMPOOLS
1069  // EXAMPLE
1070 #endif // RTREE_DONT_USE_MEMPOOLS
1071 }
1072 
1073 
1075 void RTREE_QUAL::FreeListNode( ListNode* a_listNode )
1076 {
1077 #ifdef RTREE_DONT_USE_MEMPOOLS
1078  delete a_listNode;
1079 #else // RTREE_DONT_USE_MEMPOOLS
1080  // EXAMPLE
1081 #endif // RTREE_DONT_USE_MEMPOOLS
1082 }
1083 
1084 
1086 void RTREE_QUAL::InitNode( Node* a_node )
1087 {
1088  a_node->m_count = 0;
1089  a_node->m_level = -1;
1090 }
1091 
1092 
1094 void RTREE_QUAL::InitRect( Rect* a_rect )
1095 {
1096  for( int index = 0; index < NUMDIMS; ++index )
1097  {
1098  a_rect->m_min[index] = (ELEMTYPE) 0;
1099  a_rect->m_max[index] = (ELEMTYPE) 0;
1100  }
1101 }
1102 
1103 
1104 // Inserts a new data rectangle into the index structure.
1105 // Recursively descends tree, propagates splits back up.
1106 // Returns 0 if node was not split. Old node updated.
1107 // If node was split, returns 1 and sets the pointer pointed to by
1108 // new_node to point to the new node. Old node updated to become one of two.
1109 // The level argument specifies the number of steps up from the leaf
1110 // level to insert; e.g. a data rectangle goes in at level = 0.
1112 bool RTREE_QUAL::InsertRectRec( Rect* a_rect,
1113  const DATATYPE& a_id,
1114  Node* a_node,
1115  Node** a_newNode,
1116  int a_level )
1117 {
1118  ASSERT( a_rect && a_node && a_newNode );
1119  ASSERT( a_level >= 0 && a_level <= a_node->m_level );
1120 
1121  int index;
1122  Branch branch;
1123  Node* otherNode;
1124 
1125  // Still above level for insertion, go down tree recursively
1126  if( a_node->m_level > a_level )
1127  {
1128  index = PickBranch( a_rect, a_node );
1129 
1130  if( !InsertRectRec( a_rect, a_id, a_node->m_branch[index].m_child, &otherNode, a_level ) )
1131  {
1132  // Child was not split
1133  a_node->m_branch[index].m_rect =
1134  CombineRect( a_rect, &(a_node->m_branch[index].m_rect) );
1135  return false;
1136  }
1137  else // Child was split
1138  {
1139  a_node->m_branch[index].m_rect = NodeCover( a_node->m_branch[index].m_child );
1140  branch.m_child = otherNode;
1141  branch.m_rect = NodeCover( otherNode );
1142  return AddBranch( &branch, a_node, a_newNode );
1143  }
1144  }
1145  else if( a_node->m_level == a_level ) // Have reached level for insertion. Add rect, split if necessary
1146  {
1147  branch.m_rect = *a_rect;
1148  branch.m_child = (Node*) a_id;
1149  // Child field of leaves contains id of data record
1150  return AddBranch( &branch, a_node, a_newNode );
1151  }
1152  else
1153  {
1154  // Should never occur
1155  ASSERT( 0 );
1156  return false;
1157  }
1158 }
1159 
1160 
1161 // Insert a data rectangle into an index structure.
1162 // InsertRect provides for splitting the root;
1163 // returns 1 if root was split, 0 if it was not.
1164 // The level argument specifies the number of steps up from the leaf
1165 // level to insert; e.g. a data rectangle goes in at level = 0.
1166 // InsertRect2 does the recursion.
1167 //
1169 bool RTREE_QUAL::InsertRect( Rect* a_rect, const DATATYPE& a_id, Node** a_root, int a_level )
1170 {
1171  ASSERT( a_rect && a_root );
1172  ASSERT( a_level >= 0 && a_level <= (*a_root)->m_level );
1173 #ifdef _DEBUG
1174 
1175  for( int index = 0; index < NUMDIMS; ++index )
1176  {
1177  ASSERT( a_rect->m_min[index] <= a_rect->m_max[index] );
1178  }
1179 
1180 #endif // _DEBUG
1181 
1182  Node* newRoot;
1183  Node* newNode;
1184  Branch branch;
1185 
1186  if( InsertRectRec( a_rect, a_id, *a_root, &newNode, a_level ) ) // Root split
1187  {
1188  newRoot = AllocNode(); // Grow tree taller and new root
1189  newRoot->m_level = (*a_root)->m_level + 1;
1190  branch.m_rect = NodeCover( *a_root );
1191  branch.m_child = *a_root;
1192  AddBranch( &branch, newRoot, NULL );
1193  branch.m_rect = NodeCover( newNode );
1194  branch.m_child = newNode;
1195  AddBranch( &branch, newRoot, NULL );
1196  *a_root = newRoot;
1197  return true;
1198  }
1199 
1200  return false;
1201 }
1202 
1203 
1204 // Find the smallest rectangle that includes all rectangles in branches of a node.
1206 typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover( Node* a_node )
1207 {
1208  ASSERT( a_node );
1209 
1210  int firstTime = true;
1211  Rect rect;
1212  InitRect( &rect );
1213 
1214  for( int index = 0; index < a_node->m_count; ++index )
1215  {
1216  if( firstTime )
1217  {
1218  rect = a_node->m_branch[index].m_rect;
1219  firstTime = false;
1220  }
1221  else
1222  {
1223  rect = CombineRect( &rect, &(a_node->m_branch[index].m_rect) );
1224  }
1225  }
1226 
1227  return rect;
1228 }
1229 
1230 
1231 // Add a branch to a node. Split the node if necessary.
1232 // Returns 0 if node not split. Old node updated.
1233 // Returns 1 if node split, sets *new_node to address of new node.
1234 // Old node updated, becomes one of two.
1236 bool RTREE_QUAL::AddBranch( Branch* a_branch, Node* a_node, Node** a_newNode )
1237 {
1238  ASSERT( a_branch );
1239  ASSERT( a_node );
1240 
1241  if( a_node->m_count < MAXNODES ) // Split won't be necessary
1242  {
1243  a_node->m_branch[a_node->m_count] = *a_branch;
1244  ++a_node->m_count;
1245 
1246  return false;
1247  }
1248  else
1249  {
1250  ASSERT( a_newNode );
1251 
1252  SplitNode( a_node, a_branch, a_newNode );
1253  return true;
1254  }
1255 }
1256 
1257 
1258 // Disconnect a dependent node.
1259 // Caller must return (or stop using iteration index) after this as count has changed
1261 void RTREE_QUAL::DisconnectBranch( Node* a_node, int a_index )
1262 {
1263  ASSERT( a_node && (a_index >= 0) && (a_index < MAXNODES) );
1264  ASSERT( a_node->m_count > 0 );
1265 
1266  // Remove element by swapping with the last element to prevent gaps in array
1267  a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
1268 
1269  --a_node->m_count;
1270 }
1271 
1272 
1273 // Pick a branch. Pick the one that will need the smallest increase
1274 // in area to accomodate the new rectangle. This will result in the
1275 // least total area for the covering rectangles in the current node.
1276 // In case of a tie, pick the one which was smaller before, to get
1277 // the best resolution when searching.
1279 int RTREE_QUAL::PickBranch( Rect* a_rect, Node* a_node )
1280 {
1281  ASSERT( a_rect && a_node );
1282 
1283  bool firstTime = true;
1284  ELEMTYPEREAL increase;
1285  ELEMTYPEREAL bestIncr = (ELEMTYPEREAL) -1;
1286  ELEMTYPEREAL area;
1287  ELEMTYPEREAL bestArea = 0;
1288  int best = 0;
1289  Rect tempRect;
1290 
1291  for( int index = 0; index < a_node->m_count; ++index )
1292  {
1293  Rect* curRect = &a_node->m_branch[index].m_rect;
1294  area = CalcRectVolume( curRect );
1295  tempRect = CombineRect( a_rect, curRect );
1296  increase = CalcRectVolume( &tempRect ) - area;
1297 
1298  if( (increase < bestIncr) || firstTime )
1299  {
1300  best = index;
1301  bestArea = area;
1302  bestIncr = increase;
1303  firstTime = false;
1304  }
1305  else if( (increase == bestIncr) && (area < bestArea) )
1306  {
1307  best = index;
1308  bestArea = area;
1309  bestIncr = increase;
1310  }
1311  }
1312 
1313  return best;
1314 }
1315 
1316 
1317 // Combine two rectangles into larger one containing both
1319 typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect( Rect* a_rectA, Rect* a_rectB )
1320 {
1321  ASSERT( a_rectA && a_rectB );
1322 
1323  Rect newRect;
1324 
1325  for( int index = 0; index < NUMDIMS; ++index )
1326  {
1327  newRect.m_min[index] = rMin( a_rectA->m_min[index], a_rectB->m_min[index] );
1328  newRect.m_max[index] = rMax( a_rectA->m_max[index], a_rectB->m_max[index] );
1329  }
1330 
1331  return newRect;
1332 }
1333 
1334 
1335 // Split a node.
1336 // Divides the nodes branches and the extra one between two nodes.
1337 // Old node is one of the new ones, and one really new one is created.
1338 // Tries more than one method for choosing a partition, uses best result.
1340 void RTREE_QUAL::SplitNode( Node* a_node, Branch* a_branch, Node** a_newNode )
1341 {
1342  ASSERT( a_node );
1343  ASSERT( a_branch );
1344 
1345  // Could just use local here, but member or external is faster since it is reused
1346  PartitionVars localVars;
1347  PartitionVars* parVars = &localVars;
1348  int level;
1349 
1350  // Load all the branches into a buffer, initialize old node
1351  level = a_node->m_level;
1352  GetBranches( a_node, a_branch, parVars );
1353 
1354  // Find partition
1355  ChoosePartition( parVars, MINNODES );
1356 
1357  // Put branches from buffer into 2 nodes according to chosen partition
1358  *a_newNode = AllocNode();
1359  (*a_newNode)->m_level = a_node->m_level = level;
1360  LoadNodes( a_node, *a_newNode, parVars );
1361 
1362  ASSERT( (a_node->m_count + (*a_newNode)->m_count) == parVars->m_total );
1363 }
1364 
1365 
1366 // Calculate the n-dimensional volume of a rectangle
1368 ELEMTYPEREAL RTREE_QUAL::RectVolume( Rect* a_rect )
1369 {
1370  ASSERT( a_rect );
1371 
1372  ELEMTYPEREAL volume = (ELEMTYPEREAL) 1;
1373 
1374  for( int index = 0; index<NUMDIMS; ++index )
1375  {
1376  volume *= a_rect->m_max[index] - a_rect->m_min[index];
1377  }
1378 
1379  ASSERT( volume >= (ELEMTYPEREAL) 0 );
1380 
1381  return volume;
1382 }
1383 
1384 
1385 // The exact volume of the bounding sphere for the given Rect
1387 ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume( Rect* a_rect )
1388 {
1389  ASSERT( a_rect );
1390 
1391  ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL) 0;
1392  ELEMTYPEREAL radius;
1393 
1394  for( int index = 0; index < NUMDIMS; ++index )
1395  {
1396  ELEMTYPEREAL halfExtent =
1397  ( (ELEMTYPEREAL) a_rect->m_max[index] - (ELEMTYPEREAL) a_rect->m_min[index] ) * 0.5f;
1398  sumOfSquares += halfExtent * halfExtent;
1399  }
1400 
1401  radius = (ELEMTYPEREAL) sqrt( sumOfSquares );
1402 
1403  // Pow maybe slow, so test for common dims like 2,3 and just use x*x, x*x*x.
1404  if( NUMDIMS == 3 )
1405  {
1406  return radius * radius * radius * m_unitSphereVolume;
1407  }
1408  else if( NUMDIMS == 2 )
1409  {
1410  return radius * radius * m_unitSphereVolume;
1411  }
1412  else
1413  {
1414  return (ELEMTYPEREAL) (pow( radius, NUMDIMS ) * m_unitSphereVolume);
1415  }
1416 }
1417 
1418 
1419 // Use one of the methods to calculate retangle volume
1421 ELEMTYPEREAL RTREE_QUAL::CalcRectVolume( Rect* a_rect )
1422 {
1423 #ifdef RTREE_USE_SPHERICAL_VOLUME
1424  return RectSphericalVolume( a_rect ); // Slower but helps certain merge cases
1425 #else // RTREE_USE_SPHERICAL_VOLUME
1426  return RectVolume( a_rect ); // Faster but can cause poor merges
1427 #endif // RTREE_USE_SPHERICAL_VOLUME
1428 }
1429 
1430 
1431 // Load branch buffer with branches from full node plus the extra branch.
1433 void RTREE_QUAL::GetBranches( Node* a_node, Branch* a_branch, PartitionVars* a_parVars )
1434 {
1435  ASSERT( a_node );
1436  ASSERT( a_branch );
1437 
1438  ASSERT( a_node->m_count == MAXNODES );
1439 
1440  // Load the branch buffer
1441  for( int index = 0; index < MAXNODES; ++index )
1442  {
1443  a_parVars->m_branchBuf[index] = a_node->m_branch[index];
1444  }
1445 
1446  a_parVars->m_branchBuf[MAXNODES] = *a_branch;
1447  a_parVars->m_branchCount = MAXNODES + 1;
1448 
1449  // Calculate rect containing all in the set
1450  a_parVars->m_coverSplit = a_parVars->m_branchBuf[0].m_rect;
1451 
1452  for( int index = 1; index < MAXNODES + 1; ++index )
1453  {
1454  a_parVars->m_coverSplit =
1455  CombineRect( &a_parVars->m_coverSplit, &a_parVars->m_branchBuf[index].m_rect );
1456  }
1457 
1458  a_parVars->m_coverSplitArea = CalcRectVolume( &a_parVars->m_coverSplit );
1459 
1460  InitNode( a_node );
1461 }
1462 
1463 
1464 // Method #0 for choosing a partition:
1465 // As the seeds for the two groups, pick the two rects that would waste the
1466 // most area if covered by a single rectangle, i.e. evidently the worst pair
1467 // to have in the same group.
1468 // Of the remaining, one at a time is chosen to be put in one of the two groups.
1469 // The one chosen is the one with the greatest difference in area expansion
1470 // depending on which group - the rect most strongly attracted to one group
1471 // and repelled from the other.
1472 // If one group gets too full (more would force other group to violate min
1473 // fill requirement) then other group gets the rest.
1474 // These last are the ones that can go in either group most easily.
1476 void RTREE_QUAL::ChoosePartition( PartitionVars* a_parVars, int a_minFill )
1477 {
1478  ASSERT( a_parVars );
1479 
1480  ELEMTYPEREAL biggestDiff;
1481  int group, chosen = 0, betterGroup = 0;
1482 
1483  InitParVars( a_parVars, a_parVars->m_branchCount, a_minFill );
1484  PickSeeds( a_parVars );
1485 
1486  while( ( (a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total )
1487  && ( a_parVars->m_count[0] < (a_parVars->m_total - a_parVars->m_minFill) )
1488  && ( a_parVars->m_count[1] < (a_parVars->m_total - a_parVars->m_minFill) ) )
1489  {
1490  biggestDiff = (ELEMTYPEREAL) -1;
1491 
1492  for( int index = 0; index<a_parVars->m_total; ++index )
1493  {
1494  if( !a_parVars->m_taken[index] )
1495  {
1496  Rect* curRect = &a_parVars->m_branchBuf[index].m_rect;
1497  Rect rect0 = CombineRect( curRect, &a_parVars->m_cover[0] );
1498  Rect rect1 = CombineRect( curRect, &a_parVars->m_cover[1] );
1499  ELEMTYPEREAL growth0 = CalcRectVolume( &rect0 ) - a_parVars->m_area[0];
1500  ELEMTYPEREAL growth1 = CalcRectVolume( &rect1 ) - a_parVars->m_area[1];
1501  ELEMTYPEREAL diff = growth1 - growth0;
1502 
1503  if( diff >= 0 )
1504  {
1505  group = 0;
1506  }
1507  else
1508  {
1509  group = 1;
1510  diff = -diff;
1511  }
1512 
1513  if( diff > biggestDiff )
1514  {
1515  biggestDiff = diff;
1516  chosen = index;
1517  betterGroup = group;
1518  }
1519  else if( (diff == biggestDiff)
1520  && (a_parVars->m_count[group] < a_parVars->m_count[betterGroup]) )
1521  {
1522  chosen = index;
1523  betterGroup = group;
1524  }
1525  }
1526  }
1527 
1528  Classify( chosen, betterGroup, a_parVars );
1529  }
1530 
1531  // If one group too full, put remaining rects in the other
1532  if( (a_parVars->m_count[0] + a_parVars->m_count[1]) < a_parVars->m_total )
1533  {
1534  if( a_parVars->m_count[0] >= a_parVars->m_total - a_parVars->m_minFill )
1535  {
1536  group = 1;
1537  }
1538  else
1539  {
1540  group = 0;
1541  }
1542 
1543  for( int index = 0; index<a_parVars->m_total; ++index )
1544  {
1545  if( !a_parVars->m_taken[index] )
1546  {
1547  Classify( index, group, a_parVars );
1548  }
1549  }
1550  }
1551 
1552  ASSERT( (a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total );
1553  ASSERT( (a_parVars->m_count[0] >= a_parVars->m_minFill)
1554  && (a_parVars->m_count[1] >= a_parVars->m_minFill) );
1555 }
1556 
1557 
1558 // Copy branches from the buffer into two nodes according to the partition.
1560 void RTREE_QUAL::LoadNodes( Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars )
1561 {
1562  ASSERT( a_nodeA );
1563  ASSERT( a_nodeB );
1564  ASSERT( a_parVars );
1565 
1566  for( int index = 0; index < a_parVars->m_total; ++index )
1567  {
1568  ASSERT( a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1 );
1569 
1570  if( a_parVars->m_partition[index] == 0 )
1571  {
1572  AddBranch( &a_parVars->m_branchBuf[index], a_nodeA, NULL );
1573  }
1574  else if( a_parVars->m_partition[index] == 1 )
1575  {
1576  AddBranch( &a_parVars->m_branchBuf[index], a_nodeB, NULL );
1577  }
1578  }
1579 }
1580 
1581 
1582 // Initialize a PartitionVars structure.
1584 void RTREE_QUAL::InitParVars( PartitionVars* a_parVars, int a_maxRects, int a_minFill )
1585 {
1586  ASSERT( a_parVars );
1587 
1588  a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
1589  a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL) 0;
1590  a_parVars->m_total = a_maxRects;
1591  a_parVars->m_minFill = a_minFill;
1592 
1593  for( int index = 0; index < a_maxRects; ++index )
1594  {
1595  a_parVars->m_taken[index] = false;
1596  a_parVars->m_partition[index] = -1;
1597  }
1598 }
1599 
1600 
1602 void RTREE_QUAL::PickSeeds( PartitionVars* a_parVars )
1603 {
1604  int seed0 = 0, seed1 = 0;
1605  ELEMTYPEREAL worst, waste;
1606  ELEMTYPEREAL area[MAXNODES + 1];
1607 
1608  for( int index = 0; index<a_parVars->m_total; ++index )
1609  {
1610  area[index] = CalcRectVolume( &a_parVars->m_branchBuf[index].m_rect );
1611  }
1612 
1613  worst = -a_parVars->m_coverSplitArea - 1;
1614 
1615  for( int indexA = 0; indexA < a_parVars->m_total - 1; ++indexA )
1616  {
1617  for( int indexB = indexA + 1; indexB < a_parVars->m_total; ++indexB )
1618  {
1619  Rect oneRect = CombineRect( &a_parVars->m_branchBuf[indexA].m_rect,
1620  &a_parVars->m_branchBuf[indexB].m_rect );
1621  waste = CalcRectVolume( &oneRect ) - area[indexA] - area[indexB];
1622 
1623  if( waste >= worst )
1624  {
1625  worst = waste;
1626  seed0 = indexA;
1627  seed1 = indexB;
1628  }
1629  }
1630  }
1631 
1632  Classify( seed0, 0, a_parVars );
1633  Classify( seed1, 1, a_parVars );
1634 }
1635 
1636 
1637 // Put a branch in one of the groups.
1639 void RTREE_QUAL::Classify( int a_index, int a_group, PartitionVars* a_parVars )
1640 {
1641  ASSERT( a_parVars );
1642  ASSERT( !a_parVars->m_taken[a_index] );
1643 
1644  a_parVars->m_partition[a_index] = a_group;
1645  a_parVars->m_taken[a_index] = true;
1646 
1647  if( a_parVars->m_count[a_group] == 0 )
1648  {
1649  a_parVars->m_cover[a_group] = a_parVars->m_branchBuf[a_index].m_rect;
1650  }
1651  else
1652  {
1653  a_parVars->m_cover[a_group] = CombineRect( &a_parVars->m_branchBuf[a_index].m_rect,
1654  &a_parVars->m_cover[a_group] );
1655  }
1656 
1657  a_parVars->m_area[a_group] = CalcRectVolume( &a_parVars->m_cover[a_group] );
1658  ++a_parVars->m_count[a_group];
1659 }
1660 
1661 
1662 // Delete a data rectangle from an index structure.
1663 // Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node.
1664 // Returns 1 if record not found, 0 if success.
1665 // RemoveRect provides for eliminating the root.
1667 bool RTREE_QUAL::RemoveRect( Rect* a_rect, const DATATYPE& a_id, Node** a_root )
1668 {
1669  ASSERT( a_rect && a_root );
1670  ASSERT( *a_root );
1671 
1672  Node* tempNode;
1673  ListNode* reInsertList = NULL;
1674 
1675  if( !RemoveRectRec( a_rect, a_id, *a_root, &reInsertList ) )
1676  {
1677  // Found and deleted a data item
1678  // Reinsert any branches from eliminated nodes
1679  while( reInsertList )
1680  {
1681  tempNode = reInsertList->m_node;
1682 
1683  for( int index = 0; index < tempNode->m_count; ++index )
1684  {
1685  InsertRect( &(tempNode->m_branch[index].m_rect),
1686  tempNode->m_branch[index].m_data,
1687  a_root,
1688  tempNode->m_level );
1689  }
1690 
1691  ListNode* remLNode = reInsertList;
1692  reInsertList = reInsertList->m_next;
1693 
1694  FreeNode( remLNode->m_node );
1695  FreeListNode( remLNode );
1696  }
1697 
1698  // Check for redundant root (not leaf, 1 child) and eliminate
1699  if( (*a_root)->m_count == 1 && (*a_root)->IsInternalNode() )
1700  {
1701  tempNode = (*a_root)->m_branch[0].m_child;
1702 
1703  ASSERT( tempNode );
1704  FreeNode( *a_root );
1705  *a_root = tempNode;
1706  }
1707 
1708  return false;
1709  }
1710  else
1711  {
1712  return true;
1713  }
1714 }
1715 
1716 
1717 // Delete a rectangle from non-root part of an index structure.
1718 // Called by RemoveRect. Descends tree recursively,
1719 // merges branches on the way back up.
1720 // Returns 1 if record not found, 0 if success.
1722 bool RTREE_QUAL::RemoveRectRec( Rect* a_rect,
1723  const DATATYPE& a_id,
1724  Node* a_node,
1725  ListNode** a_listNode )
1726 {
1727  ASSERT( a_rect && a_node && a_listNode );
1728  ASSERT( a_node->m_level >= 0 );
1729 
1730  if( a_node->IsInternalNode() ) // not a leaf node
1731  {
1732  for( int index = 0; index < a_node->m_count; ++index )
1733  {
1734  if( Overlap( a_rect, &(a_node->m_branch[index].m_rect) ) )
1735  {
1736  if( !RemoveRectRec( a_rect, a_id, a_node->m_branch[index].m_child, a_listNode ) )
1737  {
1738  if( a_node->m_branch[index].m_child->m_count >= MINNODES )
1739  {
1740  // child removed, just resize parent rect
1741  a_node->m_branch[index].m_rect =
1742  NodeCover( a_node->m_branch[index].m_child );
1743  }
1744  else
1745  {
1746  // child removed, not enough entries in node, eliminate node
1747  ReInsert( a_node->m_branch[index].m_child, a_listNode );
1748  DisconnectBranch( a_node, index ); // Must return after this call as count has changed
1749  }
1750 
1751  return false;
1752  }
1753  }
1754  }
1755 
1756  return true;
1757  }
1758  else // A leaf node
1759  {
1760  for( int index = 0; index < a_node->m_count; ++index )
1761  {
1762  if( a_node->m_branch[index].m_child == (Node*) a_id )
1763  {
1764  DisconnectBranch( a_node, index ); // Must return after this call as count has changed
1765  return false;
1766  }
1767  }
1768 
1769  return true;
1770  }
1771 }
1772 
1773 
1774 // Decide whether two rectangles overlap.
1776 bool RTREE_QUAL::Overlap( Rect* a_rectA, Rect* a_rectB )
1777 {
1778  ASSERT( a_rectA && a_rectB );
1779 
1780  for( int index = 0; index < NUMDIMS; ++index )
1781  {
1782  if( a_rectA->m_min[index] > a_rectB->m_max[index]
1783  || a_rectB->m_min[index] > a_rectA->m_max[index] )
1784  {
1785  return false;
1786  }
1787  }
1788 
1789  return true;
1790 }
1791 
1792 
1793 // Add a node to the reinsertion list. All its branches will later
1794 // be reinserted into the index structure.
1796 void RTREE_QUAL::ReInsert( Node* a_node, ListNode** a_listNode )
1797 {
1798  ListNode* newListNode;
1799 
1800  newListNode = AllocListNode();
1801  newListNode->m_node = a_node;
1802  newListNode->m_next = *a_listNode;
1803  *a_listNode = newListNode;
1804 }
1805 
1806 
1807 // Search in an index tree or subtree for all data retangles that overlap the argument rectangle.
1809 bool RTREE_QUAL::Search( Node* a_node, Rect* a_rect, int& a_foundCount, bool a_resultCallback(
1810  DATATYPE a_data,
1811  void* a_context ), void* a_context )
1812 {
1813  ASSERT( a_node );
1814  ASSERT( a_node->m_level >= 0 );
1815  ASSERT( a_rect );
1816 
1817  if( a_node->IsInternalNode() ) // This is an internal node in the tree
1818  {
1819  for( int index = 0; index < a_node->m_count; ++index )
1820  {
1821  if( Overlap( a_rect, &a_node->m_branch[index].m_rect ) )
1822  {
1823  if( !Search( a_node->m_branch[index].m_child, a_rect, a_foundCount,
1824  a_resultCallback, a_context ) )
1825  {
1826  return false; // Don't continue searching
1827  }
1828  }
1829  }
1830  }
1831  else // This is a leaf node
1832  {
1833  for( int index = 0; index < a_node->m_count; ++index )
1834  {
1835  if( Overlap( a_rect, &a_node->m_branch[index].m_rect ) )
1836  {
1837  DATATYPE& id = a_node->m_branch[index].m_data;
1838 
1839  // NOTE: There are different ways to return results. Here's where to modify
1840  if( &a_resultCallback )
1841  {
1842  ++a_foundCount;
1843 
1844  if( !a_resultCallback( id, a_context ) )
1845  {
1846  return false; // Don't continue searching
1847  }
1848  }
1849  }
1850  }
1851  }
1852 
1853  return true; // Continue searching
1854 }
1855 
1856 
1857 //calculate the minimum distance between a point and a rectangle as defined by Manolopoulos et al.
1858 //it uses the square distance to avoid the use of ELEMTYPEREAL values, which are slower.
1860 ELEMTYPE RTREE_QUAL::MinDist( const ELEMTYPE a_point[NUMDIMS], Rect* a_rect )
1861 {
1862  ELEMTYPE *q, *s, *t;
1863  q = (ELEMTYPE*) a_point;
1864  s = a_rect->m_min;
1865  t = a_rect->m_max;
1866  int minDist = 0;
1867  for( int index = 0; index < NUMDIMS; index++ )
1868  {
1869  int r = q[index];
1870  if( q[index] < s[index] )
1871  {
1872  r = s[index];
1873  }
1874  else if( q[index] >t[index] )
1875  {
1876  r = t[index];
1877  }
1878  int addend = q[index] - r;
1879  minDist += addend * addend;
1880  }
1881  return minDist;
1882 }
1883 
1884 
1885 //insert a NNNode in a list sorted by its minDist (desc.)
1887 void RTREE_QUAL::InsertNNListSorted( std::vector<NNNode*>* nodeList, NNNode* newNode )
1888 {
1889  typedef typename std::vector<NNNode*>::iterator iterator;
1890  iterator iter = nodeList->begin();
1891  while( iter != nodeList->end() && (*iter)->minDist > newNode->minDist )
1892  {
1893  ++iter;
1894  }
1895  nodeList->insert(iter, newNode);
1896 }
1897 
1898 
1899 #undef RTREE_TEMPLATE
1900 #undef RTREE_QUAL
1901 #undef RTREE_SEARCH_TEMPLATE
1902 #undef RTREE_SEARCH_QUAL
1903 
1904 #endif // RTREE_H
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], VISITOR &a_visitor)
Definition: rtree.h:135
int PickBranch(Rect *a_rect, Node *a_node)
#define RTREE_TEMPLATE
Definition: rtree.h:45
bool isLeaf
Definition: rtree.h:432
void GetNext(Iterator &a_it)
Get Next for iteration.
Definition: rtree.h:363
DATATYPE m_data
Data Id or Ptr.
Definition: rtree.h:388
bool OpenWrite(const char *a_fileName)
Definition: rtree.h:557
bool InsertRectRec(Rect *a_rect, const DATATYPE &a_id, Node *a_node, Node **a_newNode, int a_level)
void PickSeeds(PartitionVars *a_parVars)
FILE * m_file
Definition: rtree.h:531
StackElement & Pop()
Pop element off iteration stack (For internal use only)
Definition: rtree.h:322
bool OpenRead(const char *a_fileName)
Definition: rtree.h:545
void Close()
Definition: rtree.h:569
Min elements in node.
Definition: rtree.h:90
bool RemoveRect(Rect *a_rect, const DATATYPE &a_id, Node **a_root)
May be data or may be another subtree The parents level determines this.
Definition: rtree.h:382
#define rMax
Definition: rtree.h:38
int maxNodeLoad
Definition: rtree.h:97
Node for each branch level.
Definition: rtree.h:393
ELEMTYPEREAL RectVolume(Rect *a_rect)
const DATATYPE & operator*() const
Access the current data element. Caller must be sure iterator is not NULL first.
Definition: rtree.h:237
int Count()
Count the data elements in this container. This is slow as no internal counter is maintained...
bool Search(Node *a_node, Rect *a_rect, VISITOR &a_visitor, int &a_foundCount)
Definition: rtree.h:477
Minimal bounding rectangle (n-dimensional)
Definition: rtree.h:373
ELEMTYPE m_min[NUMDIMS]
Min dimensions of bounding box.
Definition: rtree.h:375
Node * m_root
Root of tree.
Definition: rtree.h:522
Max elements in node.
Definition: rtree.h:89
ELEMTYPE MinDist(const ELEMTYPE a_point[NUMDIMS], Rect *a_rect)
size_t Read(TYPE &a_value)
Definition: rtree.h:593
void ChoosePartition(PartitionVars *a_parVars, int a_minFill)
ELEMTYPEREAL RectSphericalVolume(Rect *a_rect)
virtual ~RTree()
Statistics CalcStats()
Calculate Statistics.
void RemoveAll()
Remove all entries from tree.
void FreeListNode(ListNode *a_listNode)
void Init()
Reset iterator.
Definition: rtree.h:264
void InitParVars(PartitionVars *a_parVars, int a_maxRects, int a_minFill)
ELEMTYPE m_max[NUMDIMS]
Max dimensions of bounding box.
Definition: rtree.h:376
bool IsLeaf()
Definition: rtree.h:396
static struct PcbQueue * Save
Definition: queue.cpp:56
Rect NodeCover(Node *a_node)
Node * m_node
Node.
Definition: rtree.h:407
bool Overlap(Rect *a_rectA, Rect *a_rectB)
#define rMin
Definition: rtree.h:35
DATATYPE NearestNeighbor(const ELEMTYPE a_point[NUMDIMS])
Find the nearest neighbor of a specific point.
Node * m_child
Child node.
Definition: rtree.h:387
void SplitNode(Node *a_node, Branch *a_branch, Node **a_newNode)
A link list of nodes for reinsertion after a delete operation.
Definition: rtree.h:404
int totalItems
Definition: rtree.h:99
int m_count
Count.
Definition: rtree.h:398
ListNode * m_next
Next in list.
Definition: rtree.h:406
Rect m_rect
Bounds.
Definition: rtree.h:384
int avgNodeLoad
Definition: rtree.h:98
bool InsertRect(Rect *a_rect, const DATATYPE &a_id, Node **a_root, int a_level)
void LoadNodes(Node *a_nodeA, Node *a_nodeB, PartitionVars *a_parVars)
void DisconnectBranch(Node *a_node, int a_index)
void Reset()
bool SaveRec(Node *a_node, RTFileStream &a_stream)
bool IsNull()
Is iterator invalid.
Definition: rtree.h:223
ELEMTYPEREAL m_unitSphereVolume
Unit sphere constant for required number of dimensions.
Definition: rtree.h:523
bool RemoveRectRec(Rect *a_rect, const DATATYPE &a_id, Node *a_node, ListNode **a_listNode)
bool IsNotNull()
Is iterator pointing to valid data.
Definition: rtree.h:226
ELEMTYPEREAL CalcRectVolume(Rect *a_rect)
void Insert(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Insert entry.
DATATYPE & operator*()
Access the current data element. Caller must be sure iterator is not NULL first.
Definition: rtree.h:229
int m_level
Leaf is zero, others positive.
Definition: rtree.h:399
Implementation of RTree, a multidimensional bounding rectangle tree.
Definition: rtree.h:79
Node * AllocNode()
void GetFirst(Iterator &a_it)
Get &#39;first&#39; for iteration.
Definition: rtree.h:337
bool IsNull(Iterator &a_it)
Is iterator NULL, or at end?
Definition: rtree.h:366
bool operator++()
Find the next data element.
Definition: rtree.h:245
DATATYPE & GetAt(Iterator &a_it)
Get object at iterator position.
Definition: rtree.h:369
Variables for finding a split partition.
Definition: rtree.h:411
void CountRec(Node *a_node, int &a_count)
Rect CombineRect(Rect *a_rectA, Rect *a_rectB)
Branch m_branch[MAXNODES]
Branch.
Definition: rtree.h:400
bool Save(const char *a_fileName)
Save tree contents to file.
void ReInsert(Node *a_node, ListNode **a_listNode)
void RemoveAllRec(Node *a_node)
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
Get the bounds for this node.
Definition: rtree.h:248
void InsertNNListSorted(std::vector< NNNode * > *nodeList, NNNode *newNode)
ListNode * AllocListNode()
void FreeNode(Node *a_node)
void Remove(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], const DATATYPE &a_dataId)
Remove entry.
bool Load(const char *a_fileName)
Load tree contents from file.
ELEMTYPE minDist
Definition: rtree.h:431
bool IsInternalNode()
Definition: rtree.h:395
void InitNode(Node *a_node)
void Push(Node *a_node, int a_branchIndex)
Push node and branch onto iteration stack (For internal use only)
Definition: rtree.h:313
int Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], bool a_resultCallback(DATATYPE a_data, void *a_context), void *a_context)
Find all within search rectangle.
KICAD_PLUGIN_EXPORT SCENEGRAPH * Load(char const *aFileName)
reads a model file and creates a generic display structure
Data structure used for Nearest Neighbor search implementation.
Definition: rtree.h:428
void Classify(int a_index, int a_group, PartitionVars *a_parVars)
~RTFileStream()
Definition: rtree.h:540
bool FindNextData()
Find the next data element in the tree (For internal use only)
Definition: rtree.h:267
bool LoadRec(Node *a_node, RTFileStream &a_stream)
size_t ReadArray(TYPE *a_array, int a_count)
Definition: rtree.h:600
#define ASSERT
Definition: rtree.h:33
size_t WriteArray(const TYPE *a_array, int a_count)
Definition: rtree.h:586
size_t Write(const TYPE &a_value)
Definition: rtree.h:579
Branch m_branch
Definition: rtree.h:430
bool AddBranch(Branch *a_branch, Node *a_node, Node **a_newNode)
Iterator is not remove safe.
Definition: rtree.h:205
void GetBranches(Node *a_node, Branch *a_branch, PartitionVars *a_parVars)
int m_tos
Top Of Stack index.
Definition: rtree.h:330
void InitRect(Rect *a_rect)
ELEMTYPEREAL m_coverSplitArea
Definition: rtree.h:424
RTFileStream()
Definition: rtree.h:535