FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

indexedOctree.H

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Class
00025     Foam::indexedOctree
00026 
00027 Description
00028     Non-pointer based hierarchical recursive searching
00029 
00030 SourceFiles
00031     indexedOctree.C
00032 
00033 \*---------------------------------------------------------------------------*/
00034 
00035 #ifndef indexedOctree_H
00036 #define indexedOctree_H
00037 
00038 #include <meshTools/treeBoundBox.H>
00039 #include <meshTools/pointIndexHit.H>
00040 #include <OpenFOAM/FixedList.H>
00041 #include <OpenFOAM/Ostream.H>
00042 #include <OpenFOAM/HashSet.H>
00043 #include "labelBits.H"
00044 #include <OpenFOAM/PackedList.H>
00045 
00046 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00047 
00048 namespace Foam
00049 {
00050 
00051 // Forward declaration of classes
00052 template<class Type> class indexedOctree;
00053 template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
00054 class Istream;
00055 
00056 
00057 /*---------------------------------------------------------------------------*\
00058                         Class indexedOctreeName Declaration
00059 \*---------------------------------------------------------------------------*/
00060 
00061 TemplateName(indexedOctree);
00062 
00063 
00064 /*---------------------------------------------------------------------------*\
00065                            Class indexedOctree Declaration
00066 \*---------------------------------------------------------------------------*/
00067 
00068 template <class Type>
00069 class indexedOctree
00070 :
00071     public indexedOctreeName
00072 {
00073 public:
00074 
00075     // Data types
00076 
00077         //- volume types
00078         enum volumeType
00079         {
00080             UNKNOWN = 0,
00081             MIXED = 1,
00082             INSIDE = 2,
00083             OUTSIDE = 3
00084         };
00085 
00086 
00087     // Tree node. Has up pointer and down pointers.
00088 
00089         class node
00090         {
00091         public:
00092 
00093             //- Bounding box of this node
00094             treeBoundBox bb_;
00095 
00096             //- parent node (index into nodes_ of tree)
00097             label parent_;
00098 
00099             //- IDs of the 8 nodes on all sides of the mid point
00100             FixedList<labelBits, 8> subNodes_;
00101 
00102             friend Ostream& operator<< (Ostream& os, const node& n)
00103             {
00104                 return os << n.bb_ << token::SPACE
00105                     << n.parent_ << token::SPACE << n.subNodes_;
00106             }
00107 
00108             friend Istream& operator>> (Istream& is, node& n)
00109             {
00110                 return is >> n.bb_ >> n.parent_ >> n.subNodes_;
00111             }
00112 
00113             friend bool operator==(const node& a, const node& b)
00114             {
00115                 return
00116                     a.bb_ == b.bb_
00117                  && a.parent_ == b.parent_
00118                  && a.subNodes_ == b.subNodes_;
00119             }
00120 
00121             friend bool operator!=(const node& a, const node& b)
00122             {
00123                 return !(a == b);
00124             }
00125         };
00126 
00127 
00128 private:
00129 
00130     // Static data
00131 
00132         //- Relative peturbation tolerance. Determines when point is
00133         //  considered to be close to face/edge of bb of node.
00134         //  The tolerance is relative to the bounding box of the smallest
00135         //  node.
00136         static scalar perturbTol_;
00137 
00138 
00139     // Private data
00140 
00141         //- Underlying shapes for geometric queries.
00142         const Type shapes_;
00143 
00144         //- List of all nodes
00145         List<node> nodes_;
00146 
00147         //- List of all contents (referenced by those nodes that are contents)
00148         labelListList contents_;
00149 
00150         //- Per node per octant whether is fully inside/outside/mixed.
00151         mutable PackedList<2> nodeTypes_;
00152 
00153     // Private Member Functions
00154 
00155         //- Helper: does bb intersect a sphere around sample? Or is any
00156         //  corner point of bb closer than nearestDistSqr to sample.
00157         //  (bb is implicitly provided as parent bb + octant)
00158         static bool overlaps
00159         (
00160             const treeBoundBox& parentBb,
00161             const direction octant,
00162             const scalar nearestDistSqr,
00163             const point& sample
00164         );
00165 
00166         // Construction
00167 
00168             //- Split list of indices into 8 bins according to where they are in
00169             //  relation to mid.
00170             void divide
00171             (
00172                 const labelList& indices,
00173                 const treeBoundBox& bb,
00174                 labelListList& result
00175             ) const;
00176 
00177             //- Subdivide the contents node at position contentI. Appends to
00178             //  contents.
00179             node divide
00180             (
00181                 const treeBoundBox& bb,
00182                 DynamicList<labelList>& contents,
00183                 const label contentI
00184             ) const;
00185 
00186             //- Split any contents node with more than minSize elements.
00187             void splitNodes
00188             (
00189                 const label minSize,
00190                 DynamicList<node>& nodes,
00191                 DynamicList<labelList>& contents
00192             ) const;
00193 
00194             static label compactContents
00195             (
00196                 DynamicList<node>& nodes,
00197                 DynamicList<labelList>& contents,
00198                 const label compactLevel,
00199                 const label nodeI,
00200                 const label level,
00201                 List<labelList>& compactedContents,
00202                 label& compactI
00203             );
00204 
00205             //- Determine inside/outside per node (mixed if cannot be
00206             //  determined). Only valid for closed shapes.
00207             volumeType calcVolumeType(const label nodeI) const;
00208 
00209             //- Search cached volume type.
00210             volumeType getVolumeType(const label nodeI, const point&) const;
00211 
00212 
00213         // Query
00214 
00215             //- Find nearest point to line.
00216             void findNearest
00217             (
00218                 const label nodeI,
00219                 const linePointRef& ln,
00220 
00221                 treeBoundBox& tightest,
00222                 label& nearestShapeI,
00223                 point& linePoint,
00224                 point& nearestPoint
00225             ) const;
00226 
00227             //- Return bbox of octant
00228             treeBoundBox subBbox
00229             (
00230                 const label parentNodeI,
00231                 const direction octant
00232             ) const;
00233 
00234             //- Helper: take a point on/close to face of bb and push it
00235             //  inside or outside of bb.
00236             static point pushPoint
00237             (
00238                 const treeBoundBox&,
00239                 const point&,
00240                 const bool pushInside
00241             );
00242 
00243             //- Helper: take a point on face of bb and push it
00244             //  inside or outside of bb.
00245             static point pushPoint
00246             (
00247                 const treeBoundBox&,
00248                 const direction,
00249                 const point&,
00250                 const bool pushInside
00251             );
00252 
00253             //- Helper: take point on face(s) of bb and push it away from
00254             //  edges of face.
00255             static point pushPointIntoFace
00256             (
00257                 const treeBoundBox& bb,
00258                 const vector& dir,          // end-start
00259                 const point& pt
00260             );
00261 
00263             //static void checkMultipleFaces
00264             //(
00265             //    const treeBoundBox& bb,
00266             //    const vector& dir,          // end-start
00267             //    pointIndexHit& faceHitInfo,
00268             //    direction& faceID
00269             //);
00270 
00271             //- Walk to parent of node+octant.
00272             bool walkToParent
00273             (
00274                 const label nodeI,
00275                 const direction octant,
00276 
00277                 label& parentNodeI,
00278                 label& parentOctant
00279             ) const;
00280 
00281             //- Walk tree to neighbouring node. Return false if edge of tree
00282             //  hit.
00283             bool walkToNeighbour
00284             (
00285                 const point& facePoint,
00286                 const direction faceID,         // direction to walk in
00287                 label& nodeI,
00288                 direction& octant
00289             ) const;
00290 
00291             //- Debug: return verbose the bounding box faces
00292             static word faceString(const direction faceID);
00293 
00294             //- Traverse a node. If intersects a triangle return first
00295             // intersection point.
00296             // findAny=true : return any intersection
00297             // findAny=false: return nearest (to start) intersection
00298             void traverseNode
00299             (
00300                 const bool findAny,
00301                 const point& treeStart,
00302                 const vector& treeVec,
00303 
00304                 const point& start,
00305                 const point& end,
00306                 const label nodeI,
00307                 const direction octantI,
00308 
00309                 pointIndexHit& hitInfo,
00310                 direction& faceID
00311             ) const;
00312 
00313             //- Find any or nearest intersection
00314             pointIndexHit findLine
00315             (
00316                 const bool findAny,
00317                 const point& treeStart,
00318                 const point& treeEnd,
00319                 const label startNodeI,
00320                 const direction startOctantI,
00321                 const bool verbose = false
00322             ) const;
00323 
00324             //- Find any or nearest intersection of line between start and end.
00325             pointIndexHit findLine
00326             (
00327                 const bool findAny,
00328                 const point& start,
00329                 const point& end
00330             ) const;
00331 
00332             //- Find all elements intersecting box.
00333             void findBox
00334             (
00335                 const label nodeI,
00336                 const treeBoundBox& searchBox,
00337                 labelHashSet& elements
00338             ) const;
00339 
00340         // Other
00341 
00342             //- Count number of elements on this and sublevels
00343             label countElements(const labelBits index) const;
00344 
00345             //- Dump node+octant to an obj file
00346             void writeOBJ(const label nodeI, const direction octant) const;
00347 
00348             //- From index into contents_ to subNodes_ entry
00349             static labelBits contentPlusOctant
00350             (
00351                 const label i,
00352                 const direction octant
00353             )
00354             {
00355                 return labelBits(-i - 1, octant);
00356             }
00357 
00358             //- From index into nodes_ to subNodes_ entry
00359             static labelBits nodePlusOctant
00360             (
00361                 const label i,
00362                 const direction octant
00363             )
00364             {
00365                 return labelBits(i + 1, octant);
00366             }
00367 
00368             //- From empty to subNodes_ entry
00369             static labelBits emptyPlusOctant
00370             (
00371                 const direction octant
00372             )
00373             {
00374                 return labelBits(0, octant);
00375             }
00376 
00377 public:
00378 
00379         //- Get the perturbation tolerance
00380         static scalar& perturbTol();
00381 
00382 
00383     // Constructors
00384 
00385         //- Construct null
00386         indexedOctree(const Type& shapes);
00387 
00388         //- Construct from components
00389         indexedOctree
00390         (
00391             const Type& shapes,
00392             const List<node>& nodes,
00393             const labelListList& contents
00394         );
00395 
00396         //- Construct from shapes
00397         indexedOctree
00398         (
00399             const Type& shapes,
00400             const treeBoundBox& bb,
00401             const label maxLevels,          // maximum number of levels
00402             const scalar maxLeafRatio,      // how many elements per leaf
00403             const scalar maxDuplicity       // in how many leaves is a shape on
00404                                             // average
00405         );
00406 
00407         //- Construct from Istream
00408         indexedOctree(const Type& shapes, Istream& is);
00409 
00410         //- Clone
00411         autoPtr<indexedOctree<Type> > clone() const
00412         {
00413             return autoPtr<indexedOctree<Type> >
00414             (
00415                 new indexedOctree<Type>(*this)
00416             );
00417         }
00418 
00419     // Member Functions
00420 
00421         // Access
00422 
00423             //- Reference to shape
00424             const Type& shapes() const
00425             {
00426                 return shapes_;
00427             }
00428 
00429             //- List of all nodes
00430             const List<node>& nodes() const
00431             {
00432                 return nodes_;
00433             }
00434 
00435             //- List of all contents (referenced by those nodes that are
00436             //  contents)
00437             const labelListList& contents() const
00438             {
00439                 return contents_;
00440             }
00441 
00442             //- Top bounding box
00443             const treeBoundBox& bb() const
00444             {
00445                 if (nodes_.empty())
00446                 {
00447                     FatalErrorIn("indexedOctree<Type>::bb() const")
00448                         << "Tree is empty" << abort(FatalError);
00449                 }
00450                 return nodes_[0].bb_;
00451             }
00452 
00453 
00454         // Conversions for entries in subNodes_.
00455 
00456             static bool isContent(const labelBits i)
00457             {
00458                 return i.val() < 0;
00459             }
00460 
00461             static bool isEmpty(const labelBits i)
00462             {
00463                 return i.val() == 0;
00464             }
00465 
00466             static bool isNode(const labelBits i)
00467             {
00468                 return i.val() > 0;
00469             }
00470 
00471             static label getContent(const labelBits i)
00472             {
00473                 if (!isContent(i))
00474                 {
00475                     FatalErrorIn("getContent(const label)")
00476                         << abort(FatalError);
00477                 }
00478                 return -i.val()-1;
00479             }
00480 
00481             static label getNode(const labelBits i)
00482             {
00483                 if (!isNode(i))
00484                 {
00485                     FatalErrorIn("getNode(const label)")
00486                         << abort(FatalError);
00487                 }
00488                 return i.val() - 1;
00489             }
00490 
00491             static direction getOctant(const labelBits i)
00492             {
00493                 return i.bits();
00494             }
00495 
00496 
00497         // Queries
00498 
00499             //- Calculate nearest point on nearest shape. Returns
00500             //  - bool : any point found nearer than nearestDistSqr
00501             //  - label: index in shapes
00502             //  - point: actual nearest point found
00503             pointIndexHit findNearest
00504             (
00505                 const point& sample,
00506                 const scalar nearestDistSqr
00507             ) const;
00508 
00509             //- Low level: calculate nearest starting from subnode.
00510             void findNearest
00511             (
00512                 const label nodeI,
00513                 const point&,
00514 
00515                 scalar& nearestDistSqr,
00516                 label& nearestShapeI,
00517                 point& nearestPoint
00518             ) const;
00519 
00520             //- Find nearest to line. Returns
00521             //  - bool : any point found?
00522             //  - label: index in shapes
00523             //  - point: actual nearest point found
00524             //  sets:
00525             //  - linePoint : corresponding nearest point on line
00526             pointIndexHit findNearest
00527             (
00528                 const linePointRef& ln,
00529                 treeBoundBox& tightest,
00530                 point& linePoint
00531             ) const;
00532 
00533             //- Find nearest intersection of line between start and end.
00534             pointIndexHit findLine
00535             (
00536                 const point& start,
00537                 const point& end
00538             ) const;
00539 
00540             //- Find any intersection of line between start and end.
00541             pointIndexHit findLineAny
00542             (
00543                 const point& start,
00544                 const point& end
00545             ) const;
00546 
00547             //- Find (in no particular order) indices of all shapes inside or
00548             //  overlapping bounding box (i.e. all shapes not outside box)
00549             labelList findBox(const treeBoundBox& bb) const;
00550 
00551             //- Find deepest node (as parent+octant) containing point. Starts
00552             //  off from starting index in nodes_ (use 0 to start from top)
00553             //  Use getNode, getOctant to extract info.
00554             labelBits findNode(const label nodeI, const point&) const;
00555 
00556             //- Determine type (inside/outside/mixed) for point. unknown if
00557             //  cannot be determined (e.g. non-manifold surface)
00558             volumeType getVolumeType(const point&) const;
00559 
00560             //- Helper function to return the side. Returns outside if
00561             //  outsideNormal&vec >= 0, inside otherwise
00562             static volumeType getSide
00563             (
00564                 const vector& outsideNormal,
00565                 const vector& vec
00566             );
00567 
00568             //- Helper: does bb intersect a sphere around sample? Or is any
00569             //  corner point of bb closer than nearestDistSqr to sample.
00570             static bool overlaps
00571             (
00572                 const point& bbMin,
00573                 const point& bbMax,
00574                 const scalar nearestDistSqr,
00575                 const point& sample
00576             );
00577 
00578 
00579         // Write
00580 
00581             //- Print tree. Either print all indices (printContent = true) or
00582             //  just size of contents nodes.
00583             void print
00584             (
00585                 prefixOSstream&,
00586                 const bool printContents,
00587                 const label
00588             ) const;
00589 
00590             bool write(Ostream& os) const;
00591 
00592     // IOstream Operators
00593 
00594         friend Ostream& operator<< <Type>(Ostream&, const indexedOctree<Type>&);
00595 
00596 };
00597 
00598 
00599 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00600 
00601 } // End namespace Foam
00602 
00603 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00604 
00605 #ifdef NoRepository
00606 #   include "indexedOctree.C"
00607 #endif
00608 
00609 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00610 
00611 #endif
00612 
00613 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines