indexedOctree.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::indexedOctree
26 
27 Description
28  Non-pointer based hierarchical recursive searching
29 
30 SourceFiles
31  indexedOctree.C
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #ifndef indexedOctree_H
36 #define indexedOctree_H
37 
38 #include "treeBoundBox.H"
39 #include "pointIndexHit.H"
40 #include "FixedList.H"
41 #include "Ostream.H"
42 #include "HashSet.H"
43 #include "labelBits.H"
44 #include "PackedList.H"
45 #include "volumeType.H"
46 
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
48 
49 namespace Foam
50 {
51 
52 // Forward declaration of classes
53 template<class Type> class indexedOctree;
54 template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
55 class Istream;
56 
57 
58 /*---------------------------------------------------------------------------*\
59  Class indexedOctreeName Declaration
60 \*---------------------------------------------------------------------------*/
61 
63 
64 
65 /*---------------------------------------------------------------------------*\
66  Class indexedOctree Declaration
67 \*---------------------------------------------------------------------------*/
68 
69 template<class Type>
70 class indexedOctree
71 :
72  public indexedOctreeName
73 {
74 public:
75 
76  // Data types
77 
78  //- Tree node. Has up pointer and down pointers.
79  class node
80  {
81  public:
82 
83  //- Bounding box of this node
85 
86  //- Parent node (index into nodes_ of tree)
87  label parent_;
88 
89  //- IDs of the 8 nodes on all sides of the mid point
91 
92  friend Ostream& operator<< (Ostream& os, const node& n)
93  {
94  return os << n.bb_ << token::SPACE
95  << n.parent_ << token::SPACE << n.subNodes_;
96  }
97 
98  friend Istream& operator>> (Istream& is, node& n)
99  {
100  return is >> n.bb_ >> n.parent_ >> n.subNodes_;
101  }
102 
103  friend bool operator==(const node& a, const node& b)
104  {
105  return
106  a.bb_ == b.bb_
107  && a.parent_ == b.parent_
108  && a.subNodes_ == b.subNodes_;
109  }
110 
111  friend bool operator!=(const node& a, const node& b)
112  {
113  return !(a == b);
114  }
115  };
116 
117 
118 private:
119 
120  // Static data
121 
122  //- Relative perturbation tolerance. Determines when point is
123  // considered to be close to face/edge of bb of node.
124  // The tolerance is relative to the bounding box of the smallest
125  // node.
126  static scalar perturbTol_;
127 
128 
129  // Private Data
130 
131  //- Underlying shapes for geometric queries.
132  const Type shapes_;
133 
134  //- List of all nodes
135  List<node> nodes_;
136 
137  //- List of all contents (referenced by those nodes that are contents)
138  labelListList contents_;
139 
140  //- Per node per octant whether is fully inside/outside/mixed.
141  mutable PackedList<2> nodeTypes_;
142 
143 
144  // Private Member Functions
145 
146  //- Helper: does bb intersect a sphere around sample? Or is any
147  // corner point of bb closer than nearestDistSqr to sample.
148  // (bb is implicitly provided as parent bb + octant)
149  static bool overlaps
150  (
151  const treeBoundBox& parentBb,
152  const direction octant,
153  const scalar nearestDistSqr,
154  const point& sample
155  );
156 
157 
158  // Construction
159 
160  //- Split list of indices into 8 bins
161  // according to where they are in relation to mid.
162  void divide
163  (
164  const labelList& indices,
165  const treeBoundBox& bb,
166  labelListList& result
167  ) const;
168 
169  //- Subdivide the contents node at position contentI.
170  // Appends to contents.
171  node divide
172  (
173  const treeBoundBox& bb,
175  const label contentI
176  ) const;
177 
178  //- Split any contents node with more than minSize elements.
179  void splitNodes
180  (
181  const label minSize,
184  ) const;
185 
186  //- Reorder contents to be in same order as nodes.
187  // Returns number of nodes on the compactLevel.
188  static label compactContents
189  (
192  const label compactLevel,
193  const label nodeI,
194  const label level,
195  List<labelList>& compactedContents,
196  label& compactI
197  );
198 
199  //- Determine inside/outside per node (mixed if cannot be
200  // determined). Only valid for closed shapes.
201  volumeType calcVolumeType(const label nodeI) const;
202 
203  //- Search cached volume type.
204  volumeType getVolumeType(const label nodeI, const point&) const;
205 
206 
207  // Query
208 
209  //- Find nearest point to line.
210  template<class FindNearestOp>
211  void findNearest
212  (
213  const label nodeI,
214  const linePointRef& ln,
215  treeBoundBox& tightest,
216  label& nearestShapeI,
217  point& linePoint,
218  point& nearestPoint,
219  const FindNearestOp& fnOp
220  ) const;
221 
222  //- Return bbox of octant
223  treeBoundBox subBbox
224  (
225  const label parentNodeI,
226  const direction octant
227  ) const;
228 
229  //- Helper: take a point on/close to face of bb and push it
230  // inside or outside of bb.
231  static point pushPoint
232  (
233  const treeBoundBox&,
234  const point&,
235  const bool pushInside
236  );
237 
238  //- Helper: take a point on face of bb and push it
239  // inside or outside of bb.
240  static point pushPoint
241  (
242  const treeBoundBox&,
243  const direction,
244  const point&,
245  const bool pushInside
246  );
247 
248  //- Helper: take point on face(s) of bb and push it away from
249  // edges of face.
250  // Guarantees that if pt is on a face it gets perturbed
251  // so it is away from the face edges.
252  // If pt is not on a face does nothing.
253  static point pushPointIntoFace
254  (
255  const treeBoundBox& bb,
256  const vector& dir, // end-start
257  const point& pt
258  );
259 
260  //- Walk to parent of node+octant.
261  bool walkToParent
262  (
263  const label nodeI,
264  const direction octant,
265  label& parentNodeI,
266  label& parentOctant
267  ) const;
268 
269  //- Walk tree to neighbouring node. Return false if edge of tree
270  // hit.
271  bool walkToNeighbour
272  (
273  const point& facePoint,
274  const direction faceID, // direction to walk in
275  label& nodeI,
276  direction& octant
277  ) const;
278 
279  //- Debug: return verbose the bounding box faces
280  static word faceString(const direction faceID);
281 
282  //- Traverse a node. If intersects a triangle return first
283  // intersection point.
284  // findAny=true : return any intersection
285  // findAny=false: return nearest (to start) intersection
286  template<class FindIntersectOp>
287  void traverseNode
288  (
289  const bool findAny,
290  const point& treeStart,
291  const vector& treeVec,
292  const point& start,
293  const point& end,
294  const label nodeI,
295  const direction octantI,
296  pointIndexHit& hitInfo,
297  direction& faceID,
298  const FindIntersectOp& fiOp
299  ) const;
300 
301  //- Find any or nearest intersection
302  template<class FindIntersectOp>
303  pointIndexHit findLine
304  (
305  const bool findAny,
306  const point& treeStart,
307  const point& treeEnd,
308  const label startNodeI,
309  const direction startOctantI,
310  const FindIntersectOp& fiOp,
311  const bool verbose = false
312  ) const;
313 
314  //- Find any or nearest intersection of line between start and end.
315  template<class FindIntersectOp>
316  pointIndexHit findLine
317  (
318  const bool findAny,
319  const point& start,
320  const point& end,
321  const FindIntersectOp& fiOp
322  ) const;
323 
324  //- Find all elements intersecting box.
325  void findBox
326  (
327  const label nodeI,
328  const treeBoundBox& searchBox,
329  labelHashSet& elements
330  ) const;
331 
332  //- Find all elements intersecting sphere.
333  void findSphere
334  (
335  const label nodeI,
336  const point& centre,
337  const scalar radiusSqr,
338  labelHashSet& elements
339  ) const;
340 
341  //- ...
342  template<class CompareOp>
343  static void findNear
344  (
345  const scalar nearDist,
346  const bool okOrder,
347  const indexedOctree<Type>& tree1,
348  const labelBits index1,
349  const treeBoundBox& bb1,
350  const indexedOctree<Type>& tree2,
351  const labelBits index2,
352  const treeBoundBox& bb2,
353  CompareOp& cop
354  );
355 
356 
357  // Other
358 
359  //- Count number of elements on this and sublevels
360  label countElements(const labelBits index) const;
361 
362  //- Dump node+octant to an obj file
363  void writeOBJ(const label nodeI, const direction octant) const;
364 
365  //- From index into contents_ to subNodes_ entry
366  static labelBits contentPlusOctant
367  (
368  const label i,
369  const direction octant
370  )
371  {
372  return labelBits(-i - 1, octant);
373  }
374 
375  //- From index into nodes_ to subNodes_ entry
376  static labelBits nodePlusOctant
377  (
378  const label i,
379  const direction octant
380  )
381  {
382  return labelBits(i + 1, octant);
383  }
384 
385  //- From empty to subNodes_ entry
386  static labelBits emptyPlusOctant
387  (
388  const direction octant
389  )
390  {
391  return labelBits(0, octant);
392  }
393 
394 public:
395 
396  //- Get the perturbation tolerance
397  static scalar& perturbTol();
398 
399 
400  // Constructors
401 
402  //- Construct null
403  indexedOctree(const Type& shapes);
404 
405  //- Construct from components
407  (
408  const Type& shapes,
409  const List<node>& nodes,
410  const labelListList& contents
411  );
412 
413  //- Construct from shapes
415  (
416  const Type& shapes,
417  const treeBoundBox& bb,
418  const label maxLevels, // maximum number of levels
419  const scalar maxLeafRatio, // how many elements per leaf
420  const scalar maxDuplicity // in how many leaves is a shape on
421  // average
422  );
423 
424  //- Construct from Istream
425  indexedOctree(const Type& shapes, Istream& is);
426 
427  //- Clone
429  {
431  (
432  new indexedOctree<Type>(*this)
433  );
434  }
435 
436 
437  // Member Functions
438 
439  // Access
440 
441  //- Reference to shape
442  const Type& shapes() const
443  {
444  return shapes_;
445  }
446 
447  //- List of all nodes
448  const List<node>& nodes() const
449  {
450  return nodes_;
451  }
452 
453  //- List of all contents (referenced by those nodes that are
454  // contents)
455  const labelListList& contents() const
456  {
457  return contents_;
458  }
459 
460  //- Top bounding box
461  const treeBoundBox& bb() const
462  {
463  if (nodes_.empty())
464  {
466  << "Tree is empty" << abort(FatalError);
467  }
468  return nodes_[0].bb_;
469  }
470 
471 
472  // Conversions for entries in subNodes_.
473 
474  static bool isContent(const labelBits i)
475  {
476  return i.val() < 0;
477  }
478 
479  static bool isEmpty(const labelBits i)
480  {
481  return i.val() == 0;
482  }
483 
484  static bool isNode(const labelBits i)
485  {
486  return i.val() > 0;
487  }
488 
489  static label getContent(const labelBits i)
490  {
491  if (!isContent(i))
492  {
494  << abort(FatalError);
495  }
496  return -i.val()-1;
497  }
498 
499  static label getNode(const labelBits i)
500  {
501  if (!isNode(i))
502  {
504  << abort(FatalError);
505  }
506  return i.val() - 1;
507  }
508 
509  static direction getOctant(const labelBits i)
510  {
511  return i.bits();
512  }
513 
514 
515  // Queries
516 
517  //- Find nearest to point
518  pointIndexHit findNearest
519  (
520  const point& sample,
521  const scalar nearestDistSqr
522  ) const;
523 
524  //- Calculate nearest point on nearest shape.
525  // Returns
526  // - bool : any point found nearer than nearestDistSqr
527  // - label: index in shapes
528  // - point: actual nearest point found
529  template<class FindNearestOp>
530  pointIndexHit findNearest
531  (
532  const point& sample,
533  const scalar nearestDistSqr,
534  const FindNearestOp& fnOp
535  ) const;
536 
537  //- Low level: calculate nearest starting from subnode.
538  template<class FindNearestOp>
539  void findNearest
540  (
541  const label nodeI,
542  const point&,
543  scalar& nearestDistSqr,
544  label& nearestShapeI,
545  point& nearestPoint,
546  const FindNearestOp& fnOp
547  ) const;
548 
549  //- Find nearest to line.
550  // Returns
551  // - bool : any point found?
552  // - label: index in shapes
553  // - point: actual nearest point found
554  // sets:
555  // - linePoint : corresponding nearest point on line
556  pointIndexHit findNearest
557  (
558  const linePointRef& ln,
559  treeBoundBox& tightest,
560  point& linePoint
561  ) const;
562 
563  //- As above but with custom operation
564  template<class FindNearestOp>
565  pointIndexHit findNearest
566  (
567  const linePointRef& ln,
568  treeBoundBox& tightest,
569  point& linePoint,
570 
571  const FindNearestOp& fnOp
572  ) const;
573 
574  //- Find nearest intersection of line between start and end.
575  pointIndexHit findLine
576  (
577  const point& start,
578  const point& end
579  ) const;
580 
581  //- Find any intersection of line between start and end.
583  (
584  const point& start,
585  const point& end
586  ) const;
587 
588  //- Find nearest intersection of line between start and end.
589  template<class FindIntersectOp>
590  pointIndexHit findLine
591  (
592  const point& start,
593  const point& end,
594  const FindIntersectOp& fiOp
595  ) const;
596 
597  //- Find any intersection of line between start and end.
598  template<class FindIntersectOp>
600  (
601  const point& start,
602  const point& end,
603  const FindIntersectOp& fiOp
604  ) const;
605 
606  //- Find (in no particular order) indices of all shapes inside or
607  // overlapping bounding box (i.e. all shapes not outside box)
608  labelList findBox(const treeBoundBox& bb) const;
609 
610  //- Find (in no particular order) indices of all shapes inside or
611  // overlapping a bounding sphere (i.e. all shapes not outside
612  // sphere)
613  labelList findSphere
614  (
615  const point& centre,
616  const scalar radiusSqr
617  ) const;
618 
619  //- Find deepest node (as parent+octant) containing point. Starts
620  // off from starting index in nodes_ (use 0 to start from top)
621  // Use getNode and getOctant to extract info, or call findIndices.
622  labelBits findNode(const label nodeI, const point&) const;
623 
624  //- Find shape containing point. Only implemented for certain
625  // shapes.
626  template<class ... Args>
627  label findInside(const point&, const Args& ...) const;
628 
629  //- Find the shape indices that occupy the result of findNode
630  const labelList& findIndices(const point&) const;
631 
632  //- Determine type (inside/outside/mixed) for point. unknown if
633  // cannot be determined (e.g. non-manifold surface)
634  volumeType getVolumeType(const point&) const;
635 
636  //- Helper function to return the side. Returns outside if
637  // outsideNormal&vec >= 0, inside otherwise
638  static volumeType getSide
639  (
640  const vector& outsideNormal,
641  const vector& vec
642  );
643 
644  //- Helper: does bb intersect a sphere around sample? Or is any
645  // corner point of bb closer than nearestDistSqr to sample.
646  static bool overlaps
647  (
648  const point& bbMin,
649  const point& bbMax,
650  const scalar nearestDistSqr,
651  const point& sample
652  );
653 
654  //- Find near pairs and apply CompareOp to them.
655  // tree2 can be *this or different tree.
656  template<class CompareOp>
657  void findNear
658  (
659  const scalar nearDist,
660  const indexedOctree<Type>& tree2,
661  CompareOp& cop
662  ) const;
663 
664 
665  // Write
666 
667  //- Print tree. Either print all indices (printContent = true) or
668  // just size of contents nodes.
669  void print
670  (
672  const bool printContents,
673  const label
674  ) const;
675 
676  //- Write to a stream
677  bool write(Ostream& os) const;
678 
679 
680  // IOstream Operators
681 
682  friend Ostream& operator<< <Type>(Ostream&, const indexedOctree<Type>&);
683 };
684 
685 
686 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
687 
688 } // End namespace Foam
689 
690 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
691 
692 #ifdef NoRepository
693  #include "indexedOctree.C"
694 #endif
695 
696 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
697 
698 #endif
699 
700 // ************************************************************************* //
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.
Definition: indexedOctree.H:79
friend Ostream & operator<<(Ostream &os, const node &n)
Definition: indexedOctree.H:91
FixedList< labelBits, 8 > subNodes_
IDs of the 8 nodes on all sides of the mid point.
Definition: indexedOctree.H:89
label parent_
Parent node (index into nodes_ of tree)
Definition: indexedOctree.H:86
friend bool operator!=(const node &a, const node &b)
friend Istream & operator>>(Istream &is, node &n)
Definition: indexedOctree.H:97
treeBoundBox bb_
Bounding box of this node.
Definition: indexedOctree.H:83
friend bool operator==(const node &a, const node &b)
Non-pointer based hierarchical recursive searching.
Definition: indexedOctree.H:72
autoPtr< indexedOctree< Type > > clone() const
Clone.
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)
indexedOctree(const Type &shapes)
Construct null.
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.
const treeBoundBox & bb() const
Top bounding box.
const labelListList & contents() const
List of all contents (referenced by those nodes that are.
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.
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
Motion of the mesh specified as a list of pointMeshMovers.
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
label facePoint(const int facei, const block &block, const label i, const label j)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
Ostream & operator<<(Ostream &os, const fvConstraints &constraints)
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