1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
28 Non-pointer based hierarchical recursive searching
33 \*---------------------------------------------------------------------------*/
35 #ifndef indexedOctree_H
36 #define indexedOctree_H
38 #include "treeBoundBox.H"
39 #include "pointIndexHit.H"
40 #include "FixedList.H"
43 #include "labelBits.H"
44 #include "PackedList.H"
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 // Forward declaration of classes
52 template<class Type> class indexedOctree;
53 template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
57 /*---------------------------------------------------------------------------*\
58 Class indexedOctreeName Declaration
59 \*---------------------------------------------------------------------------*/
61 TemplateName(indexedOctree);
64 /*---------------------------------------------------------------------------*\
65 Class indexedOctree Declaration
66 \*---------------------------------------------------------------------------*/
71 public indexedOctreeName
87 //- Tree node. Has up pointer and down pointers.
92 //- Bounding box of this node
95 //- parent node (index into nodes_ of tree)
98 //- IDs of the 8 nodes on all sides of the mid point
99 FixedList<labelBits, 8> subNodes_;
101 friend Ostream& operator<< (Ostream& os, const node& n)
103 return os << n.bb_ << token::SPACE
104 << n.parent_ << token::SPACE << n.subNodes_;
107 friend Istream& operator>> (Istream& is, node& n)
109 return is >> n.bb_ >> n.parent_ >> n.subNodes_;
112 friend bool operator==(const node& a, const node& b)
116 && a.parent_ == b.parent_
117 && a.subNodes_ == b.subNodes_;
120 friend bool operator!=(const node& a, const node& b)
131 //- Relative peturbation 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
135 static scalar perturbTol_;
140 //- Underlying shapes for geometric queries.
143 //- List of all nodes
146 //- List of all contents (referenced by those nodes that are contents)
147 labelListList contents_;
149 //- Per node per octant whether is fully inside/outside/mixed.
150 mutable PackedList<2> nodeTypes_;
152 // Private Member Functions
154 //- Helper: does bb intersect a sphere around sample? Or is any
155 // corner point of bb closer than nearestDistSqr to sample.
156 // (bb is implicitly provided as parent bb + octant)
159 const treeBoundBox& parentBb,
160 const direction octant,
161 const scalar nearestDistSqr,
167 //- Split list of indices into 8 bins
168 // according to where they are in relation to mid.
171 const labelList& indices,
172 const treeBoundBox& bb,
173 labelListList& result
176 //- Subdivide the contents node at position contentI.
177 // Appends to contents.
180 const treeBoundBox& bb,
181 DynamicList<labelList>& contents,
185 //- Split any contents node with more than minSize elements.
189 DynamicList<node>& nodes,
190 DynamicList<labelList>& contents
193 static label compactContents
195 DynamicList<node>& nodes,
196 DynamicList<labelList>& contents,
197 const label compactLevel,
200 List<labelList>& compactedContents,
204 //- Determine inside/outside per node (mixed if cannot be
205 // determined). Only valid for closed shapes.
206 volumeType calcVolumeType(const label nodeI) const;
208 //- Search cached volume type.
209 volumeType getVolumeType(const label nodeI, const point&) const;
214 //- Find nearest point to line.
218 const linePointRef& ln,
220 treeBoundBox& tightest,
221 label& nearestShapeI,
226 //- Return bbox of octant
229 const label parentNodeI,
230 const direction octant
233 //- Helper: take a point on/close to face of bb and push it
234 // inside or outside of bb.
235 static point pushPoint
239 const bool pushInside
242 //- Helper: take a point on face of bb and push it
243 // inside or outside of bb.
244 static point pushPoint
249 const bool pushInside
252 //- Helper: take point on face(s) of bb and push it away from
254 static point pushPointIntoFace
256 const treeBoundBox& bb,
257 const vector& dir, // end-start
261 ////- Push point on multiple faces away from any corner/edge.
262 //static void checkMultipleFaces
264 // const treeBoundBox& bb,
265 // const vector& dir, // end-start
266 // pointIndexHit& faceHitInfo,
270 //- Walk to parent of node+octant.
274 const direction octant,
280 //- Walk tree to neighbouring node. Return false if edge of tree
284 const point& facePoint,
285 const direction faceID, // direction to walk in
290 //- Debug: return verbose the bounding box faces
291 static word faceString(const direction faceID);
293 //- Traverse a node. If intersects a triangle return first
294 // intersection point.
295 // findAny=true : return any intersection
296 // findAny=false: return nearest (to start) intersection
300 const point& treeStart,
301 const vector& treeVec,
306 const direction octantI,
308 pointIndexHit& hitInfo,
312 //- Find any or nearest intersection
313 pointIndexHit findLine
316 const point& treeStart,
317 const point& treeEnd,
318 const label startNodeI,
319 const direction startOctantI,
320 const bool verbose = false
323 //- Find any or nearest intersection of line between start and end.
324 pointIndexHit findLine
331 //- Find all elements intersecting box.
335 const treeBoundBox& searchBox,
336 labelHashSet& elements
340 template <class CompareOp>
343 const scalar nearDist,
345 const indexedOctree<Type>& tree1,
346 const labelBits index1,
347 const treeBoundBox& bb1,
348 const indexedOctree<Type>& tree2,
349 const labelBits index2,
350 const treeBoundBox& bb2,
357 //- Count number of elements on this and sublevels
358 label countElements(const labelBits index) const;
360 //- Dump node+octant to an obj file
361 void writeOBJ(const label nodeI, const direction octant) const;
363 //- From index into contents_ to subNodes_ entry
364 static labelBits contentPlusOctant
367 const direction octant
370 return labelBits(-i - 1, octant);
373 //- From index into nodes_ to subNodes_ entry
374 static labelBits nodePlusOctant
377 const direction octant
380 return labelBits(i + 1, octant);
383 //- From empty to subNodes_ entry
384 static labelBits emptyPlusOctant
386 const direction octant
389 return labelBits(0, octant);
394 //- Get the perturbation tolerance
395 static scalar& perturbTol();
401 indexedOctree(const Type& shapes);
403 //- Construct from components
407 const List<node>& nodes,
408 const labelListList& contents
411 //- Construct from shapes
415 const treeBoundBox& bb,
416 const label maxLevels, // maximum number of levels
417 const scalar maxLeafRatio, // how many elements per leaf
418 const scalar maxDuplicity // in how many leaves is a shape on
422 //- Construct from Istream
423 indexedOctree(const Type& shapes, Istream& is);
426 autoPtr<indexedOctree<Type> > clone() const
428 return autoPtr<indexedOctree<Type> >
430 new indexedOctree<Type>(*this)
438 //- Reference to shape
439 const Type& shapes() const
444 //- List of all nodes
445 const List<node>& nodes() const
450 //- List of all contents (referenced by those nodes that are
452 const labelListList& contents() const
458 const treeBoundBox& bb() const
462 FatalErrorIn("indexedOctree<Type>::bb() const")
463 << "Tree is empty" << abort(FatalError);
465 return nodes_[0].bb_;
469 // Conversions for entries in subNodes_.
471 static bool isContent(const labelBits i)
476 static bool isEmpty(const labelBits i)
481 static bool isNode(const labelBits i)
486 static label getContent(const labelBits i)
490 FatalErrorIn("getContent(const label)")
491 << abort(FatalError);
496 static label getNode(const labelBits i)
500 FatalErrorIn("getNode(const label)")
501 << abort(FatalError);
506 static direction getOctant(const labelBits i)
514 //- Calculate nearest point on nearest shape.
516 // - bool : any point found nearer than nearestDistSqr
517 // - label: index in shapes
518 // - point: actual nearest point found
519 pointIndexHit findNearest
522 const scalar nearestDistSqr
525 //- Low level: calculate nearest starting from subnode.
531 scalar& nearestDistSqr,
532 label& nearestShapeI,
536 //- Find nearest to line.
538 // - bool : any point found?
539 // - label: index in shapes
540 // - point: actual nearest point found
542 // - linePoint : corresponding nearest point on line
543 pointIndexHit findNearest
545 const linePointRef& ln,
546 treeBoundBox& tightest,
550 //- Find nearest intersection of line between start and end.
551 pointIndexHit findLine
557 //- Find any intersection of line between start and end.
558 pointIndexHit findLineAny
564 //- Find (in no particular order) indices of all shapes inside or
565 // overlapping bounding box (i.e. all shapes not outside box)
566 labelList findBox(const treeBoundBox& bb) const;
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;
573 //- Find shape containing point. Only implemented for certain
575 label findInside(const point&) const;
577 //- Find the shape indices that occupy the result of findNode
578 const labelList& findIndices(const point&) const;
580 //- Determine type (inside/outside/mixed) for point. unknown if
581 // cannot be determined (e.g. non-manifold surface)
582 volumeType getVolumeType(const point&) const;
584 //- Helper function to return the side. Returns outside if
585 // outsideNormal&vec >= 0, inside otherwise
586 static volumeType getSide
588 const vector& outsideNormal,
592 //- Helper: does bb intersect a sphere around sample? Or is any
593 // corner point of bb closer than nearestDistSqr to sample.
598 const scalar nearestDistSqr,
602 //- Find near pairs and apply CompareOp to them.
603 // tree2 can be *this or different tree.
604 template <class CompareOp>
607 const scalar nearDist,
608 const indexedOctree<Type>& tree2,
615 //- Print tree. Either print all indices (printContent = true) or
616 // just size of contents nodes.
620 const bool printContents,
624 bool write(Ostream& os) const;
627 // IOstream Operators
629 friend Ostream& operator<< <Type>(Ostream&, const indexedOctree<Type>&);
633 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
635 } // End namespace Foam
637 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
640 # include "indexedOctree.C"
643 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
647 // ************************************************************************* //