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