1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkCellTreeLocator.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkCellTreeLocator.h"
17 #include <cstdlib>
18 #include <cassert>
19 #include <cmath>
20 #include <stack>
21 #include <vector>
22 #include <limits>
23 #include <algorithm>
24 #include "vtkObjectFactory.h"
25 #include "vtkGenericCell.h"
26 #include "vtkIdListCollection.h"
27 #include "vtkSmartPointer.h"
28 #include "vtkCellArray.h"
29 #include "vtkPolyData.h"
30 #include "vtkBoundingBox.h"
31 #include "vtkPointData.h"
32 
33 vtkStandardNewMacro(vtkCellTreeLocator);
34 
35 namespace
36 {
37   const double EPSILON_= 1E-8;
38   enum { POS_X, NEG_X, POS_Y, NEG_Y, POS_Z, NEG_Z };
39   #define CELLTREE_MAX_DEPTH 32
40 }
41 
42 // -------------------------------------------------------------------------
43 // This class is the basic building block of the cell tree.  There is a node per dimension. i.e. There are 3 vtkCellTreeNode
44 // in x,y,z directions.  In contrast, vtkModifiedBSPTree class stores the bounding planes for all 3 dimensions in a single node.
45 // LeftMax and rm defines the bounding planes.
46 // start is the location in the cell tree. e.g. for root node start is zero.
47 // size is the number of the nodes under the tree
MakeNode(unsigned int left,unsigned int d,float b[2])48 inline void vtkCellTreeLocator::vtkCellTreeNode::MakeNode( unsigned int left, unsigned int d, float b[2] ) // b is an array containing left max and right min values
49 {
50   this->Index = (d & 3) | (left << 2);
51   this->LeftMax = b[0];
52   this->RightMin = b[1];
53 }
54 //----------------------------------------------------------------------------
SetChildren(unsigned int left)55 inline void vtkCellTreeLocator::vtkCellTreeNode::SetChildren( unsigned int left )
56 {
57   this->Index = GetDimension() | (left << 2); // In index 2 LSBs (Least Significant Bits) store the dimension. MSBs store the position
58 }
59 //----------------------------------------------------------------------------
IsNode() const60 inline bool vtkCellTreeLocator::vtkCellTreeNode::IsNode() const
61 {
62   return (this->Index & 3) != 3;    // For a leaf 2 LSBs in index is 3
63 }
64 //----------------------------------------------------------------------------
GetLeftChildIndex() const65 inline unsigned int vtkCellTreeLocator::vtkCellTreeNode::GetLeftChildIndex() const
66 {
67   return (this->Index >> 2);
68 }
69 //----------------------------------------------------------------------------
GetRightChildIndex() const70 inline unsigned int vtkCellTreeLocator::vtkCellTreeNode::GetRightChildIndex() const
71 {
72   return (this->Index >> 2) + 1;  // Right child node is adjacent to the Left child node in the data structure
73 }
74 //----------------------------------------------------------------------------
GetDimension() const75 inline unsigned int vtkCellTreeLocator::vtkCellTreeNode::GetDimension() const
76 {
77   return this->Index & 3;
78 }
79 //----------------------------------------------------------------------------
GetLeftMaxValue() const80 inline const float& vtkCellTreeLocator::vtkCellTreeNode::GetLeftMaxValue() const
81 {
82   return this->LeftMax;
83 }
84 //----------------------------------------------------------------------------
GetRightMinValue() const85 inline const float& vtkCellTreeLocator::vtkCellTreeNode::GetRightMinValue() const
86 {
87   return this->RightMin;
88 }
89 //----------------------------------------------------------------------------
MakeLeaf(unsigned int start,unsigned int size)90 inline void vtkCellTreeLocator::vtkCellTreeNode::MakeLeaf( unsigned int start, unsigned int size )
91 {
92   this->Index = 3;
93   this->Sz = size;
94   this->St = start;
95 }
96 //----------------------------------------------------------------------------
IsLeaf() const97 bool vtkCellTreeLocator::vtkCellTreeNode::IsLeaf() const
98 {
99   return this->Index == 3;
100 }
101 //----------------------------------------------------------------------------
Start() const102 unsigned int vtkCellTreeLocator::vtkCellTreeNode::Start() const
103 {
104   return this->St;
105 }
106 //----------------------------------------------------------------------------
Size() const107 unsigned int vtkCellTreeLocator::vtkCellTreeNode::Size() const
108 {
109   return this->Sz;
110 }
111 //----------------------------------------------------------------------------
112 //
113 //----------------------------------------------------------------------------
114 // This is a helper class to traverse the cell tree. This is derived from avtCellLocatorBIH class in VisIT
115 // Member variables of this class starts with m_*
116 class vtkCellPointTraversal
117 {
118   private:
119     const vtkCellTreeLocator::vtkCellTree& m_ct;
120     unsigned int    m_stack[CELLTREE_MAX_DEPTH];
121     unsigned int*   m_sp; // stack pointer
122     const float*    m_pos; //3-D coordinates of the points
123     vtkCellPointTraversal(const vtkCellPointTraversal&) = delete;
124     void operator=(vtkCellPointTraversal&) = delete;
125 
126   protected:
127     friend class vtkCellTreeLocator::vtkCellTree;
128     friend class vtkCellTreeLocator::vtkCellTreeNode;
129     friend class vtkCellTreeBuilder;
130 
131   public:
vtkCellPointTraversal(const vtkCellTreeLocator::vtkCellTree & ct,const float * pos)132     vtkCellPointTraversal( const vtkCellTreeLocator::vtkCellTree& ct, const float* pos ) :
133         m_ct(ct), m_pos(pos)
134     {
135           this->m_stack[0] = 0; // first element is set to zero
136           this->m_sp = this->m_stack + 1; //this points to the second element of the stack
137     }
138 
Next()139         const vtkCellTreeLocator::vtkCellTreeNode* Next()  // this returns n (the location in the CellTree) if it is a leaf or 0 if the point doesn't contain in the data domain
140         {
141           while( true )
142           {
143             if( this->m_sp == this->m_stack ) //This means the point is not within the domain
144             {
145               return nullptr;
146             }
147 
148             const vtkCellTreeLocator::vtkCellTreeNode* n = &this->m_ct.Nodes.front() + *(--this->m_sp);
149 
150             if( n->IsLeaf() )
151             {
152               return n;
153             }
154 
155             const float p = m_pos[n->GetDimension()];
156             const unsigned int left = n->GetLeftChildIndex();
157 
158             bool l = p <= n->GetLeftMaxValue(); // Check if the points is within the left sub tree
159             bool r = p >= n->GetRightMinValue(); // Check if the point is within the right sub tree
160 
161             if( l && r ) //  This means if there is a overlap region both left and right sub trees should be traversed
162             {
163               if( n->GetLeftMaxValue()-p < p-n->GetRightMinValue() )
164               {
165                 *(this->m_sp++) = left;
166                 *(this->m_sp++) = left+1;
167               }
168               else
169               {
170                 *(this->m_sp++) = left+1;
171                 *(this->m_sp++) = left;
172               }
173             }
174             else if( l )
175             {
176               *(this->m_sp++) = left;
177             }
178             else if( r )
179             {
180               *(this->m_sp++) = left+1;
181             }
182           }
183         }
184 };
185 //----------------------------------------------------------------------------
186 // This class builds the CellTree according to the algorithm given in the paper.
187 // This class is derived from the avtCellLocatorBIH class in VisIT.  Member variables of this class starts with m_*
188 //----------------------------------------------------------------------------
189 class vtkCellTreeBuilder
190 {
191   private:
192 
193     struct Bucket
194     {
195       float  Min;
196       float  Max;
197       unsigned int Cnt;
198 
BucketvtkCellTreeBuilder::Bucket199       Bucket()
200       {
201         Cnt = 0;
202         Min =  std::numeric_limits<float>::max();
203         Max = -std::numeric_limits<float>::max();
204       }
205 
AddvtkCellTreeBuilder::Bucket206       void Add( const float _min, const float _max )
207       {
208         ++Cnt;
209 
210         if( _min < Min )
211         {
212           Min = _min;
213         }
214 
215         if( _max > Max )
216         {
217           Max = _max;
218         }
219       }
220     };
221 
222     struct PerCell
223     {
224       float  Min[3];
225       float  Max[3];
226       unsigned int Ind;
227     };
228 
229     struct CenterOrder
230     {
231       unsigned int d;
CenterOrdervtkCellTreeBuilder::CenterOrder232       CenterOrder( unsigned int _d ) : d(_d) {}
233 
operator ()vtkCellTreeBuilder::CenterOrder234       bool operator()( const PerCell& pc0, const PerCell& pc1 )
235       {
236         return (pc0.Min[d] + pc0.Max[d]) < (pc1.Min[d] + pc1.Max[d]);
237       }
238     };
239 
240     struct LeftPredicate
241     {
242       unsigned int d;
243       float  p;
LeftPredicatevtkCellTreeBuilder::LeftPredicate244       LeftPredicate( unsigned int _d, float _p ) :  d(_d), p(2.0f*_p) {}
245 
operator ()vtkCellTreeBuilder::LeftPredicate246       bool operator()( const PerCell& pc )
247       {
248         return (pc.Min[d] + pc.Max[d]) < p;
249       }
250     };
251 
252 
253     // -------------------------------------------------------------------------
254 
FindMinMax(const PerCell * begin,const PerCell * end,float * min,float * max)255     void FindMinMax( const PerCell* begin, const PerCell* end,
256       float* min, float* max )
257     {
258       if( begin == end )
259       {
260         return;
261       }
262 
263       for( unsigned int d=0; d<3; ++d )
264       {
265         min[d] = begin->Min[d];
266         max[d] = begin->Max[d];
267       }
268 
269 
270       while( ++begin != end )
271       {
272         for( unsigned int d=0; d<3; ++d )
273         {
274           if( begin->Min[d] < min[d] )    min[d] = begin->Min[d];
275           if( begin->Max[d] > max[d] )    max[d] = begin->Max[d];
276         }
277       }
278     }
279 
280     // -------------------------------------------------------------------------
281 
Split(unsigned int index,float min[3],float max[3])282     void Split( unsigned int index, float min[3], float max[3] )
283     {
284       unsigned int start = this->m_nodes[index].Start();
285       unsigned int size  = this->m_nodes[index].Size();
286 
287       if( size < this->m_leafsize )
288       {
289         return;
290       }
291 
292       PerCell* begin = &(this->m_pc[start]);
293       PerCell* end   = &(this->m_pc[0])+start + size;
294       PerCell* mid = begin;
295 
296       const int nbuckets = 6;
297 
298       const float ext[3] = { max[0]-min[0], max[1]-min[1], max[2]-min[2] };
299       const float iext[3] = { nbuckets/ext[0], nbuckets/ext[1], nbuckets/ext[2] };
300 
301       Bucket b[3][nbuckets];
302 
303       for( const PerCell* pc=begin; pc!=end; ++pc )
304       {
305         for( unsigned int d=0; d<3; ++d )
306         {
307           float cen = (pc->Min[d] + pc->Max[d])/2.0f;
308           int   ind = (int)( (cen-min[d])*iext[d] );
309 
310           if( ind<0 )
311           {
312             ind = 0;
313           }
314 
315           if( ind>=nbuckets )
316           {
317             ind = nbuckets-1;
318           }
319 
320           b[d][ind].Add( pc->Min[d], pc->Max[d] );
321         }
322       }
323 
324       float cost = std::numeric_limits<float>::max();
325       float plane = VTK_FLOAT_MIN; // bad value in case it doesn't get setx
326       unsigned int dim = VTK_INT_MAX; // bad value in case it doesn't get set
327 
328       for( unsigned int d=0; d<3; ++d )
329       {
330         unsigned int sum = 0;
331 
332         for( unsigned int n=0; n< (unsigned int)nbuckets-1; ++n )
333         {
334           float lmax = -std::numeric_limits<float>::max();
335           float rmin =  std::numeric_limits<float>::max();
336 
337           for( unsigned int m=0; m<=n; ++m )
338           {
339             if( b[d][m].Max > lmax )
340             {
341               lmax = b[d][m].Max;
342             }
343           }
344 
345           for( unsigned int m=n+1; m< (unsigned int) nbuckets; ++m )
346           {
347             if( b[d][m].Min < rmin )
348             {
349               rmin = b[d][m].Min;
350             }
351           }
352 
353           //
354           // JB : added if (...) to stop floating point error if rmin is unset
355           // this happens when some buckets are empty (bad volume calc)
356           //
357           if (lmax != -std::numeric_limits<float>::max() &&
358               rmin !=  std::numeric_limits<float>::max())
359           {
360               sum += b[d][n].Cnt;
361 
362               float lvol = (lmax-min[d])/ext[d];
363               float rvol = (max[d]-rmin)/ext[d];
364 
365               float c = lvol*sum + rvol*(size-sum);
366 
367               if( sum > 0 && sum < size && c < cost )
368               {
369                 cost    = c;
370                 dim     = d;
371                 plane   = min[d] + (n+1)/iext[d];
372               }
373           }
374         }
375       }
376 
377       if( cost != std::numeric_limits<float>::max() )
378       {
379         mid = std::partition( begin, end, LeftPredicate( dim, plane ) );
380       }
381 
382       // fallback
383       if( mid == begin || mid == end )
384       {
385         dim = std::max_element( ext, ext+3 ) - ext;
386 
387         mid = begin + (end-begin)/2;
388         std::nth_element( begin, mid, end, CenterOrder( dim ) );
389       }
390 
391       float lmin[3], lmax[3], rmin[3], rmax[3];
392 
393       FindMinMax( begin, mid, lmin, lmax );
394       FindMinMax( mid,   end, rmin, rmax );
395 
396       float clip[2] = { lmax[dim], rmin[dim]};
397 
398       vtkCellTreeLocator::vtkCellTreeNode child[2];
399       child[0].MakeLeaf( begin - &(this->m_pc[0]), mid-begin );
400       child[1].MakeLeaf( mid   - &(this->m_pc[0]), end-mid );
401 
402       this->m_nodes[index].MakeNode( (int)m_nodes.size(), dim, clip );
403       this->m_nodes.insert( m_nodes.end(), child, child+2 );
404 
405       Split( this->m_nodes[index].GetLeftChildIndex(), lmin, lmax );
406       Split( this->m_nodes[index].GetRightChildIndex(), rmin, rmax );
407     }
408 
409   public:
410 
vtkCellTreeBuilder()411     vtkCellTreeBuilder()
412     {
413       this->m_buckets =  5;
414       this->m_leafsize = 8;
415     }
416 
Build(vtkCellTreeLocator * ctl,vtkCellTreeLocator::vtkCellTree & ct,vtkDataSet * ds)417     void Build( vtkCellTreeLocator *ctl, vtkCellTreeLocator::vtkCellTree& ct, vtkDataSet* ds )
418     {
419       const vtkIdType size = ds->GetNumberOfCells();
420       double cellBounds[6];
421       this->m_pc.resize(size);
422 
423       float min[3] =
424         {
425         std::numeric_limits<float>::max(),
426         std::numeric_limits<float>::max(),
427         std::numeric_limits<float>::max()
428         };
429 
430       float max[3] =
431         {
432         -std::numeric_limits<float>::max(),
433         -std::numeric_limits<float>::max(),
434         -std::numeric_limits<float>::max(),
435         };
436 
437       for( vtkIdType i=0; i<size; ++i )
438       {
439         this->m_pc[i].Ind = i;
440 
441         double *boundsPtr = cellBounds;
442         if (ctl->CellBounds)
443         {
444           boundsPtr = ctl->CellBounds[i];
445         }
446         else
447         {
448           ds->GetCellBounds(i, boundsPtr);
449         }
450 
451         for( int d=0; d<3; ++d )
452         {
453           this->m_pc[i].Min[d] = boundsPtr[2*d+0];
454           this->m_pc[i].Max[d] = boundsPtr[2*d+1];
455 
456           if( this->m_pc[i].Min[d] < min[d] )
457           {
458             min[d] = this->m_pc[i].Min[d];
459           }
460 
461           if( this->m_pc[i].Max[d] > max[d] )  /// This can be m_pc[i].max[d] instead of min
462           {
463             max[d] = this->m_pc[i].Max[d];
464           }
465         }
466       }
467 
468       ct.DataBBox[0] = min[0];
469       ct.DataBBox[1] = max[0];
470       ct.DataBBox[2] = min[1];
471       ct.DataBBox[3] = max[1];
472       ct.DataBBox[4] = min[2];
473       ct.DataBBox[5] = max[2];
474 
475       vtkCellTreeLocator::vtkCellTreeNode root;
476       root.MakeLeaf( 0, size );
477       this->m_nodes.push_back( root );
478 
479       Split( 0, min, max );
480 
481       ct.Nodes.resize( this->m_nodes.size() );
482       ct.Nodes[0] = this->m_nodes[0];
483 
484       std::vector<vtkCellTreeLocator::vtkCellTreeNode>::iterator ni = ct.Nodes.begin();
485       std::vector<vtkCellTreeLocator::vtkCellTreeNode>::iterator nn = ct.Nodes.begin()+1;
486 
487       for( ; ni!=ct.Nodes.end(); ++ni )
488       {
489         if( ni->IsLeaf() )
490         {
491           continue;
492         }
493 
494         *(nn++) = this->m_nodes[ni->GetLeftChildIndex()];
495         *(nn++) = this->m_nodes[ni->GetRightChildIndex()];
496 
497         ni->SetChildren( nn-ct.Nodes.begin()-2 );
498       }
499 
500       // --- final
501 
502       ct.Leaves.resize( size );
503 
504       for( int i=0; i<size; ++i )
505       {
506         ct.Leaves[i] = this->m_pc[i].Ind;
507       }
508 
509       this->m_pc.clear();
510     }
511 
512   public:
513     unsigned int     m_buckets;
514     unsigned int     m_leafsize;
515     std::vector<PerCell>   m_pc;
516     std::vector<vtkCellTreeLocator::vtkCellTreeNode>    m_nodes;
517 };
518 
519 //----------------------------------------------------------------------------
520 
521 typedef std::stack<vtkCellTreeLocator::vtkCellTreeNode*, std::vector<vtkCellTreeLocator::vtkCellTreeNode*> > nodeStack;
522 
vtkCellTreeLocator()523 vtkCellTreeLocator::vtkCellTreeLocator( )
524 {
525   this->NumberOfCellsPerNode = 8;
526   this->NumberOfBuckets      = 5;
527   this->Tree                 = nullptr;
528 }
529 
530 //----------------------------------------------------------------------------
531 
~vtkCellTreeLocator()532 vtkCellTreeLocator::~vtkCellTreeLocator()
533 {
534   // make it obvious that this is calling a virtual function
535   // that IS NOT overridden by a derived class as the derived class
536   // no longer exists when this is called. really the user should
537   // call FreeSearchStructure before deleting the object
538   // but I'm not going to depend on that happening.
539   this->vtkCellTreeLocator::FreeSearchStructure();
540 }
541 
542 //----------------------------------------------------------------------------
BuildLocatorIfNeeded()543 void vtkCellTreeLocator::BuildLocatorIfNeeded()
544 {
545   if (this->LazyEvaluation)
546   {
547     if (!this->Tree || (this->MTime>this->BuildTime))
548     {
549       this->Modified();
550       vtkDebugMacro(<< "Forcing BuildLocator");
551       this->ForceBuildLocator();
552     }
553   }
554 }
555 //----------------------------------------------------------------------------
ForceBuildLocator()556 void vtkCellTreeLocator::ForceBuildLocator()
557 {
558   //
559   // don't rebuild if build time is newer than modified and dataset modified time
560   if ( (this->Tree) &&
561     (this->BuildTime>this->MTime) &&
562     (this->BuildTime>DataSet->GetMTime()))
563   {
564     return;
565   }
566   // don't rebuild if UseExistingSearchStructure is ON and a tree structure already exists
567   if ( (this->Tree) && this->UseExistingSearchStructure)
568   {
569     this->BuildTime.Modified();
570     vtkDebugMacro(<< "BuildLocator exited - UseExistingSearchStructure");
571     return;
572   }
573   this->BuildLocatorInternal();
574 }
575 //----------------------------------------------------------------------------
BuildLocatorInternal()576 void vtkCellTreeLocator::BuildLocatorInternal()
577 {
578   this->FreeSearchStructure();
579   if ( !this->DataSet || (this->DataSet->GetNumberOfCells() < 1) )
580   {
581     vtkErrorMacro( << " No Cells in the data set\n");
582     return;
583   }
584   //
585   if (this->CacheCellBounds)
586   {
587     this->StoreCellBounds();
588   }
589   //
590   this->Tree = new vtkCellTree;
591   vtkCellTreeBuilder builder;
592   builder.m_leafsize = this->NumberOfCellsPerNode;
593   builder.m_buckets  = NumberOfBuckets;
594   builder.Build( this, *(Tree), this->DataSet );
595   this->BuildTime.Modified();
596 }
597 
BuildLocator()598 void vtkCellTreeLocator::BuildLocator()
599 {
600   if (this->LazyEvaluation)
601   {
602     return;
603   }
604   this->ForceBuildLocator();
605 }
606 
607 //----------------------------------------------------------------------------
FindCell(double pos[3],double,vtkGenericCell * cell,double pcoords[3],double * weights)608 vtkIdType vtkCellTreeLocator::FindCell( double pos[3], double , vtkGenericCell *cell, double pcoords[3],
609                                         double* weights )
610 {
611   if( this->Tree == nullptr )
612   {
613     return -1;
614   }
615 
616   double dist2;
617   int subId;
618 
619   const float _pos[3] = { static_cast<float>(pos[0]), static_cast<float>(pos[1]),
620                           static_cast<float>(pos[2]) };
621   vtkCellPointTraversal pt( *(this->Tree), _pos );
622 
623   //bool found = false;
624 
625   while( const vtkCellTreeNode* n = pt.Next() )
626   {
627     const unsigned int* begin = &(this->Tree->Leaves[n->Start()]);
628     const unsigned int* end = begin + n->Size();
629 
630     for( ; begin!=end; ++begin )
631     {
632       this->DataSet->GetCell(*begin, cell);
633       if( cell->EvaluatePosition(pos, nullptr, subId, pcoords, dist2, weights)==1 )
634       {
635         return *begin;
636       }
637     }
638   }
639 
640   return -1;
641 }
642 
643 //----------------------------------------------------------------------------
644 
645 namespace
646 {
_getMinDistPOS_X(const double origin[3],const double dir[3],const double B[6])647   double _getMinDistPOS_X(const double origin[3], const double dir[3], const double B[6])
648   {
649     return ((B[0] - origin[0]) / dir[0]);
650   }
_getMinDistNEG_X(const double origin[3],const double dir[3],const double B[6])651   double _getMinDistNEG_X(const double origin[3], const double dir[3], const double B[6])
652   {
653     return ((B[1] - origin[0]) / dir[0]);
654   }
_getMinDistPOS_Y(const double origin[3],const double dir[3],const double B[6])655   double _getMinDistPOS_Y(const double origin[3], const double dir[3], const double B[6])
656   {
657     return ((B[2] - origin[1]) / dir[1]);
658   }
_getMinDistNEG_Y(const double origin[3],const double dir[3],const double B[6])659   double _getMinDistNEG_Y(const double origin[3], const double dir[3], const double B[6])
660   {
661     return ((B[3] - origin[1]) / dir[1]);
662   }
_getMinDistPOS_Z(const double origin[3],const double dir[3],const double B[6])663   double _getMinDistPOS_Z(const double origin[3], const double dir[3], const double B[6])
664   {
665     return ((B[4] - origin[2]) / dir[2]);
666   }
_getMinDistNEG_Z(const double origin[3],const double dir[3],const double B[6])667   double _getMinDistNEG_Z(const double origin[3], const double dir[3], const double B[6])
668   {
669     return ((B[5] - origin[2]) / dir[2]);
670   }
671 
672 }
673 typedef std::pair<double, int> Intersection;
674 
IntersectWithLine(const double p1[3],const double p2[3],double tol,double & t,double x[3],double pcoords[3],int & subId,vtkIdType & cellId,vtkGenericCell * cell)675 int vtkCellTreeLocator::IntersectWithLine(const double p1[3],
676                                           const double p2[3],
677                                           double tol,
678                                           double &t,
679                                           double x[3],
680                                           double pcoords[3],
681                                           int &subId,
682                                           vtkIdType &cellId,
683                                           vtkGenericCell *cell)
684 {
685   int hit = this->IntersectWithLine(p1, p2, tol, t, x, pcoords, subId, cellId);
686   if (hit)
687   {
688     this->DataSet->GetCell(cellId, cell);
689   }
690   return hit;
691 }
692 
IntersectWithLine(const double p1[3],const double p2[3],double tol,double & t,double x[3],double pcoords[3],int & subId,vtkIdType & cellIds)693 int vtkCellTreeLocator::IntersectWithLine(const double p1[3], const double p2[3], double tol,
694   double& t, double x[3], double pcoords[3],
695   int &subId, vtkIdType &cellIds)
696 {
697   //
698   vtkCellTreeNode  *node, *near, *far;
699   double    ctmin, ctmax, tmin, tmax, _tmin, _tmax, tDist;
700   double    ray_vec[3] = { p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2] };
701 
702   double cellBounds[6];
703 
704   this->BuildLocatorIfNeeded();
705 
706   // Does ray pass through root BBox
707   tmin = 0; tmax = 1;
708 
709   if (!this->RayMinMaxT(p1, ray_vec, tmin, tmax)) // 0 for root node
710   {
711     return false;
712   }
713   // Ok, setup a stack and various params
714   nodeStack  ns;
715   double    closest_intersection = VTK_FLOAT_MAX;
716   bool     HIT = false;
717   // setup our axis optimized ray box edge stuff
718   int axis = getDominantAxis(ray_vec);
719   double (*_getMinDist)(const double origin[3], const double dir[3], const double B[6]);
720   switch (axis)
721   {
722     case POS_X: _getMinDist = _getMinDistPOS_X; break;
723     case NEG_X: _getMinDist = _getMinDistNEG_X; break;
724     case POS_Y: _getMinDist = _getMinDistPOS_Y; break;
725     case NEG_Y: _getMinDist = _getMinDistNEG_Y; break;
726     case POS_Z: _getMinDist = _getMinDistPOS_Z; break;
727     default:    _getMinDist = _getMinDistNEG_Z; break;
728   }
729 
730 
731   //
732   // OK, lets walk the tree and find intersections
733   //
734   vtkCellTreeNode* n = &this->Tree->Nodes.front();
735   ns.push(n);
736   while (!ns.empty())
737   {
738     node = ns.top();
739     ns.pop();
740     // We do as few tests on the way down as possible, because our BBoxes
741     // can be quite tight and we want to reject as many boxes as possible without
742     // testing them at all - mainly because we quickly get to a leaf node and
743     // test candidates, once we've found a hit, we note the intersection t val,
744     // as soon as we pull a BBox of the stack that has a closest point further
745     // than the t val, we know we can stop.
746 
747     int mustCheck = 0;  // to check if both left and right sub trees need to be checked
748 
749     //
750     while (!node->IsLeaf())
751     { // this must be a parent node
752       // Which child node is closest to ray origin - given direction
753       Classify(p1, ray_vec, tDist, near, node, far, mustCheck);
754       // if the distance to the far edge of the near box is > tmax, no need to test far box
755       // (we still need to test Mid because it may overlap slightly)
756       if(mustCheck)
757       {
758         ns.push(far);
759         node = near;
760       }
761       else if ((tDist > tmax) || (tDist <= 0) )
762       { // <=0 for ray on edge
763         node = near;
764       }
765       // if the distance to the far edge of the near box is < tmin, no need to test near box
766       else if (tDist < tmin)
767       {
768         ns.push(near);
769         node = far;
770       }
771       // All the child nodes may be candidates, keep near, push far then mid
772       else
773       {
774         ns.push(far);
775         node = near;
776       }
777     }
778     double t_hit, ipt[3];
779     // Ok, so we're a leaf node, first check the BBox against the ray
780     // then test the candidates in our sorted ray direction order
781     _tmin = tmin; _tmax = tmax;
782     //    if (node->RayMinMaxT(p1, ray_vec, _tmin, _tmax)) {
783     // Was the closest point on the box > intersection point
784     //if (_tmax>closest_intersection) break;
785     //
786     for (int i=0; i< (int)node->Size(); i++)
787     {
788       vtkIdType cell_ID = this->Tree->Leaves[node->Start()+i];
789       //
790 
791       double* boundsPtr = cellBounds;
792       if (this->CellBounds)
793       {
794         boundsPtr = this->CellBounds[cell_ID];
795       }
796       else
797       {
798         this->DataSet->GetCellBounds(cell_ID, cellBounds);
799       }
800       if (_getMinDist(p1, ray_vec, boundsPtr) > closest_intersection)
801       {
802         break;
803       }
804       //
805       ctmin = _tmin; ctmax = _tmax;
806       if (this->RayMinMaxT(boundsPtr, p1, ray_vec, ctmin, ctmax))
807       {
808         if (this->IntersectCellInternal(cell_ID, p1, p2, tol, t_hit, ipt, pcoords, subId))
809         {
810           if (t_hit<closest_intersection)
811           {
812             HIT = true;
813             closest_intersection = t_hit;
814             cellIds = cell_ID;
815             x[0] = ipt[0];
816             x[1] = ipt[1];
817             x[2] = ipt[2];
818           }
819 
820 
821         }
822       }
823     }
824     //    }
825   }
826   if (HIT)
827   {
828     t = closest_intersection;
829   }
830   //
831   return HIT;
832 
833 }
834 //----------------------------------------------------------------------------
RayMinMaxT(const double origin[3],const double dir[3],double & rTmin,double & rTmax)835 bool vtkCellTreeLocator::RayMinMaxT(const double origin[3],
836   const double dir[3],
837   double &rTmin,
838   double &rTmax)
839 {
840   double tT;
841   // X-Axis
842   float bounds[6];
843 
844   bounds[0] = this->Tree->DataBBox[0];
845   bounds[1] = this->Tree->DataBBox[1];
846   bounds[2] = this->Tree->DataBBox[2];
847   bounds[3] = this->Tree->DataBBox[3];
848   bounds[4] = this->Tree->DataBBox[4];
849   bounds[5] = this->Tree->DataBBox[5];
850 
851   if (dir[0] < -EPSILON_)
852   {    // ray travelling in -x direction
853     tT = (bounds[0] - origin[0]) / dir[0];
854     if (tT < rTmin)
855     {
856       return (false);  // ray already left of box. Can't hit
857     }
858     if (tT <= rTmax)
859     {
860       rTmax = tT;     // update new tmax
861     }
862     tT = (bounds[1] - origin[0]) / dir[0]; // distance to right edge
863     if (tT >= rTmin)
864     {   // can't see this ever happening
865       if (tT > rTmax)
866       {
867         return false;  // clip start of ray to right edge
868       }
869       rTmin = tT;
870     }
871   }
872   else if (dir[0] > EPSILON_)
873   {
874     tT = (bounds[1] - origin[0]) / dir[0];
875     if (tT < rTmin)
876     {
877       return (false);
878     }
879     if (tT <= rTmax)
880     {
881       rTmax = tT;
882     }
883     tT = (bounds[0] - origin[0]) / dir[0];
884     if (tT >= rTmin)
885     {
886       if (tT > rTmax)
887       {
888         return (false);
889       }
890       rTmin = tT;
891     }
892   }
893   else if (origin[0] < bounds[0] || origin[0] > bounds[1])
894   {
895     return (false);
896   }
897   // Y-Axis
898   if (dir[1] < -EPSILON_)
899   {
900     tT = (bounds[2] - origin[1]) / dir[1];
901     if (tT < rTmin)
902     {
903       return (false);
904     }
905     if (tT <= rTmax)
906     {
907       rTmax = tT;
908     }
909     tT = (bounds[3] - origin[1]) / dir[1];
910     if (tT >= rTmin)
911     {
912       if (tT > rTmax)
913       {
914         return (false);
915       }
916       rTmin = tT;
917     }
918   }
919   else if (dir[1] > EPSILON_)
920   {
921     tT = (bounds[3] - origin[1]) / dir[1];
922     if (tT < rTmin)
923     {
924       return (false);
925     }
926     if (tT <= rTmax)
927     {
928       rTmax = tT;
929     }
930     tT = (bounds[2] - origin[1]) / dir[1];
931     if (tT >= rTmin)
932     {
933       if (tT > rTmax)
934       {
935         return (false);
936       }
937       rTmin = tT;
938     }
939   }
940   else if (origin[1] < bounds[2] || origin[1] > bounds[3])
941   {
942     return (false);
943   }
944   // Z-Axis
945   if (dir[2] < -EPSILON_)
946   {
947     tT = (bounds[4] - origin[2]) / dir[2];
948     if (tT < rTmin)
949     {
950       return (false);
951     }
952     if (tT <= rTmax)
953     {
954       rTmax = tT;
955     }
956     tT = (bounds[5] - origin[2]) / dir[2];
957     if (tT >= rTmin)
958     {
959       if (tT > rTmax)
960       {
961         return (false);
962       }
963       rTmin = tT;
964     }
965   }
966   else if (dir[2] > EPSILON_)
967   {
968     tT = (bounds[5] - origin[2]) / dir[2];
969     if (tT < rTmin)
970     {
971       return (false);
972     }
973     if (tT <= rTmax)
974     {
975       rTmax = tT;
976     }
977     tT = (bounds[4] - origin[2]) / dir[2];
978     if (tT >= rTmin)
979     {
980       if (tT > rTmax)
981       {
982         return (false);
983       }
984       rTmin = tT;
985     }
986   }
987   else if (origin[2] < bounds[4] || origin[2] > bounds[5])
988   {
989     return (false);
990   }
991   return (true);
992 }
993 //----------------------------------------------------------------------------
RayMinMaxT(const double bounds[6],const double origin[3],const double dir[3],double & rTmin,double & rTmax)994 bool vtkCellTreeLocator::RayMinMaxT(const double bounds[6],
995   const double origin[3],
996   const double dir[3],
997   double &rTmin,
998   double &rTmax)
999 {
1000   double tT;
1001   // X-Axis
1002   if (dir[0] < -EPSILON_)
1003   {    // ray travelling in -x direction
1004     tT = (bounds[0] - origin[0]) / dir[0]; // Ipoint less than minT - ray outside box!
1005     if (tT < rTmin)
1006     {
1007       return (false);
1008     }
1009     if (tT <= rTmax)
1010     {
1011       rTmax = tT;     // update new tmax
1012     }
1013     tT = (bounds[1] - origin[0]) / dir[0]; // distance to right edge
1014     if (tT >= rTmin)
1015     {   // can't see this ever happening
1016       if (tT > rTmax)
1017       {
1018         return false;  // clip start of ray to right edge
1019       }
1020       rTmin = tT;
1021     }
1022   }
1023   else if (dir[0] > EPSILON_)
1024   {
1025     tT = (bounds[1] - origin[0]) / dir[0];
1026     if (tT < rTmin)
1027     {
1028       return (false);
1029     }
1030     if (tT <= rTmax)
1031     {
1032       rTmax = tT;
1033     }
1034     tT = (bounds[0] - origin[0]) / dir[0];
1035     if (tT >= rTmin)
1036     {
1037       if (tT > rTmax)
1038       {
1039         return (false);
1040       }
1041       rTmin = tT;
1042     }
1043   }
1044   else if (origin[0] < bounds[0] || origin[0] > bounds[1])
1045   {
1046     return (false);
1047   }
1048   // Y-Axis
1049   if (dir[1] < -EPSILON_)
1050   {
1051     tT = (bounds[2] - origin[1]) / dir[1];
1052     if (tT < rTmin)
1053     {
1054       return (false);
1055     }
1056     if (tT <= rTmax) rTmax = tT;
1057     tT = (bounds[3] - origin[1]) / dir[1];
1058     if (tT >= rTmin)
1059     {
1060       if (tT > rTmax)
1061       {
1062         return (false);
1063       }
1064       rTmin = tT;
1065     }
1066   }
1067   else if (dir[1] > EPSILON_)
1068   {
1069     tT = (bounds[3] - origin[1]) / dir[1];
1070     if (tT < rTmin)
1071     {
1072       return (false);
1073     }
1074     if (tT <= rTmax)
1075     {
1076       rTmax = tT;
1077     }
1078     tT = (bounds[2] - origin[1]) / dir[1];
1079     if (tT >= rTmin)
1080     {
1081       if (tT > rTmax)
1082       {
1083         return (false);
1084       }
1085       rTmin = tT;
1086     }
1087   }
1088   else if (origin[1] < bounds[2] || origin[1] > bounds[3])
1089   {
1090     return (false);
1091   }
1092   // Z-Axis
1093   if (dir[2] < -EPSILON_)
1094   {
1095     tT = (bounds[4] - origin[2]) / dir[2];
1096     if (tT < rTmin)
1097     {
1098       return (false);
1099     }
1100     if (tT <= rTmax)
1101     {
1102       rTmax = tT;
1103     }
1104     tT = (bounds[5] - origin[2]) / dir[2];
1105     if (tT >= rTmin)
1106     {
1107       if (tT > rTmax)
1108       {
1109         return (false);
1110       }
1111       rTmin = tT;
1112     }
1113   }
1114   else if (dir[2] > EPSILON_)
1115   {
1116     tT = (bounds[5] - origin[2]) / dir[2];
1117     if (tT < rTmin)
1118     {
1119       return (false);
1120     }
1121     if (tT <= rTmax)
1122     {
1123       rTmax = tT;
1124     }
1125     tT = (bounds[4] - origin[2]) / dir[2];
1126     if (tT >= rTmin)
1127     {
1128       if (tT > rTmax)
1129       {
1130         return (false);
1131       }
1132       rTmin = tT;
1133     }
1134   }
1135   else if (origin[2] < bounds[4] || origin[2] > bounds[5])
1136   {
1137     return (false);
1138   }
1139   return (true);
1140 }
1141 //----------------------------------------------------------------------------
getDominantAxis(const double dir[3])1142 int vtkCellTreeLocator::getDominantAxis(const double dir[3])
1143 {
1144   double tX = (dir[0]>0) ? dir[0] : -dir[0];
1145   double tY = (dir[1]>0) ? dir[1] : -dir[1];
1146   double tZ = (dir[2]>0) ? dir[2] : -dir[2];
1147   if (tX > tY && tX > tZ)
1148   {
1149     return ((dir[0] > 0) ? POS_X : NEG_X);
1150   }
1151   else if ( tY > tZ )
1152   {
1153     return ((dir[1] > 0) ? POS_Y : NEG_Y);
1154   }
1155   else
1156   {
1157     return ((dir[2] > 0) ? POS_Z : NEG_Z);
1158   }
1159 }
1160 //----------------------------------------------------------------------------
Classify(const double origin[3],const double dir[3],double & rDist,vtkCellTreeNode * & near,vtkCellTreeNode * & parent,vtkCellTreeNode * & far,int & mustCheck)1161 void vtkCellTreeLocator::Classify(const double origin[3],
1162   const double dir[3],
1163   double &rDist,
1164   vtkCellTreeNode *&near, vtkCellTreeNode *&parent,
1165   vtkCellTreeNode *&far, int& mustCheck)
1166 {
1167   double tOriginToDivPlane = parent->GetLeftMaxValue() - origin[parent->GetDimension()];
1168   double tOriginToDivPlane2 = parent->GetRightMinValue() - origin[parent->GetDimension()];
1169   double tDivDirection   = dir[parent->GetDimension()];
1170   if ( tOriginToDivPlane2 > 0 )  // origin is right of the rmin
1171   {
1172     near = &this->Tree->Nodes.at(parent->GetLeftChildIndex());
1173     far  = &this->Tree->Nodes.at(parent->GetLeftChildIndex()+1);
1174     rDist = (tDivDirection) ? tOriginToDivPlane2 / tDivDirection : VTK_FLOAT_MAX;
1175   }
1176   else if (tOriginToDivPlane < 0)  // origin is left of the lm
1177   {
1178     far  = &this->Tree->Nodes.at(parent->GetLeftChildIndex());
1179     near = &this->Tree->Nodes.at(parent->GetLeftChildIndex()+1);
1180     rDist = (tDivDirection) ? tOriginToDivPlane / tDivDirection : VTK_FLOAT_MAX;
1181   }
1182 
1183 
1184   else
1185   {
1186     if(tOriginToDivPlane > 0 && tOriginToDivPlane2 < 0)
1187     {
1188       mustCheck = 1;  // The point is within right min and left max. both left and right subtrees must be checked
1189     }
1190 
1191     if ( tDivDirection < 0)
1192     {
1193       near = &this->Tree->Nodes.at(parent->GetLeftChildIndex());
1194       far  = &this->Tree->Nodes.at(parent->GetLeftChildIndex()+1);
1195       if(!(tOriginToDivPlane > 0 || tOriginToDivPlane < 0))
1196       {
1197         mustCheck=1;  // Ray was exactly on edge left max box.
1198       }
1199       rDist = (tDivDirection) ? 0 / tDivDirection : VTK_FLOAT_MAX;
1200     }
1201     else
1202     {
1203       far  = &this->Tree->Nodes.at(parent->GetLeftChildIndex());
1204       near = &this->Tree->Nodes.at(parent->GetLeftChildIndex()+1);
1205       if(!(tOriginToDivPlane2 > 0 || tOriginToDivPlane2 < 0))
1206       {
1207         mustCheck=1; // Ray was exactly on edge right min box.
1208       }
1209       rDist = (tDivDirection) ? 0 / tDivDirection : VTK_FLOAT_MAX;
1210     }
1211   }
1212 
1213 }
1214 //----------------------------------------------------------------------------
IntersectCellInternal(vtkIdType cell_ID,const double p1[3],const double p2[3],const double tol,double & t,double ipt[3],double pcoords[3],int & subId)1215 int vtkCellTreeLocator::IntersectCellInternal(
1216   vtkIdType cell_ID,
1217   const double p1[3],
1218   const double p2[3],
1219   const double tol,
1220   double &t,
1221   double ipt[3],
1222   double pcoords[3],
1223   int &subId)
1224 {
1225   this->DataSet->GetCell(cell_ID, this->GenericCell);
1226   return this->GenericCell->IntersectWithLine(const_cast<double*>(p1), const_cast<double*>(p2), tol, t, ipt, pcoords, subId);
1227 }
1228 //----------------------------------------------------------------------------
FreeSearchStructure(void)1229 void vtkCellTreeLocator::FreeSearchStructure(void)
1230 {
1231   delete this->Tree;
1232   this->Tree = nullptr;
1233   this->Superclass::FreeCellBounds();
1234 }
1235 //---------------------------------------------------------------------------
1236 // For drawing coloured boxes, we want the level/depth
1237 typedef std::pair<vtkBoundingBox, int> boxLevel;
1238 typedef std::vector<boxLevel> boxlist;
1239 // For testing bounds of the tree we need node/box
1240 typedef std::pair<vtkCellTreeLocator::vtkCellTreeNode*, boxLevel> nodeBoxLevel;
1241 typedef std::stack<nodeBoxLevel, std::vector<nodeBoxLevel> > nodeinfostack;
1242 //---------------------------------------------------------------------------
SplitNodeBox(vtkCellTreeLocator::vtkCellTreeNode * n,vtkBoundingBox & b,vtkBoundingBox & l,vtkBoundingBox & r)1243 static void SplitNodeBox(vtkCellTreeLocator::vtkCellTreeNode *n, vtkBoundingBox &b, vtkBoundingBox &l, vtkBoundingBox &r)
1244 {
1245   double minpt[3], maxpt[3];
1246   // create a box for left node
1247   vtkBoundingBox ll(b);
1248   ll.GetMaxPoint(maxpt[0], maxpt[1], maxpt[2]);
1249   maxpt[n->GetDimension()] = n->GetLeftMaxValue();
1250   ll.SetMaxPoint(maxpt[0], maxpt[1], maxpt[2]);
1251   l = ll;
1252   // create a box for right node
1253   vtkBoundingBox rr(b);
1254   rr.GetMinPoint(minpt[0], minpt[1], minpt[2]);
1255   minpt[n->GetDimension()] = n->GetRightMinValue();
1256   rr.SetMinPoint(minpt[0], minpt[1], minpt[2]);
1257   r = rr;
1258 }
1259 //---------------------------------------------------------------------------
AddBox(vtkPolyData * pd,double * bounds,int level)1260 static void AddBox(vtkPolyData *pd, double *bounds, int level)
1261 {
1262   vtkPoints      *pts = pd->GetPoints();
1263   vtkCellArray *lines = pd->GetLines();
1264   vtkIntArray *levels = vtkArrayDownCast<vtkIntArray>(pd->GetPointData()->GetArray(0));
1265   double x[3];
1266   vtkIdType cells[8], ids[2];
1267   //
1268   x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[4];
1269   cells[0] = pts->InsertNextPoint(x);
1270   x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[4];
1271   cells[1] = pts->InsertNextPoint(x);
1272   x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[4];
1273   cells[2] = pts->InsertNextPoint(x);
1274   x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[4];
1275   cells[3] = pts->InsertNextPoint(x);
1276   x[0] = bounds[0]; x[1] = bounds[2]; x[2] = bounds[5];
1277   cells[4] = pts->InsertNextPoint(x);
1278   x[0] = bounds[1]; x[1] = bounds[2]; x[2] = bounds[5];
1279   cells[5] = pts->InsertNextPoint(x);
1280   x[0] = bounds[0]; x[1] = bounds[3]; x[2] = bounds[5];
1281   cells[6] = pts->InsertNextPoint(x);
1282   x[0] = bounds[1]; x[1] = bounds[3]; x[2] = bounds[5];
1283   cells[7] = pts->InsertNextPoint(x);
1284   //
1285   ids[0] = cells[0]; ids[1] = cells[1];
1286   lines->InsertNextCell(2,ids);
1287   ids[0] = cells[2]; ids[1] = cells[3];
1288   lines->InsertNextCell(2,ids);
1289   ids[0] = cells[4]; ids[1] = cells[5];
1290   lines->InsertNextCell(2,ids);
1291   ids[0] = cells[6]; ids[1] = cells[7];
1292   lines->InsertNextCell(2,ids);
1293   ids[0] = cells[0]; ids[1] = cells[2];
1294   lines->InsertNextCell(2,ids);
1295   ids[0] = cells[1]; ids[1] = cells[3];
1296   lines->InsertNextCell(2,ids);
1297   ids[0] = cells[4]; ids[1] = cells[6];
1298   lines->InsertNextCell(2,ids);
1299   ids[0] = cells[5]; ids[1] = cells[7];
1300   lines->InsertNextCell(2,ids);
1301   ids[0] = cells[0]; ids[1] = cells[4];
1302   lines->InsertNextCell(2,ids);
1303   ids[0] = cells[1]; ids[1] = cells[5];
1304   lines->InsertNextCell(2,ids);
1305   ids[0] = cells[2]; ids[1] = cells[6];
1306   lines->InsertNextCell(2,ids);
1307   ids[0] = cells[3]; ids[1] = cells[7];
1308   lines->InsertNextCell(2,ids);
1309   //
1310   // Colour boxes by scalar if array present
1311   //
1312   for (int i=0; levels && i<8; i++)
1313   {
1314     levels->InsertNextTuple1(level);
1315   }
1316 }
1317 //---------------------------------------------------------------------------
GenerateRepresentation(int level,vtkPolyData * pd)1318 void vtkCellTreeLocator::GenerateRepresentation(int level, vtkPolyData *pd)
1319 {
1320   this->BuildLocatorIfNeeded();
1321   //
1322   nodeinfostack ns;
1323   boxlist   bl;
1324   //
1325   vtkCellTreeNode *n0 = &this->Tree->Nodes.front();
1326   // create a box for the root
1327   float *DataBBox = this->Tree->DataBBox;
1328   vtkBoundingBox lbox, rbox, rootbox(DataBBox[0], DataBBox[1], DataBBox[2], DataBBox[3], DataBBox[4], DataBBox[5]);
1329   ns.push(nodeBoxLevel(n0,boxLevel(rootbox,0)));
1330   while (!ns.empty())
1331   {
1332     n0 = ns.top().first;
1333     int lev = ns.top().second.second;
1334     if (n0->IsLeaf() && ((lev==level) || (level==-1)))
1335     {
1336       bl.push_back(boxLevel(ns.top().second.first,lev));
1337       ns.pop();
1338     }
1339     else if (n0->IsLeaf())
1340     {
1341       ns.pop();
1342     }
1343     else if (n0->IsNode())
1344     {
1345       SplitNodeBox(n0, ns.top().second.first, lbox, rbox);
1346       vtkCellTreeNode *n1 = &this->Tree->Nodes.at(n0->GetLeftChildIndex());
1347       vtkCellTreeNode *n2 = &this->Tree->Nodes.at(n0->GetLeftChildIndex()+1);
1348       ns.pop();
1349       ns.push(nodeBoxLevel(n1,boxLevel(lbox,lev+1)));
1350       ns.push(nodeBoxLevel(n2,boxLevel(rbox,lev+1)));
1351     }
1352   }
1353   //
1354   //
1355   //
1356   // For each node, add the bbox to our polydata
1357   int s = (int) bl.size();
1358   for (int i=0; i<s; i++)
1359   {
1360     double bounds[6];
1361     bl[i].first.GetBounds(bounds);
1362     AddBox(pd, bounds, bl[i].second);
1363   }
1364 }
1365 //---------------------------------------------------------------------------
FindCellsWithinBounds(double * bbox,vtkIdList * cells)1366 void vtkCellTreeLocator::FindCellsWithinBounds(double *bbox, vtkIdList *cells)
1367 {
1368   this->BuildLocatorIfNeeded();
1369   //
1370   nodeinfostack  ns;
1371   double         cellBounds[6];
1372   vtkBoundingBox TestBox(bbox);
1373   //
1374   vtkCellTreeNode *n0 = &this->Tree->Nodes.front();
1375   // create a box for the root
1376   float *DataBBox = this->Tree->DataBBox;
1377   vtkBoundingBox lbox, rbox, rootbox(DataBBox[0], DataBBox[1], DataBBox[2], DataBBox[3], DataBBox[4], DataBBox[5]);
1378   ns.push(nodeBoxLevel(n0,boxLevel(rootbox,0)));
1379   while (!ns.empty())
1380   {
1381     n0 = ns.top().first;
1382     vtkBoundingBox &nodebox = ns.top().second.first;
1383     if (TestBox.Intersects(nodebox))
1384     {
1385       if (n0->IsLeaf())
1386       {
1387         for (int i=0; i<(int)n0->Size(); i++)
1388         {
1389           vtkIdType cell_ID = this->Tree->Leaves[n0->Start()+i];
1390           double *boundsPtr = cellBounds;
1391           if (this->CellBounds)
1392           {
1393             boundsPtr = this->CellBounds[cell_ID];
1394           }
1395           else
1396           {
1397             this->DataSet->GetCellBounds(cell_ID, boundsPtr);
1398           }
1399           vtkBoundingBox box(boundsPtr);
1400           if (TestBox.Intersects(box))
1401           {
1402             cells->InsertNextId(cell_ID);
1403           }
1404         }
1405         ns.pop();
1406       }
1407       else
1408       {
1409         int lev = ns.top().second.second;
1410         SplitNodeBox(n0, nodebox, lbox, rbox);
1411         vtkCellTreeNode *n1 = &this->Tree->Nodes.at(n0->GetLeftChildIndex());
1412         vtkCellTreeNode *n2 = &this->Tree->Nodes.at(n0->GetLeftChildIndex()+1);
1413         ns.pop();
1414         ns.push(nodeBoxLevel(n1,boxLevel(lbox,lev+1)));
1415         ns.push(nodeBoxLevel(n2,boxLevel(rbox,lev+1)));
1416       }
1417     }
1418     else
1419     {
1420       ns.pop();
1421     }
1422   }
1423 }
1424 //---------------------------------------------------------------------------
1425 
PrintSelf(ostream & os,vtkIndent indent)1426 void vtkCellTreeLocator::PrintSelf(ostream& os, vtkIndent indent)
1427 {
1428   this->Superclass::PrintSelf(os,indent);
1429 }
1430