dynamicIndexedOctree.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Class
28  Foam::dynamicIndexedOctree
29 
30 Description
31  Non-pointer based hierarchical recursive searching.
32  Storage is dynamic, so elements can be deleted.
33 
34 SourceFiles
35  dynamicIndexedOctree.C
36 
37 \*---------------------------------------------------------------------------*/
38 
39 #ifndef Foam_dynamicIndexedOctree_H
40 #define Foam_dynamicIndexedOctree_H
41 
42 #include "indexedOctree.H"
43 #include "DynamicList.H"
44 
45 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
46 
47 namespace Foam
48 {
49 
50 // Forward Declarations
51 template<class Type> class dynamicIndexedOctree;
52 template<class Type>
53 Ostream& operator<<(Ostream&, const dynamicIndexedOctree<Type>&);
54 
55 
56 /*---------------------------------------------------------------------------*\
57  Class dynamicIndexedOctreeBase Declaration
58 \*---------------------------------------------------------------------------*/
59 
60 //- Template invariant parts for dynamicIndexedOctree
61 // Same type of node bookkeeping as indexedOctree
63 :
64  public indexedOctreeBase
65 {
66 public:
67 
68  //- Document that we are using the same types of node
70 
71  //- Runtime type information
72  ClassName("dynamicIndexedOctree");
73 
74 
75  // Constructors
76 
77  //- Default construct
78  dynamicIndexedOctreeBase() = default;
79 };
80 
81 
82 /*---------------------------------------------------------------------------*\
83  Class dynamicIndexedOctree Declaration
84 \*---------------------------------------------------------------------------*/
85 
86 template<class Type>
88 :
90 {
91  // Private Data
92 
93  //- Underlying shapes for geometric queries.
94  const Type shapes_;
95 
96  const treeBoundBox bb_;
97 
98  const label maxLevels_;
99 
100  //- Current number of levels in the tree.
101  label nLevelsMax_;
102 
103  const scalar maxLeafRatio_;
104 
105  const label minSize_;
106 
107  const scalar maxDuplicity_;
108 
109  //- List of all nodes
110  DynamicList<node> nodes_;
111 
112  //- List of all contents (referenced by those nodes that are contents)
114 
115  //- Per node per octant whether is fully inside/outside/mixed.
116  mutable PackedList<2> nodeTypes_;
117 
118 
119  // Private Member Functions
120 
121  // Construction
122 
123  //- Split list of indices into 8 bins
124  // according to where they are in relation to mid.
125  void divide
126  (
127  const labelUList& indices,
128  const treeBoundBox& bb,
129  FixedList<DynamicList<label>, 8>& dividedIndices
130  ) const;
131 
132  //- Subdivide the contents node at position contentI.
133  // Appends to contents.
134  node divide
135  (
136  const treeBoundBox& bb,
137  label contentIndex,
138  const label parentNodeIndex,
139  const label octantToBeDivided
140  );
141 
142  // Recursively call the divide function
143  void recursiveSubDivision
144  (
145  const treeBoundBox& subBb,
146  const label contentI,
147  const label parentIndex,
148  const label octant,
149  label& nLevels
150  );
151 
152  //- Determine inside/outside per node (mixed if cannot be
153  // determined). Only valid for closed shapes.
154  volumeType calcVolumeType(const label nodeI) const;
155 
156  //- Search cached volume type.
157  volumeType getVolumeType(const label nodeI, const point&) const;
158 
159 
160  // Query
161 
162  //- Find nearest point to line.
163  void findNearest
164  (
165  const label nodeI,
166  const linePointRef& ln,
167 
168  treeBoundBox& tightest,
169  label& nearestShapeI,
170  point& linePoint,
171  point& nearestPoint
172  ) const;
173 
174  //- Return bbox of octant
175  treeBoundBox subBbox
176  (
177  const label parentNodeI,
178  const direction octant
179  ) const;
180 
181  //- Helper: take a point on/close to face of bb and push it
182  // inside or outside of bb.
183  static point pushPoint
184  (
185  const treeBoundBox&,
186  const point&,
187  const bool pushInside
188  );
189 
190  //- Helper: take a point on face of bb and push it
191  // inside or outside of bb.
192  static point pushPoint
193  (
194  const treeBoundBox&,
195  const direction,
196  const point&,
197  const bool pushInside
198  );
199 
200  //- Helper: take point on face(s) of bb and push it away from
201  // edges of face. If pt is not on a face does nothing.
202  static point pushPointIntoFace
203  (
204  const treeBoundBox& bb,
205  const vector& dir, // end-start
206  const point& pt
207  );
208 
209  //- Walk to parent of node+octant.
210  // Return false if top of tree reached.
211  bool walkToParent
212  (
213  const label nodeI,
214  const direction octant,
215 
216  label& parentNodeI,
217  label& parentOctant
218  ) const;
219 
220  //- Walk tree to neighbouring node. Return false if edge of tree
221  // hit.
222  bool walkToNeighbour
223  (
224  const point& facePoint,
225  const direction faceID, // direction to walk in
226  label& nodeI,
227  direction& octant
228  ) const;
229 
230  //- Debug: return verbose the bounding box faces
231  static word faceString(const direction faceID);
232 
233  //- Traverse a node. If intersects a triangle return first
234  // intersection point.
235  // findAny=true : return any intersection
236  // findAny=false: return nearest (to start) intersection
237  void traverseNode
238  (
239  const bool findAny,
240  const point& treeStart,
241  const vector& treeVec,
242 
243  const point& start,
244  const point& end,
245  const label nodeI,
246  const direction octantI,
247 
248  pointIndexHit& hitInfo,
249  direction& faceID
250  ) const;
251 
252  //- Find any or nearest intersection
253  pointIndexHit findLine
254  (
255  const bool findAny,
256  const point& treeStart,
257  const point& treeEnd,
258  const label startNodeI,
259  const direction startOctantI,
260  const bool verbose = false
261  ) const;
262 
263  //- Find any or nearest intersection of line between start and end.
264  pointIndexHit findLine
265  (
266  const bool findAny,
267  const point& start,
268  const point& end
269  ) const;
270 
271  //- Find elements intersecting box
272  // Store all results in elements (if non-null), or early exit
273  bool findBox
274  (
275  const label nodeI,
276  const treeBoundBox& searchBox,
277  labelHashSet* elements
278  ) const;
279 
280  //- Find elements intersecting sphere.
281  // Store all results in elements (if non-null), or early exit
282  bool findSphere
283  (
284  const label nodeI,
285  const point& centre,
286  const scalar radiusSqr,
287  labelHashSet* elements
288  ) const;
289 
290 
291  template<class CompareOp>
292  static void findNear
293  (
294  const scalar nearDist,
295  const bool okOrder,
296  const dynamicIndexedOctree<Type>& tree1,
297  const labelBits index1,
298  const treeBoundBox& bb1,
299  const dynamicIndexedOctree<Type>& tree2,
300  const labelBits index2,
301  const treeBoundBox& bb2,
302  CompareOp& cop
303  );
304 
305 
306  // Other
307 
308  //- Count number of elements on this and sublevels
309  label countElements(const labelBits index) const;
310 
311  //- Write node treeBoundBoxes in OBJ format
312  void writeOBJ
313  (
314  const label nodeI,
315  Ostream& os,
316  label& vertIndex,
317  const bool leavesOnly,
318  const bool writeLinesOnly = false
319  ) const;
320 
321  //- Dump node+octant to an obj file
322  void writeOBJ(const label nodeI, const direction octant) const;
323 
324 
325 public:
326 
327  // Constructors
328 
329  //- Construct from shapes
331  (
332  const Type& shapes,
333  const treeBoundBox& bb,
334  const label maxLevels, // maximum number of levels
335  const scalar maxLeafRatio, // how many elements per leaf
336  const scalar maxDuplicity // in how many leaves is a shape on
337  // average
338  );
339 
340  //- Clone
342  {
344  }
345 
346 
347  // Member Functions
348 
349  // Access
350 
351  //- Reference to shape
352  const Type& shapes() const noexcept { return shapes_; }
353 
354  //- List of all nodes
355  const List<node>& nodes() const noexcept { return nodes_; }
356 
357  //- List of all contents
358  //- (referenced by those nodes that are contents)
359  const DynamicList<DynamicList<label>>& contents() const noexcept
360  {
361  return contents_;
362  }
363 
364  //- Per node, per octant whether is fully inside/outside/mixed.
365  PackedList<2>& nodeTypes() const noexcept
366  {
367  return nodeTypes_;
368  }
369 
370  //- Top bounding box
371  const treeBoundBox& bb() const
372  {
373  if (nodes_.empty())
374  {
375  return treeBoundBox::null();
376  }
377  return nodes_[0].bb_;
378  }
379 
380 
381  // Queries
382 
383  //- Calculate nearest point on nearest shape.
384  // Returns
385  // - bool : any point found nearer than nearestDistSqr
386  // - label: index in shapes
387  // - point: actual nearest point found
388  pointIndexHit findNearest
389  (
390  const point& sample,
391  const scalar nearestDistSqr
392  ) const;
393 
394  //- Low level: calculate nearest starting from subnode.
395  void findNearest
396  (
397  const label nodeI,
398  const point&,
399 
400  scalar& nearestDistSqr,
401  label& nearestShapeI,
402  point& nearestPoint
403  ) const;
404 
405  //- Find nearest to line.
406  // Returns
407  // - bool : any point found?
408  // - label: index in shapes
409  // - point: actual nearest point found
410  // sets:
411  // - linePoint : corresponding nearest point on line
412  pointIndexHit findNearest
413  (
414  const linePointRef& ln,
415  treeBoundBox& tightest,
416  point& linePoint
417  ) const;
418 
419  //- Find nearest intersection of line between start and end.
420  pointIndexHit findLine
421  (
422  const point& start,
423  const point& end
424  ) const;
425 
426  //- Find any intersection of line between start and end.
428  (
429  const point& start,
430  const point& end
431  ) const;
432 
433  //- True if any shapes overlap the bounding box
434  bool overlaps(const treeBoundBox& bb) const;
435 
436  //- Find indices of all shapes inside or overlapping
437  //- a bounding box (i.e. all shapes not outside box)
438  // \returns the indices (in no particular order)
439  labelList findBox
440  (
441  const treeBoundBox& bb
442  ) const;
443 
444  //- Find indices of all shapes inside or overlapping
445  //- a bounding box (i.e. all shapes not outside box)
446  // \returns the number of elements found
447  label findBox
448  (
449  const treeBoundBox& bb,
450  labelHashSet& elements
451  ) const;
452 
453  //- True if any shapes overlap the bounding sphere
454  bool overlaps
455  (
456  const point& centre,
457  const scalar radiusSqr
458  ) const;
459 
460  //- Find indices of all shapes inside or overlapping
461  //- a bounding sphere (i.e. all shapes not outside a sphere)
462  // \returns the indices (in no particular order)
463  labelList findSphere
464  (
465  const point& centre,
466  const scalar radiusSqr
467  ) const;
468 
469  //- Find indices of all shapes inside or overlapping
470  //- a bounding sphere (i.e. all shapes not outside sphere)
471  // \returns the number of elements found
472  label findSphere
473  (
474  const point& centre,
475  const scalar radiusSqr,
476  labelHashSet& elements
477  ) const;
478 
479 
480  //- Find deepest node (as parent+octant) containing point. Starts
481  // off from starting index in nodes_ (use 0 to start from top)
482  // Use getNode and getOctant to extract info, or call findIndices.
483  labelBits findNode(const label nodeI, const point&) const;
484 
485  //- Find shape containing point. Only implemented for certain
486  // shapes.
487  label findInside(const point&) const;
488 
489  //- Find the shape indices that occupy the result of findNode
490  const labelList& findIndices(const point&) const;
491 
492  //- Determine type (inside/outside/mixed) for point. unknown if
493  // cannot be determined (e.g. non-manifold surface)
494  volumeType getVolumeType(const point&) const;
495 
496  //- Helper function to return the side. Returns outside if
497  // outsideNormal&vec >= 0, inside otherwise
498  static volumeType getSide
499  (
500  const vector& outsideNormal,
501  const vector& vec
502  );
503 
504  //- Find near pairs and apply CompareOp to them.
505  // tree2 can be *this or different tree.
506  template<class CompareOp>
507  void findNear
508  (
509  const scalar nearDist,
510  const dynamicIndexedOctree<Type>& tree2,
511  CompareOp& cop
512  ) const;
513 
514 
515  // Edit
516 
517  //- Insert a new object into the tree.
518  bool insert(label startIndex, label endIndex);
519 
520  bool insertIndex
521  (
522  const label nodIndex,
523  const label index,
524  label& nLevels
525  );
526 
527  //- Remove an object from the tree.
528  bool remove(const label index);
529 
530  label removeIndex(const label nodIndex, const label index);
531 
532 
533  // Write
534 
535  //- Write all tree boxes as OBJ format
536  void writeOBJ(Ostream& os) const;
537 
538  //- Print tree. Either print all indices (printContent = true) or
539  // just size of contents nodes.
540  void print
541  (
543  const bool printContents,
544  const label
545  ) const;
546 
547  bool write(Ostream& os) const;
548 
549  void writeTreeInfo() const;
550 
551 
552  // IOstream Operators
553 
554  friend Ostream& operator<< <Type>
555  (
556  Ostream&,
558  );
559 };
560 
561 
562 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
563 
564 } // End namespace Foam
565 
566 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
567 
568 #ifdef NoRepository
569  #include "dynamicIndexedOctree.C"
570 #endif
571 
572 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
573 
574 #endif
575 
576 // ************************************************************************* //
const labelList & findIndices(const point &) const
Find the shape indices that occupy the result of findNode.
indexedOctreeBase::node node
Document that we are using the same types of node.
uint8_t direction
Definition: direction.H:46
A line primitive.
Definition: line.H:52
static const treeBoundBox & null() noexcept
The null treeBoundBox is the same as an inverted box.
Definition: treeBoundBox.H:187
Template invariant parts for dynamicIndexedOctree.
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:107
PackedList< 2 > & nodeTypes() const noexcept
Per node, per octant whether is fully inside/outside/mixed.
void print(prefixOSstream &, const bool printContents, const label) const
Print tree. Either print all indices (printContent = true) or.
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
dynamicIndexedOctreeBase()=default
Default construct.
bool insert(label startIndex, label endIndex)
Insert a new object into the tree.
This class describes the interaction of an object (often a face) and a point. It carries the info of ...
Definition: pointIndexHit.H:44
ClassName("dynamicIndexedOctree")
Runtime type information.
const Type & shapes() const noexcept
Reference to shape.
An enumeration wrapper for classification of a location as being inside/outside of a volume...
Definition: volumeType.H:55
label removeIndex(const label nodIndex, const label index)
Version of OSstream that prints a prefix on each line.
A class for handling words, derived from Foam::string.
Definition: word.H:63
Non-pointer based hierarchical recursive searching. Storage is dynamic, so elements can be deleted...
const DynamicList< DynamicList< label > > & contents() const noexcept
List of all contents (referenced by those nodes that are contents)
bool ln(const fileName &src, const fileName &dst)
Create a softlink. dst should not exist. Returns true if successful.
Definition: POSIX.C:1237
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: Scalar.H:258
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
bool insertIndex(const label nodIndex, const label index, label &nLevels)
label facePoint(const int facei, const block &block, const label i, const label j)
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
OBJstream os(runTime.globalPath()/outputName)
dynamicIndexedOctree(const Type &shapes, const treeBoundBox &bb, const label maxLevels, const scalar maxLeafRatio, const scalar maxDuplicity)
Construct from shapes.
Template invariant parts for indexedOctree.
Definition: indexedOctree.H:67
static volumeType getSide(const vector &outsideNormal, const vector &vec)
Helper function to return the side. Returns outside if.
bool overlaps(const treeBoundBox &bb) const
True if any shapes overlap the bounding box.
vector point
Point is a vector.
Definition: point.H:37
pointIndexHit findLineAny(const point &start, const point &end) const
Find any intersection of line between start and end.
autoPtr< dynamicIndexedOctree< Type > > clone() const
Clone.
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:90
A 29bits (or 61bits) integer label with 3bits direction (eg, octant) packed into single label...
Definition: labelBits.H:48
labelBits findNode(const label nodeI, const point &) const
Find deepest node (as parent+octant) containing point. Starts.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
label findInside(const point &) const
Find shape containing point. Only implemented for certain.
const List< node > & nodes() const noexcept
List of all nodes.
bool write(Ostream &os) const
Namespace for OpenFOAM.
Tree node. Has up pointer and down pointers.
Definition: indexedOctree.H:76
const treeBoundBox & bb() const
Top bounding box.