1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkKdTree.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 /*----------------------------------------------------------------------------
17  Copyright (c) Sandia Corporation
18  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
19 ----------------------------------------------------------------------------*/
20 
21 #include "vtkKdTree.h"
22 
23 #include "vtkKdNode.h"
24 #include "vtkBSPCuts.h"
25 #include "vtkBSPIntersections.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkDataSet.h"
28 #include "vtkDataSetCollection.h"
29 #include "vtkFloatArray.h"
30 #include "vtkMath.h"
31 #include "vtkCell.h"
32 #include "vtkCellArray.h"
33 #include "vtkGarbageCollector.h"
34 #include "vtkIdList.h"
35 #include "vtkPolyData.h"
36 #include "vtkPoints.h"
37 #include "vtkIdTypeArray.h"
38 #include "vtkIntArray.h"
39 #include "vtkPointSet.h"
40 #include "vtkImageData.h"
41 #include "vtkTimerLog.h"
42 #include "vtkUniformGrid.h"
43 #include "vtkRectilinearGrid.h"
44 #include "vtkCallbackCommand.h"
45 
46 #include <algorithm>
47 #include <list>
48 #include <map>
49 #include <queue>
50 #include <set>
51 
52 namespace
53 {
54 class TimeLog // Similar to vtkTimerLogScope, but can be disabled at runtime.
55 {
56   const std::string Event;
57   int Timing;
58 
59 public:
TimeLog(const char * event,int timing)60   TimeLog(const char *event, int timing)
61     : Event(event ? event : "")
62     , Timing(timing)
63   {
64     if (this->Timing)
65     {
66       vtkTimerLog::MarkStartEvent(this->Event.c_str());
67     }
68   }
69 
~TimeLog()70   ~TimeLog()
71   {
72     if (this->Timing)
73     {
74       vtkTimerLog::MarkEndEvent(this->Event.c_str());
75     }
76   }
77 
StartEvent(const char * event,int timing)78   static void StartEvent(const char *event, int timing)
79   {
80     if (timing)
81     {
82       vtkTimerLog::MarkStartEvent(event);
83     }
84   }
85 
EndEvent(const char * event,int timing)86   static void EndEvent(const char *event, int timing)
87   {
88     if (timing)
89     {
90       vtkTimerLog::MarkEndEvent(event);
91     }
92   }
93 
94 private:
95   // Explicit disable copy/assignment to prevent MSVC from complaining (C4512)
96   TimeLog(const TimeLog&) = delete;
97   TimeLog& operator=(const TimeLog&) = delete;
98 };
99 }
100 
101 #define SCOPETIMER(msg) TimeLog _timer("KdTree: " msg, this->Timing); (void)_timer
102 #define TIMER(msg) TimeLog::StartEvent("KdTree: " msg, this->Timing)
103 #define TIMERDONE(msg) TimeLog::EndEvent("KdTree: " msg, this->Timing)
104 
105 //-----------------------------------------------------------------------------
LastInputDeletedCallback(vtkObject * vtkNotUsed (caller),unsigned long vtkNotUsed (eid),void * _self,void * vtkNotUsed (calldata))106 static void LastInputDeletedCallback(vtkObject * vtkNotUsed(caller),
107                                      unsigned long vtkNotUsed(eid),
108                                      void * _self,
109                                      void * vtkNotUsed(calldata))
110 {
111   vtkKdTree *self = reinterpret_cast<vtkKdTree *>(_self);
112 
113   self->InvalidateGeometry();
114 }
115 
116 // helper class for ordering the points in vtkKdTree::FindClosestNPoints()
117 namespace
118 {
119   class OrderPoints
120   {
121   public:
OrderPoints(int N)122     OrderPoints(int N)
123     {
124         this->NumDesiredPoints = N;
125         this->NumPoints = 0;
126         this->LargestDist2 = VTK_FLOAT_MAX;
127     }
128 
InsertPoint(float dist2,vtkIdType id)129     void InsertPoint(float dist2, vtkIdType id)
130     {
131         if(dist2 <= this->LargestDist2 || this->NumPoints < this->NumDesiredPoints)
132         {
133           std::map<float, std::list<vtkIdType> >::iterator it=this->dist2ToIds.find(dist2);
134           this->NumPoints++;
135           if(it == this->dist2ToIds.end())
136           {
137             std::list<vtkIdType> idset;
138             idset.push_back(id);
139             this->dist2ToIds[dist2] = idset;
140           }
141           else
142           {
143             it->second.push_back(id);
144           }
145           if(this->NumPoints > this->NumDesiredPoints)
146           {
147             it=this->dist2ToIds.end();
148             --it;
149             if((this->NumPoints-it->second.size()) > this->NumDesiredPoints)
150             {
151               this->NumPoints -= it->second.size();
152               std::map<float, std::list<vtkIdType> >::iterator it2 = it;
153               --it2;
154               this->LargestDist2 = it2->first;
155               this->dist2ToIds.erase(it);
156             }
157           }
158         }
159     }
GetSortedIds(vtkIdList * ids)160     void GetSortedIds(vtkIdList* ids)
161     {
162         ids->Reset();
163         vtkIdType numIds = static_cast<vtkIdType>(
164           (this->NumDesiredPoints < this->NumPoints)
165             ? this->NumDesiredPoints : this->NumPoints);
166         ids->SetNumberOfIds(numIds);
167         vtkIdType counter = 0;
168         std::map<float, std::list<vtkIdType> >::iterator it=this->dist2ToIds.begin();
169         while(counter < numIds && it!=this->dist2ToIds.end())
170         {
171           std::list<vtkIdType>::iterator lit=it->second.begin();
172           while(counter < numIds && lit!=it->second.end())
173           {
174             ids->InsertId(counter, *lit);
175             counter++;
176             ++lit;
177           }
178           ++it;
179         }
180     }
181 
GetLargestDist2()182     float GetLargestDist2()
183     {
184         return this->LargestDist2;
185     }
186 
187   private:
188     size_t NumDesiredPoints, NumPoints;
189     float LargestDist2;
190     std::map<float, std::list<vtkIdType> > dist2ToIds; // map from dist^2 to a list of ids
191   };
192 }
193 
194 vtkStandardNewMacro(vtkKdTree);
195 
196 //----------------------------------------------------------------------------
vtkKdTree()197 vtkKdTree::vtkKdTree()
198 {
199   this->FudgeFactor = 0;
200   this->MaxWidth = 0.0;
201   this->MaxLevel  = 20;
202   this->Level    = 0;
203 
204   this->NumberOfRegionsOrLess = 0;
205   this->NumberOfRegionsOrMore = 0;
206 
207   this->ValidDirections =
208   (1 << vtkKdTree::XDIM) | (1 << vtkKdTree::YDIM) | (1 << vtkKdTree::ZDIM);
209 
210   this->MinCells = 100;
211   this->NumberOfRegions     = 0;
212 
213   this->DataSets = vtkDataSetCollection::New();
214 
215   this->Top      = nullptr;
216   this->RegionList   = nullptr;
217 
218   this->Timing = 0;
219   this->TimerLog = nullptr;
220 
221   this->IncludeRegionBoundaryCells = 0;
222   this->GenerateRepresentationUsingDataBounds = 0;
223 
224   this->InitializeCellLists();
225   this->CellRegionList = nullptr;
226 
227   this->NumberOfLocatorPoints = 0;
228   this->LocatorPoints = nullptr;
229   this->LocatorIds = nullptr;
230   this->LocatorRegionLocation = nullptr;
231 
232   this->LastDataCacheSize = 0;
233   this->LastNumDataSets = 0;
234   this->ClearLastBuildCache();
235 
236   this->BSPCalculator = nullptr;
237   this->Cuts = nullptr;
238   this->UserDefinedCuts = 0;
239 
240   this->Progress = 0;
241   this->ProgressOffset = 0;
242   this->ProgressScale = 1.0;
243 }
244 
245 //----------------------------------------------------------------------------
DeleteAllDescendants(vtkKdNode * nd)246 void vtkKdTree::DeleteAllDescendants(vtkKdNode *nd)
247 {
248   vtkKdNode *left = nd->GetLeft();
249   vtkKdNode *right = nd->GetRight();
250 
251   if (left && left->GetLeft())
252   {
253     vtkKdTree::DeleteAllDescendants(left);
254   }
255 
256   if (right && right->GetLeft())
257   {
258     vtkKdTree::DeleteAllDescendants(right);
259   }
260 
261   if (left && right)
262   {
263     nd->DeleteChildNodes();   // undo AddChildNodes
264     left->Delete();           // undo vtkKdNode::New()
265     right->Delete();
266   }
267 }
268 
269 //----------------------------------------------------------------------------
InitializeCellLists()270 void vtkKdTree::InitializeCellLists()
271 {
272   this->CellList.dataSet       = nullptr;
273   this->CellList.regionIds     = nullptr;
274   this->CellList.nRegions      = 0;
275   this->CellList.cells         = nullptr;
276   this->CellList.boundaryCells = nullptr;
277   this->CellList.emptyList = nullptr;
278 }
279 
280 //----------------------------------------------------------------------------
DeleteCellLists()281 void vtkKdTree::DeleteCellLists()
282 {
283   int i;
284   int num = this->CellList.nRegions;
285 
286   delete [] this->CellList.regionIds;
287 
288   if (this->CellList.cells)
289   {
290     for (i=0; i<num; i++)
291     {
292       this->CellList.cells[i]->Delete();
293     }
294 
295     delete [] this->CellList.cells;
296   }
297 
298   if (this->CellList.boundaryCells)
299   {
300     for (i=0; i<num; i++)
301     {
302       this->CellList.boundaryCells[i]->Delete();
303     }
304     delete [] this->CellList.boundaryCells;
305   }
306 
307   if (this->CellList.emptyList)
308   {
309     this->CellList.emptyList->Delete();
310   }
311 
312   this->InitializeCellLists();
313 }
314 
315 //----------------------------------------------------------------------------
~vtkKdTree()316 vtkKdTree::~vtkKdTree()
317 {
318   if (this->DataSets)
319   {
320     this->DataSets->Delete();
321     this->DataSets = nullptr;
322   }
323 
324   this->FreeSearchStructure();
325 
326   this->DeleteCellLists();
327 
328   delete [] this->CellRegionList;
329   this->CellRegionList = nullptr;
330 
331   if (this->TimerLog)
332   {
333     this->TimerLog->Delete();
334   }
335 
336   this->ClearLastBuildCache();
337 
338   this->SetCalculator(nullptr);
339   this->SetCuts(nullptr);
340 }
341 //----------------------------------------------------------------------------
SetCalculator(vtkKdNode * kd)342 void vtkKdTree::SetCalculator(vtkKdNode *kd)
343 {
344   if (this->BSPCalculator)
345   {
346     this->BSPCalculator->Delete();
347     this->BSPCalculator = nullptr;
348   }
349 
350   if (!this->UserDefinedCuts)
351   {
352     this->SetCuts(nullptr, 0);
353   }
354 
355   if (kd == nullptr)
356   {
357     return;
358   }
359 
360   if (!this->UserDefinedCuts)
361   {
362     vtkBSPCuts *cuts = vtkBSPCuts::New();
363     cuts->CreateCuts(kd);
364     this->SetCuts(cuts, 0);
365   }
366 
367   this->BSPCalculator = vtkBSPIntersections::New();
368   this->BSPCalculator->SetCuts(this->Cuts);
369 }
370 //----------------------------------------------------------------------------
SetCuts(vtkBSPCuts * cuts)371 void vtkKdTree::SetCuts(vtkBSPCuts *cuts)
372 {
373   this->SetCuts(cuts, 1);
374 }
375 //----------------------------------------------------------------------------
SetCuts(vtkBSPCuts * cuts,int userDefined)376 void vtkKdTree::SetCuts(vtkBSPCuts *cuts, int userDefined)
377 {
378   if (userDefined != 0)
379   {
380     userDefined = 1;
381   }
382 
383   if ((cuts == this->Cuts) && (userDefined == this->UserDefinedCuts))
384   {
385     return;
386   }
387 
388   if (!this->Cuts || !this->Cuts->Equals(cuts))
389   {
390     this->Modified();
391   }
392 
393   if (this->Cuts)
394   {
395     if (this->UserDefinedCuts)
396     {
397       this->Cuts->UnRegister(this);
398     }
399     else
400     {
401       this->Cuts->Delete();
402     }
403 
404     this->Cuts = nullptr;
405     this->UserDefinedCuts = 0;
406   }
407 
408   if (cuts == nullptr)
409   {
410     return;
411   }
412 
413   this->Cuts = cuts;
414   this->UserDefinedCuts = userDefined;
415 
416   if (this->UserDefinedCuts)
417   {
418     this->Cuts->Register(this);
419   }
420 }
421 //----------------------------------------------------------------------------
422 // Add and remove data sets.  We don't update this->Modify() here, because
423 // changing the data sets doesn't necessarily require rebuilding the
424 // k-d tree.  We only need to build a new k-d tree in BuildLocator if
425 // the geometry has changed, and we check for that with NewGeometry in
426 // BuildLocator.  We Modify() for changes that definitely require a
427 // rebuild of the tree, like changing the depth of the k-d tree.
428 
SetDataSet(vtkDataSet * set)429 void vtkKdTree::SetDataSet(vtkDataSet *set)
430 {
431   this->DataSets->RemoveAllItems();
432   this->AddDataSet(set);
433 }
434 
AddDataSet(vtkDataSet * set)435 void vtkKdTree::AddDataSet(vtkDataSet *set)
436 {
437   if (set == nullptr)
438   {
439     return;
440   }
441 
442   if (this->DataSets->IsItemPresent(set))
443   {
444     return;
445   }
446 
447   this->DataSets->AddItem(set);
448 }
449 
RemoveDataSet(vtkDataSet * set)450 void vtkKdTree::RemoveDataSet(vtkDataSet *set)
451 {
452   this->DataSets->RemoveItem(set);
453 }
454 
RemoveDataSet(int index)455 void vtkKdTree::RemoveDataSet(int index)
456 {
457   this->DataSets->RemoveItem(index);
458 }
459 
RemoveAllDataSets()460 void vtkKdTree::RemoveAllDataSets()
461 {
462   this->DataSets->RemoveAllItems();
463 }
464 
465 //-----------------------------------------------------------------------------
466 
GetNumberOfDataSets()467 int vtkKdTree::GetNumberOfDataSets()
468 {
469   return this->DataSets->GetNumberOfItems();
470 }
471 
GetDataSetIndex(vtkDataSet * set)472 int vtkKdTree::GetDataSetIndex(vtkDataSet *set)
473 {
474   // This is weird, but IsItemPresent returns the index + 1 (so that 0
475   // corresponds to item not present).
476   return this->DataSets->IsItemPresent(set) - 1;
477 }
478 
GetDataSet(int index)479 vtkDataSet *vtkKdTree::GetDataSet(int index)
480 {
481   return this->DataSets->GetItem(index);
482 }
483 
GetDataSetsNumberOfCells(int from,int to)484 int vtkKdTree::GetDataSetsNumberOfCells(int from, int to)
485 {
486   int numCells = 0;
487 
488   for (int i=from; i<=to; i++)
489   {
490     vtkDataSet *data = this->GetDataSet(i);
491     if (data)
492     {
493       numCells += data->GetNumberOfCells();
494     }
495   }
496 
497   return numCells;
498 }
499 
500 //----------------------------------------------------------------------------
GetNumberOfCells()501 int vtkKdTree::GetNumberOfCells()
502 {
503   return this->GetDataSetsNumberOfCells(0, this->GetNumberOfDataSets()-1);
504 }
505 
506 //----------------------------------------------------------------------------
GetBounds(double * bounds)507 void vtkKdTree::GetBounds(double *bounds)
508 {
509   if (this->Top)
510   {
511     this->Top->GetBounds(bounds);
512   }
513 }
514 
515 //----------------------------------------------------------------------------
GetRegionBounds(int regionID,double bounds[6])516 void vtkKdTree::GetRegionBounds(int regionID, double bounds[6])
517 {
518   if ( (regionID < 0) || (regionID >= this->NumberOfRegions))
519   {
520     vtkErrorMacro( << "vtkKdTree::GetRegionBounds invalid region");
521     return;
522   }
523 
524   vtkKdNode *node = this->RegionList[regionID];
525 
526   node->GetBounds(bounds);
527 }
528 
529 //----------------------------------------------------------------------------
GetRegionDataBounds(int regionID,double bounds[6])530 void vtkKdTree::GetRegionDataBounds(int regionID, double bounds[6])
531 {
532   if ( (regionID < 0) || (regionID >= this->NumberOfRegions))
533   {
534     vtkErrorMacro( << "vtkKdTree::GetRegionDataBounds invalid region");
535     return;
536   }
537 
538   vtkKdNode *node = this->RegionList[regionID];
539 
540   node->GetDataBounds(bounds);
541 }
542 
543 //----------------------------------------------------------------------------
_GetRegionsAtLevel(int level,vtkKdNode ** nodes,vtkKdNode * kd)544 vtkKdNode **vtkKdTree::_GetRegionsAtLevel(int level, vtkKdNode **nodes, vtkKdNode *kd)
545 {
546   if (level > 0)
547   {
548     vtkKdNode **nodes0 = _GetRegionsAtLevel(level-1, nodes, kd->GetLeft());
549     vtkKdNode **nodes1 = _GetRegionsAtLevel(level-1, nodes0, kd->GetRight());
550 
551     return nodes1;
552   }
553   else
554   {
555     nodes[0] = kd;
556     return nodes+1;
557   }
558 }
559 
560 //----------------------------------------------------------------------------
GetRegionsAtLevel(int level,vtkKdNode ** nodes)561 void vtkKdTree::GetRegionsAtLevel(int level, vtkKdNode **nodes)
562 {
563   if ( (level < 0) || (level > this->Level))
564   {
565     return;
566   }
567 
568   vtkKdTree::_GetRegionsAtLevel(level, nodes, this->Top);
569 }
570 
571 //----------------------------------------------------------------------------
GetLeafNodeIds(vtkKdNode * node,vtkIntArray * ids)572 void vtkKdTree::GetLeafNodeIds(vtkKdNode *node, vtkIntArray *ids)
573 {
574   int id = node->GetID();
575 
576   if (id < 0)
577   {
578     vtkKdTree::GetLeafNodeIds(node->GetLeft(), ids);
579     vtkKdTree::GetLeafNodeIds(node->GetRight(), ids);
580   }
581   else
582   {
583     ids->InsertNextValue(id);
584   }
585 }
586 
587 //----------------------------------------------------------------------------
ComputeCellCenters()588 float *vtkKdTree::ComputeCellCenters()
589 {
590   vtkDataSet *allSets = nullptr;
591   return this->ComputeCellCenters(allSets);
592 }
593 
594 //----------------------------------------------------------------------------
ComputeCellCenters(int set)595 float *vtkKdTree::ComputeCellCenters(int set)
596 {
597   vtkDataSet *data = this->GetDataSet(set);
598   if (!data)
599   {
600     vtkErrorMacro(<<"vtkKdTree::ComputeCellCenters no such data set");
601     return nullptr;
602   }
603   return this->ComputeCellCenters(data);
604 }
605 
606 //----------------------------------------------------------------------------
ComputeCellCenters(vtkDataSet * set)607 float *vtkKdTree::ComputeCellCenters(vtkDataSet *set)
608 {
609   SCOPETIMER("ComputeCellCenters");
610   this->UpdateSubOperationProgress(0);
611   int totalCells;
612 
613   if (set)
614   {
615     totalCells = set->GetNumberOfCells();
616   }
617   else
618   {
619     totalCells = this->GetNumberOfCells();   // all data sets
620   }
621 
622   if (totalCells == 0)
623   {
624     return nullptr;
625   }
626 
627   float *center = new float [3 * totalCells];
628 
629   if (!center)
630   {
631     return nullptr;
632   }
633 
634   int maxCellSize = 0;
635 
636   if (set)
637   {
638     maxCellSize = set->GetMaxCellSize();
639   }
640   else
641   {
642     vtkCollectionSimpleIterator cookie;
643     this->DataSets->InitTraversal(cookie);
644     for (vtkDataSet *iset = this->DataSets->GetNextDataSet(cookie);
645          iset != nullptr; iset = this->DataSets->GetNextDataSet(cookie))
646     {
647       int cellSize = iset->GetMaxCellSize();
648       maxCellSize = (cellSize > maxCellSize) ? cellSize : maxCellSize;
649     }
650   }
651 
652   double *weights = new double [maxCellSize];
653 
654   float *cptr = center;
655   double dcenter[3];
656 
657   if (set)
658   {
659     for (int j=0; j<totalCells; j++)
660     {
661       this->ComputeCellCenter(set->GetCell(j), dcenter, weights);
662       cptr[0] = static_cast<float>(dcenter[0]);
663       cptr[1] = static_cast<float>(dcenter[1]);
664       cptr[2] = static_cast<float>(dcenter[2]);
665       cptr += 3;
666       if (j%1000 == 0)
667       {
668         this->UpdateSubOperationProgress(static_cast<double>(j)/totalCells);
669       }
670     }
671   }
672   else
673   {
674     vtkCollectionSimpleIterator cookie;
675     this->DataSets->InitTraversal(cookie);
676     for (vtkDataSet *iset = this->DataSets->GetNextDataSet(cookie);
677          iset != nullptr; iset = this->DataSets->GetNextDataSet(cookie))
678     {
679       int nCells = iset->GetNumberOfCells();
680 
681       for (int j=0; j<nCells; j++)
682       {
683         this->ComputeCellCenter(iset->GetCell(j), dcenter, weights);
684         cptr[0] = static_cast<float>(dcenter[0]);
685         cptr[1] = static_cast<float>(dcenter[1]);
686         cptr[2] = static_cast<float>(dcenter[2]);
687         cptr += 3;
688         if (j%1000 == 0)
689         {
690           this->UpdateSubOperationProgress(static_cast<double>(j)/totalCells);
691         }
692       }
693     }
694   }
695 
696   delete [] weights;
697 
698   this->UpdateSubOperationProgress(1.0);
699   return center;
700 }
701 
702 //----------------------------------------------------------------------------
ComputeCellCenter(vtkDataSet * set,int cellId,float * center)703 void vtkKdTree::ComputeCellCenter(vtkDataSet *set, int cellId, float *center)
704 {
705   double dcenter[3];
706 
707   this->ComputeCellCenter(set, cellId, dcenter);
708 
709   center[0] = static_cast<float>(dcenter[0]);
710   center[1] = static_cast<float>(dcenter[1]);
711   center[2] = static_cast<float>(dcenter[2]);
712 }
713 
714 //----------------------------------------------------------------------------
ComputeCellCenter(vtkDataSet * set,int cellId,double * center)715 void vtkKdTree::ComputeCellCenter(vtkDataSet *set, int cellId, double *center)
716 {
717   int setNum;
718 
719   if (set)
720   {
721     setNum = this->GetDataSetIndex(set);
722 
723     if ( setNum < 0)
724     {
725       vtkErrorMacro(<<"vtkKdTree::ComputeCellCenter invalid data set");
726       return;
727     }
728   }
729   else
730   {
731     set = this->GetDataSet();
732   }
733 
734   if ( (cellId < 0) || (cellId >= set->GetNumberOfCells()))
735   {
736     vtkErrorMacro(<<"vtkKdTree::ComputeCellCenter invalid cell ID");
737     return;
738   }
739 
740   double *weights = new double [set->GetMaxCellSize()];
741 
742   this->ComputeCellCenter(set->GetCell(cellId), center, weights);
743 
744   delete [] weights;
745 }
746 
747 //----------------------------------------------------------------------------
ComputeCellCenter(vtkCell * cell,double * center,double * weights)748 void vtkKdTree::ComputeCellCenter(vtkCell *cell, double *center,
749                                   double *weights)
750 {
751   double pcoords[3];
752 
753   int subId = cell->GetParametricCenter(pcoords);
754 
755   cell->EvaluateLocation(subId, pcoords, center, weights);
756 }
757 
758 //----------------------------------------------------------------------------
759 // Build the kdtree structure based on location of cell centroids.
760 //
BuildLocator()761 void vtkKdTree::BuildLocator()
762 {
763   SCOPETIMER("BuildLocator");
764 
765   this->UpdateProgress(0);
766   int nCells=0;
767   int i;
768 
769   if ((this->Top != nullptr) &&
770       (this->BuildTime > this->GetMTime()) &&
771       (this->NewGeometry() == 0))
772   {
773     return;
774   }
775 
776   nCells = this->GetNumberOfCells();
777 
778   if (nCells == 0)
779   {
780      vtkErrorMacro( << "vtkKdTree::BuildLocator - No cells to subdivide");
781      return;
782   }
783 
784   vtkDebugMacro( << "Creating Kdtree" );
785   this->InvokeEvent(vtkCommand::StartEvent);
786 
787   if ((this->Timing) && (this->TimerLog == nullptr))
788   {
789     this->TimerLog = vtkTimerLog::New();
790   }
791 
792   TIMER("Set up to build k-d tree");
793 
794   this->FreeSearchStructure();
795 
796   // volume bounds - push out a little if flat
797   vtkCollectionSimpleIterator cookie;
798   this->DataSets->InitTraversal(cookie);
799   vtkDataSet *iset = this->DataSets->GetNextDataSet(cookie);
800   double volBounds[6];
801   iset->GetBounds(volBounds);
802 
803   while ((iset = this->DataSets->GetNextDataSet(cookie)))
804   {
805     double setBounds[6];
806     iset->GetBounds(setBounds);
807     if (setBounds[0] < volBounds[0])
808     {
809       volBounds[0] = setBounds[0];
810     }
811     if (setBounds[2] < volBounds[2])
812     {
813       volBounds[2] = setBounds[2];
814     }
815     if (setBounds[4] < volBounds[4])
816     {
817       volBounds[4] = setBounds[4];
818     }
819     if (setBounds[1] > volBounds[1])
820     {
821       volBounds[1] = setBounds[1];
822     }
823     if (setBounds[3] > volBounds[3])
824     {
825       volBounds[3] = setBounds[3];
826     }
827     if (setBounds[5] > volBounds[5])
828     {
829       volBounds[5] = setBounds[5];
830     }
831   }
832 
833   double diff[3], aLittle = 0.0;
834   this->MaxWidth = 0.0;
835 
836   for (i=0; i<3; i++)
837   {
838      diff[i] = volBounds[2*i+1] - volBounds[2*i];
839      this->MaxWidth = static_cast<float>(
840        (diff[i] > this->MaxWidth) ? diff[i] : this->MaxWidth);
841   }
842 
843   this->FudgeFactor = this->MaxWidth * 10e-6;
844 
845   aLittle = this->MaxWidth / 100.0;
846 
847   for (i=0; i<3; i++)
848   {
849     if (diff[i] <= 0)
850     {
851       volBounds[2*i]   -= aLittle;
852       volBounds[2*i+1] += aLittle;
853     }
854     else // need lower bound to be strictly less than any point in decomposition
855     {
856       volBounds[2*i] -= this->FudgeFactor;
857       volBounds[2*i+1] += this->FudgeFactor;
858     }
859   }
860   TIMERDONE("Set up to build k-d tree");
861 
862   if (this->UserDefinedCuts)
863   {
864     // Actually, we will not compute the k-d tree.  We will use a
865     // k-d tree provided to us.
866 
867     int fail = this->ProcessUserDefinedCuts(volBounds);
868 
869     if (fail)
870     {
871       return;
872     }
873   }
874   else
875   {
876     // cell centers - basis of spatial decomposition
877 
878     TIMER("Create centroid list");
879     this->ProgressOffset = 0;
880     this->ProgressScale = 0.3;
881     float *ptarray = this->ComputeCellCenters();
882 
883     TIMERDONE("Create centroid list");
884 
885     if (!ptarray)
886     {
887       vtkErrorMacro( << "vtkKdTree::BuildLocator - insufficient memory");
888       return;
889     }
890 
891     // create kd tree structure that balances cell centers
892 
893     vtkKdNode *kd = this->Top = vtkKdNode::New();
894 
895     kd->SetBounds(volBounds[0], volBounds[1],
896                   volBounds[2], volBounds[3],
897                   volBounds[4], volBounds[5]);
898 
899     kd->SetNumberOfPoints(nCells);
900 
901     kd->SetDataBounds(volBounds[0], volBounds[1],
902                       volBounds[2], volBounds[3],
903                       volBounds[4], volBounds[5]);
904 
905     TIMER("Build tree");
906 
907     this->ProgressOffset += this->ProgressScale;
908     this->ProgressScale = 0.7;
909     this->DivideRegion(kd, ptarray, nullptr, 0);
910 
911     TIMERDONE("Build tree");
912 
913     // In the process of building the k-d tree regions,
914     //   the cell centers became reordered, so no point
915     //   in saving them, for example to build cell lists.
916 
917     delete [] ptarray;
918   }
919 
920   this->SetActualLevel();
921   this->BuildRegionList();
922 
923   this->InvokeEvent(vtkCommand::EndEvent);
924 
925   this->UpdateBuildTime();
926 
927   this->SetCalculator(this->Top);
928 
929   this->UpdateProgress(1.0);
930 }
931 
ProcessUserDefinedCuts(double * minBounds)932 int vtkKdTree::ProcessUserDefinedCuts(double *minBounds)
933 {
934   SCOPETIMER("ProcessUserDefinedCuts");
935 
936   if (!this->Cuts)
937   {
938     vtkErrorMacro(<< "vtkKdTree::ProcessUserDefinedCuts - no cuts" );
939     return 1;
940   }
941   // Fix the bounds for the entire partitioning.  They must be at
942   // least as large of the bounds of all the data sets.
943 
944   vtkKdNode *kd = this->Cuts->GetKdNodeTree();
945   double bounds[6];
946   kd->GetBounds(bounds);
947   int fixBounds = 0;
948 
949   for (int j=0; j<3; j++)
950   {
951     int min = 2*j;
952     int max = min+1;
953 
954     if (minBounds[min] < bounds[min])
955     {
956       bounds[min] = minBounds[min];
957       fixBounds = 1;
958     }
959     if (minBounds[max] > bounds[max])
960     {
961       bounds[max] = minBounds[max];
962       fixBounds = 1;
963     }
964   }
965 
966   this->Top = vtkKdTree::CopyTree(kd);
967 
968   if (fixBounds)
969   {
970     this->SetNewBounds(bounds);
971   }
972 
973   // We don't really know the data bounds, so we'll just set them
974   // to the spatial bounds.
975 
976   vtkKdTree::SetDataBoundsToSpatialBounds(this->Top);
977 
978   // And, we don't know how many points are in each region.  The number
979   // in the provided vtkBSPCuts object was for some other dataset.  So
980   // we zero out those fields.
981 
982   vtkKdTree::ZeroNumberOfPoints(this->Top);
983 
984   return 0;
985 }
986 //----------------------------------------------------------------------------
ZeroNumberOfPoints(vtkKdNode * kd)987 void vtkKdTree::ZeroNumberOfPoints(vtkKdNode *kd)
988 {
989   kd->SetNumberOfPoints(0);
990 
991   if (kd->GetLeft())
992   {
993     vtkKdTree::ZeroNumberOfPoints(kd->GetLeft());
994     vtkKdTree::ZeroNumberOfPoints(kd->GetRight());
995   }
996 }
997 //----------------------------------------------------------------------------
SetNewBounds(double * bounds)998 void vtkKdTree::SetNewBounds(double *bounds)
999 {
1000   vtkKdNode *kd = this->Top;
1001 
1002   if (!kd)
1003   {
1004     return;
1005   }
1006 
1007   int fixDimLeft[6], fixDimRight[6];
1008   int go=0;
1009 
1010   double kdb[6];
1011   kd->GetBounds(kdb);
1012 
1013   for (int i=0; i<3; i++)
1014   {
1015     int min = 2*i;
1016     int max = 2*i + 1;
1017 
1018     fixDimLeft[min] = fixDimRight[min] = 0;
1019     fixDimLeft[max] = fixDimRight[max] = 0;
1020 
1021     if (kdb[min] > bounds[min])
1022     {
1023       kdb[min] = bounds[min];
1024       go = fixDimLeft[min] = fixDimRight[min] = 1;
1025     }
1026     if (kdb[max] < bounds[max])
1027     {
1028       kdb[max] = bounds[max];
1029       go = fixDimLeft[max] = fixDimRight[max] = 1;
1030     }
1031   }
1032 
1033   if (go)
1034   {
1035     kd->SetBounds(kdb[0],kdb[1],kdb[2],kdb[3],kdb[4],kdb[5]);
1036 
1037     if (kd->GetLeft())
1038     {
1039       int cutDim = kd->GetDim() * 2;
1040 
1041       fixDimLeft[cutDim + 1] = 0;
1042       vtkKdTree::_SetNewBounds(kd->GetLeft(), bounds, fixDimLeft);
1043 
1044       fixDimRight[cutDim] = 0;
1045       vtkKdTree::_SetNewBounds(kd->GetRight(), bounds, fixDimRight);
1046     }
1047   }
1048 }
1049 //----------------------------------------------------------------------------
_SetNewBounds(vtkKdNode * kd,double * b,int * fixDim)1050 void vtkKdTree::_SetNewBounds(vtkKdNode *kd, double *b, int *fixDim)
1051 {
1052   int go=0;
1053   int fixDimLeft[6], fixDimRight[6];
1054 
1055   double kdb[6];
1056   kd->GetBounds(kdb);
1057 
1058   for (int i=0; i<6; i++)
1059   {
1060     if (fixDim[i])
1061     {
1062       kdb[i] = b[i];
1063       go = 1;
1064     }
1065     fixDimLeft[i] = fixDim[i];
1066     fixDimRight[i] = fixDim[i];
1067   }
1068 
1069   if (go)
1070   {
1071     kd->SetBounds(kdb[0],kdb[1],kdb[2],kdb[3],kdb[4],kdb[5]);
1072 
1073     if (kd->GetLeft())
1074     {
1075       int cutDim = kd->GetDim() * 2;
1076 
1077       fixDimLeft[cutDim + 1] = 0;
1078       vtkKdTree::_SetNewBounds(kd->GetLeft(), b, fixDimLeft);
1079 
1080       fixDimRight[cutDim] = 0;
1081       vtkKdTree::_SetNewBounds(kd->GetRight(), b, fixDimRight);
1082     }
1083   }
1084 }
1085 //----------------------------------------------------------------------------
CopyTree(vtkKdNode * kd)1086 vtkKdNode *vtkKdTree::CopyTree(vtkKdNode *kd)
1087 {
1088   vtkKdNode *top = vtkKdNode::New();
1089   vtkKdTree::CopyKdNode(top, kd);
1090   vtkKdTree::CopyChildNodes(top, kd);
1091 
1092   return top;
1093 }
1094 //----------------------------------------------------------------------------
CopyChildNodes(vtkKdNode * to,vtkKdNode * from)1095 void vtkKdTree::CopyChildNodes(vtkKdNode *to, vtkKdNode *from)
1096 {
1097   if (from->GetLeft())
1098   {
1099     vtkKdNode *left = vtkKdNode::New();
1100     vtkKdNode *right = vtkKdNode::New();
1101 
1102     vtkKdTree::CopyKdNode(left, from->GetLeft());
1103     vtkKdTree::CopyKdNode(right, from->GetRight());
1104 
1105     to->AddChildNodes(left, right);
1106 
1107     vtkKdTree::CopyChildNodes(to->GetLeft(), from->GetLeft());
1108     vtkKdTree::CopyChildNodes(to->GetRight(), from->GetRight());
1109   }
1110 }
1111 //----------------------------------------------------------------------------
CopyKdNode(vtkKdNode * to,vtkKdNode * from)1112 void vtkKdTree::CopyKdNode(vtkKdNode *to, vtkKdNode *from)
1113 {
1114   to->SetMinBounds(from->GetMinBounds());
1115   to->SetMaxBounds(from->GetMaxBounds());
1116   to->SetMinDataBounds(from->GetMinDataBounds());
1117   to->SetMaxDataBounds(from->GetMaxDataBounds());
1118   to->SetID(from->GetID());
1119   to->SetMinID(from->GetMinID());
1120   to->SetMaxID(from->GetMaxID());
1121   to->SetNumberOfPoints(from->GetNumberOfPoints());
1122   to->SetDim(from->GetDim());
1123 }
1124 
1125 //----------------------------------------------------------------------------
ComputeLevel(vtkKdNode * kd)1126 int vtkKdTree::ComputeLevel(vtkKdNode *kd)
1127 {
1128   if (!kd)
1129   {
1130     return 0;
1131   }
1132 
1133   int iam = 1;
1134 
1135   if (kd->GetLeft() != nullptr)
1136   {
1137      int depth1 = vtkKdTree::ComputeLevel(kd->GetLeft());
1138      int depth2 = vtkKdTree::ComputeLevel(kd->GetRight());
1139 
1140      if (depth1 > depth2)
1141      {
1142        iam += depth1;
1143      }
1144      else
1145      {
1146        iam += depth2;
1147      }
1148   }
1149   return iam;
1150 }
1151 //----------------------------------------------------------------------------
SetDataBoundsToSpatialBounds(vtkKdNode * kd)1152 void vtkKdTree::SetDataBoundsToSpatialBounds(vtkKdNode *kd)
1153 {
1154   kd->SetMinDataBounds(kd->GetMinBounds());
1155   kd->SetMaxDataBounds(kd->GetMaxBounds());
1156 
1157   if (kd->GetLeft())
1158   {
1159     vtkKdTree::SetDataBoundsToSpatialBounds(kd->GetLeft());
1160     vtkKdTree::SetDataBoundsToSpatialBounds(kd->GetRight());
1161   }
1162 }
1163 //----------------------------------------------------------------------------
SelectCutDirection(vtkKdNode * kd)1164 int vtkKdTree::SelectCutDirection(vtkKdNode *kd)
1165 {
1166   int dim=0, i;
1167 
1168   int xdir = 1 << vtkKdTree::XDIM;
1169   int ydir = 1 << vtkKdTree::YDIM;
1170   int zdir = 1 << vtkKdTree::ZDIM;
1171 
1172   // determine direction in which to divide this region
1173 
1174   if (this->ValidDirections == xdir)
1175   {
1176     dim = vtkKdTree::XDIM;
1177   }
1178   else if (this->ValidDirections == ydir)
1179   {
1180     dim = vtkKdTree::YDIM;
1181   }
1182   else if (this->ValidDirections == zdir)
1183   {
1184     dim = vtkKdTree::ZDIM;
1185   }
1186   else
1187   {
1188     // divide in the longest direction, for more compact regions
1189 
1190     double diff[3], dataBounds[6], maxdiff;
1191     kd->GetDataBounds(dataBounds);
1192 
1193     for (i=0; i<3; i++)
1194     {
1195       diff[i] = dataBounds[i*2+1] - dataBounds[i*2];
1196     }
1197 
1198     maxdiff = -1.0;
1199 
1200     if ((this->ValidDirections & xdir) && (diff[vtkKdTree::XDIM] > maxdiff))
1201     {
1202       dim = vtkKdTree::XDIM;
1203       maxdiff = diff[vtkKdTree::XDIM];
1204     }
1205 
1206     if ((this->ValidDirections & ydir) && (diff[vtkKdTree::YDIM] > maxdiff))
1207     {
1208       dim = vtkKdTree::YDIM;
1209       maxdiff = diff[vtkKdTree::YDIM];
1210     }
1211 
1212     if ((this->ValidDirections & zdir) && (diff[vtkKdTree::ZDIM] > maxdiff))
1213     {
1214       dim = vtkKdTree::ZDIM;
1215     }
1216   }
1217   return dim;
1218 }
1219 //----------------------------------------------------------------------------
DivideTest(int size,int level)1220 int vtkKdTree::DivideTest(int size, int level)
1221 {
1222   if (level >= this->MaxLevel) return 0;
1223 
1224   int minCells = this->GetMinCells();
1225 
1226   if (minCells && (minCells > (size/2))) return 0;
1227 
1228   int nRegionsNow  = 1 << level;
1229   int nRegionsNext = nRegionsNow << 1;
1230 
1231   if (this->NumberOfRegionsOrLess && (nRegionsNext > this->NumberOfRegionsOrLess)) return 0;
1232   if (this->NumberOfRegionsOrMore && (nRegionsNow >= this->NumberOfRegionsOrMore)) return 0;
1233 
1234   return 1;
1235 }
1236 //----------------------------------------------------------------------------
DivideRegion(vtkKdNode * kd,float * c1,int * ids,int level)1237 int vtkKdTree::DivideRegion(vtkKdNode *kd, float *c1, int *ids, int level)
1238 {
1239   int ok = this->DivideTest(kd->GetNumberOfPoints(), level);
1240 
1241   if (!ok)
1242   {
1243     return 0;
1244   }
1245 
1246   int maxdim = this->SelectCutDirection(kd);
1247 
1248   kd->SetDim(maxdim);
1249 
1250   int dim1 = maxdim;   // best cut direction
1251   int dim2 = -1;       // other valid cut directions
1252   int dim3 = -1;
1253 
1254   int otherDirections = this->ValidDirections ^ (1 << maxdim);
1255 
1256   if (otherDirections)
1257   {
1258     int x = otherDirections & (1 << vtkKdTree::XDIM);
1259     int y = otherDirections & (1 << vtkKdTree::YDIM);
1260     int z = otherDirections & (1 << vtkKdTree::ZDIM);
1261 
1262     if (x)
1263     {
1264       dim2 = vtkKdTree::XDIM;
1265 
1266       if (y)
1267       {
1268         dim3 = vtkKdTree::YDIM;
1269       }
1270       else if (z)
1271       {
1272         dim3 = vtkKdTree::ZDIM;
1273       }
1274     }
1275     else if (y)
1276     {
1277       dim2 = vtkKdTree::YDIM;
1278 
1279       if (z)
1280       {
1281         dim3 = vtkKdTree::ZDIM;
1282       }
1283     }
1284     else if (z)
1285     {
1286       dim2 = vtkKdTree::ZDIM;
1287     }
1288   }
1289 
1290   this->DoMedianFind(kd, c1, ids, dim1, dim2, dim3);
1291 
1292   if (kd->GetLeft() == nullptr)
1293   {
1294     return 0;   // unable to divide region further
1295   }
1296 
1297   int nleft = kd->GetLeft()->GetNumberOfPoints();
1298 
1299   int *leftIds  = ids;
1300   int *rightIds = ids ? ids + nleft : nullptr;
1301 
1302   this->DivideRegion(kd->GetLeft(), c1, leftIds, level + 1);
1303 
1304   this->DivideRegion(kd->GetRight(), c1 + nleft*3, rightIds, level + 1);
1305 
1306   return 0;
1307 }
1308 
1309 //----------------------------------------------------------------------------
1310 // Rearrange the point array.  Try dim1 first.  If there's a problem
1311 // go to dim2, then dim3.
1312 //
DoMedianFind(vtkKdNode * kd,float * c1,int * ids,int dim1,int dim2,int dim3)1313 void vtkKdTree::DoMedianFind(vtkKdNode *kd, float *c1, int *ids,
1314                              int dim1, int dim2, int dim3)
1315 {
1316   double coord;
1317   int dim;
1318   int midpt;
1319 
1320   int npoints = kd->GetNumberOfPoints();
1321 
1322   int dims[3] = {dim1, dim2, dim3};
1323 
1324   for (dim = 0; dim < 3; dim++)
1325   {
1326     if (dims[dim] < 0)
1327     {
1328       break;
1329     }
1330 
1331     midpt = vtkKdTree::Select(dims[dim], c1, ids, npoints, coord);
1332 
1333     if (midpt == 0)
1334     {
1335       continue;    // fatal
1336     }
1337 
1338     kd->SetDim(dims[dim]);
1339 
1340     vtkKdTree::AddNewRegions(kd, c1, midpt, dims[dim], coord);
1341 
1342     break;   // division is fine
1343   }
1344 }
1345 
1346 //----------------------------------------------------------------------------
AddNewRegions(vtkKdNode * kd,float * c1,int midpt,int dim,double coord)1347 void vtkKdTree::AddNewRegions(vtkKdNode *kd, float *c1, int midpt, int dim, double coord)
1348 {
1349   vtkKdNode *left = vtkKdNode::New();
1350   vtkKdNode *right = vtkKdNode::New();
1351 
1352   int npoints = kd->GetNumberOfPoints();
1353 
1354   int nleft = midpt;
1355   int nright = npoints - midpt;
1356 
1357   kd->AddChildNodes(left, right);
1358 
1359   double bounds[6];
1360   kd->GetBounds(bounds);
1361 
1362   left->SetBounds(
1363      bounds[0], ((dim == vtkKdTree::XDIM) ? coord : bounds[1]),
1364      bounds[2], ((dim == vtkKdTree::YDIM) ? coord : bounds[3]),
1365      bounds[4], ((dim == vtkKdTree::ZDIM) ? coord : bounds[5]));
1366 
1367   left->SetNumberOfPoints(nleft);
1368 
1369   right->SetBounds(
1370      ((dim == vtkKdTree::XDIM) ? coord : bounds[0]), bounds[1],
1371      ((dim == vtkKdTree::YDIM) ? coord : bounds[2]), bounds[3],
1372      ((dim == vtkKdTree::ZDIM) ? coord : bounds[4]), bounds[5]);
1373 
1374   right->SetNumberOfPoints(nright);
1375 
1376   left->SetDataBounds(c1);
1377   right->SetDataBounds(c1 + nleft*3);
1378 }
1379 // Use Floyd & Rivest (1975) to find the median:
1380 // Given an array X with element indices ranging from L to R, and
1381 // a K such that L <= K <= R, rearrange the elements such that
1382 // X[K] contains the ith sorted element,  where i = K - L + 1, and
1383 // all the elements X[j], j < k satisfy X[j] < X[K], and all the
1384 // elements X[j], j > k satisfy X[j] >= X[K].
1385 
1386 #define Exchange(array, ids, x, y) \
1387   {                                 \
1388   float temp[3];                    \
1389   temp[0]        = array[3*x];      \
1390   temp[1]        = array[3*x + 1];  \
1391   temp[2]        = array[3*x + 2];  \
1392   array[3*x]     = array[3*y];      \
1393   array[3*x + 1] = array[3*y + 1];  \
1394   array[3*x + 2] = array[3*y + 2];  \
1395   array[3*y]     = temp[0];         \
1396   array[3*y + 1] = temp[1];         \
1397   array[3*y + 2] = temp[2];         \
1398   if (ids)                          \
1399   {                               \
1400     vtkIdType tempid = ids[x];      \
1401     ids[x]           = ids[y];      \
1402     ids[y]           = tempid;      \
1403   }                               \
1404 }
1405 
1406 #define sign(x) (((x)<0) ? (-1) : (1))
1407 
1408 //----------------------------------------------------------------------------
Select(int dim,float * c1,int * ids,int nvals,double & coord)1409 int vtkKdTree::Select(int dim, float *c1, int *ids, int nvals, double &coord)
1410 {
1411   int left = 0;
1412   int mid = nvals / 2;
1413   int right = nvals -1;
1414 
1415   vtkKdTree::_Select(dim, c1, ids, left, right, mid);
1416 
1417   // We need to be careful in the case where the "mid"
1418   // value is repeated several times in the array.  We
1419   // want to roll the dividing index (mid) back to the
1420   // first occurrence in the array, so that there is no
1421   // ambiguity about which spatial region a given point
1422   // belongs in.
1423   //
1424   // The array has been rearranged (in _Select) like this:
1425   //
1426   // All values c1[n], left <= n < mid, satisfy c1[n] <= c1[mid]
1427   // All values c1[n], mid < n <= right, satisfy c1[n] >= c1[mid]
1428   //
1429   // In addition, by careful construction, there is a J <= mid
1430   // such that
1431   //
1432   // All values c1[n], n < J, satisfy c1[n] < c1[mid] STRICTLY
1433   // All values c1[n], J <= n <= mid, satisfy c1[n] = c1[mid]
1434   // All values c1[n], mid < n <= right , satisfy c1[n] >= c1[mid]
1435   //
1436   // We need to roll back the "mid" value to the "J".  This
1437   // means our spatial regions are less balanced, but there
1438   // is no ambiguity regarding which region a point belongs in.
1439 
1440   int midValIndex = mid*3 + dim;
1441 
1442   while ((mid > left) && (c1[midValIndex-3] == c1[midValIndex]))
1443   {
1444     mid--;
1445     midValIndex -= 3;
1446   }
1447 
1448   if (mid == left)
1449   {
1450     return mid;     // failed to divide region
1451   }
1452 
1453   float leftMax = vtkKdTree::FindMaxLeftHalf(dim, c1, mid);
1454 
1455   coord=(static_cast<double>(c1[midValIndex])
1456          +static_cast<double>(leftMax))/2.0;
1457 
1458   return mid;
1459 }
1460 
1461 //----------------------------------------------------------------------------
FindMaxLeftHalf(int dim,float * c1,int K)1462 float vtkKdTree::FindMaxLeftHalf(int dim, float *c1, int K)
1463 {
1464   int i;
1465 
1466   float *Xcomponent = c1 + dim;
1467   float max = Xcomponent[0];
1468 
1469   for (i=3; i<K*3; i+=3)
1470   {
1471     if (Xcomponent[i] > max)
1472     {
1473       max = Xcomponent[i];
1474     }
1475   }
1476   return max;
1477 }
1478 
1479 //----------------------------------------------------------------------------
1480 // Note: The indices (L, R, X) into the point array should be vtkIdTypes rather
1481 // than ints, but this change causes the k-d tree build time to double.
1482 // _Select is the heart of this build, called for every sub-interval that
1483 // is to be reordered.  We will leave these as ints now.
1484 
_Select(int dim,float * X,int * ids,int L,int R,int K)1485 void vtkKdTree::_Select(int dim, float *X, int *ids,
1486                         int L, int R, int K)
1487 {
1488   int N, I, J, S, SD, LL, RR;
1489   float Z, T;
1490   int manyTValues=0;
1491 
1492   while (R > L)
1493   {
1494     if ( R - L > 600)
1495     {
1496       // "Recurse on a sample of size S to get an estimate for the
1497       // (K-L+1)-th smallest element into X[K], biased slightly so
1498       // that the (K-L+1)-th element is expected to lie in the
1499       // smaller set after partitioning"
1500 
1501       N = R - L + 1;
1502       I = K - L + 1;
1503       Z = static_cast<float>(log(static_cast<float>(N)));
1504       S = static_cast<int>(.5 * exp(2*Z/3));
1505       SD = static_cast<int>(.5 * sqrt(Z*S*static_cast<float>(N-S)/N) * sign(I - N/2));
1506       LL = vtkMath::Max(L, K - static_cast<int>(I*static_cast<float>(S)/N) + SD);
1507       RR = vtkMath::Min(R, K + static_cast<int>((N-I)*static_cast<float>(S)/N) + SD);
1508       _Select(dim, X, ids, LL, RR, K);
1509     }
1510 
1511     float *Xcomponent = X + dim;   // x, y or z component
1512 
1513     T = Xcomponent[K*3];
1514 
1515     // "the following code partitions X[L:R] about T."
1516 
1517     I = L;
1518     J = R;
1519 
1520     Exchange(X, ids, L, K);
1521 
1522     if (Xcomponent[R*3] >= T)
1523     {
1524       if (Xcomponent[R*3] == T) manyTValues++;
1525       Exchange(X, ids, R, L);
1526     }
1527     while (I < J)
1528     {
1529       Exchange(X, ids, I, J);
1530 
1531       while (Xcomponent[(++I)*3] < T)
1532       {
1533         ;
1534       }
1535 
1536       while ((J>L) && (Xcomponent[(--J)*3] >= T))
1537       {
1538         if (!manyTValues && (J>L) && (Xcomponent[J*3] == T))
1539         {
1540           manyTValues = 1;
1541         }
1542       }
1543     }
1544 
1545     if (Xcomponent[L*3] == T)
1546     {
1547       Exchange(X, ids, L, J);
1548     }
1549     else
1550     {
1551       J++;
1552       Exchange(X, ids, J, R);
1553     }
1554 
1555     if ((J < K) && manyTValues)
1556     {
1557       // Select has a worst case - when many of the same values
1558       // are repeated in an array.  It is bad enough that it is
1559       // worth detecting and optimizing for.  Here we're taking the
1560       // interval of values that are >= T, and rearranging it into
1561       // an interval of values = T followed by those > T.
1562 
1563       I = J;
1564       J = R+1;
1565 
1566       while (I < J)
1567       {
1568         while ((++I < J) && (Xcomponent[I*3] == T))
1569         {
1570           ;
1571         }
1572         if (I == J) break;
1573 
1574         while ((--J > I) && (Xcomponent[J*3] > T))
1575         {
1576           ;
1577         }
1578         if (J == I) break;
1579 
1580         Exchange(X, ids, I, J);
1581       }
1582 
1583       // I and J are at the first array element that is > T
1584       // If K is within the sequence of T's, we're done, else
1585       // move the new [L,R] interval to the sequence of values
1586       // that are strictly greater than T.
1587 
1588       if (K < J)
1589       {
1590         J = K;
1591       }
1592       else
1593       {
1594         J = J-1;
1595       }
1596     }
1597 
1598     // "now adjust L,R so they surround the subset containing
1599     // the (K-L+1)-th smallest element"
1600 
1601     if (J <= K)
1602     {
1603       L = J + 1;
1604     }
1605     if (K <= J)
1606     {
1607       R = J - 1;
1608     }
1609   }
1610 }
1611 
1612 //----------------------------------------------------------------------------
SelfRegister(vtkKdNode * kd)1613 void vtkKdTree::SelfRegister(vtkKdNode *kd)
1614 {
1615   if (kd->GetLeft() == nullptr)
1616   {
1617     this->RegionList[kd->GetID()] = kd;
1618   }
1619   else
1620   {
1621     this->SelfRegister(kd->GetLeft());
1622     this->SelfRegister(kd->GetRight());
1623   }
1624 }
1625 
1626 //----------------------------------------------------------------------------
SelfOrder(int startId,vtkKdNode * kd)1627 int vtkKdTree::SelfOrder(int startId, vtkKdNode *kd)
1628 {
1629   int nextId;
1630 
1631   if (kd->GetLeft() == nullptr)
1632   {
1633     kd->SetID(startId);
1634     kd->SetMaxID(startId);
1635     kd->SetMinID(startId);
1636 
1637     nextId = startId + 1;
1638   }
1639   else
1640   {
1641     kd->SetID(-1);
1642     nextId = vtkKdTree::SelfOrder(startId, kd->GetLeft());
1643     nextId = vtkKdTree::SelfOrder(nextId, kd->GetRight());
1644 
1645     kd->SetMinID(startId);
1646     kd->SetMaxID(nextId - 1);
1647   }
1648 
1649   return nextId;
1650 }
1651 
BuildRegionList()1652 void vtkKdTree::BuildRegionList()
1653 {
1654   SCOPETIMER("BuildRegionList");
1655 
1656   if (this->Top == nullptr)
1657   {
1658     return;
1659   }
1660 
1661   this->NumberOfRegions = vtkKdTree::SelfOrder(0, this->Top);
1662 
1663   this->RegionList = new vtkKdNode * [this->NumberOfRegions];
1664 
1665   this->SelfRegister(this->Top);
1666 }
1667 
1668 //----------------------------------------------------------------------------
1669 // K-d tree from points, for finding duplicate and near-by points
1670 //
BuildLocatorFromPoints(vtkPointSet * pointset)1671 void vtkKdTree::BuildLocatorFromPoints(vtkPointSet *pointset)
1672 {
1673   this->BuildLocatorFromPoints(pointset->GetPoints());
1674 }
1675 
BuildLocatorFromPoints(vtkPoints * ptArray)1676 void vtkKdTree::BuildLocatorFromPoints(vtkPoints *ptArray)
1677 {
1678   this->BuildLocatorFromPoints(&ptArray, 1);
1679 }
1680 
1681 //----------------------------------------------------------------------------
BuildLocatorFromPoints(vtkPoints ** ptArrays,int numPtArrays)1682 void vtkKdTree::BuildLocatorFromPoints(vtkPoints **ptArrays, int numPtArrays)
1683 {
1684   int ptId;
1685   int i;
1686 
1687   int totalNumPoints = 0;
1688 
1689   for (i = 0; i < numPtArrays; i++)
1690   {
1691     totalNumPoints += ptArrays[i]->GetNumberOfPoints();
1692   }
1693 
1694   if (totalNumPoints < 1)
1695   {
1696     vtkErrorMacro(<< "vtkKdTree::BuildLocatorFromPoints - no points");
1697     return;
1698   }
1699 
1700   if (totalNumPoints >= VTK_INT_MAX)
1701   {
1702      // The heart of the k-d tree build is the recursive median find in
1703      // _Select.  It rearranges point IDs along with points themselves.
1704      // When point IDs are stored in an "int" instead of a vtkIdType,
1705      // performance doubles.  So we store point IDs in an "int" during
1706      // the calculation.  This will need to be rewritten if true 64 bit
1707      // IDs are required.
1708 
1709      vtkErrorMacro(<<
1710     "BuildLocatorFromPoints - intentional 64 bit error - time to rewrite code");
1711      return;
1712   }
1713 
1714   vtkDebugMacro( << "Creating Kdtree" );
1715 
1716   if ((this->Timing) && (this->TimerLog == nullptr) )
1717   {
1718     this->TimerLog = vtkTimerLog::New();
1719   }
1720 
1721   TIMER("Set up to build k-d tree");
1722 
1723   this->FreeSearchStructure();
1724   this->ClearLastBuildCache();
1725 
1726   // Fix bounds - (1) push out a little if flat
1727   // (2) pull back the x, y and z lower bounds a little bit so that
1728   // points are clearly "inside" the spatial region.  Point p is
1729   // "inside" region r = [r1, r2] if r1 < p <= r2.
1730 
1731   double bounds[6], diff[3];
1732 
1733   ptArrays[0]->GetBounds(bounds);
1734 
1735   for (i=1; i<numPtArrays; i++)
1736   {
1737     double tmpbounds[6];
1738     ptArrays[i]->GetBounds(tmpbounds);
1739 
1740     if (tmpbounds[0] < bounds[0])
1741     {
1742       bounds[0] = tmpbounds[0];
1743     }
1744     if (tmpbounds[2] < bounds[2])
1745     {
1746       bounds[2] = tmpbounds[2];
1747     }
1748     if (tmpbounds[4] < bounds[4])
1749     {
1750       bounds[4] = tmpbounds[4];
1751     }
1752     if (tmpbounds[1] > bounds[1])
1753     {
1754       bounds[1] = tmpbounds[1];
1755     }
1756     if (tmpbounds[3] > bounds[3])
1757     {
1758       bounds[3] = tmpbounds[3];
1759     }
1760     if (tmpbounds[5] > bounds[5])
1761     {
1762       bounds[5] = tmpbounds[5];
1763     }
1764   }
1765 
1766   this->MaxWidth = 0.0;
1767 
1768   for (i=0; i<3; i++)
1769   {
1770     diff[i] = bounds[2*i+1] - bounds[2*i];
1771     this->MaxWidth = static_cast<float>
1772       ((diff[i] > this->MaxWidth) ? diff[i] : this->MaxWidth);
1773   }
1774 
1775   this->FudgeFactor = this->MaxWidth * 10e-6;
1776 
1777   double aLittle = this->MaxWidth * 10e-2;
1778 
1779   for (i=0; i<3; i++)
1780   {
1781     if (diff[i] < aLittle)         // case (1) above
1782     {
1783       double temp = bounds[2*i];
1784       bounds[2*i]   = bounds[2*i+1] - aLittle;
1785       bounds[2*i+1] = temp + aLittle;
1786     }
1787     else                           // case (2) above
1788     {
1789       bounds[2*i] -= this->FudgeFactor;
1790       bounds[2*i+1] += this->FudgeFactor;
1791     }
1792   }
1793 
1794   // root node of k-d tree - it's the whole space
1795 
1796   vtkKdNode *kd = this->Top = vtkKdNode::New();
1797 
1798   kd->SetBounds(bounds[0], bounds[1],
1799                 bounds[2], bounds[3],
1800                 bounds[4], bounds[5]);
1801 
1802   kd->SetNumberOfPoints(totalNumPoints);
1803 
1804   kd->SetDataBounds(bounds[0], bounds[1],
1805                     bounds[2], bounds[3],
1806                     bounds[4], bounds[5]);
1807 
1808 
1809   this->LocatorIds = new int [totalNumPoints];
1810   this->LocatorPoints = new float [3 * totalNumPoints];
1811 
1812   if ( !this->LocatorPoints || !this->LocatorIds)
1813   {
1814     this->FreeSearchStructure();
1815     vtkErrorMacro(<< "vtkKdTree::BuildLocatorFromPoints - memory allocation");
1816     return;
1817   }
1818 
1819   int *ptIds = this->LocatorIds;
1820   float *points = this->LocatorPoints;
1821 
1822   for (i=0, ptId = 0; i<numPtArrays; i++)
1823   {
1824     int npoints = ptArrays[i]->GetNumberOfPoints();
1825     int nvals = npoints * 3;
1826 
1827     int pointArrayType = ptArrays[i]->GetDataType();
1828 
1829     if (pointArrayType == VTK_FLOAT)
1830     {
1831       vtkDataArray *da = ptArrays[i]->GetData();
1832       vtkFloatArray *fa = vtkArrayDownCast<vtkFloatArray>(da);
1833       memcpy(points + ptId, fa->GetPointer(0), sizeof(float) * nvals );
1834       ptId += nvals;
1835     }
1836     else
1837     {
1838       // Hopefully point arrays are usually floats.  This conversion will
1839       // really slow things down.
1840 
1841       for (vtkIdType ii=0; ii<npoints; ii++)
1842       {
1843         double *pt = ptArrays[i]->GetPoint(ii);
1844 
1845         points[ptId++] = static_cast<float>(pt[0]);
1846         points[ptId++] = static_cast<float>(pt[1]);
1847         points[ptId++] = static_cast<float>(pt[2]);
1848       }
1849     }
1850   }
1851 
1852   for (ptId=0; ptId<totalNumPoints; ptId++)
1853   {
1854     // _Select dominates DivideRegion algorithm, operating on
1855     // ints is much fast than operating on long longs
1856 
1857     ptIds[ptId] = ptId;
1858   }
1859 
1860   TIMERDONE("Set up to build k-d tree");
1861 
1862   TIMER("Build tree");
1863 
1864   this->DivideRegion(kd, points, ptIds, 0);
1865 
1866   this->SetActualLevel();
1867   this->BuildRegionList();
1868 
1869   // Create a location array for the points of each region
1870 
1871   this->LocatorRegionLocation = new int [this->NumberOfRegions];
1872 
1873   int idx = 0;
1874 
1875   for (int reg = 0; reg < this->NumberOfRegions; reg++)
1876   {
1877     this->LocatorRegionLocation[reg] = idx;
1878 
1879     idx += this->RegionList[reg]->GetNumberOfPoints();
1880   }
1881 
1882   this->NumberOfLocatorPoints = idx;
1883 
1884   this->SetCalculator(this->Top);
1885 
1886   TIMERDONE("Build tree");
1887 }
1888 
1889 //----------------------------------------------------------------------------
1890 // Query functions subsequent to BuildLocatorFromPoints,
1891 // relating to duplicate and nearby points
1892 //
BuildMapForDuplicatePoints(float tolerance=0.0)1893 vtkIdTypeArray *vtkKdTree::BuildMapForDuplicatePoints(float tolerance = 0.0)
1894 {
1895   int i;
1896 
1897   if ((tolerance < 0.0) || (tolerance >= this->MaxWidth))
1898   {
1899     vtkWarningMacro(<< "vtkKdTree::BuildMapForDuplicatePoints - invalid tolerance");
1900     tolerance = this->MaxWidth;
1901   }
1902 
1903   TIMER("Find duplicate points");
1904 
1905   int *idCount = new int [this->NumberOfRegions];
1906   int **uniqueFound = new int * [this->NumberOfRegions];
1907 
1908   if (!idCount || !uniqueFound)
1909   {
1910     delete [] idCount;
1911     delete [] uniqueFound;
1912 
1913     vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints memory allocation");
1914     return nullptr;
1915   }
1916 
1917   memset(idCount, 0, sizeof(int) * this->NumberOfRegions);
1918 
1919   for (i=0; i<this->NumberOfRegions; i++)
1920   {
1921     uniqueFound[i] = new int [this->RegionList[i]->GetNumberOfPoints()];
1922 
1923     if (!uniqueFound[i])
1924     {
1925       delete [] idCount;
1926       for (int j=0; j<i; j++) delete [] uniqueFound[j];
1927       delete [] uniqueFound;
1928       vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints memory allocation");
1929       return nullptr;
1930     }
1931   }
1932 
1933   float tolerance2 = tolerance * tolerance;
1934 
1935   vtkIdTypeArray *uniqueIds = vtkIdTypeArray::New();
1936   uniqueIds->SetNumberOfValues(this->NumberOfLocatorPoints);
1937 
1938   int idx = 0;
1939   int nextRegionId = 0;
1940   float *point = this->LocatorPoints;
1941 
1942   while (idx < this->NumberOfLocatorPoints)
1943   {
1944     // first point we have in this region
1945 
1946     int currentId = this->LocatorIds[idx];
1947 
1948     int regionId = this->GetRegionContainingPoint(point[0],point[1],point[2]);
1949 
1950     if ((regionId == -1) || (regionId != nextRegionId))
1951     {
1952       delete [] idCount;
1953       for (i=0; i<this->NumberOfRegions; i++) delete [] uniqueFound[i];
1954       delete [] uniqueFound;
1955       uniqueIds->Delete();
1956       vtkErrorMacro(<< "vtkKdTree::BuildMapForDuplicatePoints corrupt k-d tree");
1957       return nullptr;
1958     }
1959 
1960     int duplicateFound = -1;
1961 
1962     if ((tolerance > 0.0) && (regionId > 0))
1963     {
1964       duplicateFound = this->SearchNeighborsForDuplicate(regionId, point,
1965                                uniqueFound, idCount, tolerance, tolerance2);
1966     }
1967 
1968     if (duplicateFound >= 0)
1969     {
1970       uniqueIds->SetValue(currentId, this->LocatorIds[duplicateFound]);
1971     }
1972     else
1973     {
1974       uniqueFound[regionId][idCount[regionId]++] = idx;
1975       uniqueIds->SetValue(currentId, currentId);
1976     }
1977 
1978     // test the other points in this region
1979 
1980     int numRegionPoints = this->RegionList[regionId]->GetNumberOfPoints();
1981 
1982     int secondIdx = idx + 1;
1983     int nextFirstIdx = idx + numRegionPoints;
1984 
1985     for (int idx2 = secondIdx ; idx2 < nextFirstIdx; idx2++)
1986     {
1987       point += 3;
1988       currentId = this->LocatorIds[idx2];
1989 
1990       duplicateFound = this->SearchRegionForDuplicate(point,
1991                             uniqueFound[regionId], idCount[regionId], tolerance2);
1992 
1993       if ((tolerance > 0.0) && (duplicateFound < 0) && (regionId > 0))
1994       {
1995         duplicateFound =  this->SearchNeighborsForDuplicate(regionId, point,
1996                                      uniqueFound, idCount, tolerance, tolerance2);
1997       }
1998 
1999       if (duplicateFound >= 0)
2000       {
2001         uniqueIds->SetValue(currentId, this->LocatorIds[duplicateFound]);
2002       }
2003       else
2004       {
2005         uniqueFound[regionId][idCount[regionId]++] = idx2;
2006         uniqueIds->SetValue(currentId, currentId);
2007       }
2008     }
2009 
2010     idx = nextFirstIdx;
2011     point += 3;
2012     nextRegionId++;
2013   }
2014 
2015   for (i=0; i<this->NumberOfRegions; i++)
2016   {
2017     delete [] uniqueFound[i];
2018   }
2019   delete [] uniqueFound;
2020   delete [] idCount;
2021 
2022   TIMERDONE("Find duplicate points");
2023 
2024   return uniqueIds;
2025 }
2026 
2027 //----------------------------------------------------------------------------
SearchRegionForDuplicate(float * point,int * pointsSoFar,int len,float tolerance2)2028 int vtkKdTree::SearchRegionForDuplicate(float *point, int *pointsSoFar,
2029                                         int len, float tolerance2)
2030 {
2031   int duplicateFound = -1;
2032   int id;
2033 
2034   for (id=0; id < len; id++)
2035   {
2036     int otherId = pointsSoFar[id];
2037 
2038     float *otherPoint = this->LocatorPoints + (otherId * 3);
2039 
2040     float distance2 = vtkMath::Distance2BetweenPoints(point, otherPoint);
2041 
2042     if (distance2 <= tolerance2)
2043     {
2044       duplicateFound = otherId;
2045       break;
2046     }
2047   }
2048   return duplicateFound;
2049 }
2050 
2051 //----------------------------------------------------------------------------
SearchNeighborsForDuplicate(int regionId,float * point,int ** pointsSoFar,int * len,float tolerance,float tolerance2)2052 int vtkKdTree::SearchNeighborsForDuplicate(int regionId, float *point,
2053                                     int **pointsSoFar, int *len,
2054                                     float tolerance, float tolerance2)
2055 {
2056   int duplicateFound = -1;
2057 
2058   float dist2 =
2059     this->RegionList[regionId]->GetDistance2ToInnerBoundary(point[0],point[1],point[2]);
2060 
2061   if (dist2 >= tolerance2)
2062   {
2063     // There are no other regions with data that are within the
2064     // tolerance distance of this point.
2065 
2066     return duplicateFound;
2067   }
2068 
2069   // Find all regions that are within the tolerance distance of the point
2070 
2071   int *regionIds = new int [this->NumberOfRegions];
2072 
2073   this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOn();
2074 
2075 #ifdef USE_SPHERE
2076 
2077   // Find all regions which intersect a sphere around the point
2078   // with radius equal to tolerance.  Compute the intersection using
2079   // the bounds of data within regions, not the bounds of the region.
2080 
2081   int nRegions =
2082     this->BSPCalculator->IntersectsSphere2(regionIds, this->NumberOfRegions,
2083                                      point[0], point[1], point[2], tolerance2);
2084 #else
2085 
2086   // Technically, we want all regions that intersect a sphere around the
2087   // point. But this takes much longer to compute than a box.  We'll compute
2088   // all regions that intersect a box.  We may occasionally get a region
2089   // we don't need, but that's OK.
2090 
2091   double box[6];
2092   box[0] = point[0] - tolerance; box[1] = point[0] + tolerance;
2093   box[2] = point[1] - tolerance; box[3] = point[1] + tolerance;
2094   box[4] = point[2] - tolerance; box[5] = point[2] + tolerance;
2095 
2096   int nRegions = this->BSPCalculator->IntersectsBox(regionIds, this->NumberOfRegions, box);
2097 
2098 #endif
2099 
2100   this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOff();
2101 
2102   for (int reg=0; reg < nRegions; reg++)
2103   {
2104     if ((regionIds[reg] == regionId)  || (len[reg] == 0) )
2105     {
2106       continue;
2107     }
2108 
2109     duplicateFound = this->SearchRegionForDuplicate(point,  pointsSoFar[reg],
2110                                                   len[reg], tolerance2);
2111 
2112     if (duplicateFound)
2113     {
2114       break;
2115     }
2116   }
2117 
2118   delete [] regionIds;
2119 
2120   return duplicateFound;
2121 }
2122 
2123 //----------------------------------------------------------------------------
FindPoint(double x[3])2124 vtkIdType vtkKdTree::FindPoint(double x[3])
2125 {
2126   return this->FindPoint(x[0], x[1], x[2]);
2127 }
2128 
2129 //----------------------------------------------------------------------------
FindPoint(double x,double y,double z)2130 vtkIdType vtkKdTree::FindPoint(double x, double y, double z)
2131 {
2132   if (!this->LocatorPoints)
2133   {
2134     vtkErrorMacro(<< "vtkKdTree::FindPoint - must build locator first");
2135     return -1;
2136   }
2137 
2138   int regionId = this->GetRegionContainingPoint(x, y, z);
2139 
2140   if (regionId == -1)
2141   {
2142     return -1;
2143   }
2144 
2145   int idx = this->LocatorRegionLocation[regionId];
2146 
2147   vtkIdType ptId = -1;
2148 
2149   float *point = this->LocatorPoints + (idx * 3);
2150 
2151   float fx = static_cast<float>(x);
2152   float fy = static_cast<float>(y);
2153   float fz = static_cast<float>(z);
2154 
2155   for (int i=0; i < this->RegionList[regionId]->GetNumberOfPoints(); i++)
2156   {
2157     if ( (point[0] == fx) && (point[1] == fy) && (point[2] == fz))
2158     {
2159       ptId = static_cast<vtkIdType>(this->LocatorIds[idx + i]);
2160       break;
2161     }
2162 
2163     point += 3;
2164   }
2165 
2166   return ptId;
2167 }
2168 
2169 //----------------------------------------------------------------------------
FindClosestPoint(double x[3],double & dist2)2170 vtkIdType vtkKdTree::FindClosestPoint(double x[3], double &dist2)
2171 {
2172   vtkIdType id = this->FindClosestPoint(x[0], x[1], x[2], dist2);
2173 
2174   return id;
2175 }
2176 
2177 //----------------------------------------------------------------------------
FindClosestPoint(double x,double y,double z,double & dist2)2178 vtkIdType vtkKdTree::FindClosestPoint(double x, double y, double z, double &dist2)
2179 {
2180   if (!this->LocatorPoints)
2181   {
2182     vtkErrorMacro(<< "vtkKdTree::FindClosestPoint: must build locator first");
2183     return -1;
2184   }
2185 
2186   double minDistance2 = 0.0;
2187 
2188   int closeId=-1, newCloseId=-1;
2189   double newDistance2 = 4 * this->MaxWidth * this->MaxWidth;
2190 
2191   int regionId = this->GetRegionContainingPoint(x, y, z);
2192 
2193   if (regionId < 0)
2194   {
2195     // This point is not inside the space divided by the k-d tree.
2196     // Find the point on the boundary that is closest to it.
2197 
2198     double pt[3];
2199     this->Top->GetDistance2ToBoundary(x, y, z, pt, 1);
2200 
2201     double *min = this->Top->GetMinBounds();
2202     double *max = this->Top->GetMaxBounds();
2203 
2204     // GetDistance2ToBoundary will sometimes return a point *just*
2205     // *barely* outside the bounds of the region.  Move that point to
2206     // just barely *inside* instead.
2207 
2208     if (pt[0] <= min[0])
2209     {
2210       pt[0] = min[0] + this->FudgeFactor;
2211     }
2212     if (pt[1] <= min[1])
2213     {
2214       pt[1] = min[1] + this->FudgeFactor;
2215     }
2216     if (pt[2] <= min[2])
2217     {
2218       pt[2] = min[2] + this->FudgeFactor;
2219     }
2220     if (pt[0] >= max[0])
2221     {
2222       pt[0] = max[0] - this->FudgeFactor;
2223     }
2224     if (pt[1] >= max[1])
2225     {
2226       pt[1] = max[1] - this->FudgeFactor;
2227     }
2228     if (pt[2] >= max[2])
2229     {
2230       pt[2] = max[2] - this->FudgeFactor;
2231     }
2232 
2233     regionId = this->GetRegionContainingPoint(pt[0], pt[1], pt[2]);
2234 
2235     closeId = this->_FindClosestPointInRegion(regionId,
2236                                               x, y, z,
2237                                               minDistance2);
2238 
2239     // Check to see if neighboring regions have a closer point
2240 
2241     newCloseId =
2242       this->FindClosestPointInSphere(x, y, z,
2243                                      sqrt(minDistance2),    // radius
2244                                      regionId,        // skip this region
2245                                      newDistance2);   // distance to closest point
2246 
2247   }
2248   else     // Point is inside a k-d tree region
2249   {
2250     closeId =
2251       this->_FindClosestPointInRegion(regionId, x, y, z, minDistance2);
2252 
2253     if (minDistance2 > 0.0)
2254     {
2255       float dist2ToBoundary =
2256         this->RegionList[regionId]->GetDistance2ToInnerBoundary(x, y, z);
2257 
2258       if (dist2ToBoundary < minDistance2)
2259       {
2260         // The closest point may be in a neighboring region
2261 
2262         newCloseId = this->FindClosestPointInSphere(x, y, z,
2263                                                     sqrt(minDistance2),   // radius
2264                                                     regionId,       // skip this region
2265                                                     newDistance2);
2266       }
2267     }
2268   }
2269 
2270   if (newDistance2 < minDistance2 && newCloseId != -1)
2271   {
2272     closeId = newCloseId;
2273     minDistance2 = newDistance2;
2274   }
2275 
2276   vtkIdType closePointId = static_cast<vtkIdType>(this->LocatorIds[closeId]);
2277 
2278   dist2 = minDistance2;
2279 
2280   return closePointId;
2281 }
2282 
2283 //----------------------------------------------------------------------------
FindClosestPointWithinRadius(double radius,const double x[3],double & dist2)2284 vtkIdType vtkKdTree::FindClosestPointWithinRadius(
2285   double radius, const double x[3], double& dist2)
2286 {
2287   int localCloseId =
2288     this->FindClosestPointInSphere(x[0], x[1], x[2], radius, -1, dist2);
2289   if(localCloseId >= 0)
2290   {
2291     return static_cast<vtkIdType>(this->LocatorIds[localCloseId]);
2292   }
2293   return -1;
2294 }
2295 
2296 
2297 //----------------------------------------------------------------------------
FindClosestPointInRegion(int regionId,double * x,double & dist2)2298 vtkIdType vtkKdTree::FindClosestPointInRegion(int regionId, double *x, double &dist2)
2299 {
2300   return this->FindClosestPointInRegion(regionId, x[0], x[1], x[2], dist2);
2301 }
2302 
2303 //----------------------------------------------------------------------------
FindClosestPointInRegion(int regionId,double x,double y,double z,double & dist2)2304 vtkIdType vtkKdTree::FindClosestPointInRegion(int regionId,
2305                                               double x, double y,
2306                                               double z, double &dist2)
2307 {
2308   if (!this->LocatorPoints)
2309   {
2310     vtkErrorMacro(<< "vtkKdTree::FindClosestPointInRegion - must build locator first");
2311     return -1;
2312   }
2313   int localId = this->_FindClosestPointInRegion(regionId, x, y, z, dist2);
2314 
2315   vtkIdType originalId = -1;
2316 
2317   if (localId >= 0)
2318   {
2319     originalId = static_cast<vtkIdType>(this->LocatorIds[localId]);
2320   }
2321 
2322   return originalId;
2323 }
2324 
2325 //----------------------------------------------------------------------------
_FindClosestPointInRegion(int regionId,double x,double y,double z,double & dist2)2326 int vtkKdTree::_FindClosestPointInRegion(int regionId,
2327                                      double x, double y, double z, double &dist2)
2328 {
2329   int minId=0;
2330 
2331   double minDistance2 = 4 * this->MaxWidth * this->MaxWidth;
2332 
2333   int idx = this->LocatorRegionLocation[regionId];
2334 
2335   float *candidate = this->LocatorPoints + (idx * 3);
2336 
2337   int numPoints = this->RegionList[regionId]->GetNumberOfPoints();
2338   for (int i=0; i < numPoints; i++)
2339   {
2340     double dx = (x - candidate[0]) * (x - candidate[0]);
2341 
2342     if (dx < minDistance2)
2343     {
2344       double dxy = dx + ((y - candidate[1]) * (y - candidate[1]));
2345 
2346       if (dxy < minDistance2)
2347       {
2348         double dxyz = dxy + ((z - candidate[2]) * (z - candidate[2]));
2349 
2350         if (dxyz < minDistance2)
2351         {
2352           minId = idx + i;
2353           minDistance2 = dxyz;
2354 
2355           if (dxyz == 0.0)
2356           {
2357             break;
2358           }
2359         }
2360       }
2361     }
2362 
2363     candidate += 3;
2364   }
2365 
2366   dist2 = minDistance2;
2367 
2368   return minId;
2369 }
2370 
2371 //----------------------------------------------------------------------------
FindClosestPointInSphere(double x,double y,double z,double radius,int skipRegion,double & dist2)2372 int vtkKdTree::FindClosestPointInSphere(double x, double y, double z,
2373                                         double radius, int skipRegion,
2374                                         double &dist2)
2375 {
2376   if (!this->LocatorPoints)
2377   {
2378     vtkErrorMacro(<< "vtkKdTree::FindClosestPointInSphere - must build locator first");
2379     return -1;
2380   }
2381   int *regionIds = new int [this->NumberOfRegions];
2382 
2383   this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOn();
2384 
2385   int nRegions =
2386     this->BSPCalculator->IntersectsSphere2(regionIds, this->NumberOfRegions, x, y, z, radius*radius);
2387 
2388   this->BSPCalculator->ComputeIntersectionsUsingDataBoundsOff();
2389 
2390   double minDistance2 = 4 * this->MaxWidth * this->MaxWidth;
2391   int localCloseId = -1;
2392 
2393   bool recheck = 0; // used to flag that we should recheck the distance
2394   for (int reg=0; reg < nRegions; reg++)
2395   {
2396     if (regionIds[reg] == skipRegion)
2397     {
2398       continue;
2399     }
2400 
2401     int neighbor = regionIds[reg];
2402 
2403     // recheck that the bin is closer than the current minimum distance
2404     if(!recheck || this->RegionList[neighbor]->GetDistance2ToBoundary(x, y, z, 1) < minDistance2)
2405     {
2406       double newDistance2;
2407       int newLocalCloseId = this->_FindClosestPointInRegion(neighbor,
2408                                                             x, y, z, newDistance2);
2409 
2410       if (newDistance2 < minDistance2 && newDistance2 <= radius*radius)
2411       {
2412         minDistance2 = newDistance2;
2413         localCloseId = newLocalCloseId;
2414         recheck = 1; // changed the minimum distance so mark to check subsequent bins
2415       }
2416     }
2417   }
2418 
2419   delete [] regionIds;
2420 
2421   dist2 = minDistance2;
2422   return localCloseId;
2423 }
2424 
2425 //----------------------------------------------------------------------------
FindPointsWithinRadius(double R,const double x[3],vtkIdList * result)2426 void vtkKdTree::FindPointsWithinRadius(double R, const double x[3],
2427                                        vtkIdList* result)
2428 {
2429   result->Reset();
2430   // don't forget to square the radius
2431   this->FindPointsWithinRadius(this->Top, R*R, x, result);
2432 }
2433 
2434 //----------------------------------------------------------------------------
FindPointsWithinRadius(vtkKdNode * node,double R2,const double x[3],vtkIdList * result)2435 void vtkKdTree::FindPointsWithinRadius(vtkKdNode* node, double R2,
2436                                        const double x[3],
2437                                        vtkIdList* result)
2438 
2439 {
2440   if (!this->LocatorPoints)
2441   {
2442     vtkErrorMacro(<< "vtkKdTree::FindPointsWithinRadius - must build locator first");
2443     return;
2444   }
2445 
2446   double b[6];
2447   node->GetBounds(b);
2448 
2449   double mindist2 = 0; // distance to closest vertex of BB
2450   double maxdist2 = 0; // distance to furthest vertex of BB
2451   // x-dir
2452   if(x[0] < b[0])
2453   {
2454     mindist2 = (b[0]-x[0])*(b[0]-x[0]);
2455     maxdist2 = (b[1]-x[0])*(b[1]-x[0]);
2456   }
2457   else if(x[0] > b[1])
2458   {
2459     mindist2 = (b[1]-x[0])*(b[1]-x[0]);
2460     maxdist2 = (b[0]-x[0])*(b[0]-x[0]);
2461   }
2462   else if((b[1]-x[0]) > (x[0]-b[0]))
2463   {
2464     maxdist2 = (b[1]-x[0])*(b[1]-x[0]);
2465   }
2466   else
2467   {
2468     maxdist2 = (b[0]-x[0])*(b[0]-x[0]);
2469   }
2470   // y-dir
2471   if(x[1] < b[2])
2472   {
2473     mindist2 += (b[2]-x[1])*(b[2]-x[1]);
2474     maxdist2 += (b[3]-x[1])*(b[3]-x[1]);
2475   }
2476   else if(x[1] > b[3])
2477   {
2478     mindist2 += (b[3]-x[1])*(b[3]-x[1]);
2479     maxdist2 += (b[2]-x[1])*(b[2]-x[1]);
2480   }
2481   else if((b[3]-x[1]) > (x[1]-b[2]))
2482   {
2483     maxdist2 += (b[3]-x[1])*(b[3]-x[1]);
2484   }
2485   else
2486   {
2487     maxdist2 += (b[2]-x[1])*(b[2]-x[1]);
2488   }
2489   // z-dir
2490   if(x[2] < b[4])
2491   {
2492     mindist2 += (b[4]-x[2])*(b[4]-x[2]);
2493     maxdist2 += (b[5]-x[2])*(b[5]-x[2]);
2494   }
2495   else if(x[2] > b[5])
2496   {
2497     mindist2 += (b[5]-x[2])*(b[5]-x[2]);
2498     maxdist2 += (b[4]-x[2])*(b[4]-x[2]);
2499   }
2500   else if((b[5]-x[2]) > (x[2]-b[4]))
2501   {
2502     maxdist2 += (b[5]-x[2])*(b[5]-x[2]);
2503   }
2504   else
2505   {
2506     maxdist2 += (x[2]-b[4])*(x[2]-b[4]);
2507   }
2508 
2509   if(mindist2 > R2)
2510   {
2511     // non-intersecting
2512     return;
2513   }
2514 
2515   if(maxdist2 <= R2)
2516   {
2517     // sphere contains BB
2518     this->AddAllPointsInRegion(node, result);
2519     return;
2520   }
2521 
2522   // partial intersection of sphere & BB
2523   if (node->GetLeft() == nullptr)
2524   {
2525     int regionID = node->GetID();
2526     int regionLoc = this->LocatorRegionLocation[regionID];
2527     float* pt = this->LocatorPoints + (regionLoc * 3);
2528     vtkIdType numPoints = this->RegionList[regionID]->GetNumberOfPoints();
2529     for (vtkIdType i = 0; i < numPoints; i++)
2530     {
2531       double dist2 = (pt[0]-x[0])*(pt[0]-x[0])+
2532         (pt[1]-x[1])*(pt[1]-x[1])+(pt[2]-x[2])*(pt[2]-x[2]);
2533       if(dist2 <= R2)
2534       {
2535         vtkIdType ptId = static_cast<vtkIdType>(this->LocatorIds[regionLoc + i]);
2536         result->InsertNextId(ptId);
2537       }
2538       pt += 3;
2539     }
2540   }
2541   else
2542   {
2543     this->FindPointsWithinRadius(node->GetLeft(), R2, x, result);
2544     this->FindPointsWithinRadius(node->GetRight(), R2, x, result);
2545   }
2546 }
2547 
2548 //----------------------------------------------------------------------------
FindClosestNPoints(int N,const double x[3],vtkIdList * result)2549 void vtkKdTree::FindClosestNPoints(int N, const double x[3],
2550                                    vtkIdList* result)
2551 {
2552   result->Reset();
2553   if(N<=0)
2554   {
2555     return;
2556   }
2557   if (!this->LocatorPoints)
2558   {
2559     vtkErrorMacro(<< "vtkKdTree::FindClosestNPoints - must build locator first");
2560     return;
2561   }
2562 
2563   int numTotalPoints = this->Top->GetNumberOfPoints();
2564   if(numTotalPoints < N)
2565   {
2566     vtkWarningMacro("Number of requested points is greater than total number of points in KdTree");
2567     N = numTotalPoints;
2568   }
2569   result->SetNumberOfIds(N);
2570 
2571   // now we want to go about finding a region that contains at least N points
2572   // but not many more -- hopefully the region contains X as well but we
2573   // can't depend on that
2574   vtkKdNode* node = this->Top;
2575   vtkKdNode* startingNode = nullptr;
2576   if(!node->ContainsPoint(x[0], x[1], x[2], 0))
2577   {
2578     // point is not in the region
2579     int numPoints = node->GetNumberOfPoints();
2580     vtkKdNode* prevNode = node;
2581     while(node->GetLeft() && numPoints > N)
2582     {
2583       prevNode = node;
2584       double leftDist2 = node->GetLeft()->GetDistance2ToBoundary(x[0], x[1], x[2], 1);
2585       double rightDist2 = node->GetRight()->GetDistance2ToBoundary(x[0], x[1], x[2], 1);
2586       if(leftDist2 < rightDist2)
2587       {
2588         node = node->GetLeft();
2589       }
2590       else
2591       {
2592         node = node->GetRight();
2593       }
2594       numPoints = node->GetNumberOfPoints();
2595     }
2596     if(numPoints < N)
2597     {
2598       startingNode = prevNode;
2599     }
2600     else
2601     {
2602       startingNode = node;
2603     }
2604   }
2605   else
2606   {
2607     int numPoints = node->GetNumberOfPoints();
2608     vtkKdNode* prevNode = node;
2609     while(node->GetLeft() && numPoints > N)
2610     {
2611       prevNode = node;
2612       if(node->GetLeft()->ContainsPoint(x[0], x[1], x[2], 0))
2613       {
2614         node = node->GetLeft();
2615       }
2616       else
2617       {
2618         node = node->GetRight();
2619       }
2620       numPoints = node->GetNumberOfPoints();
2621     }
2622     if(numPoints < N)
2623     {
2624       startingNode = prevNode;
2625     }
2626     else
2627     {
2628       startingNode = node;
2629     }
2630   }
2631 
2632   // now that we have a starting region, go through its points
2633   // and order them
2634   int regionId = startingNode->GetID();
2635   int numPoints = startingNode->GetNumberOfPoints();
2636   int where;
2637   if(regionId >= 0)
2638   {
2639     where = this->LocatorRegionLocation[regionId];
2640   }
2641   else
2642   {
2643     vtkKdNode* left = startingNode->GetLeft();
2644     vtkKdNode* next = left->GetLeft();
2645     while(next)
2646     {
2647       left = next;
2648       next = next->GetLeft();
2649     }
2650     int leftRegionId = left->GetID();
2651     where = this->LocatorRegionLocation[leftRegionId];
2652   }
2653   int *ids = this->LocatorIds + where;
2654   float* pt = this->LocatorPoints + (where*3);
2655   float xfloat[3] = {static_cast<float>(x[0]), static_cast<float>(x[1]),
2656                      static_cast<float>(x[2])};
2657   OrderPoints orderedPoints(N);
2658   for (int i=0; i<numPoints; i++)
2659   {
2660     float dist2 = vtkMath::Distance2BetweenPoints(xfloat, pt);
2661     orderedPoints.InsertPoint(dist2, ids[i]);
2662     pt += 3;
2663   }
2664 
2665   // to finish up we have to check other regions for
2666   // closer points
2667   float LargestDist2 = orderedPoints.GetLargestDist2();
2668   double delta[3] = {0,0,0};
2669   double bounds[6];
2670   node = this->Top;
2671   std::queue<vtkKdNode*> nodesToBeSearched;
2672   nodesToBeSearched.push(node);
2673   while(!nodesToBeSearched.empty())
2674   {
2675     node = nodesToBeSearched.front();
2676     nodesToBeSearched.pop();
2677     if(node == startingNode)
2678     {
2679       continue;
2680     }
2681     vtkKdNode* left = node->GetLeft();
2682     if(left)
2683     {
2684       left->GetDataBounds(bounds);
2685       if(vtkMath::PointIsWithinBounds(const_cast<double*>(x), bounds, delta) == 1 ||
2686          left->GetDistance2ToBoundary(x[0], x[1], x[2], 1) < LargestDist2)
2687       {
2688         nodesToBeSearched.push(left);
2689       }
2690       node->GetRight()->GetDataBounds(bounds);
2691       if(vtkMath::PointIsWithinBounds(const_cast<double*>(x), bounds, delta) == 1 ||
2692          node->GetRight()->GetDistance2ToBoundary(x[0], x[1], x[2], 1) < LargestDist2)
2693       {
2694         nodesToBeSearched.push(node->GetRight());
2695       }
2696     }
2697     else if(node->GetDistance2ToBoundary(x[0], x[1], x[2], 1) < LargestDist2)
2698     {
2699       regionId = node->GetID();
2700       numPoints = node->GetNumberOfPoints();
2701       where = this->LocatorRegionLocation[regionId];
2702       ids = this->LocatorIds + where;
2703       pt = this->LocatorPoints + (where*3);
2704       for (int i=0; i<numPoints; i++)
2705       {
2706         float dist2 = vtkMath::Distance2BetweenPoints(xfloat, pt);
2707         orderedPoints.InsertPoint(dist2, ids[i]);
2708         pt += 3;
2709       }
2710       LargestDist2 = orderedPoints.GetLargestDist2();
2711     }
2712   }
2713   orderedPoints.GetSortedIds(result);
2714 }
2715 
2716 
2717 //----------------------------------------------------------------------------
GetPointsInRegion(int regionId)2718 vtkIdTypeArray *vtkKdTree::GetPointsInRegion(int regionId)
2719 {
2720   if ( (regionId < 0) || (regionId >= this->NumberOfRegions))
2721   {
2722     vtkErrorMacro(<< "vtkKdTree::GetPointsInRegion invalid region ID");
2723     return nullptr;
2724   }
2725 
2726   if (!this->LocatorIds)
2727   {
2728     vtkErrorMacro(<< "vtkKdTree::GetPointsInRegion build locator first");
2729     return nullptr;
2730   }
2731 
2732   int numPoints = this->RegionList[regionId]->GetNumberOfPoints();
2733   int where = this->LocatorRegionLocation[regionId];
2734 
2735   vtkIdTypeArray *ptIds = vtkIdTypeArray::New();
2736   ptIds->SetNumberOfValues(numPoints);
2737 
2738   int *ids = this->LocatorIds + where;
2739 
2740   for (int i=0; i<numPoints; i++)
2741   {
2742     ptIds->SetValue(i, ids[i]);
2743   }
2744 
2745   return ptIds;
2746 }
2747 
2748 //----------------------------------------------------------------------------
2749 // Code to save state/time of last k-d tree build, and to
2750 // determine if a data set's geometry has changed since the
2751 // last build.
2752 //
InvalidateGeometry()2753 void vtkKdTree::InvalidateGeometry()
2754 {
2755   // Remove observers to data sets.
2756   for (int i = 0; i < this->LastNumDataSets; i++)
2757   {
2758     this->LastInputDataSets[i]
2759       ->RemoveObserver(this->LastDataSetObserverTags[i]);
2760   }
2761 
2762   this->LastNumDataSets = 0;
2763 }
2764 
2765 //-----------------------------------------------------------------------------
ClearLastBuildCache()2766 void vtkKdTree::ClearLastBuildCache()
2767 {
2768   this->InvalidateGeometry();
2769 
2770   if (this->LastDataCacheSize > 0)
2771   {
2772     delete [] this->LastInputDataSets;
2773     delete [] this->LastDataSetObserverTags;
2774     delete [] this->LastDataSetType;
2775     delete [] this->LastInputDataInfo;
2776     delete [] this->LastBounds;
2777     delete [] this->LastNumCells;
2778     delete [] this->LastNumPoints;
2779     this->LastDataCacheSize = 0;
2780   }
2781   this->LastNumDataSets = 0;
2782   this->LastInputDataSets = nullptr;
2783   this->LastDataSetObserverTags = nullptr;
2784   this->LastDataSetType = nullptr;
2785   this->LastInputDataInfo = nullptr;
2786   this->LastBounds        = nullptr;
2787   this->LastNumPoints     = nullptr;
2788   this->LastNumCells      = nullptr;
2789 }
2790 
2791 //----------------------------------------------------------------------------
UpdateBuildTime()2792 void vtkKdTree::UpdateBuildTime()
2793 {
2794   this->BuildTime.Modified();
2795 
2796   // Save enough information so that next time we execute,
2797   // we can determine whether input geometry has changed.
2798 
2799   this->InvalidateGeometry();
2800 
2801   int numDataSets = this->GetNumberOfDataSets();
2802   if (numDataSets > this->LastDataCacheSize)
2803   {
2804     this->ClearLastBuildCache();
2805 
2806     this->LastInputDataSets = new vtkDataSet * [numDataSets];
2807     this->LastDataSetObserverTags = new unsigned long [numDataSets];
2808     this->LastDataSetType = new int [numDataSets];
2809     this->LastInputDataInfo = new double [9 * numDataSets];
2810     this->LastBounds = new double [6 * numDataSets];
2811     this->LastNumPoints = new vtkIdType [numDataSets];
2812     this->LastNumCells = new vtkIdType [numDataSets];
2813     this->LastDataCacheSize = numDataSets;
2814   }
2815 
2816   this->LastNumDataSets = numDataSets;
2817 
2818   int nextds = 0;
2819 
2820   vtkCollectionSimpleIterator cookie;
2821   this->DataSets->InitTraversal(cookie);
2822   for (vtkDataSet *in = this->DataSets->GetNextDataSet(cookie);
2823        in != nullptr; in = this->DataSets->GetNextDataSet(cookie))
2824   {
2825     if (nextds >= numDataSets)
2826     {
2827       vtkErrorMacro(<< "vtkKdTree::UpdateBuildTime corrupt counts");
2828       return;
2829     }
2830 
2831     vtkCallbackCommand *cbc = vtkCallbackCommand::New();
2832     cbc->SetCallback(LastInputDeletedCallback);
2833     cbc->SetClientData(this);
2834     this->LastDataSetObserverTags[nextds]
2835       = in->AddObserver(vtkCommand::DeleteEvent, cbc);
2836     cbc->Delete();
2837 
2838     this->LastInputDataSets[nextds] = in;
2839 
2840     this->LastNumPoints[nextds] = in->GetNumberOfPoints();
2841     this->LastNumCells[nextds] = in->GetNumberOfCells();
2842 
2843     in->GetBounds(this->LastBounds + 6*nextds);
2844 
2845     int type = this->LastDataSetType[nextds] = in->GetDataObjectType();
2846 
2847     if ((type == VTK_IMAGE_DATA) || (type == VTK_UNIFORM_GRID))
2848     {
2849       double origin[3], spacing[3];
2850       int dims[3];
2851 
2852       if (type == VTK_IMAGE_DATA)
2853       {
2854         vtkImageData *id = vtkImageData::SafeDownCast(in);
2855         id->GetDimensions(dims);
2856         id->GetOrigin(origin);
2857         id->GetSpacing(spacing);
2858       }
2859       else
2860       {
2861         vtkUniformGrid *ug = vtkUniformGrid::SafeDownCast(in);
2862         ug->GetDimensions(dims);
2863         ug->GetOrigin(origin);
2864         ug->GetSpacing(spacing);
2865       }
2866 
2867       this->SetInputDataInfo(nextds, dims, origin, spacing);
2868     }
2869 
2870     nextds++;
2871   }
2872 }
2873 
2874 //----------------------------------------------------------------------------
SetInputDataInfo(int i,int dims[3],double origin[3],double spacing[3])2875 void vtkKdTree::SetInputDataInfo(int i, int dims[3], double origin[3],
2876                                  double spacing[3])
2877 {
2878   int idx = 9*i;
2879   this->LastInputDataInfo[idx++] = static_cast<double>(dims[0]);
2880   this->LastInputDataInfo[idx++] = static_cast<double>(dims[1]);
2881   this->LastInputDataInfo[idx++] = static_cast<double>(dims[2]);
2882   this->LastInputDataInfo[idx++] = origin[0];
2883   this->LastInputDataInfo[idx++] = origin[1];
2884   this->LastInputDataInfo[idx++] = origin[2];
2885   this->LastInputDataInfo[idx++] = spacing[0];
2886   this->LastInputDataInfo[idx++] = spacing[1];
2887   this->LastInputDataInfo[idx++] = spacing[2];
2888 }
2889 
2890 //----------------------------------------------------------------------------
CheckInputDataInfo(int i,int dims[3],double origin[3],double spacing[3])2891 int vtkKdTree::CheckInputDataInfo(int i, int dims[3], double origin[3],
2892                                   double spacing[3])
2893 {
2894   int sameValues = 1;
2895   int idx = 9*i;
2896 
2897   if ((dims[0] != static_cast<int>(this->LastInputDataInfo[idx])) ||
2898       (dims[1] != static_cast<int>(this->LastInputDataInfo[idx+1])) ||
2899       (dims[2] != static_cast<int>(this->LastInputDataInfo[idx+2])) ||
2900       (origin[0] != this->LastInputDataInfo[idx+3]) ||
2901       (origin[1] != this->LastInputDataInfo[idx+4]) ||
2902       (origin[2] != this->LastInputDataInfo[idx+5]) ||
2903       (spacing[0] != this->LastInputDataInfo[idx+6]) ||
2904       (spacing[1] != this->LastInputDataInfo[idx+7]) ||
2905       (spacing[2] != this->LastInputDataInfo[idx+8]) )
2906   {
2907     sameValues = 0;
2908   }
2909 
2910   return sameValues;
2911 }
2912 
2913 //----------------------------------------------------------------------------
NewGeometry()2914 int vtkKdTree::NewGeometry()
2915 {
2916   if (this->GetNumberOfDataSets() != this->LastNumDataSets)
2917   {
2918     return 1;
2919   }
2920 
2921   vtkDataSet **tmp = new vtkDataSet * [this->GetNumberOfDataSets()];
2922   for (int i=0; i < this->GetNumberOfDataSets(); i++)
2923   {
2924     tmp[i] = this->GetDataSet(i);
2925   }
2926 
2927   int itsNew = this->NewGeometry(tmp, this->GetNumberOfDataSets());
2928 
2929   delete [] tmp;
2930 
2931   return itsNew;
2932 }
NewGeometry(vtkDataSet ** sets,int numSets)2933 int vtkKdTree::NewGeometry(vtkDataSet **sets, int numSets)
2934 {
2935   int newGeometry = 0;
2936 #if 0
2937   vtkPointSet *ps = nullptr;
2938 #endif
2939   vtkRectilinearGrid *rg = nullptr;
2940   vtkImageData *id = nullptr;
2941   vtkUniformGrid *ug = nullptr;
2942   int same=0;
2943   int dims[3];
2944   double origin[3], spacing[3];
2945 
2946   if (numSets != this->LastNumDataSets)
2947   {
2948     return 1;
2949   }
2950 
2951   for (int i=0; i<numSets; i++)
2952   {
2953     vtkDataSet *in = this->LastInputDataSets[i];
2954     int type = in->GetDataObjectType();
2955 
2956     if (type != this->LastDataSetType[i])
2957     {
2958       newGeometry = 1;
2959       break;
2960     }
2961 
2962     switch (type)
2963     {
2964       case VTK_POLY_DATA:
2965       case VTK_UNSTRUCTURED_GRID:
2966       case VTK_STRUCTURED_GRID:
2967   #if 0
2968         // For now, vtkPExodusReader creates a whole new
2969         // vtkUnstructuredGrid, even when just changing
2970         // field arrays.  So we'll just check bounds.
2971         ps = vtkPointSet::SafeDownCast(in);
2972         if (ps->GetPoints()->GetMTime() > this->BuildTime)
2973         {
2974           newGeometry = 1;
2975         }
2976   #else
2977         if ((sets[i]->GetNumberOfPoints() != this->LastNumPoints[i]) ||
2978             (sets[i]->GetNumberOfCells() != this->LastNumCells[i]) )
2979         {
2980           newGeometry = 1;
2981         }
2982         else
2983         {
2984           double b[6];
2985           sets[i]->GetBounds(b);
2986           double *lastb = this->LastBounds + 6*i;
2987 
2988           for (int dim=0; dim<6; dim++)
2989           {
2990             if (*lastb++ != b[dim])
2991             {
2992               newGeometry = 1;
2993               break;
2994             }
2995           }
2996         }
2997   #endif
2998         break;
2999 
3000       case VTK_RECTILINEAR_GRID:
3001 
3002         rg = vtkRectilinearGrid::SafeDownCast(in);
3003         if ((rg->GetXCoordinates()->GetMTime() > this->BuildTime) ||
3004             (rg->GetYCoordinates()->GetMTime() > this->BuildTime) ||
3005             (rg->GetZCoordinates()->GetMTime() > this->BuildTime) )
3006         {
3007           newGeometry = 1;
3008         }
3009         break;
3010 
3011       case VTK_IMAGE_DATA:
3012       case VTK_STRUCTURED_POINTS:
3013 
3014         id = vtkImageData::SafeDownCast(in);
3015 
3016         id->GetDimensions(dims);
3017         id->GetOrigin(origin);
3018         id->GetSpacing(spacing);
3019 
3020         same = this->CheckInputDataInfo(i, dims, origin, spacing);
3021 
3022         if (!same)
3023         {
3024           newGeometry = 1;
3025         }
3026 
3027         break;
3028 
3029       case VTK_UNIFORM_GRID:
3030 
3031         ug = vtkUniformGrid::SafeDownCast(in);
3032 
3033         ug->GetDimensions(dims);
3034         ug->GetOrigin(origin);
3035         ug->GetSpacing(spacing);
3036 
3037         same = this->CheckInputDataInfo(i, dims, origin, spacing);
3038 
3039         if (!same)
3040         {
3041           newGeometry = 1;
3042         }
3043         else if (ug->GetPointGhostArray()
3044                  && ug->GetPointGhostArray()->GetMTime() > this->BuildTime)
3045         {
3046           newGeometry = 1;
3047         }
3048         else if (ug->GetCellGhostArray()
3049                  && ug->GetCellGhostArray()->GetMTime() > this->BuildTime)
3050         {
3051           newGeometry = 1;
3052         }
3053         break;
3054 
3055       default:
3056         vtkWarningMacro(<<
3057           "vtkKdTree::NewGeometry: unanticipated type");
3058 
3059         newGeometry = 1;
3060     }
3061     if (newGeometry)
3062     {
3063       break;
3064     }
3065   }
3066 
3067   return newGeometry;
3068 }
3069 
3070 //----------------------------------------------------------------------------
__printTree(vtkKdNode * kd,int depth,int v)3071 void vtkKdTree::__printTree(vtkKdNode *kd, int depth, int v)
3072 {
3073   if (v)
3074   {
3075     kd->PrintVerboseNode(depth);
3076   }
3077   else
3078   {
3079     kd->PrintNode(depth);
3080   }
3081 
3082   if (kd->GetLeft())
3083   {
3084     vtkKdTree::__printTree(kd->GetLeft(), depth+1, v);
3085   }
3086   if (kd->GetRight())
3087   {
3088     vtkKdTree::__printTree(kd->GetRight(), depth+1, v);
3089   }
3090 }
3091 
3092 //----------------------------------------------------------------------------
_printTree(int v)3093 void vtkKdTree::_printTree(int v)
3094 {
3095   vtkKdTree::__printTree(this->Top, 0, v);
3096 }
3097 
3098 //----------------------------------------------------------------------------
PrintRegion(int id)3099 void vtkKdTree::PrintRegion(int id)
3100 {
3101   this->RegionList[id]->PrintNode(0);
3102 }
3103 
3104 //----------------------------------------------------------------------------
PrintTree()3105 void vtkKdTree::PrintTree()
3106 {
3107   _printTree(0);
3108 }
3109 
3110 //----------------------------------------------------------------------------
PrintVerboseTree()3111 void vtkKdTree::PrintVerboseTree()
3112 {
3113   _printTree(1);
3114 }
3115 
3116 //----------------------------------------------------------------------------
FreeSearchStructure()3117 void vtkKdTree::FreeSearchStructure()
3118 {
3119   SCOPETIMER("FreeSearchStructure");
3120 
3121   if (this->Top)
3122   {
3123     vtkKdTree::DeleteAllDescendants(this->Top);
3124     this->Top->Delete();
3125     this->Top = nullptr;
3126   }
3127 
3128   delete [] this->RegionList;
3129   this->RegionList = nullptr;
3130 
3131   this->NumberOfRegions = 0;
3132   this->SetActualLevel();
3133 
3134   this->DeleteCellLists();
3135 
3136   delete [] this->CellRegionList;
3137   this->CellRegionList = nullptr;
3138 
3139   delete [] this->LocatorPoints;
3140   this->LocatorPoints = nullptr;
3141 
3142   delete [] this->LocatorIds;
3143   this->LocatorIds = nullptr;
3144 
3145   delete [] this->LocatorRegionLocation;
3146   this->LocatorRegionLocation = nullptr;
3147 }
3148 
3149 //----------------------------------------------------------------------------
3150 // build PolyData representation of all spacial regions------------
3151 //
GenerateRepresentation(int level,vtkPolyData * pd)3152 void vtkKdTree::GenerateRepresentation(int level, vtkPolyData *pd)
3153 {
3154   if (this->GenerateRepresentationUsingDataBounds)
3155   {
3156     this->GenerateRepresentationDataBounds(level, pd);
3157   }
3158   else
3159   {
3160     this->GenerateRepresentationWholeSpace(level, pd);
3161   }
3162 }
3163 
3164 //----------------------------------------------------------------------------
GenerateRepresentationWholeSpace(int level,vtkPolyData * pd)3165 void vtkKdTree::GenerateRepresentationWholeSpace(int level, vtkPolyData *pd)
3166 {
3167   int i;
3168 
3169   vtkPoints *pts;
3170   vtkCellArray *polys;
3171 
3172   if ( this->Top == nullptr )
3173   {
3174     vtkErrorMacro(<<"vtkKdTree::GenerateRepresentation empty tree");
3175     return;
3176   }
3177 
3178   if ((level < 0) || (level > this->Level))
3179   {
3180     level = this->Level;
3181   }
3182 
3183   // points and quads for level 0 bounding box
3184   int npoints = 8;
3185   int npolys  = 6;
3186 
3187   for (i = 1; i < level; i++)
3188   {
3189     int levelPolys = 1 << (i-1);
3190     npoints += (4 * levelPolys);
3191     npolys += levelPolys;
3192   }
3193 
3194   pts = vtkPoints::New();
3195   pts->Allocate(npoints);
3196   polys = vtkCellArray::New();
3197   polys->Allocate(npolys);
3198 
3199   // level 0 bounding box
3200 
3201   vtkIdType ids[8];
3202   vtkIdType idList[4];
3203   double     x[3];
3204   vtkKdNode    *kd    = this->Top;
3205 
3206   double *min = kd->GetMinBounds();
3207   double *max = kd->GetMaxBounds();
3208 
3209   x[0]  = min[0]; x[1]  = max[1]; x[2]  = min[2];
3210   ids[0] = pts->InsertNextPoint(x);
3211 
3212   x[0]  = max[0]; x[1]  = max[1]; x[2]  = min[2];
3213   ids[1] = pts->InsertNextPoint(x);
3214 
3215   x[0]  = max[0]; x[1]  = max[1]; x[2]  = max[2];
3216   ids[2] = pts->InsertNextPoint(x);
3217 
3218   x[0]  = min[0]; x[1]  = max[1]; x[2]  = max[2];
3219   ids[3] = pts->InsertNextPoint(x);
3220 
3221   x[0]  = min[0]; x[1]  = min[1]; x[2]  = min[2];
3222   ids[4] = pts->InsertNextPoint(x);
3223 
3224   x[0]  = max[0]; x[1]  = min[1]; x[2]  = min[2];
3225   ids[5] = pts->InsertNextPoint(x);
3226 
3227   x[0]  = max[0]; x[1]  = min[1]; x[2]  = max[2];
3228   ids[6] = pts->InsertNextPoint(x);
3229 
3230   x[0]  = min[0]; x[1]  = min[1]; x[2]  = max[2];
3231   ids[7] = pts->InsertNextPoint(x);
3232 
3233   idList[0] = ids[0]; idList[1] = ids[1]; idList[2] = ids[2]; idList[3] = ids[3];
3234   polys->InsertNextCell(4, idList);
3235 
3236   idList[0] = ids[1]; idList[1] = ids[5]; idList[2] = ids[6]; idList[3] = ids[2];
3237   polys->InsertNextCell(4, idList);
3238 
3239   idList[0] = ids[5]; idList[1] = ids[4]; idList[2] = ids[7]; idList[3] = ids[6];
3240   polys->InsertNextCell(4, idList);
3241 
3242   idList[0] = ids[4]; idList[1] = ids[0]; idList[2] = ids[3]; idList[3] = ids[7];
3243   polys->InsertNextCell(4, idList);
3244 
3245   idList[0] = ids[3]; idList[1] = ids[2]; idList[2] = ids[6]; idList[3] = ids[7];
3246   polys->InsertNextCell(4, idList);
3247 
3248   idList[0] = ids[1]; idList[1] = ids[0]; idList[2] = ids[4]; idList[3] = ids[5];
3249   polys->InsertNextCell(4, idList);
3250 
3251   if (kd->GetLeft() && (level > 0))
3252   {
3253     this->_generateRepresentationWholeSpace(kd, pts, polys, level-1);
3254   }
3255 
3256   pd->SetPoints(pts);
3257   pts->Delete();
3258   pd->SetPolys(polys);
3259   polys->Delete();
3260   pd->Squeeze();
3261 }
3262 
3263 //----------------------------------------------------------------------------
_generateRepresentationWholeSpace(vtkKdNode * kd,vtkPoints * pts,vtkCellArray * polys,int level)3264 void vtkKdTree::_generateRepresentationWholeSpace(vtkKdNode *kd,
3265                                         vtkPoints *pts,
3266                                         vtkCellArray *polys,
3267                                         int level)
3268 {
3269   int i;
3270   double p[4][3];
3271   vtkIdType ids[4];
3272 
3273   if ((level < 0) || (kd->GetLeft() == nullptr))
3274   {
3275     return;
3276   }
3277 
3278   double *min = kd->GetMinBounds();
3279   double *max = kd->GetMaxBounds();
3280   double *leftmax = kd->GetLeft()->GetMaxBounds();
3281 
3282   // splitting plane
3283 
3284   switch (kd->GetDim())
3285   {
3286     case XDIM:
3287 
3288       p[0][0] = leftmax[0]; p[0][1] = max[1]; p[0][2] = max[2];
3289       p[1][0] = leftmax[0]; p[1][1] = max[1]; p[1][2] = min[2];
3290       p[2][0] = leftmax[0]; p[2][1] = min[1]; p[2][2] = min[2];
3291       p[3][0] = leftmax[0]; p[3][1] = min[1]; p[3][2] = max[2];
3292 
3293       break;
3294 
3295     case YDIM:
3296 
3297       p[0][0] = min[0]; p[0][1] = leftmax[1]; p[0][2] = max[2];
3298       p[1][0] = min[0]; p[1][1] = leftmax[1]; p[1][2] = min[2];
3299       p[2][0] = max[0]; p[2][1] = leftmax[1]; p[2][2] = min[2];
3300       p[3][0] = max[0]; p[3][1] = leftmax[1]; p[3][2] = max[2];
3301 
3302       break;
3303 
3304     case ZDIM:
3305 
3306       p[0][0] = min[0]; p[0][1] = min[1]; p[0][2] = leftmax[2];
3307       p[1][0] = min[0]; p[1][1] = max[1]; p[1][2] = leftmax[2];
3308       p[2][0] = max[0]; p[2][1] = max[1]; p[2][2] = leftmax[2];
3309       p[3][0] = max[0]; p[3][1] = min[1]; p[3][2] = leftmax[2];
3310 
3311       break;
3312   }
3313 
3314 
3315   for (i=0; i<4; i++) ids[i] = pts->InsertNextPoint(p[i]);
3316 
3317   polys->InsertNextCell(4, ids);
3318 
3319   this->_generateRepresentationWholeSpace(kd->GetLeft(), pts, polys, level-1);
3320   this->_generateRepresentationWholeSpace(kd->GetRight(), pts, polys, level-1);
3321 }
3322 
3323 //----------------------------------------------------------------------------
GenerateRepresentationDataBounds(int level,vtkPolyData * pd)3324 void vtkKdTree::GenerateRepresentationDataBounds(int level, vtkPolyData *pd)
3325 {
3326   int i;
3327   vtkPoints *pts;
3328   vtkCellArray *polys;
3329 
3330   if ( this->Top == nullptr )
3331   {
3332     vtkErrorMacro(<<"vtkKdTree::GenerateRepresentation no tree");
3333     return;
3334   }
3335 
3336   if ((level < 0) || (level > this->Level))
3337   {
3338     level = this->Level;
3339   }
3340 
3341   int npoints = 0;
3342   int npolys  = 0;
3343 
3344   for (i=0; i < level; i++)
3345   {
3346     int levelBoxes= 1 << i;
3347     npoints += (8 * levelBoxes);
3348     npolys += (6 * levelBoxes);
3349   }
3350 
3351   pts = vtkPoints::New();
3352   pts->Allocate(npoints);
3353   polys = vtkCellArray::New();
3354   polys->Allocate(npolys);
3355 
3356   _generateRepresentationDataBounds(this->Top, pts, polys, level);
3357 
3358   pd->SetPoints(pts);
3359   pts->Delete();
3360   pd->SetPolys(polys);
3361   polys->Delete();
3362   pd->Squeeze();
3363 }
3364 
3365 //----------------------------------------------------------------------------
_generateRepresentationDataBounds(vtkKdNode * kd,vtkPoints * pts,vtkCellArray * polys,int level)3366 void vtkKdTree::_generateRepresentationDataBounds(vtkKdNode *kd, vtkPoints *pts,
3367                      vtkCellArray *polys, int level)
3368 {
3369   if (level > 0)
3370   {
3371       if (kd->GetLeft())
3372       {
3373         _generateRepresentationDataBounds(kd->GetLeft(), pts, polys, level-1);
3374         _generateRepresentationDataBounds(kd->GetRight(), pts, polys, level-1);
3375       }
3376 
3377       return;
3378   }
3379   vtkKdTree::AddPolys(kd, pts, polys);
3380 }
3381 
3382 //----------------------------------------------------------------------------
3383 // PolyData rep. of all spacial regions, shrunk to data bounds-------
3384 //
AddPolys(vtkKdNode * kd,vtkPoints * pts,vtkCellArray * polys)3385 void vtkKdTree::AddPolys(vtkKdNode *kd, vtkPoints *pts, vtkCellArray *polys)
3386 {
3387   vtkIdType ids[8];
3388   vtkIdType idList[4];
3389   double     x[3];
3390 
3391   double *min;
3392   double *max;
3393 
3394   if (this->GenerateRepresentationUsingDataBounds)
3395   {
3396     min = kd->GetMinDataBounds();
3397     max = kd->GetMaxDataBounds();
3398   }
3399   else
3400   {
3401     min = kd->GetMinBounds();
3402     max = kd->GetMaxBounds();
3403   }
3404 
3405   x[0]  = min[0]; x[1]  = max[1]; x[2]  = min[2];
3406   ids[0] = pts->InsertNextPoint(x);
3407 
3408   x[0]  = max[0]; x[1]  = max[1]; x[2]  = min[2];
3409   ids[1] = pts->InsertNextPoint(x);
3410 
3411   x[0]  = max[0]; x[1]  = max[1]; x[2]  = max[2];
3412   ids[2] = pts->InsertNextPoint(x);
3413 
3414   x[0]  = min[0]; x[1]  = max[1]; x[2]  = max[2];
3415   ids[3] = pts->InsertNextPoint(x);
3416 
3417   x[0]  = min[0]; x[1]  = min[1]; x[2]  = min[2];
3418   ids[4] = pts->InsertNextPoint(x);
3419 
3420   x[0]  = max[0]; x[1]  = min[1]; x[2]  = min[2];
3421   ids[5] = pts->InsertNextPoint(x);
3422 
3423   x[0]  = max[0]; x[1]  = min[1]; x[2]  = max[2];
3424   ids[6] = pts->InsertNextPoint(x);
3425 
3426   x[0]  = min[0]; x[1]  = min[1]; x[2]  = max[2];
3427   ids[7] = pts->InsertNextPoint(x);
3428 
3429   idList[0] = ids[0]; idList[1] = ids[1]; idList[2] = ids[2]; idList[3] = ids[3];
3430   polys->InsertNextCell(4, idList);
3431 
3432   idList[0] = ids[1]; idList[1] = ids[5]; idList[2] = ids[6]; idList[3] = ids[2];
3433   polys->InsertNextCell(4, idList);
3434 
3435   idList[0] = ids[5]; idList[1] = ids[4]; idList[2] = ids[7]; idList[3] = ids[6];
3436   polys->InsertNextCell(4, idList);
3437 
3438   idList[0] = ids[4]; idList[1] = ids[0]; idList[2] = ids[3]; idList[3] = ids[7];
3439   polys->InsertNextCell(4, idList);
3440 
3441   idList[0] = ids[3]; idList[1] = ids[2]; idList[2] = ids[6]; idList[3] = ids[7];
3442   polys->InsertNextCell(4, idList);
3443 
3444   idList[0] = ids[1]; idList[1] = ids[0]; idList[2] = ids[4]; idList[3] = ids[5];
3445   polys->InsertNextCell(4, idList);
3446 }
3447 
3448 //----------------------------------------------------------------------------
3449 // PolyData representation of a list of spacial regions------------
3450 //
GenerateRepresentation(int * regions,int len,vtkPolyData * pd)3451 void vtkKdTree::GenerateRepresentation(int *regions, int len, vtkPolyData *pd)
3452 {
3453   int i;
3454   vtkPoints *pts;
3455   vtkCellArray *polys;
3456 
3457   if ( this->Top == nullptr )
3458   {
3459     vtkErrorMacro(<<"vtkKdTree::GenerateRepresentation no tree");
3460     return;
3461   }
3462 
3463   int npoints = 8 * len;
3464   int npolys  = 6 * len;
3465 
3466   pts = vtkPoints::New();
3467   pts->Allocate(npoints);
3468   polys = vtkCellArray::New();
3469   polys->Allocate(npolys);
3470 
3471   for (i=0; i<len; i++)
3472   {
3473     if ((regions[i] < 0) || (regions[i] >= this->NumberOfRegions))
3474     {
3475       break;
3476     }
3477 
3478     vtkKdTree::AddPolys(this->RegionList[regions[i]], pts, polys);
3479   }
3480 
3481   pd->SetPoints(pts);
3482   pts->Delete();
3483   pd->SetPolys(polys);
3484   polys->Delete();
3485   pd->Squeeze();
3486 }
3487 
3488 //----------------------------------------------------------------------------
3489 //  Cell ID lists
3490 //
3491 #define SORTLIST(l, lsize) std::sort(l, (l) + (lsize))
3492 
3493 #define REMOVEDUPLICATES(l, lsize, newsize) \
3494 {                                     \
3495 int ii,jj;                            \
3496 for (ii=0, jj=0; ii<(lsize); ii++)      \
3497 {                                   \
3498   if ((ii > 0) && (l[ii] == l[jj-1])) \
3499   {         \
3500     continue; \
3501   }         \
3502   if (jj != ii)    \
3503   {              \
3504     l[jj] = l[ii]; \
3505   }              \
3506   jj++;            \
3507 }                  \
3508 newsize = jj;      \
3509 }
3510 
3511 //----------------------------------------------------------------------------
FoundId(vtkIntArray * idArray,int id)3512 int vtkKdTree::FoundId(vtkIntArray *idArray, int id)
3513 {
3514   // This is a simple linear search, because I think it is rare that
3515   // an id array would be provided, and if one is it should be small.
3516 
3517   int found = 0;
3518   int len = idArray->GetNumberOfTuples();
3519   int *ids = idArray->GetPointer(0);
3520 
3521   for (int i=0; i<len; i++)
3522   {
3523     if (ids[i] == id)
3524     {
3525       found = 1;
3526     }
3527   }
3528 
3529   return found;
3530 }
3531 
3532 //----------------------------------------------------------------------------
findRegion(vtkKdNode * node,float x,float y,float z)3533 int vtkKdTree::findRegion(vtkKdNode *node, float x, float y, float z)
3534 {
3535   return vtkKdTree::findRegion(node,static_cast<double>(x),static_cast<double>(y),static_cast<double>(z));
3536 }
3537 
3538 //----------------------------------------------------------------------------
findRegion(vtkKdNode * node,double x,double y,double z)3539 int vtkKdTree::findRegion(vtkKdNode *node, double x, double y, double z)
3540 {
3541   int regionId;
3542 
3543   if (!node->ContainsPoint(x, y, z, 0))
3544   {
3545     return -1;
3546   }
3547 
3548   if (node->GetLeft() == nullptr)
3549   {
3550     regionId = node->GetID();
3551   }
3552   else
3553   {
3554     regionId = vtkKdTree::findRegion(node->GetLeft(), x, y, z);
3555 
3556     if (regionId < 0)
3557     {
3558       regionId = vtkKdTree::findRegion(node->GetRight(), x, y, z);
3559     }
3560   }
3561 
3562   return regionId;
3563 }
3564 
3565 //----------------------------------------------------------------------------
CreateCellLists()3566 void vtkKdTree::CreateCellLists()
3567 {
3568   this->CreateCellLists(static_cast<int *>(nullptr), 0);
3569 }
3570 
3571 //----------------------------------------------------------------------------
CreateCellLists(int * regionList,int listSize)3572 void vtkKdTree::CreateCellLists(int *regionList, int listSize)
3573 {
3574   this->CreateCellLists(this->GetDataSet(), regionList, listSize);
3575 }
3576 
3577 //----------------------------------------------------------------------------
CreateCellLists(int dataSetIndex,int * regionList,int listSize)3578 void vtkKdTree::CreateCellLists(int dataSetIndex, int *regionList, int listSize)
3579 {
3580   vtkDataSet *dataSet = this->GetDataSet(dataSetIndex);
3581   if (!dataSet)
3582   {
3583     vtkErrorMacro(<<"vtkKdTree::CreateCellLists invalid data set");
3584     return;
3585   }
3586 
3587   this->CreateCellLists(dataSet, regionList, listSize);
3588 }
3589 
3590 //----------------------------------------------------------------------------
CreateCellLists(vtkDataSet * set,int * regionList,int listSize)3591 void vtkKdTree::CreateCellLists(vtkDataSet *set, int *regionList, int listSize)
3592 {
3593   int i, AllRegions;
3594 
3595   if ( this->GetDataSetIndex(set) < 0)
3596   {
3597     vtkErrorMacro(<<"vtkKdTree::CreateCellLists invalid data set");
3598     return;
3599   }
3600 
3601   vtkKdTree::_cellList *list = &this->CellList;
3602 
3603   if (list->nRegions > 0)
3604   {
3605     this->DeleteCellLists();
3606   }
3607 
3608   list->emptyList = vtkIdList::New();
3609 
3610   list->dataSet = set;
3611 
3612   if ((regionList == nullptr) || (listSize == 0))
3613   {
3614     list->nRegions = this->NumberOfRegions;    // all regions
3615   }
3616   else
3617   {
3618     list->regionIds = new int [listSize];
3619 
3620     if (!list->regionIds)
3621     {
3622       vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation");
3623       return;
3624     }
3625 
3626     memcpy(list->regionIds, regionList, sizeof(int) * listSize);
3627     SORTLIST(list->regionIds, listSize);
3628     REMOVEDUPLICATES(list->regionIds, listSize, list->nRegions);
3629 
3630     if (list->nRegions == this->NumberOfRegions)
3631     {
3632       delete [] list->regionIds;
3633       list->regionIds = nullptr;
3634     }
3635   }
3636 
3637   if (list->nRegions == this->NumberOfRegions)
3638   {
3639     AllRegions = 1;
3640   }
3641   else
3642   {
3643     AllRegions = 0;
3644   }
3645 
3646   int *idlist = nullptr;
3647   int idListLen = 0;
3648 
3649   if (this->IncludeRegionBoundaryCells)
3650   {
3651     list->boundaryCells = new vtkIdList * [list->nRegions];
3652 
3653     if (!list->boundaryCells)
3654     {
3655       vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation");
3656       return;
3657     }
3658 
3659     for (i=0; i<list->nRegions; i++)
3660     {
3661       list->boundaryCells[i] = vtkIdList::New();
3662     }
3663     idListLen = this->NumberOfRegions;
3664 
3665     idlist = new int [idListLen];
3666   }
3667 
3668   int *listptr = nullptr;
3669 
3670   if (!AllRegions)
3671   {
3672     listptr = new int [this->NumberOfRegions];
3673 
3674     if (!listptr)
3675     {
3676       vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation");
3677       delete [] idlist;
3678       return;
3679     }
3680 
3681     for (i=0; i<this->NumberOfRegions; i++)
3682     {
3683       listptr[i] = -1;
3684     }
3685   }
3686 
3687   list->cells = new vtkIdList * [list->nRegions];
3688 
3689   if (!list->cells)
3690   {
3691     vtkErrorMacro(<<"vtkKdTree::CreateCellLists memory allocation");
3692     delete [] idlist;
3693     delete [] listptr;
3694     return;
3695   }
3696 
3697   for (i = 0; i < list->nRegions; i++)
3698   {
3699     list->cells[i] = vtkIdList::New();
3700 
3701     if (listptr)
3702     {
3703       listptr[list->regionIds[i]] = i;
3704     }
3705   }
3706 
3707   // acquire a list in cell Id order of the region Id each
3708   // cell centroid falls in
3709 
3710   int *regList = this->CellRegionList;
3711 
3712   if (regList == nullptr)
3713   {
3714     regList = this->AllGetRegionContainingCell();
3715   }
3716 
3717   int setNum = this->GetDataSetIndex(set);
3718 
3719   if (setNum > 0)
3720   {
3721     int ncells = this->GetDataSetsNumberOfCells(0,setNum-1);
3722     regList += ncells;
3723   }
3724 
3725   int nCells = set->GetNumberOfCells();
3726 
3727   for (int cellId=0; cellId<nCells; cellId++)
3728   {
3729     if (this->IncludeRegionBoundaryCells)
3730     {
3731       // Find all regions the cell intersects, including
3732       // the region the cell centroid lies in.
3733       // This can be an expensive calculation, intersections
3734       // of a convex region with axis aligned boxes.
3735 
3736       int nRegions =
3737         this->BSPCalculator->IntersectsCell(idlist, idListLen,
3738           set->GetCell(cellId), regList[cellId]);
3739 
3740       if (nRegions == 1)
3741       {
3742         int idx = (listptr) ? listptr[idlist[0]] : idlist[0];
3743 
3744         if (idx >= 0)
3745         {
3746           list->cells[idx]->InsertNextId(cellId);
3747         }
3748       }
3749       else
3750       {
3751         for (int r=0; r < nRegions; r++)
3752         {
3753           int regionId = idlist[r];
3754 
3755           int idx = (listptr) ? listptr[regionId] : regionId;
3756 
3757           if (idx < 0)
3758           {
3759             continue;
3760           }
3761 
3762           if (regionId == regList[cellId])
3763           {
3764             list->cells[idx]->InsertNextId(cellId);
3765           }
3766           else
3767           {
3768             list->boundaryCells[idx]->InsertNextId(cellId);
3769           }
3770         }
3771       }
3772     }
3773     else
3774     {
3775       // just find the region the cell centroid lies in - easy
3776 
3777       int regionId = regList[cellId];
3778 
3779       int idx = (listptr) ? listptr[regionId] : regionId;
3780 
3781       if (idx >= 0)
3782       {
3783         list->cells[idx]->InsertNextId(cellId);
3784       }
3785     }
3786   }
3787 
3788   delete [] listptr;
3789   delete [] idlist;
3790 }
3791 
3792 //----------------------------------------------------------------------------
GetList(int regionId,vtkIdList ** which)3793 vtkIdList * vtkKdTree::GetList(int regionId, vtkIdList **which)
3794 {
3795   int i;
3796   struct _cellList *list = &this->CellList;
3797   vtkIdList *cellIds = nullptr;
3798 
3799   if (which && (list->nRegions == this->NumberOfRegions))
3800   {
3801     cellIds = which[regionId];
3802   }
3803   else if (which)
3804   {
3805     for (i=0; i< list->nRegions; i++)
3806     {
3807       if (list->regionIds[i] == regionId)
3808       {
3809         cellIds = which[i];
3810         break;
3811       }
3812     }
3813   }
3814   else
3815   {
3816     cellIds = list->emptyList;
3817   }
3818 
3819   return cellIds;
3820 }
3821 
3822 //----------------------------------------------------------------------------
GetCellList(int regionID)3823 vtkIdList * vtkKdTree::GetCellList(int regionID)
3824 {
3825   return this->GetList(regionID, this->CellList.cells);
3826 }
3827 
3828 //----------------------------------------------------------------------------
GetBoundaryCellList(int regionID)3829 vtkIdList * vtkKdTree::GetBoundaryCellList(int regionID)
3830 {
3831   return this->GetList(regionID, this->CellList.boundaryCells);
3832 }
3833 
3834 //----------------------------------------------------------------------------
GetCellLists(vtkIntArray * regions,int setIndex,vtkIdList * inRegionCells,vtkIdList * onBoundaryCells)3835 vtkIdType vtkKdTree::GetCellLists(vtkIntArray *regions,
3836           int setIndex, vtkIdList *inRegionCells, vtkIdList *onBoundaryCells)
3837 {
3838   vtkDataSet *set = this->GetDataSet(setIndex);
3839   if (!set)
3840   {
3841     vtkErrorMacro(<<"vtkKdTree::GetCellLists no such data set");
3842     return 0;
3843   }
3844   return this->GetCellLists(regions, set,
3845                             inRegionCells, onBoundaryCells);
3846 }
3847 
3848 //----------------------------------------------------------------------------
GetCellLists(vtkIntArray * regions,vtkIdList * inRegionCells,vtkIdList * onBoundaryCells)3849 vtkIdType vtkKdTree::GetCellLists(vtkIntArray *regions,
3850           vtkIdList *inRegionCells, vtkIdList *onBoundaryCells)
3851 {
3852   return this->GetCellLists(regions, this->GetDataSet(),
3853                             inRegionCells, onBoundaryCells);
3854 }
3855 
3856 //----------------------------------------------------------------------------
GetCellLists(vtkIntArray * regions,vtkDataSet * set,vtkIdList * inRegionCells,vtkIdList * onBoundaryCells)3857 vtkIdType vtkKdTree::GetCellLists(vtkIntArray *regions, vtkDataSet *set,
3858           vtkIdList *inRegionCells, vtkIdList *onBoundaryCells)
3859 {
3860   int reg, regionId;
3861   vtkIdType cell, cellId, numCells;
3862   vtkIdList *cellIds;
3863 
3864   vtkIdType totalCells = 0;
3865 
3866   if ( (inRegionCells == nullptr) && (onBoundaryCells == nullptr))
3867   {
3868     return totalCells;
3869   }
3870 
3871   int nregions = regions->GetNumberOfTuples();
3872 
3873   if (nregions == 0)
3874   {
3875     return totalCells;
3876   }
3877 
3878   // Do I have cell lists for all these regions?  If not, build cell
3879   // lists for all regions for this data set.
3880 
3881   int rebuild = 0;
3882 
3883   if (this->CellList.dataSet != set)
3884   {
3885     rebuild = 1;
3886   }
3887   else if (nregions > this->CellList.nRegions)
3888   {
3889     rebuild = 1;
3890   }
3891   else if ((onBoundaryCells != nullptr) && (this->CellList.boundaryCells == nullptr))
3892   {
3893     rebuild = 1;
3894   }
3895   else if (this->CellList.nRegions < this->NumberOfRegions)
3896   {
3897     // these two lists should generally be "short"
3898 
3899     int *haveIds = this->CellList.regionIds;
3900 
3901     for (int wantReg=0; wantReg < nregions; wantReg++)
3902     {
3903       int wantRegion = regions->GetValue(wantReg);
3904       int gotId = 0;
3905 
3906       for (int haveReg=0; haveReg < this->CellList.nRegions; haveReg++)
3907       {
3908         if (haveIds[haveReg] == wantRegion)
3909         {
3910           gotId = 1;
3911           break;
3912         }
3913       }
3914       if (!gotId)
3915       {
3916         rebuild = 1;
3917         break;
3918       }
3919     }
3920   }
3921 
3922   if (rebuild)
3923   {
3924     if (onBoundaryCells != nullptr)
3925     {
3926       this->IncludeRegionBoundaryCellsOn();
3927     }
3928     this->CreateCellLists(set, nullptr, 0);  // for all regions
3929   }
3930 
3931   // OK, we have cell lists for these regions.  Make lists of region
3932   // cells and boundary cells.
3933 
3934   int CheckSet = (onBoundaryCells && (nregions > 1));
3935 
3936   std::set<vtkIdType> ids;
3937   std::pair<std::set<vtkIdType>::iterator, bool> idRec;
3938 
3939   vtkIdType totalRegionCells = 0;
3940   vtkIdType totalBoundaryCells = 0;
3941 
3942   vtkIdList **inRegionList = new vtkIdList * [nregions];
3943 
3944   // First the cell IDs with centroid in the regions
3945 
3946   for (reg = 0; reg < nregions; reg++)
3947   {
3948     regionId = regions->GetValue(reg);
3949 
3950     inRegionList[reg] = this->GetCellList(regionId);
3951 
3952     totalRegionCells += inRegionList[reg]->GetNumberOfIds();
3953   }
3954 
3955   if (inRegionCells)
3956   {
3957     inRegionCells->Initialize();
3958     inRegionCells->SetNumberOfIds(totalRegionCells);
3959   }
3960 
3961   int nextCell = 0;
3962 
3963   for (reg = 0; reg <  nregions; reg++)
3964   {
3965     cellIds = inRegionList[reg];
3966 
3967     numCells = cellIds->GetNumberOfIds();
3968 
3969     for (cell = 0; cell < numCells; cell++)
3970     {
3971       if (inRegionCells)
3972       {
3973         inRegionCells->SetId(nextCell++, cellIds->GetId(cell));
3974       }
3975 
3976       if (CheckSet)
3977       {
3978         // We have to save the ids, so we don't include
3979         // them as boundary cells.  A cell in one region
3980         // may be a boundary cell of another region.
3981 
3982         ids.insert(cellIds->GetId(cell));
3983       }
3984     }
3985   }
3986 
3987   delete [] inRegionList;
3988 
3989   if (onBoundaryCells == nullptr)
3990   {
3991     return totalRegionCells;
3992   }
3993 
3994   // Now the list of all cells on the boundary of the regions,
3995   // which do not have their centroid in one of the regions
3996 
3997   onBoundaryCells->Initialize();
3998 
3999   for (reg = 0; reg < nregions; reg++)
4000   {
4001     regionId = regions->GetValue(reg);
4002 
4003     cellIds = this->GetBoundaryCellList(regionId);
4004 
4005     numCells = cellIds->GetNumberOfIds();
4006 
4007     for (cell = 0; cell < numCells; cell++)
4008     {
4009       cellId = cellIds->GetId(cell);
4010 
4011       if (CheckSet)
4012       {
4013         // if we already included this cell because it is within
4014         // one of the regions, or on the boundary of another, skip it
4015 
4016         idRec = ids.insert(cellId);
4017 
4018         if (idRec.second == 0)
4019         {
4020           continue;
4021         }
4022       }
4023 
4024       onBoundaryCells->InsertNextId(cellId);
4025       totalBoundaryCells++;
4026     }
4027 
4028     totalCells += totalBoundaryCells;
4029   }
4030 
4031   return totalCells;
4032 }
4033 
4034 //----------------------------------------------------------------------------
GetRegionContainingCell(vtkIdType cellID)4035 int vtkKdTree::GetRegionContainingCell(vtkIdType cellID)
4036 {
4037   return this->GetRegionContainingCell(this->GetDataSet(), cellID);
4038 }
4039 
4040 //----------------------------------------------------------------------------
GetRegionContainingCell(int setIndex,vtkIdType cellID)4041 int vtkKdTree::GetRegionContainingCell(int setIndex, vtkIdType cellID)
4042 {
4043   vtkDataSet *set = this->GetDataSet(setIndex);
4044   if (!set)
4045   {
4046     vtkErrorMacro(<<"vtkKdTree::GetRegionContainingCell no such data set");
4047     return -1;
4048   }
4049   return this->GetRegionContainingCell(set, cellID);
4050 }
4051 
4052 //----------------------------------------------------------------------------
GetRegionContainingCell(vtkDataSet * set,vtkIdType cellID)4053 int vtkKdTree::GetRegionContainingCell(vtkDataSet *set, vtkIdType cellID)
4054 {
4055   int regionID = -1;
4056 
4057   if ( this->GetDataSetIndex(set) < 0)
4058   {
4059     vtkErrorMacro(<<"vtkKdTree::GetRegionContainingCell no such data set");
4060     return -1;
4061   }
4062   if ( (cellID < 0) || (cellID >= set->GetNumberOfCells()))
4063   {
4064     vtkErrorMacro(<<"vtkKdTree::GetRegionContainingCell bad cell ID");
4065     return -1;
4066   }
4067 
4068   if (this->CellRegionList)
4069   {
4070     if (set == this->GetDataSet())        // 99.99999% of the time
4071     {
4072       return this->CellRegionList[cellID];
4073     }
4074 
4075     int setNum = this->GetDataSetIndex(set);
4076 
4077     int offset = this->GetDataSetsNumberOfCells(0, setNum-1);
4078 
4079     return this->CellRegionList[offset + cellID];
4080   }
4081 
4082   float center[3];
4083 
4084   this->ComputeCellCenter(set, cellID, center);
4085 
4086   regionID = this->GetRegionContainingPoint(center[0], center[1], center[2]);
4087 
4088   return regionID;
4089 }
4090 
4091 //----------------------------------------------------------------------------
AllGetRegionContainingCell()4092 int *vtkKdTree::AllGetRegionContainingCell()
4093 {
4094   if (this->CellRegionList)
4095   {
4096     return this->CellRegionList;
4097   }
4098   this->CellRegionList = new int [this->GetNumberOfCells()];
4099 
4100   if (!this->CellRegionList)
4101   {
4102     vtkErrorMacro(<<"vtkKdTree::AllGetRegionContainingCell memory allocation");
4103     return nullptr;
4104   }
4105 
4106   int *listPtr = this->CellRegionList;
4107 
4108   vtkCollectionSimpleIterator cookie;
4109   this->DataSets->InitTraversal(cookie);
4110   for (vtkDataSet *iset = this->DataSets->GetNextDataSet(cookie);
4111        iset != nullptr; iset = this->DataSets->GetNextDataSet(cookie))
4112   {
4113     int setCells = iset->GetNumberOfCells();
4114 
4115     float *centers = this->ComputeCellCenters(iset);
4116 
4117     float *pt = centers;
4118 
4119     for (int cellId = 0; cellId < setCells; cellId++)
4120     {
4121       listPtr[cellId] =
4122         this->GetRegionContainingPoint(pt[0], pt[1], pt[2]);
4123 
4124       pt += 3;
4125     }
4126 
4127     listPtr += setCells;
4128 
4129     delete [] centers;
4130   }
4131 
4132   return this->CellRegionList;
4133 }
4134 
4135 //----------------------------------------------------------------------------
GetRegionContainingPoint(double x,double y,double z)4136 int vtkKdTree::GetRegionContainingPoint(double x, double y, double z)
4137 {
4138   return vtkKdTree::findRegion(this->Top, x, y, z);
4139 }
4140 //----------------------------------------------------------------------------
MinimalNumberOfConvexSubRegions(vtkIntArray * regionIdList,double ** convexSubRegions)4141 int vtkKdTree::MinimalNumberOfConvexSubRegions(vtkIntArray *regionIdList,
4142                                                double **convexSubRegions)
4143 {
4144   int nids = 0;
4145 
4146   if ((regionIdList == nullptr) ||
4147       ((nids = regionIdList->GetNumberOfTuples()) == 0))
4148   {
4149     vtkErrorMacro(<<
4150       "vtkKdTree::MinimalNumberOfConvexSubRegions no regions specified");
4151     return 0;
4152   }
4153 
4154   int i;
4155   int *ids = regionIdList->GetPointer(0);
4156 
4157   if (nids == 1)
4158   {
4159     if ( (ids[0] < 0) || (ids[0] >= this->NumberOfRegions))
4160     {
4161       vtkErrorMacro(<<
4162         "vtkKdTree::MinimalNumberOfConvexSubRegions bad region ID");
4163       return 0;
4164     }
4165 
4166     double *bounds = new double [6];
4167 
4168     this->RegionList[ids[0]]->GetBounds(bounds);
4169 
4170     *convexSubRegions = bounds;
4171 
4172     return 1;
4173   }
4174 
4175   // create a sorted list of unique region Ids
4176 
4177   std::set<int> idSet;
4178   std::set<int>::iterator it;
4179 
4180   for (i=0; i<nids; i++)
4181   {
4182     idSet.insert(ids[i]);
4183   }
4184 
4185   int nUniqueIds = static_cast<int>(idSet.size());
4186 
4187   int *idList = new int [nUniqueIds];
4188 
4189   for (i=0, it = idSet.begin(); it != idSet.end(); ++it, ++i)
4190   {
4191     idList[i] = *it;
4192   }
4193 
4194   vtkKdNode **regions = new vtkKdNode * [nUniqueIds];
4195 
4196   int nregions = vtkKdTree::__ConvexSubRegions(idList, nUniqueIds, this->Top, regions);
4197 
4198   double *bounds = new double [nregions * 6];
4199 
4200   for (i=0; i<nregions; i++)
4201   {
4202     regions[i]->GetBounds(bounds + (i*6));
4203   }
4204 
4205   *convexSubRegions = bounds;
4206 
4207   delete [] idList;
4208   delete [] regions;
4209 
4210   return nregions;
4211 }
4212 //----------------------------------------------------------------------------
__ConvexSubRegions(int * ids,int len,vtkKdNode * tree,vtkKdNode ** nodes)4213 int vtkKdTree::__ConvexSubRegions(int *ids, int len, vtkKdNode *tree, vtkKdNode **nodes)
4214 {
4215   int nregions = tree->GetMaxID() - tree->GetMinID() + 1;
4216 
4217   if (nregions == len)
4218   {
4219     *nodes = tree;
4220     return 1;
4221   }
4222 
4223   if (tree->GetLeft() == nullptr)
4224   {
4225     return 0;
4226   }
4227 
4228   int min = ids[0];
4229   int max = ids[len-1];
4230 
4231   int leftMax = tree->GetLeft()->GetMaxID();
4232   int rightMin = tree->GetRight()->GetMinID();
4233 
4234   if (max <= leftMax)
4235   {
4236     return vtkKdTree::__ConvexSubRegions(ids, len, tree->GetLeft(), nodes);
4237   }
4238   else if (min >= rightMin)
4239   {
4240     return vtkKdTree::__ConvexSubRegions(ids, len, tree->GetRight(), nodes);
4241   }
4242   else
4243   {
4244     int leftIds = 1;
4245 
4246     for (int i=1; i<len-1; i++)
4247     {
4248       if (ids[i] <= leftMax)
4249       {
4250         leftIds++;
4251       }
4252       else
4253       {
4254         break;
4255       }
4256     }
4257 
4258     int numNodesLeft =
4259       vtkKdTree::__ConvexSubRegions(ids, leftIds, tree->GetLeft(), nodes);
4260 
4261 
4262     int numNodesRight =
4263       vtkKdTree::__ConvexSubRegions(ids + leftIds, len - leftIds,
4264                                tree->GetRight(), nodes + numNodesLeft);
4265 
4266     return (numNodesLeft + numNodesRight);
4267   }
4268 }
4269 
4270 //----------------------------------------------------------------------------
ViewOrderRegionsInDirection(vtkIntArray * regionIds,const double directionOfProjection[3],vtkIntArray * orderedList)4271 int vtkKdTree::ViewOrderRegionsInDirection(
4272                                           vtkIntArray *regionIds,
4273                                           const double directionOfProjection[3],
4274                                           vtkIntArray *orderedList)
4275 {
4276   int i;
4277 
4278   vtkIntArray *IdsOfInterest = nullptr;
4279 
4280   if (regionIds && (regionIds->GetNumberOfTuples() > 0))
4281   {
4282     // Created sorted list of unique ids
4283 
4284     std::set<int> ids;
4285     std::set<int>::iterator it;
4286     int nids = regionIds->GetNumberOfTuples();
4287 
4288     for (i=0; i<nids; i++)
4289     {
4290       ids.insert(regionIds->GetValue(i));
4291     }
4292 
4293     if (ids.size() < static_cast<unsigned int>(this->NumberOfRegions))
4294     {
4295       IdsOfInterest = vtkIntArray::New();
4296       IdsOfInterest->SetNumberOfValues(
4297         static_cast<vtkIdType>(ids.size()));
4298 
4299       for (it = ids.begin(), i=0; it != ids.end(); ++it, ++i)
4300       {
4301         IdsOfInterest->SetValue(i, *it);
4302       }
4303     }
4304   }
4305 
4306   int size = this->_ViewOrderRegionsInDirection(IdsOfInterest,
4307                                                 directionOfProjection,
4308                                                 orderedList);
4309 
4310   if (IdsOfInterest)
4311   {
4312     IdsOfInterest->Delete();
4313   }
4314 
4315   return size;
4316 }
4317 
4318 //----------------------------------------------------------------------------
ViewOrderAllRegionsInDirection(const double directionOfProjection[3],vtkIntArray * orderedList)4319 int vtkKdTree::ViewOrderAllRegionsInDirection(
4320                                           const double directionOfProjection[3],
4321                                           vtkIntArray *orderedList)
4322 {
4323   return this->_ViewOrderRegionsInDirection(nullptr, directionOfProjection,
4324                                             orderedList);
4325 }
4326 
4327 //----------------------------------------------------------------------------
ViewOrderRegionsFromPosition(vtkIntArray * regionIds,const double cameraPosition[3],vtkIntArray * orderedList)4328 int vtkKdTree::ViewOrderRegionsFromPosition(vtkIntArray *regionIds,
4329                                             const double cameraPosition[3],
4330                                             vtkIntArray *orderedList)
4331 {
4332   int i;
4333 
4334   vtkIntArray *IdsOfInterest = nullptr;
4335 
4336   if (regionIds && (regionIds->GetNumberOfTuples() > 0))
4337   {
4338     // Created sorted list of unique ids
4339 
4340     std::set<int> ids;
4341     std::set<int>::iterator it;
4342     int nids = regionIds->GetNumberOfTuples();
4343 
4344     for (i=0; i<nids; i++)
4345     {
4346       ids.insert(regionIds->GetValue(i));
4347     }
4348 
4349     if (ids.size() < static_cast<unsigned int>(this->NumberOfRegions))
4350     {
4351       IdsOfInterest = vtkIntArray::New();
4352       IdsOfInterest->SetNumberOfValues(static_cast<vtkIdType>(ids.size()));
4353 
4354       for (it = ids.begin(), i=0; it != ids.end(); ++it, ++i)
4355       {
4356         IdsOfInterest->SetValue(i, *it);
4357       }
4358     }
4359   }
4360 
4361   int size = this->_ViewOrderRegionsFromPosition(IdsOfInterest,
4362                                                  cameraPosition,
4363                                                  orderedList);
4364 
4365   if (IdsOfInterest)
4366   {
4367     IdsOfInterest->Delete();
4368   }
4369 
4370   return size;
4371 }
4372 
4373 //----------------------------------------------------------------------------
ViewOrderAllRegionsFromPosition(const double cameraPosition[3],vtkIntArray * orderedList)4374 int vtkKdTree::ViewOrderAllRegionsFromPosition(const double cameraPosition[3],
4375                                                vtkIntArray *orderedList)
4376 {
4377   return this->_ViewOrderRegionsFromPosition(nullptr, cameraPosition, orderedList);
4378 }
4379 
4380 //----------------------------------------------------------------------------
_ViewOrderRegionsInDirection(vtkIntArray * IdsOfInterest,const double dir[3],vtkIntArray * orderedList)4381 int vtkKdTree::_ViewOrderRegionsInDirection(vtkIntArray *IdsOfInterest,
4382                                             const double dir[3],
4383                                             vtkIntArray *orderedList)
4384 {
4385   int nextId = 0;
4386 
4387   int numValues = (IdsOfInterest ? IdsOfInterest->GetNumberOfTuples() :
4388                                    this->NumberOfRegions);
4389 
4390   orderedList->Initialize();
4391   orderedList->SetNumberOfValues(numValues);
4392 
4393   int size = vtkKdTree::__ViewOrderRegionsInDirection(this->Top, orderedList,
4394                                                       IdsOfInterest, dir,
4395                                                       nextId);
4396   if (size < 0)
4397   {
4398     vtkErrorMacro(<<"vtkKdTree::DepthOrderRegions k-d tree structure is corrupt");
4399     orderedList->Initialize();
4400     return 0;
4401   }
4402 
4403   return size;
4404 }
4405 //----------------------------------------------------------------------------
__ViewOrderRegionsInDirection(vtkKdNode * node,vtkIntArray * list,vtkIntArray * IdsOfInterest,const double dir[3],int nextId)4406 int vtkKdTree::__ViewOrderRegionsInDirection(vtkKdNode *node,
4407                                              vtkIntArray *list,
4408                                              vtkIntArray *IdsOfInterest,
4409                                              const double dir[3], int nextId)
4410 {
4411   if (node->GetLeft() == nullptr)
4412   {
4413     if (!IdsOfInterest || vtkKdTree::FoundId(IdsOfInterest, node->GetID()))
4414     {
4415       list->SetValue(nextId, node->GetID());
4416       nextId = nextId+1;
4417     }
4418 
4419       return nextId;
4420   }
4421 
4422   int cutPlane = node->GetDim();
4423 
4424   if ((cutPlane < 0) || (cutPlane > 2))
4425   {
4426     return -1;
4427   }
4428 
4429   double closest = dir[cutPlane] * -1;
4430 
4431   vtkKdNode *closeNode = (closest < 0) ? node->GetLeft() : node->GetRight();
4432   vtkKdNode *farNode  = (closest >= 0) ? node->GetLeft() : node->GetRight();
4433 
4434   int nextNextId = vtkKdTree::__ViewOrderRegionsInDirection(closeNode, list,
4435                                                             IdsOfInterest, dir,
4436                                                             nextId);
4437 
4438   if (nextNextId == -1)
4439   {
4440     return -1;
4441   }
4442 
4443   nextNextId = vtkKdTree::__ViewOrderRegionsInDirection(farNode, list,
4444                                                         IdsOfInterest, dir,
4445                                                         nextNextId);
4446 
4447   return nextNextId;
4448 }
4449 
4450 //----------------------------------------------------------------------------
_ViewOrderRegionsFromPosition(vtkIntArray * IdsOfInterest,const double pos[3],vtkIntArray * orderedList)4451 int vtkKdTree::_ViewOrderRegionsFromPosition(vtkIntArray *IdsOfInterest,
4452                                              const double pos[3],
4453                                              vtkIntArray *orderedList)
4454 {
4455   int nextId = 0;
4456 
4457   int numValues = (IdsOfInterest ? IdsOfInterest->GetNumberOfTuples() :
4458                                    this->NumberOfRegions);
4459 
4460   orderedList->Initialize();
4461   orderedList->SetNumberOfValues(numValues);
4462 
4463   int size = vtkKdTree::__ViewOrderRegionsFromPosition(this->Top, orderedList,
4464                                                        IdsOfInterest, pos,
4465                                                        nextId);
4466   if (size < 0)
4467   {
4468     vtkErrorMacro(<<"vtkKdTree::DepthOrderRegions k-d tree structure is corrupt");
4469     orderedList->Initialize();
4470     return 0;
4471   }
4472 
4473   return size;
4474 }
4475 //----------------------------------------------------------------------------
__ViewOrderRegionsFromPosition(vtkKdNode * node,vtkIntArray * list,vtkIntArray * IdsOfInterest,const double pos[3],int nextId)4476 int vtkKdTree::__ViewOrderRegionsFromPosition(vtkKdNode *node,
4477                                               vtkIntArray *list,
4478                                               vtkIntArray *IdsOfInterest,
4479                                               const double pos[3], int nextId)
4480 {
4481   if (node->GetLeft() == nullptr)
4482   {
4483     if (!IdsOfInterest || vtkKdTree::FoundId(IdsOfInterest, node->GetID()))
4484     {
4485       list->SetValue(nextId, node->GetID());
4486       nextId = nextId+1;
4487     }
4488 
4489       return nextId;
4490   }
4491 
4492   int cutPlane = node->GetDim();
4493 
4494   if ((cutPlane < 0) || (cutPlane > 2))
4495   {
4496     return -1;
4497   }
4498 
4499   double closest = pos[cutPlane] - node->GetDivisionPosition();
4500 
4501   vtkKdNode *closeNode = (closest < 0) ? node->GetLeft() : node->GetRight();
4502   vtkKdNode *farNode  = (closest >= 0) ? node->GetLeft() : node->GetRight();
4503 
4504   int nextNextId = vtkKdTree::__ViewOrderRegionsFromPosition(closeNode, list,
4505                                                              IdsOfInterest, pos,
4506                                                              nextId);
4507 
4508   if (nextNextId == -1)
4509   {
4510     return -1;
4511   }
4512 
4513   nextNextId = vtkKdTree::__ViewOrderRegionsFromPosition(farNode, list,
4514                                                          IdsOfInterest, pos,
4515                                                          nextNextId);
4516 
4517   return nextNextId;
4518 }
4519 
4520 //----------------------------------------------------------------------------
4521 // These requests change the boundaries of the k-d tree, so must
4522 // update the MTime.
4523 //
NewPartitioningRequest(int req)4524 void vtkKdTree::NewPartitioningRequest(int req)
4525 {
4526   if (req != this->ValidDirections)
4527   {
4528     this->Modified();
4529     this->ValidDirections = req;
4530   }
4531 }
4532 
4533 //----------------------------------------------------------------------------
OmitXPartitioning()4534 void vtkKdTree::OmitXPartitioning()
4535 {
4536   this->NewPartitioningRequest((1 << vtkKdTree::YDIM) | (1 << vtkKdTree::ZDIM));
4537 }
4538 
4539 //----------------------------------------------------------------------------
OmitYPartitioning()4540 void vtkKdTree::OmitYPartitioning()
4541 {
4542   this->NewPartitioningRequest((1 << vtkKdTree::ZDIM) | (1 << vtkKdTree::XDIM));
4543 }
4544 
4545 //----------------------------------------------------------------------------
OmitZPartitioning()4546 void vtkKdTree::OmitZPartitioning()
4547 {
4548   this->NewPartitioningRequest((1 << vtkKdTree::XDIM) | (1 << vtkKdTree::YDIM));
4549 }
4550 
4551 //----------------------------------------------------------------------------
OmitXYPartitioning()4552 void vtkKdTree::OmitXYPartitioning()
4553 {
4554   this->NewPartitioningRequest((1 << vtkKdTree::ZDIM));
4555 }
4556 
4557 //----------------------------------------------------------------------------
OmitYZPartitioning()4558 void vtkKdTree::OmitYZPartitioning()
4559 {
4560   this->NewPartitioningRequest((1 << vtkKdTree::XDIM));
4561 }
4562 
4563 //----------------------------------------------------------------------------
OmitZXPartitioning()4564 void vtkKdTree::OmitZXPartitioning()
4565 {
4566   this->NewPartitioningRequest((1 << vtkKdTree::YDIM));
4567 }
4568 
4569 //----------------------------------------------------------------------------
OmitNoPartitioning()4570 void vtkKdTree::OmitNoPartitioning()
4571 {
4572   int req = ((1 << vtkKdTree::XDIM)|(1 << vtkKdTree::YDIM)|(1 << vtkKdTree::ZDIM));
4573   this->NewPartitioningRequest(req);
4574 }
4575 
4576 //---------------------------------------------------------------------------
PrintTiming(ostream & os,vtkIndent)4577 void vtkKdTree::PrintTiming(ostream& os, vtkIndent )
4578 {
4579   vtkTimerLog::DumpLogWithIndents(&os, 0.0f);
4580 }
4581 
4582 //----------------------------------------------------------------------------
UpdateProgress(double amt)4583 void vtkKdTree::UpdateProgress(double amt)
4584 {
4585   this->Progress = amt;
4586   this->InvokeEvent(vtkCommand::ProgressEvent,static_cast<void *>(&amt));
4587 }
4588 
4589 //----------------------------------------------------------------------------
UpdateSubOperationProgress(double amt)4590 void vtkKdTree::UpdateSubOperationProgress(double amt)
4591 {
4592   this->UpdateProgress(this->ProgressOffset + this->ProgressScale*amt);
4593 }
4594 
4595 //----------------------------------------------------------------------------
FindPointsInArea(double * area,vtkIdTypeArray * ids,bool clearArray)4596 void vtkKdTree::FindPointsInArea(double* area, vtkIdTypeArray* ids, bool clearArray)
4597 {
4598   if (clearArray)
4599   {
4600     ids->Reset();
4601   }
4602   if (!this->LocatorPoints)
4603   {
4604     vtkErrorMacro(<< "vtkKdTree::FindPointsInArea - must build locator first");
4605     return;
4606   }
4607   this->FindPointsInArea(this->Top, area, ids);
4608 }
4609 
4610 //----------------------------------------------------------------------------
FindPointsInArea(vtkKdNode * node,double * area,vtkIdTypeArray * ids)4611 void vtkKdTree::FindPointsInArea(vtkKdNode* node, double* area, vtkIdTypeArray* ids)
4612 {
4613   double b[6];
4614   node->GetBounds(b);
4615 
4616   if (b[0] > area[1] || b[1] < area[0] ||
4617     b[2] > area[3] || b[3] < area[2] ||
4618     b[4] > area[5] || b[5] < area[4])
4619   {
4620     return;
4621   }
4622 
4623   bool contains = false;
4624   if (area[0] <= b[0] && b[1] <= area[1] &&
4625     area[2] <= b[2] && b[3] <= area[3] &&
4626     area[4] <= b[4] && b[5] <= area[5])
4627   {
4628     contains = true;
4629   }
4630 
4631   if (contains)
4632   {
4633     this->AddAllPointsInRegion(node, ids);
4634   }
4635   else // intersects
4636   {
4637     if (node->GetLeft() == nullptr)
4638     {
4639       int regionID = node->GetID();
4640       int regionLoc = this->LocatorRegionLocation[regionID];
4641       float* pt = this->LocatorPoints + (regionLoc * 3);
4642       vtkIdType numPoints = this->RegionList[regionID]->GetNumberOfPoints();
4643       for (vtkIdType i = 0; i < numPoints; i++)
4644       {
4645         if (area[0] <= pt[0] && pt[0] <= area[1] &&
4646           area[2] <= pt[1] && pt[1] <= area[3] &&
4647           area[4] <= pt[2] && pt[2] <= area[5])
4648         {
4649           vtkIdType ptId = static_cast<vtkIdType>(this->LocatorIds[regionLoc + i]);
4650           ids->InsertNextValue(ptId);
4651         }
4652         pt += 3;
4653       }
4654     }
4655     else
4656     {
4657       this->FindPointsInArea(node->GetLeft(), area, ids);
4658       this->FindPointsInArea(node->GetRight(), area, ids);
4659     }
4660   }
4661 }
4662 
4663 //----------------------------------------------------------------------------
AddAllPointsInRegion(vtkKdNode * node,vtkIdTypeArray * ids)4664 void vtkKdTree::AddAllPointsInRegion(vtkKdNode* node, vtkIdTypeArray* ids)
4665 {
4666   if (node->GetLeft() == nullptr)
4667   {
4668     int regionID = node->GetID();
4669     int regionLoc = this->LocatorRegionLocation[regionID];
4670     vtkIdType numPoints = this->RegionList[regionID]->GetNumberOfPoints();
4671     for (vtkIdType i = 0; i < numPoints; i++)
4672     {
4673       vtkIdType ptId = static_cast<vtkIdType>(this->LocatorIds[regionLoc + i]);
4674       ids->InsertNextValue(ptId);
4675     }
4676   }
4677   else
4678   {
4679     this->AddAllPointsInRegion(node->GetLeft(), ids);
4680     this->AddAllPointsInRegion(node->GetRight(), ids);
4681   }
4682 }
4683 
4684 //----------------------------------------------------------------------------
AddAllPointsInRegion(vtkKdNode * node,vtkIdList * ids)4685 void vtkKdTree::AddAllPointsInRegion(vtkKdNode* node, vtkIdList* ids)
4686 {
4687   if (node->GetLeft() == nullptr)
4688   {
4689     int regionID = node->GetID();
4690     int regionLoc = this->LocatorRegionLocation[regionID];
4691     vtkIdType numPoints = this->RegionList[regionID]->GetNumberOfPoints();
4692     for (vtkIdType i = 0; i < numPoints; i++)
4693     {
4694       vtkIdType ptId = static_cast<vtkIdType>(this->LocatorIds[regionLoc + i]);
4695       ids->InsertNextId(ptId);
4696     }
4697   }
4698   else
4699   {
4700     this->AddAllPointsInRegion(node->GetLeft(), ids);
4701     this->AddAllPointsInRegion(node->GetRight(), ids);
4702   }
4703 }
4704 
4705 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)4706 void vtkKdTree::PrintSelf(ostream& os, vtkIndent indent)
4707 {
4708   this->Superclass::PrintSelf(os,indent);
4709 
4710   os << indent << "ValidDirections: " << this->ValidDirections << endl;
4711   os << indent << "MinCells: " << this->MinCells << endl;
4712   os << indent << "NumberOfRegionsOrLess: " << this->NumberOfRegionsOrLess << endl;
4713   os << indent << "NumberOfRegionsOrMore: " << this->NumberOfRegionsOrMore << endl;
4714 
4715   os << indent << "NumberOfRegions: " << this->NumberOfRegions << endl;
4716 
4717   os << indent << "DataSets: " << this->DataSets << endl;
4718 
4719   os << indent << "Top: " << this->Top << endl;
4720   os << indent << "RegionList: " << this->RegionList << endl;
4721 
4722   os << indent << "Timing: " << this->Timing << endl;
4723   os << indent << "TimerLog: " << this->TimerLog << endl;
4724 
4725   os << indent << "IncludeRegionBoundaryCells: ";
4726         os << this->IncludeRegionBoundaryCells << endl;
4727   os << indent << "GenerateRepresentationUsingDataBounds: ";
4728         os<< this->GenerateRepresentationUsingDataBounds << endl;
4729 
4730   if (this->CellList.nRegions > 0)
4731   {
4732     os << indent << "CellList.dataSet " << this->CellList.dataSet << endl;
4733     os << indent << "CellList.regionIds " << this->CellList.regionIds << endl;
4734     os << indent << "CellList.nRegions " << this->CellList.nRegions << endl;
4735     os << indent << "CellList.cells " << this->CellList.cells << endl;
4736     os << indent << "CellList.boundaryCells " << this->CellList.boundaryCells << endl;
4737   }
4738   os << indent << "CellRegionList: " << this->CellRegionList << endl;
4739 
4740   os << indent << "LocatorPoints: " << this->LocatorPoints << endl;
4741   os << indent << "NumberOfLocatorPoints: " << this->NumberOfLocatorPoints << endl;
4742   os << indent << "LocatorIds: " << this->LocatorIds << endl;
4743   os << indent << "LocatorRegionLocation: " << this->LocatorRegionLocation << endl;
4744 
4745   os << indent << "FudgeFactor: " << this->FudgeFactor << endl;
4746   os << indent << "MaxWidth: " << this->MaxWidth << endl;
4747 
4748   os << indent << "Cuts: ";
4749   if( this->Cuts )
4750   {
4751     this->Cuts->PrintSelf(os << endl, indent.GetNextIndent() );
4752   }
4753   else
4754   {
4755     os << "(none)" << endl;
4756   }
4757   os << indent << "Progress: " << this->Progress << endl;
4758 }
4759