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 class Istream;
52 template<class Type> class dynamicIndexedOctree;
53 template<class Type>
54 Ostream& operator<<(Ostream&, const dynamicIndexedOctree<Type>&);
55 
56 
57 /*---------------------------------------------------------------------------*\
58  Class dynamicIndexedOctreeBase Declaration
59 \*---------------------------------------------------------------------------*/
60 
61 //- Template invariant parts for dynamicIndexedOctree
62 // Same type of node bookkeeping as indexedOctree
64 :
65  public indexedOctreeBase
66 {
67 public:
68 
69  //- Document that we are using the same types of node
71 
72  //- Runtime type information
73  ClassName("dynamicIndexedOctree");
74 
75 
76  // Constructors
77 
78  //- Default construct
79  dynamicIndexedOctreeBase() = default;
80 };
81 
82 
83 /*---------------------------------------------------------------------------*\
84  Class dynamicIndexedOctree Declaration
85 \*---------------------------------------------------------------------------*/
86 
87 template<class Type>
89 :
91 {
92  // Private Data
93 
94  //- Underlying shapes for geometric queries.
95  const Type shapes_;
96 
97  const treeBoundBox bb_;
98 
99  const label maxLevels_;
100 
101  //- Current number of levels in the tree.
102  label nLevelsMax_;
103 
104  const scalar maxLeafRatio_;
105 
106  const label minSize_;
107 
108  const scalar maxDuplicity_;
109 
110  //- List of all nodes
111  DynamicList<node> nodes_;
112 
113  //- List of all contents (referenced by those nodes that are contents)
115 
116  //- Per node per octant whether is fully inside/outside/mixed.
117  mutable PackedList<2> nodeTypes_;
118 
119 
120  // Private Member Functions
121 
122  // Construction
123 
124  //- Split list of indices into 8 bins
125  // according to where they are in relation to mid.
126  void divide
127  (
128  const labelUList& indices,
129  const treeBoundBox& bb,
130  FixedList<DynamicList<label>, 8>& dividedIndices
131  ) const;
132 
133  //- Subdivide the contents node at position contentI.
134  // Appends to contents.
135  node divide
136  (
137  const treeBoundBox& bb,
138  label contentIndex,
139  const label parentNodeIndex,
140  const label octantToBeDivided
141  );
142 
143  // Recursively call the divide function
144  void recursiveSubDivision
145  (
146  const treeBoundBox& subBb,
147  const label contentI,
148  const label parentIndex,
149  const label octant,
150  label& nLevels
151  );
152 
153  //- Determine inside/outside per node (mixed if cannot be
154  // determined). Only valid for closed shapes.
155  volumeType calcVolumeType(const label nodeI) const;
156 
157  //- Search cached volume type.
158  volumeType getVolumeType(const label nodeI, const point&) const;
159 
160 
161  // Query
162 
163  //- Find nearest point to line.
164  void findNearest
165  (
166  const label nodeI,
167  const linePointRef& ln,
168 
169  treeBoundBox& tightest,
170  label& nearestShapeI,
171  point& linePoint,
172  point& nearestPoint
173  ) const;
174 
175  //- Return bbox of octant
176  treeBoundBox subBbox
177  (
178  const label parentNodeI,
179  const direction octant
180  ) const;
181 
182  //- Helper: take a point on/close to face of bb and push it
183  // inside or outside of bb.
184  static point pushPoint
185  (
186  const treeBoundBox&,
187  const point&,
188  const bool pushInside
189  );
190 
191  //- Helper: take a point on face of bb and push it
192  // inside or outside of bb.
193  static point pushPoint
194  (
195  const treeBoundBox&,
196  const direction,
197  const point&,
198  const bool pushInside
199  );
200 
201  //- Helper: take point on face(s) of bb and push it away from
202  // edges of face. If pt is not on a face does nothing.
203  static point pushPointIntoFace
204  (
205  const treeBoundBox& bb,
206  const vector& dir, // end-start
207  const point& pt
208  );
209 
210  //- Walk to parent of node+octant.
211  // Return false if top of tree reached.
212  bool walkToParent
213  (
214  const label nodeI,
215  const direction octant,
216 
217  label& parentNodeI,
218  label& parentOctant
219  ) const;
220 
221  //- Walk tree to neighbouring node. Return false if edge of tree
222  // hit.
223  bool walkToNeighbour
224  (
225  const point& facePoint,
226  const direction faceID, // direction to walk in
227  label& nodeI,
228  direction& octant
229  ) const;
230 
231  //- Debug: return verbose the bounding box faces
232  static word faceString(const direction faceID);
233 
234  //- Traverse a node. If intersects a triangle return first
235  // intersection point.
236  // findAny=true : return any intersection
237  // findAny=false: return nearest (to start) intersection
238  void traverseNode
239  (
240  const bool findAny,
241  const point& treeStart,
242  const vector& treeVec,
243 
244  const point& start,
245  const point& end,
246  const label nodeI,
247  const direction octantI,
248 
249  pointIndexHit& hitInfo,
250  direction& faceID
251  ) const;
252 
253  //- Find any or nearest intersection
254  pointIndexHit findLine
255  (
256  const bool findAny,
257  const point& treeStart,
258  const point& treeEnd,
259  const label startNodeI,
260  const direction startOctantI,
261  const bool verbose = false
262  ) const;
263 
264  //- Find any or nearest intersection of line between start and end.
265  pointIndexHit findLine
266  (
267  const bool findAny,
268  const point& start,
269  const point& end
270  ) const;
271 
272  //- Find elements intersecting box
273  // Store all results in elements (if non-null), or early exit
274  bool findBox
275  (
276  const label nodeI,
277  const treeBoundBox& searchBox,
278  labelHashSet* elements
279  ) const;
280 
281  //- Find elements intersecting sphere.
282  // Store all results in elements (if non-null), or early exit
283  bool findSphere
284  (
285  const label nodeI,
286  const point& centre,
287  const scalar radiusSqr,
288  labelHashSet* elements
289  ) const;
290 
291 
292  template<class CompareOp>
293  static void findNear
294  (
295  const scalar nearDist,
296  const bool okOrder,
297  const dynamicIndexedOctree<Type>& tree1,
298  const labelBits index1,
299  const treeBoundBox& bb1,
300  const dynamicIndexedOctree<Type>& tree2,
301  const labelBits index2,
302  const treeBoundBox& bb2,
303  CompareOp& cop
304  );
305 
306 
307  // Other
308 
309  //- Count number of elements on this and sublevels
310  label countElements(const labelBits index) const;
311 
312  //- Write node treeBoundBoxes in OBJ format
313  void writeOBJ
314  (
315  const label nodeI,
316  Ostream& os,
317  label& vertIndex,
318  const bool leavesOnly,
319  const bool writeLinesOnly = false
320  ) const;
321 
322  //- Dump node+octant to an obj file
323  void writeOBJ(const label nodeI, const direction octant) const;
324 
325 
326 public:
327 
328  // Constructors
329 
330  //- Construct from shapes
332  (
333  const Type& shapes,
334  const treeBoundBox& bb,
335  const label maxLevels, // maximum number of levels
336  const scalar maxLeafRatio, // how many elements per leaf
337  const scalar maxDuplicity // in how many leaves is a shape on
338  // average
339  );
340 
341  //- Clone
343  {
345  }
346 
347 
348  // Member Functions
349 
350  // Access
351 
352  //- Reference to shape
353  const Type& shapes() const noexcept { return shapes_; }
354 
355  //- List of all nodes
356  const List<node>& nodes() const noexcept { return nodes_; }
357 
358  //- List of all contents
359  //- (referenced by those nodes that are contents)
360  const DynamicList<DynamicList<label>>& contents() const noexcept
361  {
362  return contents_;
363  }
364 
365  //- Per node, per octant whether is fully inside/outside/mixed.
366  PackedList<2>& nodeTypes() const noexcept
367  {
368  return nodeTypes_;
369  }
370 
371  //- Top bounding box
372  const treeBoundBox& bb() const
373  {
374  if (nodes_.empty())
375  {
376  return treeBoundBox::null();
377  }
378  return nodes_[0].bb_;
379  }
380 
381 
382  // Queries
383 
384  //- Calculate nearest point on nearest shape.
385  // Returns
386  // - bool : any point found nearer than nearestDistSqr
387  // - label: index in shapes
388  // - point: actual nearest point found
389  pointIndexHit findNearest
390  (
391  const point& sample,
392  const scalar nearestDistSqr
393  ) const;
394 
395  //- Low level: calculate nearest starting from subnode.
396  void findNearest
397  (
398  const label nodeI,
399  const point&,
400 
401  scalar& nearestDistSqr,
402  label& nearestShapeI,
403  point& nearestPoint
404  ) const;
405 
406  //- Find nearest to line.
407  // Returns
408  // - bool : any point found?
409  // - label: index in shapes
410  // - point: actual nearest point found
411  // sets:
412  // - linePoint : corresponding nearest point on line
413  pointIndexHit findNearest
414  (
415  const linePointRef& ln,
416  treeBoundBox& tightest,
417  point& linePoint
418  ) const;
419 
420  //- Find nearest intersection of line between start and end.
421  pointIndexHit findLine
422  (
423  const point& start,
424  const point& end
425  ) const;
426 
427  //- Find any intersection of line between start and end.
429  (
430  const point& start,
431  const point& end
432  ) const;
433 
434  //- True if any shapes overlap the bounding box
435  bool overlaps(const treeBoundBox& bb) const;
436 
437  //- Find indices of all shapes inside or overlapping
438  //- a bounding box (i.e. all shapes not outside box)
439  // \returns the indices (in no particular order)
440  labelList findBox
441  (
442  const treeBoundBox& bb
443  ) const;
444 
445  //- Find indices of all shapes inside or overlapping
446  //- a bounding box (i.e. all shapes not outside box)
447  // \returns the number of elements found
448  label findBox
449  (
450  const treeBoundBox& bb,
451  labelHashSet& elements
452  ) const;
453 
454  //- True if any shapes overlap the bounding sphere
455  bool overlaps
456  (
457  const point& centre,
458  const scalar radiusSqr
459  ) const;
460 
461  //- Find indices of all shapes inside or overlapping
462  //- a bounding sphere (i.e. all shapes not outside a sphere)
463  // \returns the indices (in no particular order)
464  labelList findSphere
465  (
466  const point& centre,
467  const scalar radiusSqr
468  ) const;
469 
470  //- Find indices of all shapes inside or overlapping
471  //- a bounding sphere (i.e. all shapes not outside sphere)
472  // \returns the number of elements found
473  label findSphere
474  (
475  const point& centre,
476  const scalar radiusSqr,
477  labelHashSet& elements
478  ) const;
479 
480 
481  //- Find deepest node (as parent+octant) containing point. Starts
482  // off from starting index in nodes_ (use 0 to start from top)
483  // Use getNode and getOctant to extract info, or call findIndices.
484  labelBits findNode(const label nodeI, const point&) const;
485 
486  //- Find shape containing point. Only implemented for certain
487  // shapes.
488  label findInside(const point&) const;
489 
490  //- Find the shape indices that occupy the result of findNode
491  const labelList& findIndices(const point&) const;
492 
493  //- Determine type (inside/outside/mixed) for point. unknown if
494  // cannot be determined (e.g. non-manifold surface)
495  volumeType getVolumeType(const point&) const;
496 
497  //- Helper function to return the side. Returns outside if
498  // outsideNormal&vec >= 0, inside otherwise
499  static volumeType getSide
500  (
501  const vector& outsideNormal,
502  const vector& vec
503  );
504 
505  //- Find near pairs and apply CompareOp to them.
506  // tree2 can be *this or different tree.
507  template<class CompareOp>
508  void findNear
509  (
510  const scalar nearDist,
511  const dynamicIndexedOctree<Type>& tree2,
512  CompareOp& cop
513  ) const;
514 
515 
516  // Edit
517 
518  //- Insert a new object into the tree.
519  bool insert(label startIndex, label endIndex);
520 
521  bool insertIndex
522  (
523  const label nodIndex,
524  const label index,
525  label& nLevels
526  );
527 
528  //- Remove an object from the tree.
529  bool remove(const label index);
530 
531  label removeIndex(const label nodIndex, const label index);
532 
533 
534  // Write
535 
536  //- Write all tree boxes as OBJ format
537  void writeOBJ(Ostream& os) const;
538 
539  //- Print tree. Either print all indices (printContent = true) or
540  // just size of contents nodes.
541  void print
542  (
544  const bool printContents,
545  const label
546  ) const;
547 
548  bool write(Ostream& os) const;
549 
550  void writeTreeInfo() const;
551 
552 
553  // IOstream Operators
554 
555  friend Ostream& operator<< <Type>
556  (
557  Ostream&,
559  );
560 };
561 
562 
563 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
564 
565 } // End namespace Foam
566 
567 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
568 
569 #ifdef NoRepository
570  #include "dynamicIndexedOctree.C"
571 #endif
572 
573 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
574 
575 #endif
576 
577 // ************************************************************************* //
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:101
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.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:420
PointIndexHit< point > pointIndexHit
A PointIndexHit with a 3D point.
Definition: pointIndexHit.H:58
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
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
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:1190
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
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:193
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:68
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:77
const treeBoundBox & bb() const
Top bounding box.