1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkIncrementalOctreePointLocator.h
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 // .NAME vtkIncrementalOctreePointLocator - Incremental octree in support
16 //  of both point location and point insertion.
17 //
18 // .SECTION Description
19 //  As opposed to the uniform bin-based search structure (adopted in class
20 //  vtkPointLocator) with a fixed spatial resolution, an octree mechanism
21 //  employs a hierarchy of tree-like sub-division of the 3D data domain. Thus
22 //  it enables data-aware multi-resolution and accordingly accelerated point
23 //  location as well as insertion, particularly when handling a radically
24 //  imbalanced layout of points as not uncommon in datasets defined on
25 //  adaptive meshes. Compared to a static point locator supporting pure
26 //  location functionalities through some search structure established from
27 //  a fixed set of points, an incremental point locator allows for, in addition,
28 //  point insertion capabilities, with the search structure maintaining a
29 //  dynamically increasing number of points.
30 //  Class vtkIncrementalOctreePointLocator is an octree-based accelerated
31 //  implementation of the functionalities of the uniform bin-based incremental
32 //  point locator vtkPointLocator. For point location, an octree is built by
33 //  accessing a vtkDataSet, specifically a vtkPointSet. For point insertion,
34 //  an empty octree is inited and then incrementally populated as points are
35 //  inserted. Three increasingly complex point insertion modes, i.e., direct
36 //  check-free insertion, zero tolerance insertion, and non-zero tolerance
37 //  insertion, are supported. In fact, the octree used in the point location
38 //  mode is actually constructed via direct check-free point insertion. This
39 //  class also provides a polygonal representation of the octree boundary.
40 //
41 // .SECTION See Also
42 //  vtkAbstractPointLocator, vtkIncrementalPointLocator, vtkPointLocator,
43 //  vtkMergePoints
44 
45 #ifndef vtkIncrementalOctreePointLocator_h
46 #define vtkIncrementalOctreePointLocator_h
47 
48 #include "vtkCommonDataModelModule.h" // For export macro
49 #include "vtkIncrementalPointLocator.h"
50 
51 class vtkPoints;
52 class vtkIdList;
53 class vtkPolyData;
54 class vtkCellArray;
55 class vtkIncrementalOctreeNode;
56 
57 class VTKCOMMONDATAMODEL_EXPORT vtkIncrementalOctreePointLocator : public vtkIncrementalPointLocator
58 {
59 public:
60 
61   vtkTypeMacro( vtkIncrementalOctreePointLocator, vtkIncrementalPointLocator );
62   void PrintSelf( ostream & os, vtkIndent indent );
63 
64   static vtkIncrementalOctreePointLocator * New();
65 
66   // Description:
67   // Set/Get the maximum number of points that a leaf node may maintain.
68   // Note that the actual number of points maintained by a leaf node might
69   // exceed this threshold if there is a large number (equal to or greater
70   // than the threshold) of exactly duplicate points (with zero distance)
71   // to be inserted (e.g., to construct an octree for subsequent point
72   // location) in extreme cases. Respecting this threshold in such scenarios
73   // would cause endless node sub-division. Thus this threshold is broken, but
74   // only in case of such situations.
75   vtkSetClampMacro( MaxPointsPerLeaf, int, 16, 256 );
76   vtkGetMacro( MaxPointsPerLeaf, int );
77 
78   // Description:
79   // Set/Get whether the search octree is built as a cubic shape or not.
80   vtkSetMacro( BuildCubicOctree, int );
81   vtkGetMacro( BuildCubicOctree, int );
82   vtkBooleanMacro( BuildCubicOctree, int );
83 
84   // Description:
85   // Get access to the vtkPoints object in which point coordinates are stored
86   // for either point location or point insertion.
87   vtkGetObjectMacro( LocatorPoints, vtkPoints );
88 
89   // Description:
90   // Delete the octree search structure.
Initialize()91   virtual void Initialize() { this->FreeSearchStructure(); }
92 
93   // Description:
94   // Delete the octree search structure.
95   virtual void FreeSearchStructure();
96 
97   // Description:
98   // Get the spatial bounding box of the octree.
99   virtual void GetBounds( double * bounds );
100 
101   // Description:
102   // Get the spatial bounding box of the octree.
GetBounds()103   virtual double * GetBounds()
104     { this->GetBounds( this->Bounds );  return this->Bounds; }
105 
106   // Description:
107   // Get the number of points maintained by the octree.
108   int GetNumberOfPoints();
109 
110   // Description:
111   // Given a point x assumed to be covered by the octree, return the index of
112   // the closest in-octree point regardless of the associated minimum squared
113   // distance relative to the squared insertion-tolerance distance. This method
114   // is used when performing incremental point insertion. Note -1 indicates that
115   // no point is found. InitPointInsertion() should have been called in advance.
116   virtual vtkIdType FindClosestInsertedPoint( const double x[3] );
117 
118   // Description:
119   // Create a polygonal representation of the octree boundary (from the root
120   // node to a specified level).
121   virtual void GenerateRepresentation( int nodeLevel, vtkPolyData * polysData );
122 
123   // -------------------------------------------------------------------------
124   // ---------------------------- Point  Location ----------------------------
125   // -------------------------------------------------------------------------
126 
127   // Description:
128   // Load points from a dataset to construct an octree for point location.
129   // This function resorts to InitPointInsertion() to fulfill some of the work.
130   virtual void BuildLocator();
131 
132   // Description:
133   // Given a point x, return the id of the closest point. BuildLocator() should
134   // have been called prior to this function. This method is thread safe if
135   // BuildLocator() is directly or indirectly called from a single thread first.
136   virtual vtkIdType FindClosestPoint( const double x[3] );
137 
138   // Description:
139   // Given a point (x, y, z), return the id of the closest point. Note that
140   // BuildLocator() should have been called prior to this function. This method
141   // is thread safe if BuildLocator() is directly or indirectly called from a
142   // single thread first.
143   virtual vtkIdType FindClosestPoint( double x, double y, double z );
144 
145   // Description:
146   // Given a point x, return the id of the closest point and the associated
147   // minimum squared distance (via miniDist2). Note BuildLocator() should have
148   // been called prior to this function. This method is thread safe if
149   // BuildLocator() is directly or indirectly called from a single thread first.
150   virtual vtkIdType FindClosestPoint( const double x[3], double * miniDist2 );
151 
152   // Description:
153   // Given a point (x, y, z), return the id of the closest point and the
154   // associated minimum squared distance (via miniDist2). BuildLocator() should
155   // have been called prior to this function. This method is thread safe if
156   // BuildLocator() is directly or indirectly called from a single thread first.
157   virtual vtkIdType FindClosestPoint( double x, double y, double z, double * miniDist2 );
158 
159   // Description:
160   // Given a point x and a radius, return the id of the closest point within
161   // the radius and the associated minimum squared distance (via dist2, this
162   // returned distance is valid only if the point id is not -1). Note that
163   // BuildLocator() should have been called prior to this function. This method
164   // is thread safe if BuildLocator() is directly or indirectly called from a
165   // single thread first.
166   virtual vtkIdType FindClosestPointWithinRadius
167     ( double radius, const double x[3], double & dist2 );
168 
169   // Description:
170   // Given a point x and a squared radius radius2, return the id of the closest
171   // point within the radius and the associated minimum squared distance (via
172   // dist2, note this returned distance is valid only if the point id is not
173   // -1). BuildLocator() should have been called prior to this function.This
174   // method is thread safe if BuildLocator() is directly or indirectly called
175   // from a single thread first.
176   vtkIdType FindClosestPointWithinSquaredRadius
177     ( double radius2, const double x[3], double & dist2 );
178 
179   // Description:
180   // Find all points within a radius R relative to a given point x. The returned
181   // point ids (stored in result) are not sorted in any way. BuildLocator() should
182   // have been called prior to this function. This method is thread safe if
183   // BuildLocator() is directly or indirectly called from a single thread first.
184   virtual void FindPointsWithinRadius
185     ( double R, const double x[3], vtkIdList * result );
186 
187   // Description:
188   // Find all points within a squared radius R2 relative to a given point x. The
189   // returned point ids (stored in result) are not sorted in any way. BuildLocator()
190   // should have been called prior to this function. This method is thread safe if
191   // BuildLocator() is directly or indirectly called from a single thread first.
192   void FindPointsWithinSquaredRadius
193     ( double R2, const double x[3], vtkIdList * result );
194 
195   // Description:
196   // Find the closest N points to a given point. The returned point ids (via
197   // result) are sorted from closest to farthest. BuildLocator() should have
198   // been called prior to this function. This method is thread safe if
199   // BuildLocator() is directly or indirectly called from a single thread first.
200   virtual void FindClosestNPoints
201     ( int N, const double x[3], vtkIdList * result );
202 
203   // -------------------------------------------------------------------------
204   // ---------------------------- Point Insertion ----------------------------
205   // -------------------------------------------------------------------------
206 
207   // Description:
208   // Initialize the point insertion process. points is an object, storing 3D
209   // point coordinates, to which incremental point insertion put coordinates.
210   // It is created and provided by an external VTK class. Argument bounds
211   // represents the spatial bounding box, into which the points fall. In fact,
212   // an adjusted version of the bounding box is used to build the octree to
213   // make sure no any point (to be inserted) falls outside the octree. This
214   // function is not thread safe.
215   virtual int InitPointInsertion( vtkPoints * points, const double bounds[6] );
216 
217   // Description:
218   // Initialize the point insertion process. points is an object, storing 3D
219   // point coordinates, to which incremental point insertion put coordinates.
220   // It is created and provided by an external VTK class. Argument bounds
221   // represents the spatial bounding box, into which the points fall. In fact,
222   // an adjusted version of the bounding box is used to build the octree to
223   // make sure no any point (to be inserted) falls outside the octree. Argument
224   // estSize specifies the initial estimated size of the vtkPoints object. This
225   // function is not thread safe.
226   virtual int InitPointInsertion( vtkPoints * points, const double bounds[6],
227                                   vtkIdType estSize );
228 
229   // Description:
230   // Determine whether or not a given point has been inserted into the octree.
231   // Return the id of the already inserted point if true, otherwise return -1.
232   // InitPointInsertion() should have been called in advance.
233   virtual vtkIdType IsInsertedPoint( const double x[3] );
234 
235   // Description:
236   // Determine whether or not a given point has been inserted into the octree.
237   // Return the id of the already inserted point if true, otherwise return -1.
238   // InitPointInsertion() should have been called in advance.
239   virtual vtkIdType IsInsertedPoint( double x, double  y, double z );
240 
241   // Description:
242   // Insert a point to the octree unless there has been a duplciate point.
243   // Whether the point is actually inserted (return 1) or not (return 0 upon a
244   // rejection by an existing duplicate), the index of the point (either new
245   // or the duplicate) is returned via pntId. Note that InitPointInsertion()
246   // should have been called prior to this function. vtkPoints::InsertNextPoint()
247   // is invoked. This method is not thread safe.
248   virtual int InsertUniquePoint( const double point[3], vtkIdType & pntId );
249 
250   // Description:
251   // Insert a given point into the octree with a specified point index ptId.
252   // InitPointInsertion() should have been called prior to this function. In
253   // addition, IsInsertedPoint() should have been called in advance to ensure
254   // that the given point has not been inserted unless point duplication is
255   // allowed (Note that in this case, this function involves a repeated leaf
256   // container location). vtkPoints::InsertPoint() is invoked.
257   virtual void InsertPoint( vtkIdType ptId, const double x[3] );
258 
259   // Description:
260   // Insert a given point into the octree and return the point index. Note that
261   // InitPointInsertion() should have been called prior to this function. In
262   // addition, IsInsertedPoint() should have been called in advance to ensure
263   // that the given point has not been inserted unless point duplication is
264   // allowed (in this case, this function invovles a repeated leaf container
265   // location). vtkPoints::InsertNextPoint() is invoked.
266   virtual vtkIdType InsertNextPoint( const double x[3] );
267 
268   // Description:
269   // "Insert" a point to the octree without any checking. Argument insert means
270   // whether vtkPoints::InsertNextPoint() upon 1 is called or the point itself
271   // is not inserted to the vtkPoints at all but instead only the point index is
272   // inserted to a vtkIdList upon 0. For case 0, the point index needs to be
273   // specified via pntId. For case 1, the actual point index is returned via
274   // pntId. InitPointInsertion() should have been called.
275   void InsertPointWithoutChecking
276     ( const double point[3], vtkIdType  & pntId, int insert );
277 
278 //BTX
279 protected:
280 
281   vtkIncrementalOctreePointLocator();
282   virtual ~vtkIncrementalOctreePointLocator();
283 
284 private:
285 
286   int         BuildCubicOctree;
287   int         MaxPointsPerLeaf;
288   double      InsertTolerance2;
289   double      OctreeMaxDimSize;
290   double      FudgeFactor;
291   vtkPoints * LocatorPoints;
292   vtkIncrementalOctreeNode * OctreeRootNode;
293 
294   // Description:
295   // Delete all descendants of a node.
296   static void DeleteAllDescendants( vtkIncrementalOctreeNode * node );
297 
298   // Description:
299   // Add the polygonal representation of a given node to the allocated vtkPoints
300   // and vtkCellArray objects.
301   static void AddPolys( vtkIncrementalOctreeNode * node,
302                         vtkPoints * points, vtkCellArray * polygs );
303 
304   // Description:
305   // Given a point and a reference node, find the leaf containing the point.
306   // Note the point is assumed to be inside or under the reference node.
307   vtkIncrementalOctreeNode * GetLeafContainer( vtkIncrementalOctreeNode * node,
308     const double pnt[3] );
309 
310   // Description:
311   // Given a point (under check, either inside or outside the octree) and a leaf
312   // node (not necessarily the container of this point), find the closest point
313   // (possibly a duplicate of the point under check) within the node and return
314   // the point index as well as the associated minimum squared distance (via dist2).
315   // InitPointInsertion() or BuildLocator() should have been called.
316   vtkIdType FindClosestPointInLeafNode( vtkIncrementalOctreeNode * leafNode,
317                                         const double point[3], double * dist2 );
318 
319   // Description:
320   // This function may not be directly called. Please use the follwing two ones:
321   // FindClosestPointInSphereWithTolerance() for point insertion and
322   // FindClosestPointInSphereWithoutTolerance() for point location. Arguments
323   // refDist2 and the initialization of minDist2 determine which version is used.
324   // Given a point (under check) and an already-checked node (possibly NULL),
325   // find the closest point across a set of neighboring nodes within a specified
326   // squared radius to the given point --- to perform an extended within-radius
327   // inter-node search. The leaf (mask) node itself is excluded from the search
328   // scope. Returned are the point index and the associated minimum squared
329   // distance. InitPointInsertion() or BuildLocator() should have been called.
330   vtkIdType FindClosestPointInSphere
331     ( const double point[3], double radius2, vtkIncrementalOctreeNode * maskNode,
332       double * minDist2, const double * refDist2 );
333 
334 
335   // -------------------------------------------------------------------------
336   // ---------------------------- Point  Location ----------------------------
337   // -------------------------------------------------------------------------
338 
339   // Description:
340   // This function is intended for point location, excluding point insertion.
341   // Given a point (under check, covered or uncovered by the octree) and an
342   // already-checked leaf node (maskNode, possibly NULL), find the closest point
343   // across a set of neighboring nodes within a specified squared radius to the
344   // given point --- to perform an extended within-radius inter-node search. The
345   // leaf (mask) node itself is excluded from the search scope. Returned are the
346   // point index and the associated minimum squared distance (via minDist2). Note
347   // that BuildLocator() should have been called.
348   vtkIdType FindClosestPointInSphereWithoutTolerance( const double point[3],
349     double radius2, vtkIncrementalOctreeNode * maskNode, double * minDist2 );
350 
351   // Description:
352   // Find all points, inside a given node, within a squared radius relative to
353   // a given point. Returned are the associated un-sorted point indices (idList).
354   // Note that BuildLocator() should have been called prior to this function.
355   void FindPointsWithinSquaredRadius( vtkIncrementalOctreeNode * node,
356     double radius2, const double point[3], vtkIdList * idList );
357 
358   // -------------------------------------------------------------------------
359   // ---------------------------- Point Insertion ----------------------------
360   // -------------------------------------------------------------------------
361 
362   // Description:
363   // This function is intended for point insertion, excluding point location.
364   // Given a point (under check for insertion, must be covered by the octree)
365   // and an already-checked node (maskNode, the container leaf node, possibly
366   // NULL if no any node has been checked), find the closest point across a set
367   // of neighbor nodes within a specified squared radius radius2 to the given
368   // point --- to perform an extended within-radius inter-node search. The leaf
369   // (mask) node itself is excluded from the search scope. Returned are the point
370   // index and the associated minimum squared distance (via minDist2). Note that
371   // InitPointInsertion() should have been called.
372   vtkIdType FindClosestPointInSphereWithTolerance( const double point[3],
373     double radius2, vtkIncrementalOctreeNode * maskNode, double * minDist2 );
374 
375   // Description:
376   // Determine whether or not a given point has been inserted into the octree.
377   // Return the id of the already inserted point if true, otherwise return -1.
378   // Argument leafContainer is useful for access only if -1 is returned. This
379   // returned parameter indicates the leaf node that contains the given point.
380   // This function resorts to IsInsertedPointForZeroTolerance() for zero
381   // tolerance insertion or IsInsertedPointForNonZeroTolerance() for non-zero
382   // tolerance insertion. InitPointInsertion() should have been called.
383   vtkIdType IsInsertedPoint( const double x[3],
384                              vtkIncrementalOctreeNode ** leafContainer );
385 
386   // Description:
387   // Determine whether or not a given point has been inserted into the octree.
388   // Return the id of the already inserted point if true, otherwise return -1.
389   // Argument leafContainer is useful for access only if -1 is returned. This
390   // returned parameter indicates the leaf node that contains the given point.
391   // This variant is invoked by IsInsertedPoint(x, vtkIncrementalOctreeNode **)
392   // for zero tolerance insertion. InitPointInsertion() should have been called.
393   vtkIdType IsInsertedPointForZeroTolerance
394     ( const double x[3], vtkIncrementalOctreeNode ** leafContainer );
395 
396   // Description:
397   // Determine whether or not a given point has been inserted into the octree.
398   // Return the id of the already inserted point if true, otherwise return -1.
399   // Argument leafContainer is useful for access only if -1 is returned. This
400   // returned parameter indicates the leaf node that contains the given point.
401   // This variant is invoked by IsInsertedPoint(x, vtkIncrementalOctreeNode **)
402   // for non-zero tolerance insertion. InitPointInsertion() should have been
403   // called in advance.
404   vtkIdType IsInsertedPointForNonZeroTolerance
405     ( const double x[3], vtkIncrementalOctreeNode ** leafContainer );
406 
407   // Description:
408   // Given a point (under check for zero tolerance insertion) and a leaf node,
409   // find its duplicate, if any, in the node and return the point index (-1 if
410   // no duplicate is found). Note that the leaf node, already with at least one
411   // point, is the container of the point under check. InitPointInsertion()
412   // should have been called.
413   vtkIdType FindDuplicatePointInLeafNode( vtkIncrementalOctreeNode * leafNode,
414                                           const double point[3] );
415 
416   // Description:
417   // Given a point (under check for zero tolerance insertion) and a leaf node,
418   // find its duplicate, if any, in the node and return the point index (-1 if
419   // no duplicate is found). Note that the leaf node, already with at least one
420   // point, is the container of the point under check. This function is invoked
421   // for type VTK_FLOAT. InitPointInsertion() should have been called.
422   vtkIdType FindDuplicateFloatTypePointInVisitedLeafNode
423     ( vtkIncrementalOctreeNode * leafNode, const double point[3] );
424 
425   // Description:
426   // Given a point (under check for zero tolerance insertion) and a leaf node,
427   // find its duplicate, if any, in the node and return the point index (-1 if
428   // no duplicate is found). Note that the leaf node, already with at least one
429   // point, is the container of the point under check. This function is invoked
430   // for type VTK_DOUBLE. InitPointInsertion() should have been called.
431   vtkIdType FindDuplicateDoubleTypePointInVisitedLeafNode
432     ( vtkIncrementalOctreeNode * leafNode, const double point[3] );
433 
434   vtkIncrementalOctreePointLocator
435     ( const vtkIncrementalOctreePointLocator & ); // Not implemented
436   void operator = ( const vtkIncrementalOctreePointLocator & );// Not implemented
437 //ETX
438 };
439 #endif
440