1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 Non-pointer based hierarchical recursive searching
34 \*---------------------------------------------------------------------------*/
36 #ifndef indexedOctree_H
37 #define indexedOctree_H
39 #include "treeBoundBox.H"
40 #include "pointIndexHit.H"
41 #include "FixedList.H"
44 #include "labelBits.H"
45 #include "PackedList.H"
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
52 // Forward declaration of classes
53 template<class Type> class indexedOctree;
54 template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
58 /*---------------------------------------------------------------------------*\
59 Class indexedOctreeName Declaration
60 \*---------------------------------------------------------------------------*/
62 TemplateName(indexedOctree);
65 /*---------------------------------------------------------------------------*\
66 Class indexedOctree Declaration
67 \*---------------------------------------------------------------------------*/
72 public indexedOctreeName
88 // Tree node. Has up pointer and down pointers.
94 //- Bounding box of this node
97 //- parent node (index into nodes_ of tree)
100 //- IDs of the 8 nodes on all sides of the mid point
101 FixedList<labelBits, 8> subNodes_;
103 friend Ostream& operator<< (Ostream& os, const node& n)
105 return os << n.bb_ << token::SPACE
106 << n.parent_ << token::SPACE << n.subNodes_;
109 friend Istream& operator>> (Istream& is, node& n)
111 return is >> n.bb_ >> n.parent_ >> n.subNodes_;
114 friend bool operator==(const node& a, const node& b)
118 && a.parent_ == b.parent_
119 && a.subNodes_ == b.subNodes_;
122 friend bool operator!=(const node& a, const node& b)
133 //- Relative peturbation tolerance. Determines when point is
134 // considered to be close to face/edge of bb of node.
135 // The tolerance is relative to the bounding box of the smallest
137 static scalar perturbTol_;
142 //- Underlying shapes for geometric queries.
145 //- List of all nodes
148 //- List of all contents (referenced by those nodes that are contents)
149 labelListList contents_;
151 //- Per node per octant whether is fully inside/outside/mixed.
152 mutable PackedList<2> nodeTypes_;
154 // Private Member Functions
156 //- Helper: does bb intersect a sphere around sample? Or is any
157 // corner point of bb closer than nearestDistSqr to sample.
158 // (bb is implicitly provided as parent bb + octant)
161 const treeBoundBox& parentBb,
162 const direction octant,
163 const scalar nearestDistSqr,
169 //- Split list of indices into 8 bins according to where they are in
173 const labelList& indices,
174 const treeBoundBox& bb,
175 labelListList& result
178 //- Subdivide the contents node at position contentI. Appends to
182 const treeBoundBox& bb,
183 DynamicList<labelList>& contents,
187 //- Split any contents node with more than minSize elements.
191 DynamicList<node>& nodes,
192 DynamicList<labelList>& contents
195 static label compactContents
197 DynamicList<node>& nodes,
198 DynamicList<labelList>& contents,
199 const label compactLevel,
202 List<labelList>& compactedContents,
206 //- Determine inside/outside per node (mixed if cannot be
207 // determined). Only valid for closed shapes.
208 volumeType calcVolumeType(const label nodeI) const;
210 //- Search cached volume type.
211 volumeType getVolumeType(const label nodeI, const point&) const;
216 //- Find nearest point to line.
220 const linePointRef& ln,
222 treeBoundBox& tightest,
223 label& nearestShapeI,
228 //- Return bbox of octant
231 const label parentNodeI,
232 const direction octant
235 //- Helper: take a point on/close to face of bb and push it
236 // inside or outside of bb.
237 static point pushPoint
241 const bool pushInside
244 //- Helper: take a point on face of bb and push it
245 // inside or outside of bb.
246 static point pushPoint
251 const bool pushInside
254 //- Helper: take point on face(s) of bb and push it away from
256 static point pushPointIntoFace
258 const treeBoundBox& bb,
259 const vector& dir, // end-start
263 ////- Push point on multiple faces away from any corner/edge.
264 //static void checkMultipleFaces
266 // const treeBoundBox& bb,
267 // const vector& dir, // end-start
268 // pointIndexHit& faceHitInfo,
272 //- Walk to parent of node+octant.
276 const direction octant,
282 //- Walk tree to neighbouring node. Return false if edge of tree
286 const point& facePoint,
287 const direction faceID, // direction to walk in
292 //- Debug: return verbose the bounding box faces
293 static word faceString(const direction faceID);
295 //- Traverse a node. If intersects a triangle return first
296 // intersection point.
297 // findAny=true : return any intersection
298 // findAny=false: return nearest (to start) intersection
302 const point& treeStart,
303 const vector& treeVec,
308 const direction octantI,
310 pointIndexHit& hitInfo,
314 //- Find any or nearest intersection
315 pointIndexHit findLine
318 const point& treeStart,
319 const point& treeEnd,
320 const label startNodeI,
321 const direction startOctantI,
322 const bool verbose = false
325 //- Find any or nearest intersection of line between start and end.
326 pointIndexHit findLine
333 //- Find all elements intersecting box.
337 const treeBoundBox& searchBox,
338 labelHashSet& elements
343 //- Count number of elements on this and sublevels
344 label countElements(const labelBits index) const;
346 //- Dump node+octant to an obj file
347 void writeOBJ(const label nodeI, const direction octant) const;
349 //- From index into contents_ to subNodes_ entry
350 static labelBits contentPlusOctant
353 const direction octant
356 return labelBits(-i - 1, octant);
359 //- From index into nodes_ to subNodes_ entry
360 static labelBits nodePlusOctant
363 const direction octant
366 return labelBits(i + 1, octant);
369 //- From empty to subNodes_ entry
370 static labelBits emptyPlusOctant
372 const direction octant
375 return labelBits(0, octant);
380 //- Get the perturbation tolerance
381 static scalar& perturbTol();
387 indexedOctree(const Type& shapes);
389 //- Construct from components
393 const List<node>& nodes,
394 const labelListList& contents
397 //- Construct from shapes
401 const treeBoundBox& bb,
402 const label maxLevels, // maximum number of levels
403 const scalar maxLeafRatio, // how many elements per leaf
404 const scalar maxDuplicity // in how many leaves is a shape on
408 //- Construct from Istream
409 indexedOctree(const Type& shapes, Istream& is);
412 autoPtr<indexedOctree<Type> > clone() const
414 return autoPtr<indexedOctree<Type> >
416 new indexedOctree<Type>(*this)
424 //- Reference to shape
425 const Type& shapes() const
430 //- List of all nodes
431 const List<node>& nodes() const
436 //- List of all contents (referenced by those nodes that are
438 const labelListList& contents() const
444 const treeBoundBox& bb() const
448 FatalErrorIn("indexedOctree<Type>::bb() const")
449 << "Tree is empty" << abort(FatalError);
451 return nodes_[0].bb_;
455 // Conversions for entries in subNodes_.
457 static bool isContent(const labelBits i)
462 static bool isEmpty(const labelBits i)
467 static bool isNode(const labelBits i)
472 static label getContent(const labelBits i)
476 FatalErrorIn("getContent(const label)")
477 << abort(FatalError);
482 static label getNode(const labelBits i)
486 FatalErrorIn("getNode(const label)")
487 << abort(FatalError);
492 static direction getOctant(const labelBits i)
500 //- Calculate nearest point on nearest shape. Returns
501 // - bool : any point found nearer than nearestDistSqr
502 // - label: index in shapes
503 // - point: actual nearest point found
504 pointIndexHit findNearest
507 const scalar nearestDistSqr
510 //- Low level: calculate nearest starting from subnode.
516 scalar& nearestDistSqr,
517 label& nearestShapeI,
521 //- Find nearest to line. Returns
522 // - bool : any point found?
523 // - label: index in shapes
524 // - point: actual nearest point found
526 // - linePoint : corresponding nearest point on line
527 pointIndexHit findNearest
529 const linePointRef& ln,
530 treeBoundBox& tightest,
534 //- Find nearest intersection of line between start and end.
535 pointIndexHit findLine
541 //- Find any intersection of line between start and end.
542 pointIndexHit findLineAny
548 //- Find (in no particular order) indices of all shapes inside or
549 // overlapping bounding box (i.e. all shapes not outside box)
550 labelList findBox(const treeBoundBox& bb) const;
552 //- Find deepest node (as parent+octant) containing point. Starts
553 // off from starting index in nodes_ (use 0 to start from top)
554 // Use getNode, getOctant to extract info.
555 labelBits findNode(const label nodeI, const point&) const;
557 //- Determine type (inside/outside/mixed) for point. unknown if
558 // cannot be determined (e.g. non-manifold surface)
559 volumeType getVolumeType(const point&) const;
561 //- Helper function to return the side. Returns outside if
562 // outsideNormal&vec >= 0, inside otherwise
563 static volumeType getSide
565 const vector& outsideNormal,
569 //- Helper: does bb intersect a sphere around sample? Or is any
570 // corner point of bb closer than nearestDistSqr to sample.
575 const scalar nearestDistSqr,
582 //- Print tree. Either print all indices (printContent = true) or
583 // just size of contents nodes.
587 const bool printContents,
591 bool write(Ostream& os) const;
593 // IOstream Operators
595 friend Ostream& operator<< <Type>(Ostream&, const indexedOctree<Type>&);
600 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
602 } // End namespace Foam
604 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
607 # include "indexedOctree.C"
610 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
614 // ************************************************************************* //