1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkIncrementalOctreeNode.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 /**
16  * @class   vtkIncrementalOctreeNode
17  * @brief   Octree node constituting incremental
18  *  octree (in support of both point location and point insertion)
19  *
20  *
21  *  Octree nodes serve as spatial sub-division primitives to build the search
22  *  structure of an incremental octree in a recursive top-down manner. The
23  *  hierarchy takes the form of a tree-like representation by which a parent
24  *  node contains eight mutually non-overlapping child nodes. Each child is
25  *  assigned with an axis-aligned rectangular volume (Spatial Bounding Box)
26  *  and the eight children together cover exactly the same region as governed
27  *  by their parent. The eight child nodes / octants are ordered as
28  *
29  *  { (xBBoxMin, xBBoxMid] & (yBBoxMin, yBBoxMid] & (zBBoxMin, zBBoxMid] },
30  *  { (xBBoxMid, xBBoxMax] & (yBBoxMin, yBBoxMid] & (zBBoxMin, zBBoxMid] },
31  *  { (xBBoxMin, xBBoxMid] & (yBBoxMid, yBBoxMax] & (zBBoxMin, zBBoxMid] },
32  *  { (xBBoxMid, xBBoxMax] & (yBBoxMid, yBBoxMax] & (zBBoxMin, zBBoxMid] },
33  *  { (xBBoxMin, xBBoxMid] & (yBBoxMin, yBBoxMid] & (zBBoxMid, zBBoxMax] },
34  *  { (xBBoxMid, xBBoxMax] & (yBBoxMin, yBBoxMid] & (zBBoxMid, zBBoxMax] },
35  *  { (xBBoxMin, xBBoxMid] & (yBBoxMid, yBBoxMax] & (zBBoxMid, zBBoxMax] },
36  *  { (xBBoxMid, xBBoxMax] & (yBBoxMid, yBBoxMax] & (zBBoxMid, zBBoxMax] },
37  *
38  *  where { xrange & yRange & zRange } defines the region of each 3D octant.
39  *  In addition, the points falling within and registered, by means of point
40  *  indices, in the parent node are distributed to the child nodes for delegated
41  *  maintenance. In fact, only leaf nodes, i.e., those without any descendants,
42  *  actually store point indices while each node, regardless of a leaf or non-
43  *  leaf node, keeps a dynamically updated Data Bounding Box of the inhabitant
44  *  points, if any. Given a maximum number of points per leaf node, an octree
45  *  is initialized with an empty leaf node that is then recursively sub-divided,
46  *  but only on demand as points are incrementally inserted, to construct a
47  *  populated tree.
48  *
49  *  Please note that this octree node class is able to handle a large number
50  *  of EXACTLY duplicate points that is greater than the specified maximum
51  *  number of points per leaf node. In other words, as an exception, a leaf
52  *  node may maintain an arbitrary number of exactly duplicate points to deal
53  *  with possible extreme cases.
54  *
55  * @sa
56  *  vtkIncrementalOctreePointLocator
57  */
58 
59 #ifndef vtkIncrementalOctreeNode_h
60 #define vtkIncrementalOctreeNode_h
61 
62 #include "vtkCommonDataModelModule.h" // For export macro
63 #include "vtkDeprecation.h"           // For VTK_DEPRECATED_IN_9_1_0
64 #include "vtkObject.h"
65 
66 class vtkPoints;
67 class vtkIdList;
68 
69 class VTKCOMMONDATAMODEL_EXPORT vtkIncrementalOctreeNode : public vtkObject
70 {
71 public:
72   vtkTypeMacro(vtkIncrementalOctreeNode, vtkObject);
73   void PrintSelf(ostream& os, vtkIndent indent) override;
74 
75   static vtkIncrementalOctreeNode* New();
76 
77   ///@{
78   /**
79    * Get the number of points inside or under this node.
80    */
81   vtkGetMacro(NumberOfPoints, int);
82   ///@}
83 
84   ///@{
85   /**
86    * Get the list of point indices, nullptr for a non-leaf node.
87    */
88   vtkGetObjectMacro(PointIdSet, vtkIdList);
89   ///@}
90 
91   /**
92    * Delete the eight child nodes.
93    */
94   void DeleteChildNodes();
95 
96   /**
97    * Set the spatial bounding box of the node. This function sets a default
98    * data bounding box.
99    */
100   void SetBounds(double x1, double x2, double y1, double y2, double z1, double z2);
101 
102   /**
103    * Get the spatial bounding box of the node. The values are returned via
104    * an array in order of: x_min, x_max, y_min, y_max, z_min, z_max.
105    */
106   void GetBounds(double bounds[6]) const;
107 
108   ///@{
109   /**
110    * Get access to MinBounds. Do not free this pointer.
111    */
112   vtkGetVector3Macro(MinBounds, double);
113   ///@}
114 
115   ///@{
116   /**
117    * Get access to MaxBounds. Do not free this pointer.
118    */
119   vtkGetVector3Macro(MaxBounds, double);
120   ///@}
121 
122   /**
123    * Get access to MinDataBounds. Note that MinDataBounds is not valid until
124    * point insertion.
125    */
GetMinDataBounds()126   double* GetMinDataBounds()
127   {
128     return this->NumberOfPoints ? this->MinDataBounds : this->MinBounds;
129   }
130 
131   /**
132    * Get access to MaxDataBounds. Note that MaxDataBounds is not valid until
133    * point insertion.
134    */
GetMaxDataBounds()135   double* GetMaxDataBounds()
136   {
137     return this->NumberOfPoints ? this->MaxDataBounds : this->MaxBounds;
138   }
139 
140   /**
141    * Determine whether or not this node is a leaf.
142    */
IsLeaf()143   int IsLeaf() { return (this->Children == nullptr) ? 1 : 0; }
144 
145   /**
146    * Determine which specific child / octant contains a given point. Note that
147    * the point is assumed to be inside this node and no checking is performed
148    * on the inside issue.
149    */
150   int GetChildIndex(const double point[3]);
151 
152   /**
153    * Get quick access to a child of this node. Note that this node is assumed
154    * to be a non-leaf one and no checking is performed on the node type.
155    */
GetChild(int i)156   vtkIncrementalOctreeNode* GetChild(int i) { return this->Children[i]; }
157 
158   /**
159    * A point is in a node if and only if MinBounds[i] < p[i] <= MaxBounds[i],
160    * which allows a node to be divided into eight non-overlapping children.
161    */
162   vtkTypeBool ContainsPoint(const double pnt[3]);
163 
164   /**
165    * A point is in a node, in terms of data, if and only if MinDataBounds[i]
166    * <= p[i] <= MaxDataBounds[i].
167    */
168   vtkTypeBool ContainsPointByData(const double pnt[3]);
169 
170   //@{
171   /**
172    * This function is called after a successful point-insertion check and
173    * only applies to a leaf node. Prior to a call to this function, the
174    * octree should have been retrieved top-down to find the specific leaf
175    * node in which this new point (newPt) will be inserted. The actual index
176    * of the new point (to be inserted to points) is stored in pntId. Argument
177    * ptMode specifies whether the point is not inserted at all but instead only
178    * the point index is provided upon 0, the point is inserted via vtkPoints::
179    * InsertPoint() upon 1, or it is inserted via vtkPoints::InsertNextPoint()
180    * upon 2. For case 0, pntId needs to be specified. For cases 1 and 2, the
181    * actual point index is returned via pntId. Note that this function always
182    * returns 1 to indicate the success of point insertion.
183    * numberOfNodes is the number of nodes present in the tree at this time.
184    * it is used to assign an ID to each node which can be used to associate
185    * application specifc information with each node. It is updated if new nodes
186    * are added to the tree.
187    */
188   VTK_DEPRECATED_IN_9_1_0("Use the version with numberOfNodes parameter instead.")
189   int InsertPoint(
190     vtkPoints* points, const double newPnt[3], int maxPts, vtkIdType* pntId, int ptMode);
191   int InsertPoint(vtkPoints* points, const double newPnt[3], int maxPts, vtkIdType* pntId,
192     int ptMode, int& numberOfNodes);
193   //@}
194 
195   /**
196    * Given a point inside this node, get the minimum squared distance to all
197    * inner boundaries. An inner boundary is a node's face that is shared by
198    * another non-root node.
199    */
200   double GetDistance2ToInnerBoundary(const double point[3], vtkIncrementalOctreeNode* rootNode);
201 
202   /**
203    * Compute the minimum squared distance from a point to this node, with all
204    * six boundaries considered. The data bounding box is checked if checkData
205    * is non-zero.
206    */
207   double GetDistance2ToBoundary(
208     const double point[3], vtkIncrementalOctreeNode* rootNode, int checkData);
209 
210   /**
211    * Compute the minimum squared distance from a point to this node, with all
212    * six boundaries considered. The data bounding box is checked if checkData
213    * is non-zero. The closest on-boundary point is returned via closest.
214    */
215   double GetDistance2ToBoundary(
216     const double point[3], double closest[3], vtkIncrementalOctreeNode* rootNode, int checkData);
217 
218   /**
219    * Export all the indices of the points (contained in or under this node) by
220    * inserting them to an allocated vtkIdList via vtkIdList::InsertNextId().
221    */
222   void ExportAllPointIdsByInsertion(vtkIdList* idList);
223 
224   /**
225    * Export all the indices of the points (contained in or under this node) by
226    * directly setting them in an allocated vtkIdList object. pntIdx indicates
227    * the starting location (in terms of vtkIdList) from which new point indices
228    * are added to vtkIdList by vtkIdList::SetId().
229    */
230   void ExportAllPointIdsByDirectSet(vtkIdType* pntIdx, vtkIdList* idList);
231   //@}
232   /**
233    * Computes and returns the maximum level of the tree. If a tree has
234    * one node it returns 1 else it returns the maximum level of its
235    * children plus 1.
236    */
237   int GetNumberOfLevels() const;
238   /**
239    * Returns the ID of this node which is the index of the node in the
240    * octree. The index of the node enables users of this class to
241    * associate additional information with each node.
242    */
GetID()243   int GetID() const { return this->ID; }
GetPointIds()244   vtkIdList* GetPointIds() const { return this->PointIdSet; }
245 
246 protected:
247   vtkIncrementalOctreeNode();
248   ~vtkIncrementalOctreeNode() override;
249 
250 private:
251   /**
252    * Number of points inside or under this node.
253    */
254   int NumberOfPoints;
255 
256   /**
257    * The minimum coordinate of this node's spatial bounding box.
258    */
259   double MinBounds[3];
260 
261   /**
262    * The maximum coordinate of this node's spatial bounding box.
263    */
264   double MaxBounds[3];
265 
266   /**
267    * The minimum coordinate of the data bounding box that encompasses the
268    * points inserted, by means of the point index, to this node. Note this
269    * information is invalid if no any point has been inserted to this node.
270    */
271   double MinDataBounds[3];
272 
273   /**
274    * The maximum coordinate of the data bounding box that encompasses the
275    * points inserted, by means of the point index, to this node. Note this
276    * information is invalid if no any point has been inserted to this node.
277    */
278   double MaxDataBounds[3];
279 
280   /**
281    * The list of indices of the points maintained by this LEAF node. It is
282    * nullptr if this is a non-leaf node.
283    */
284   vtkIdList* PointIdSet;
285 
286   /**
287    * Index of the node.
288    * Nodes are assigned an index from 0 to number of nodes - 1. Root node
289    * has index 0.
290    */
291   int ID;
292 
293   /**
294    * The parent of this node, nullptr for the root node of an octree.
295    */
296   vtkIncrementalOctreeNode* Parent;
297 
298   /**
299    * A pointer to the eight children of this node.
300    */
301   vtkIncrementalOctreeNode** Children;
302 
303   /**
304    * Set the parent of this node, nullptr for the root node of an octree.
305    */
306   virtual void SetParent(vtkIncrementalOctreeNode*);
307 
308   /**
309    * Set the list of point indices, nullptr for a non-leaf node.
310    */
311   virtual void SetPointIdSet(vtkIdList*);
312 
313   /**
314    * Divide this LEAF node into eight child nodes as the number of points
315    * maintained by this leaf node has reached the threshold maxPts while
316    * another point newPnt is just going to be inserted to it. The available
317    * point-indices pntIds are distributed to the child nodes based on the
318    * point coordinates (available through points). Note that this function
319    * can incur recursive node-division to determine the specific leaf node
320    * for accepting the new point (with pntIdx storing the index in points)
321    * because the existing maxPts points may fall within only one of the eight
322    * child nodes to make a radically imbalanced layout within the node (to
323    * be divided). Argument ptMode specifies whether the point is not inserted
324    * at all but instead only the point index is provided upon 0, the point is
325    * inserted via vtkPoints::InsertPoint() upon 1, or the point is inserted by
326    * vtkPoints::InsertNextPoint() upon 2. The returned value of this function
327    * indicates whether pntIds needs to be destroyed (1) or just unregistered
328    * from this node as it has been attached to another node (0).
329    * numberOfNodes in the tree is updated with new created nodes
330    */
331   int CreateChildNodes(vtkPoints* points, vtkIdList* pntIds, const double newPnt[3],
332     vtkIdType* pntIdx, int maxPts, int ptMode, int& numberOfNodes);
333 
334   /**
335    * Create a vtkIdList object for storing point indices. Two arguments
336    * specifies the initial and growing sizes, respectively, of the object.
337    */
338   void CreatePointIdSet(int initSize, int growSize);
339 
340   /**
341    * Delete the list of point indices.
342    */
343   void DeletePointIdSet();
344 
345   /**
346    * Given a point inserted to either this node (a leaf node) or a descendant
347    * leaf (of this node --- when this node is a non-leaf node), update the
348    * counter and the data bounding box for this node only.
349    */
350   void UpdateCounterAndDataBounds(const double point[3]);
351 
352   /**
353    * Given a point inserted to either this node (a leaf node) or a descendant
354    * leaf (of this node --- when this node is a non-leaf node), update the
355    * counter and the data bounding box for this node only. The data bounding box
356    * is considered only if updateData is non-zero. The returned value indicates
357    * whether (1) or not (0) the data bounding box is actually updated. Note that
358    * argument nHits must be 1 unless this node is updated with a number (nHits)
359    * of exactly duplicate points as a whole via a single call to this function.
360    */
361   int UpdateCounterAndDataBounds(const double point[3], int nHits, int updateData);
362 
363   /**
364    * Given a point inserted to either this node (a leaf node) or a descendant
365    * leaf (of this node --- when this node is a non-leaf node), update the
366    * counter and the data bounding box recursively bottom-up until a specified
367    * node. The data bounding box is considered only if updateData is non-zero.
368    * The returned value indicates whether (1) or not (0) the data bounding box
369    * is actually updated. Note that argument nHits must be 1 unless this node
370    * is updated with a number (nHits) of exactly duplicate points as a whole
371    * via a single call to this function.
372    */
373   int UpdateCounterAndDataBoundsRecursively(
374     const double point[3], int nHits, int updateData, vtkIncrementalOctreeNode* endNode);
375 
376   /**
377    * Given a point, determine whether (1) or not (0) it is an exact duplicate
378    * of all the points, if any, maintained in this node. In other words, to
379    * check if this given point and all existing points, if any, of this node
380    * are exactly duplicate with one another.
381    */
382   int ContainsDuplicatePointsOnly(const double pnt[3]);
383 
384   /**
385    * Given a number (>= threshold) of all exactly duplicate points (accessible
386    * via points and pntIds, but with exactly the same 3D coordinate) maintained
387    * in this leaf node and a point (absolutely not a duplicate any more, with
388    * pntIdx storing the index in points)) to be inserted to this node, separate
389    * all the duplicate points from this new point by means of usually recursive
390    * node sub-division such that the former points are inserted to a descendant
391    * leaf while the new point is inserted to a sibling of this descendant leaf.
392    * Argument ptMode specifies whether the point is not inserted at all but only
393    * the point index is provided upon 0, the point is inserted via vtkPoints::
394    * InsertPoint() upon 1, or this point is instead inserted through vtkPoints::
395    * InsertNextPoint() upon 2.
396    */
397   void SeperateExactlyDuplicatePointsFromNewInsertion(vtkPoints* points, vtkIdList* pntIds,
398     const double newPnt[3], vtkIdType* pntIdx, int maxPts, int ptMode);
399 
400   /**
401    * Given a point, obtain the minimum squared distance to the closest point
402    * on a boundary of this node. As two options, the outer boundaries may be
403    * excluded (by comparing them against those of the root node) from
404    * consideration and the data bounding box may be checked in place of the
405    * spatial bounding box.
406    */
407   double GetDistance2ToBoundary(const double point[3], double closest[3], int innerOnly,
408     vtkIncrementalOctreeNode* rootNode, int checkData = 0);
409 
410   vtkIncrementalOctreeNode(const vtkIncrementalOctreeNode&) = delete;
411   void operator=(const vtkIncrementalOctreeNode&) = delete;
412 };
413 
414 // In-lined for performance
GetChildIndex(const double point[3])415 inline int vtkIncrementalOctreeNode::GetChildIndex(const double point[3])
416 {
417   // Children[0]->MaxBounds[] is exactly the center point of this node.
418   return int(point[0] > this->Children[0]->MaxBounds[0]) +
419     ((int(point[1] > this->Children[0]->MaxBounds[1])) << 1) +
420     ((int(point[2] > this->Children[0]->MaxBounds[2])) << 2);
421 }
422 
423 // In-lined for performance
ContainsPoint(const double pnt[3])424 inline vtkTypeBool vtkIncrementalOctreeNode::ContainsPoint(const double pnt[3])
425 {
426   return (
427     (this->MinBounds[0] < pnt[0] && pnt[0] <= this->MaxBounds[0] && this->MinBounds[1] < pnt[1] &&
428       pnt[1] <= this->MaxBounds[1] && this->MinBounds[2] < pnt[2] && pnt[2] <= this->MaxBounds[2])
429       ? 1
430       : 0);
431 }
432 
433 // In-lined for performance
ContainsPointByData(const double pnt[3])434 inline vtkTypeBool vtkIncrementalOctreeNode::ContainsPointByData(const double pnt[3])
435 {
436   return ((this->MinDataBounds[0] <= pnt[0] && pnt[0] <= this->MaxDataBounds[0] &&
437             this->MinDataBounds[1] <= pnt[1] && pnt[1] <= this->MaxDataBounds[1] &&
438             this->MinDataBounds[2] <= pnt[2] && pnt[2] <= this->MaxDataBounds[2])
439       ? 1
440       : 0);
441 }
442 
443 // In-lined for performance
ContainsDuplicatePointsOnly(const double pnt[3])444 inline int vtkIncrementalOctreeNode::ContainsDuplicatePointsOnly(const double pnt[3])
445 {
446   return ((this->MinDataBounds[0] == pnt[0] && pnt[0] == this->MaxDataBounds[0] &&
447             this->MinDataBounds[1] == pnt[1] && pnt[1] == this->MaxDataBounds[1] &&
448             this->MinDataBounds[2] == pnt[2] && pnt[2] == this->MaxDataBounds[2])
449       ? 1
450       : 0);
451 }
452 
453 // In-lined for performance
UpdateCounterAndDataBounds(const double point[3])454 inline void vtkIncrementalOctreeNode::UpdateCounterAndDataBounds(const double point[3])
455 {
456   this->NumberOfPoints++;
457 
458   this->MinDataBounds[0] = (point[0] < this->MinDataBounds[0]) ? point[0] : this->MinDataBounds[0];
459   this->MinDataBounds[1] = (point[1] < this->MinDataBounds[1]) ? point[1] : this->MinDataBounds[1];
460   this->MinDataBounds[2] = (point[2] < this->MinDataBounds[2]) ? point[2] : this->MinDataBounds[2];
461   this->MaxDataBounds[0] = (point[0] > this->MaxDataBounds[0]) ? point[0] : this->MaxDataBounds[0];
462   this->MaxDataBounds[1] = (point[1] > this->MaxDataBounds[1]) ? point[1] : this->MaxDataBounds[1];
463   this->MaxDataBounds[2] = (point[2] > this->MaxDataBounds[2]) ? point[2] : this->MaxDataBounds[2];
464 }
465 
466 // In-lined for performance
UpdateCounterAndDataBoundsRecursively(const double point[3],int nHits,int updateData,vtkIncrementalOctreeNode * endNode)467 inline int vtkIncrementalOctreeNode::UpdateCounterAndDataBoundsRecursively(
468   const double point[3], int nHits, int updateData, vtkIncrementalOctreeNode* endNode)
469 {
470   int updated = this->UpdateCounterAndDataBounds(point, nHits, updateData);
471 
472   return ((this->Parent == endNode)
473       ? updated
474       : this->Parent->UpdateCounterAndDataBoundsRecursively(point, nHits, updated, endNode));
475 }
476 #endif
477