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