dynamicIndexedOctree.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Class
25  Foam::dynamicIndexedOctree
26 
27 Description
28  Non-pointer based hierarchical recursive searching.
29  Storage is dynamic, so elements can be deleted.
30 
31 SourceFiles
32  dynamicIndexedOctree.C
33 
34 \*---------------------------------------------------------------------------*/
35 
36 #ifndef dynamicIndexedOctree_H
37 #define dynamicIndexedOctree_H
38 
39 #include "treeBoundBox.H"
40 #include "pointIndexHit.H"
41 #include "FixedList.H"
42 #include "Ostream.H"
43 #include "HashSet.H"
44 #include "labelBits.H"
45 #include "PackedList.H"
46 #include "volumeType.H"
47 
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 
50 namespace Foam
51 {
52 
54 
55 // Forward declaration of classes
56 template<class Type> class dynamicIndexedOctree;
57 
58 template<class Type> Ostream& operator<<
59 (
60  Ostream&,
62 );
63 
64 class Istream;
65 
66 
67 /*---------------------------------------------------------------------------*\
68  Class dynamicIndexedOctreeName Declaration
69 \*---------------------------------------------------------------------------*/
70 
72 
73 
74 /*---------------------------------------------------------------------------*\
75  Class dynamicIndexedOctree Declaration
76 \*---------------------------------------------------------------------------*/
77 
78 template<class Type>
80 :
81  public dynamicIndexedOctreeName
82 {
83 public:
84 
85  // Data types
86 
87  //- Tree node. Has up pointer and down pointers.
88  class node
89  {
90  public:
91 
92  //- Bounding box of this node
94 
95  //- Parent node (index into nodes_ of tree)
96  label parent_;
97 
98  //- IDs of the 8 nodes on all sides of the mid point
100 
101  friend Ostream& operator<< (Ostream& os, const node& n)
102  {
103  return os << n.bb_ << token::SPACE
104  << n.parent_ << token::SPACE << n.subNodes_;
105  }
106 
107  friend Istream& operator>> (Istream& is, node& n)
108  {
109  return is >> n.bb_ >> n.parent_ >> n.subNodes_;
110  }
111 
112  friend bool operator==(const node& a, const node& b)
113  {
114  return
115  a.bb_ == b.bb_
116  && a.parent_ == b.parent_
117  && a.subNodes_ == b.subNodes_;
118  }
119 
120  friend bool operator!=(const node& a, const node& b)
121  {
122  return !(a == b);
123  }
124  };
125 
126 
127 private:
128 
129  // Static data
130 
131  //- Relative perturbation tolerance. Determines when point is
132  // considered to be close to face/edge of bb of node.
133  // The tolerance is relative to the bounding box of the smallest
134  // node.
135  static scalar perturbTol_;
136 
137 
138  // Private Data
139 
140  //- Underlying shapes for geometric queries.
141  const Type shapes_;
142 
143  const treeBoundBox bb_;
144 
145  const label maxLevels_;
146 
147  //- Current number of levels in the tree.
148  label nLevelsMax_;
149 
150  const scalar maxLeafRatio_;
151 
152  const label minSize_;
153 
154  const scalar maxDuplicity_;
155 
156  //- List of all nodes
157  DynamicList<node> nodes_;
158 
159  //- List of all contents (referenced by those nodes that are contents)
160  contentListList contents_;
161 
162  //- Per node per octant whether is fully inside/outside/mixed.
163  mutable PackedList<2> nodeTypes_;
164 
165 
166  // Private Member Functions
167 
168  //- Helper: does bb intersect a sphere around sample? Or is any
169  // corner point of bb closer than nearestDistSqr to sample.
170  // (bb is implicitly provided as parent bb + octant)
171  static bool overlaps
172  (
173  const treeBoundBox& parentBb,
174  const direction octant,
175  const scalar nearestDistSqr,
176  const point& sample
177  );
178 
179 
180  // Construction
181 
182  //- Split list of indices into 8 bins
183  // according to where they are in relation to mid.
184  void divide
185  (
186  const autoPtr<DynamicList<label>>& indices,
187  const treeBoundBox& bb,
188  contentListList& result
189  ) const;
190 
191  //- Subdivide the contents node at position contentI.
192  // Appends to contents.
193  node divide
194  (
195  const treeBoundBox& bb,
196  const label contentI,
197  const label parentNodeIndex,
198  const label octantToBeDivided
199  );
200 
201  // Recursively call the divide function
202  void recursiveSubDivision
203  (
204  const treeBoundBox& subBb,
205  const label contentI,
206  const label parentIndex,
207  const label octant,
208  label& nLevels
209  );
210 
211  //- Determine inside/outside per node (mixed if cannot be
212  // determined). Only valid for closed shapes.
213  volumeType calcVolumeType(const label nodeI) const;
214 
215  //- Search cached volume type.
216  volumeType getVolumeType(const label nodeI, const point&) const;
217 
218 
219  // Query
220 
221  //- Find nearest point to line.
222  void findNearest
223  (
224  const label nodeI,
225  const linePointRef& ln,
226 
227  treeBoundBox& tightest,
228  label& nearestShapeI,
229  point& linePoint,
230  point& nearestPoint
231  ) const;
232 
233  //- Return bbox of octant
234  treeBoundBox subBbox
235  (
236  const label parentNodeI,
237  const direction octant
238  ) const;
239 
240  //- Helper: take a point on/close to face of bb and push it
241  // inside or outside of bb.
242  static point pushPoint
243  (
244  const treeBoundBox&,
245  const point&,
246  const bool pushInside
247  );
248 
249  //- Helper: take a point on face of bb and push it
250  // inside or outside of bb.
251  static point pushPoint
252  (
253  const treeBoundBox&,
254  const direction,
255  const point&,
256  const bool pushInside
257  );
258 
259  //- Helper: take point on face(s) of bb and push it away from
260  // edges of face. If pt is not on a face does nothing.
261  static point pushPointIntoFace
262  (
263  const treeBoundBox& bb,
264  const vector& dir, // end-start
265  const point& pt
266  );
267 
268  //- Walk to parent of node+octant.
269  // Return false if top of tree reached.
270  bool walkToParent
271  (
272  const label nodeI,
273  const direction octant,
274  label& parentNodeI,
275  label& parentOctant
276  ) const;
277 
278  //- Walk tree to neighbouring node. Return false if edge of tree
279  // hit.
280  bool walkToNeighbour
281  (
282  const point& facePoint,
283  const direction faceID, // direction to walk in
284  label& nodeI,
285  direction& octant
286  ) const;
287 
288  //- Debug: return verbose the bounding box faces
289  static word faceString(const direction faceID);
290 
291  //- Traverse a node. If intersects a triangle return first
292  // intersection point.
293  // findAny=true : return any intersection
294  // findAny=false: return nearest (to start) intersection
295  void traverseNode
296  (
297  const bool findAny,
298  const point& treeStart,
299  const vector& treeVec,
300  const point& start,
301  const point& end,
302  const label nodeI,
303  const direction octantI,
304  pointIndexHit& hitInfo,
305  direction& faceID
306  ) const;
307 
308  //- Find any or nearest intersection
309  pointIndexHit findLine
310  (
311  const bool findAny,
312  const point& treeStart,
313  const point& treeEnd,
314  const label startNodeI,
315  const direction startOctantI,
316  const bool verbose = false
317  ) const;
318 
319  //- Find any or nearest intersection of line between start and end.
320  pointIndexHit findLine
321  (
322  const bool findAny,
323  const point& start,
324  const point& end
325  ) const;
326 
327  //- Find all elements intersecting box.
328  void findBox
329  (
330  const label nodeI,
331  const treeBoundBox& searchBox,
332  labelHashSet& elements
333  ) const;
334 
335  //- Find all elements intersecting sphere.
336  void findSphere
337  (
338  const label nodeI,
339  const point& centre,
340  const scalar radiusSqr,
341  labelHashSet& elements
342  ) const;
343 
344  //- ...
345  template<class CompareOp>
346  static void findNear
347  (
348  const scalar nearDist,
349  const bool okOrder,
350  const dynamicIndexedOctree<Type>& tree1,
351  const labelBits index1,
352  const treeBoundBox& bb1,
353  const dynamicIndexedOctree<Type>& tree2,
354  const labelBits index2,
355  const treeBoundBox& bb2,
356  CompareOp& cop
357  );
358 
359 
360  // Other
361 
362  //- Count number of elements on this and sublevels
363  label countElements(const labelBits index) const;
364 
365  //- Dump node+octant to an obj file
366  void writeOBJ(const label nodeI, const direction octant) const;
367 
368  //- From index into contents_ to subNodes_ entry
369  static labelBits contentPlusOctant
370  (
371  const label i,
372  const direction octant
373  )
374  {
375  return labelBits(-i - 1, octant);
376  }
377 
378  //- From index into nodes_ to subNodes_ entry
379  static labelBits nodePlusOctant
380  (
381  const label i,
382  const direction octant
383  )
384  {
385  return labelBits(i + 1, octant);
386  }
387 
388  //- From empty to subNodes_ entry
389  static labelBits emptyPlusOctant
390  (
391  const direction octant
392  )
393  {
394  return labelBits(0, octant);
395  }
396 
397 public:
398 
399  //- Get the perturbation tolerance
400  static scalar& perturbTol();
401 
402 
403  // Constructors
404 
405  //- Construct from shapes
407  (
408  const Type& shapes,
409  const treeBoundBox& bb,
410  const label maxLevels, // maximum number of levels
411  const scalar maxLeafRatio, // how many elements per leaf
412  const scalar maxDuplicity // in how many leaves is a shape on
413  // average
414  );
415 
416  //- Clone
418  {
420  (
421  new dynamicIndexedOctree<Type>(*this)
422  );
423  }
424 
425 
426  // Member Functions
427 
428  // Access
429 
430  //- Reference to shape
431  const Type& shapes() const
432  {
433  return shapes_;
434  }
435 
436  //- List of all nodes
437  const List<node>& nodes() const
438  {
439  return nodes_;
440  }
441 
442  //- List of all contents (referenced by those nodes that are
443  // contents)
444  const contentListList& contents() const
445  {
446  return contents_;
447  }
448 
449  //- Top bounding box
450  const treeBoundBox& bb() const
451  {
452  if (nodes_.empty())
453  {
455  << "Tree is empty" << abort(FatalError);
456  }
457  return nodes_[0].bb_;
458  }
459 
460 
461  // Conversions for entries in subNodes_.
462 
463  static bool isContent(const labelBits i)
464  {
465  return i.val() < 0;
466  }
467 
468  static bool isEmpty(const labelBits i)
469  {
470  return i.val() == 0;
471  }
472 
473  static bool isNode(const labelBits i)
474  {
475  return i.val() > 0;
476  }
477 
478  static label getContent(const labelBits i)
479  {
480  if (!isContent(i))
481  {
483  << abort(FatalError);
484  }
485  return -i.val()-1;
486  }
487 
488  static label getNode(const labelBits i)
489  {
490  if (!isNode(i))
491  {
493  << abort(FatalError);
494  }
495  return i.val() - 1;
496  }
497 
498  static direction getOctant(const labelBits i)
499  {
500  return i.bits();
501  }
502 
503 
504  // Queries
505 
506  //- Calculate nearest point on nearest shape.
507  // Returns
508  // - bool : any point found nearer than nearestDistSqr
509  // - label: index in shapes
510  // - point: actual nearest point found
511  pointIndexHit findNearest
512  (
513  const point& sample,
514  const scalar nearestDistSqr
515  ) const;
516 
517  //- Low level: calculate nearest starting from subnode.
518  void findNearest
519  (
520  const label nodeI,
521  const point&,
522  scalar& nearestDistSqr,
523  label& nearestShapeI,
524  point& nearestPoint
525  ) const;
526 
527  //- Find nearest to line.
528  // Returns
529  // - bool : any point found?
530  // - label: index in shapes
531  // - point: actual nearest point found
532  // sets:
533  // - linePoint : corresponding nearest point on line
534  pointIndexHit findNearest
535  (
536  const linePointRef& ln,
537  treeBoundBox& tightest,
538  point& linePoint
539  ) const;
540 
541  //- Find nearest intersection of line between start and end.
542  pointIndexHit findLine
543  (
544  const point& start,
545  const point& end
546  ) const;
547 
548  //- Find any intersection of line between start and end.
550  (
551  const point& start,
552  const point& end
553  ) const;
554 
555  //- Find (in no particular order) indices of all shapes inside or
556  // overlapping bounding box (i.e. all shapes not outside box)
557  labelList findBox(const treeBoundBox& bb) const;
558 
559  //- Find (in no particular order) indices of all shapes inside or
560  // overlapping a bounding sphere (i.e. all shapes not outside
561  // sphere)
562  labelList findSphere
563  (
564  const point& centre,
565  const scalar radiusSqr
566  ) const;
567 
568  //- Find deepest node (as parent+octant) containing point. Starts
569  // off from starting index in nodes_ (use 0 to start from top)
570  // Use getNode and getOctant to extract info, or call findIndices.
571  labelBits findNode(const label nodeI, const point&) const;
572 
573  //- Find shape containing point. Only implemented for certain
574  // shapes.
575  template<class ... Args>
576  label findInside(const point&, const Args& ...) const;
577 
578  //- Find the shape indices that occupy the result of findNode
579  const labelList& findIndices(const point&) const;
580 
581  //- Determine type (inside/outside/mixed) for point. unknown if
582  // cannot be determined (e.g. non-manifold surface)
583  volumeType getVolumeType(const point&) const;
584 
585  //- Helper function to return the side. Returns outside if
586  // outsideNormal&vec >= 0, inside otherwise
587  static volumeType getSide
588  (
589  const vector& outsideNormal,
590  const vector& vec
591  );
592 
593  //- Helper: does bb intersect a sphere around sample? Or is any
594  // corner point of bb closer than nearestDistSqr to sample.
595  static bool overlaps
596  (
597  const point& bbMin,
598  const point& bbMax,
599  const scalar nearestDistSqr,
600  const point& sample
601  );
602 
603  //- Find near pairs and apply CompareOp to them.
604  // tree2 can be *this or different tree.
605  template<class CompareOp>
606  void findNear
607  (
608  const scalar nearDist,
609  const dynamicIndexedOctree<Type>& tree2,
610  CompareOp& cop
611  ) const;
612 
613 
614  // Edit
615 
616  //- Insert a new object into the tree.
617  bool insert(label startIndex, label endIndex);
618 
619  bool insertIndex
620  (
621  const label nodIndex,
622  const label index,
623  label& nLevels
624  );
625 
626  //- Remove an object from the tree.
627  bool remove(const label index);
628 
629  label removeIndex(const label nodIndex, const label index);
630 
631 
632  // Write
633 
634  //- Print tree. Either print all indices (printContent = true) or
635  // just size of contents nodes.
636  void print
637  (
639  const bool printContents,
640  const label
641  ) const;
642 
643  //- Write to a stream
644  bool write(Ostream& os) const;
645 
646  //- Print information
647  void writeTreeInfo() const;
648 
649 
650  // IOstream Operators
651 
652  friend Ostream& operator<< <Type>
653  (
654  Ostream&,
656  );
657 };
658 
659 
660 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
661 
662 } // End namespace Foam
663 
664 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
665 
666 #ifdef NoRepository
667  #include "dynamicIndexedOctree.C"
668 #endif
669 
670 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
671 
672 #endif
673 
674 // ************************************************************************* //
label n
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:78
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:78
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:54
bool empty() const
Return true if the UList is empty (ie, size() is zero)
Definition: UListI.H:325
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
Tree node. Has up pointer and down pointers.
friend Ostream & operator<<(Ostream &os, const node &n)
FixedList< labelBits, 8 > subNodes_
IDs of the 8 nodes on all sides of the mid point.
label parent_
Parent node (index into nodes_ of tree)
friend bool operator!=(const node &a, const node &b)
friend Istream & operator>>(Istream &is, node &n)
treeBoundBox bb_
Bounding box of this node.
friend bool operator==(const node &a, const node &b)
Non-pointer based hierarchical recursive searching. Storage is dynamic, so elements can be deleted.
const Type & shapes() const
Reference to shape.
static bool isEmpty(const labelBits i)
const labelList & findIndices(const point &) const
Find the shape indices that occupy the result of findNode.
static label getNode(const labelBits i)
static direction getOctant(const labelBits i)
const List< node > & nodes() const
List of all nodes.
static scalar & perturbTol()
Get the perturbation tolerance.
static bool isContent(const labelBits i)
static label getContent(const labelBits i)
label removeIndex(const label nodIndex, const label index)
void print(prefixOSstream &, const bool printContents, const label) const
Print tree. Either print all indices (printContent = true) or.
static volumeType getSide(const vector &outsideNormal, const vector &vec)
Helper function to return the side. Returns outside if.
bool write(Ostream &os) const
Write to a stream.
dynamicIndexedOctree(const Type &shapes, const treeBoundBox &bb, const label maxLevels, const scalar maxLeafRatio, const scalar maxDuplicity)
Construct from shapes.
const treeBoundBox & bb() const
Top bounding box.
bool remove(const label index)
Remove an object from the tree.
bool insert(label startIndex, label endIndex)
Insert a new object into the tree.
labelBits findNode(const label nodeI, const point &) const
Find deepest node (as parent+octant) containing point. Starts.
static bool isNode(const labelBits i)
label findInside(const point &, const Args &...) const
Find shape containing point. Only implemented for certain.
autoPtr< dynamicIndexedOctree< Type > > clone() const
Clone.
void writeTreeInfo() const
Print information.
const contentListList & contents() const
List of all contents (referenced by those nodes that are.
bool insertIndex(const label nodIndex, const label index, label &nLevels)
pointIndexHit findLineAny(const point &start, const point &end) const
Find any intersection of line between start and end.
A 29bits label and 3bits direction packed into single label.
Definition: labelBits.H:52
label val() const
Definition: labelBits.H:97
direction bits() const
Definition: labelBits.H:102
A line primitive.
Definition: line.H:71
Version of OSstream which prints a prefix on each line.
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:90
A class for handling words, derived from string.
Definition: word.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
volScalarField & b
Definition: createFields.H:27
Namespace for OpenFOAM.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManip< error > abort(error &err)
Definition: errorManip.H:131
DynamicList< autoPtr< DynamicList< label > > > contentListList
label facePoint(const int facei, const block &block, const label i, const label j)
error FatalError
TemplateName(FvFaceCellWave)
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:908
uint8_t direction
Definition: direction.H:45