mirror of
https://github.com/OpenFOAM/OpenFOAM-6.git
synced 2025-12-08 06:57:46 +00:00
Add the OpenFOAM source tree
This commit is contained in:
3019
src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.C
Normal file
3019
src/OpenFOAM/algorithms/dynamicIndexedOctree/dynamicIndexedOctree.C
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,693 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::dynamicIndexedOctree
|
||||
|
||||
Description
|
||||
Non-pointer based hierarchical recursive searching.
|
||||
Storage is dynamic, so elements can be deleted.
|
||||
|
||||
SourceFiles
|
||||
dynamicIndexedOctree.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef dynamicIndexedOctree_H
|
||||
#define dynamicIndexedOctree_H
|
||||
|
||||
#include "treeBoundBox.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "FixedList.H"
|
||||
#include "Ostream.H"
|
||||
#include "HashSet.H"
|
||||
#include "labelBits.H"
|
||||
#include "PackedList.H"
|
||||
#include "volumeType.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
typedef DynamicList<autoPtr<DynamicList<label > > > contentListList;
|
||||
|
||||
// Forward declaration of classes
|
||||
template<class Type> class dynamicIndexedOctree;
|
||||
|
||||
template<class Type> Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const dynamicIndexedOctree<Type>&
|
||||
);
|
||||
|
||||
class Istream;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class dynamicIndexedOctreeName Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
TemplateName(dynamicIndexedOctree);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class dynamicIndexedOctree Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class dynamicIndexedOctree
|
||||
:
|
||||
public dynamicIndexedOctreeName
|
||||
{
|
||||
public:
|
||||
|
||||
// Data types
|
||||
|
||||
//- Tree node. Has up pointer and down pointers.
|
||||
class node
|
||||
{
|
||||
public:
|
||||
|
||||
//- Bounding box of this node
|
||||
treeBoundBox bb_;
|
||||
|
||||
//- parent node (index into nodes_ of tree)
|
||||
label parent_;
|
||||
|
||||
//- IDs of the 8 nodes on all sides of the mid point
|
||||
FixedList<labelBits, 8> subNodes_;
|
||||
|
||||
friend Ostream& operator<< (Ostream& os, const node& n)
|
||||
{
|
||||
return os << n.bb_ << token::SPACE
|
||||
<< n.parent_ << token::SPACE << n.subNodes_;
|
||||
}
|
||||
|
||||
friend Istream& operator>> (Istream& is, node& n)
|
||||
{
|
||||
return is >> n.bb_ >> n.parent_ >> n.subNodes_;
|
||||
}
|
||||
|
||||
friend bool operator==(const node& a, const node& b)
|
||||
{
|
||||
return
|
||||
a.bb_ == b.bb_
|
||||
&& a.parent_ == b.parent_
|
||||
&& a.subNodes_ == b.subNodes_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const node& a, const node& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Static data
|
||||
|
||||
//- Relative peturbation tolerance. Determines when point is
|
||||
// considered to be close to face/edge of bb of node.
|
||||
// The tolerance is relative to the bounding box of the smallest
|
||||
// node.
|
||||
static scalar perturbTol_;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Underlying shapes for geometric queries.
|
||||
const Type shapes_;
|
||||
|
||||
const treeBoundBox bb_;
|
||||
|
||||
const label maxLevels_;
|
||||
|
||||
//- Current number of levels in the tree.
|
||||
label nLevelsMax_;
|
||||
|
||||
const scalar maxLeafRatio_;
|
||||
|
||||
const label minSize_;
|
||||
|
||||
const scalar maxDuplicity_;
|
||||
|
||||
//- List of all nodes
|
||||
DynamicList<node> nodes_;
|
||||
|
||||
//- List of all contents (referenced by those nodes that are contents)
|
||||
contentListList contents_;
|
||||
|
||||
//- Per node per octant whether is fully inside/outside/mixed.
|
||||
mutable PackedList<2> nodeTypes_;
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper: does bb intersect a sphere around sample? Or is any
|
||||
// corner point of bb closer than nearestDistSqr to sample.
|
||||
// (bb is implicitly provided as parent bb + octant)
|
||||
static bool overlaps
|
||||
(
|
||||
const treeBoundBox& parentBb,
|
||||
const direction octant,
|
||||
const scalar nearestDistSqr,
|
||||
const point& sample
|
||||
);
|
||||
|
||||
// Construction
|
||||
|
||||
//- Split list of indices into 8 bins
|
||||
// according to where they are in relation to mid.
|
||||
void divide
|
||||
(
|
||||
const autoPtr<DynamicList<label> >& indices,
|
||||
const treeBoundBox& bb,
|
||||
contentListList& result
|
||||
) const;
|
||||
|
||||
//- Subdivide the contents node at position contentI.
|
||||
// Appends to contents.
|
||||
node divide
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
const label contentI,
|
||||
const label parentNodeIndex,
|
||||
const label octantToBeDivided
|
||||
);
|
||||
|
||||
// Recursively call the divide function
|
||||
void recursiveSubDivision
|
||||
(
|
||||
const treeBoundBox& subBb,
|
||||
const label contentI,
|
||||
const label parentIndex,
|
||||
const label octant,
|
||||
label& nLevels
|
||||
);
|
||||
|
||||
// static label compactContents
|
||||
// (
|
||||
// DynamicList<node>& nodes,
|
||||
// DynamicList<labelList>& contents,
|
||||
// const label compactLevel,
|
||||
// const label nodeI,
|
||||
// const label level,
|
||||
// List<labelList>& compactedContents,
|
||||
// label& compactI
|
||||
// );
|
||||
|
||||
//- Determine inside/outside per node (mixed if cannot be
|
||||
// determined). Only valid for closed shapes.
|
||||
volumeType calcVolumeType(const label nodeI) const;
|
||||
|
||||
//- Search cached volume type.
|
||||
volumeType getVolumeType(const label nodeI, const point&) const;
|
||||
|
||||
|
||||
// Query
|
||||
|
||||
//- Find nearest point to line.
|
||||
void findNearest
|
||||
(
|
||||
const label nodeI,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& nearestShapeI,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Return bbox of octant
|
||||
treeBoundBox subBbox
|
||||
(
|
||||
const label parentNodeI,
|
||||
const direction octant
|
||||
) const;
|
||||
|
||||
//- Helper: take a point on/close to face of bb and push it
|
||||
// inside or outside of bb.
|
||||
static point pushPoint
|
||||
(
|
||||
const treeBoundBox&,
|
||||
const point&,
|
||||
const bool pushInside
|
||||
);
|
||||
|
||||
//- Helper: take a point on face of bb and push it
|
||||
// inside or outside of bb.
|
||||
static point pushPoint
|
||||
(
|
||||
const treeBoundBox&,
|
||||
const direction,
|
||||
const point&,
|
||||
const bool pushInside
|
||||
);
|
||||
|
||||
//- Helper: take point on face(s) of bb and push it away from
|
||||
// edges of face.
|
||||
static point pushPointIntoFace
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
const vector& dir, // end-start
|
||||
const point& pt
|
||||
);
|
||||
|
||||
////- Push point on multiple faces away from any corner/edge.
|
||||
//static void checkMultipleFaces
|
||||
//(
|
||||
// const treeBoundBox& bb,
|
||||
// const vector& dir, // end-start
|
||||
// pointIndexHit& faceHitInfo,
|
||||
// direction& faceID
|
||||
//);
|
||||
|
||||
//- Walk to parent of node+octant.
|
||||
bool walkToParent
|
||||
(
|
||||
const label nodeI,
|
||||
const direction octant,
|
||||
|
||||
label& parentNodeI,
|
||||
label& parentOctant
|
||||
) const;
|
||||
|
||||
//- Walk tree to neighbouring node. Return false if edge of tree
|
||||
// hit.
|
||||
bool walkToNeighbour
|
||||
(
|
||||
const point& facePoint,
|
||||
const direction faceID, // direction to walk in
|
||||
label& nodeI,
|
||||
direction& octant
|
||||
) const;
|
||||
|
||||
//- Debug: return verbose the bounding box faces
|
||||
static word faceString(const direction faceID);
|
||||
|
||||
//- Traverse a node. If intersects a triangle return first
|
||||
// intersection point.
|
||||
// findAny=true : return any intersection
|
||||
// findAny=false: return nearest (to start) intersection
|
||||
void traverseNode
|
||||
(
|
||||
const bool findAny,
|
||||
const point& treeStart,
|
||||
const vector& treeVec,
|
||||
|
||||
const point& start,
|
||||
const point& end,
|
||||
const label nodeI,
|
||||
const direction octantI,
|
||||
|
||||
pointIndexHit& hitInfo,
|
||||
direction& faceID
|
||||
) const;
|
||||
|
||||
//- Find any or nearest intersection
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const bool findAny,
|
||||
const point& treeStart,
|
||||
const point& treeEnd,
|
||||
const label startNodeI,
|
||||
const direction startOctantI,
|
||||
const bool verbose = false
|
||||
) const;
|
||||
|
||||
//- Find any or nearest intersection of line between start and end.
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const bool findAny,
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find all elements intersecting box.
|
||||
void findBox
|
||||
(
|
||||
const label nodeI,
|
||||
const treeBoundBox& searchBox,
|
||||
labelHashSet& elements
|
||||
) const;
|
||||
|
||||
|
||||
//- Find all elements intersecting sphere.
|
||||
void findSphere
|
||||
(
|
||||
const label nodeI,
|
||||
const point& centre,
|
||||
const scalar radiusSqr,
|
||||
labelHashSet& elements
|
||||
) const;
|
||||
|
||||
|
||||
template<class CompareOp>
|
||||
static void findNear
|
||||
(
|
||||
const scalar nearDist,
|
||||
const bool okOrder,
|
||||
const dynamicIndexedOctree<Type>& tree1,
|
||||
const labelBits index1,
|
||||
const treeBoundBox& bb1,
|
||||
const dynamicIndexedOctree<Type>& tree2,
|
||||
const labelBits index2,
|
||||
const treeBoundBox& bb2,
|
||||
CompareOp& cop
|
||||
);
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Count number of elements on this and sublevels
|
||||
label countElements(const labelBits index) const;
|
||||
|
||||
//- Dump node+octant to an obj file
|
||||
void writeOBJ(const label nodeI, const direction octant) const;
|
||||
|
||||
//- From index into contents_ to subNodes_ entry
|
||||
static labelBits contentPlusOctant
|
||||
(
|
||||
const label i,
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(-i - 1, octant);
|
||||
}
|
||||
|
||||
//- From index into nodes_ to subNodes_ entry
|
||||
static labelBits nodePlusOctant
|
||||
(
|
||||
const label i,
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(i + 1, octant);
|
||||
}
|
||||
|
||||
//- From empty to subNodes_ entry
|
||||
static labelBits emptyPlusOctant
|
||||
(
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(0, octant);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//- Get the perturbation tolerance
|
||||
static scalar& perturbTol();
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from shapes
|
||||
dynamicIndexedOctree
|
||||
(
|
||||
const Type& shapes,
|
||||
const treeBoundBox& bb,
|
||||
const label maxLevels, // maximum number of levels
|
||||
const scalar maxLeafRatio, // how many elements per leaf
|
||||
const scalar maxDuplicity // in how many leaves is a shape on
|
||||
// average
|
||||
);
|
||||
|
||||
//- Clone
|
||||
autoPtr<dynamicIndexedOctree<Type> > clone() const
|
||||
{
|
||||
return autoPtr<dynamicIndexedOctree<Type> >
|
||||
(
|
||||
new dynamicIndexedOctree<Type>(*this)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Reference to shape
|
||||
const Type& shapes() const
|
||||
{
|
||||
return shapes_;
|
||||
}
|
||||
|
||||
//- List of all nodes
|
||||
const List<node>& nodes() const
|
||||
{
|
||||
return nodes_;
|
||||
}
|
||||
|
||||
//- List of all contents (referenced by those nodes that are
|
||||
// contents)
|
||||
const contentListList& contents() const
|
||||
{
|
||||
return contents_;
|
||||
}
|
||||
|
||||
//- Top bounding box
|
||||
const treeBoundBox& bb() const
|
||||
{
|
||||
if (nodes_.empty())
|
||||
{
|
||||
FatalErrorIn("dynamicIndexedOctree<Type>::bb() const")
|
||||
<< "Tree is empty" << abort(FatalError);
|
||||
}
|
||||
return nodes_[0].bb_;
|
||||
}
|
||||
|
||||
|
||||
// Conversions for entries in subNodes_.
|
||||
|
||||
static bool isContent(const labelBits i)
|
||||
{
|
||||
return i.val() < 0;
|
||||
}
|
||||
|
||||
static bool isEmpty(const labelBits i)
|
||||
{
|
||||
return i.val() == 0;
|
||||
}
|
||||
|
||||
static bool isNode(const labelBits i)
|
||||
{
|
||||
return i.val() > 0;
|
||||
}
|
||||
|
||||
static label getContent(const labelBits i)
|
||||
{
|
||||
if (!isContent(i))
|
||||
{
|
||||
FatalErrorIn("getContent(const label)")
|
||||
<< abort(FatalError);
|
||||
}
|
||||
return -i.val()-1;
|
||||
}
|
||||
|
||||
static label getNode(const labelBits i)
|
||||
{
|
||||
if (!isNode(i))
|
||||
{
|
||||
FatalErrorIn("getNode(const label)")
|
||||
<< abort(FatalError);
|
||||
}
|
||||
return i.val() - 1;
|
||||
}
|
||||
|
||||
static direction getOctant(const labelBits i)
|
||||
{
|
||||
return i.bits();
|
||||
}
|
||||
|
||||
|
||||
// Queries
|
||||
|
||||
//- Calculate nearest point on nearest shape.
|
||||
// Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: index in shapes
|
||||
// - point: actual nearest point found
|
||||
pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Low level: calculate nearest starting from subnode.
|
||||
void findNearest
|
||||
(
|
||||
const label nodeI,
|
||||
const point&,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestShapeI,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Find nearest to line.
|
||||
// Returns
|
||||
// - bool : any point found?
|
||||
// - label: index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - linePoint : corresponding nearest point on line
|
||||
pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find (in no particular order) indices of all shapes inside or
|
||||
// overlapping bounding box (i.e. all shapes not outside box)
|
||||
labelList findBox(const treeBoundBox& bb) const;
|
||||
|
||||
//- Find (in no particular order) indices of all shapes inside or
|
||||
// overlapping a bounding sphere (i.e. all shapes not outside
|
||||
// sphere)
|
||||
labelList findSphere
|
||||
(
|
||||
const point& centre,
|
||||
const scalar radiusSqr
|
||||
) const;
|
||||
|
||||
//- Find deepest node (as parent+octant) containing point. Starts
|
||||
// off from starting index in nodes_ (use 0 to start from top)
|
||||
// Use getNode and getOctant to extract info, or call findIndices.
|
||||
labelBits findNode(const label nodeI, const point&) const;
|
||||
|
||||
//- Find shape containing point. Only implemented for certain
|
||||
// shapes.
|
||||
label findInside(const point&) const;
|
||||
|
||||
//- Find the shape indices that occupy the result of findNode
|
||||
const labelList& findIndices(const point&) const;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
volumeType getVolumeType(const point&) const;
|
||||
|
||||
//- Helper function to return the side. Returns outside if
|
||||
// outsideNormal&vec >= 0, inside otherwise
|
||||
static volumeType getSide
|
||||
(
|
||||
const vector& outsideNormal,
|
||||
const vector& vec
|
||||
);
|
||||
|
||||
//- Helper: does bb intersect a sphere around sample? Or is any
|
||||
// corner point of bb closer than nearestDistSqr to sample.
|
||||
static bool overlaps
|
||||
(
|
||||
const point& bbMin,
|
||||
const point& bbMax,
|
||||
const scalar nearestDistSqr,
|
||||
const point& sample
|
||||
);
|
||||
|
||||
//- Find near pairs and apply CompareOp to them.
|
||||
// tree2 can be *this or different tree.
|
||||
template<class CompareOp>
|
||||
void findNear
|
||||
(
|
||||
const scalar nearDist,
|
||||
const dynamicIndexedOctree<Type>& tree2,
|
||||
CompareOp& cop
|
||||
) const;
|
||||
|
||||
|
||||
// Edit
|
||||
|
||||
//- Insert a new object into the tree.
|
||||
bool insert(label startIndex, label endIndex);
|
||||
|
||||
bool insertIndex
|
||||
(
|
||||
const label nodIndex,
|
||||
const label index,
|
||||
label& nLevels
|
||||
);
|
||||
|
||||
//- Remove an object from the tree.
|
||||
bool remove(const label index);
|
||||
|
||||
label removeIndex(const label nodIndex, const label index);
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- Print tree. Either print all indices (printContent = true) or
|
||||
// just size of contents nodes.
|
||||
void print
|
||||
(
|
||||
prefixOSstream&,
|
||||
const bool printContents,
|
||||
const label
|
||||
) const;
|
||||
|
||||
bool write(Ostream& os) const;
|
||||
|
||||
void writeTreeInfo() const;
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
friend Ostream& operator<< <Type>
|
||||
(
|
||||
Ostream&,
|
||||
const dynamicIndexedOctree<Type>&
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "dynamicIndexedOctree.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "dynamicIndexedOctree.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(dynamicIndexedOctreeName, 0);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,187 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "dynamicTreeDataPoint.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "dynamicIndexedOctree.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(dynamicTreeDataPoint, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::dynamicTreeDataPoint::dynamicTreeDataPoint
|
||||
(
|
||||
const DynamicList<point>& points
|
||||
)
|
||||
:
|
||||
points_(points)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
const Foam::DynamicList<Foam::point>&
|
||||
Foam::dynamicTreeDataPoint::shapePoints() const
|
||||
{
|
||||
return points_;
|
||||
}
|
||||
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
Foam::volumeType Foam::dynamicTreeDataPoint::getVolumeType
|
||||
(
|
||||
const dynamicIndexedOctree<dynamicTreeDataPoint>& oc,
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
return volumeType::UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
// Check if any point on shape is inside cubeBb.
|
||||
bool Foam::dynamicTreeDataPoint::overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& cubeBb
|
||||
) const
|
||||
{
|
||||
return cubeBb.contains(points_[index]);
|
||||
}
|
||||
|
||||
|
||||
// Check if any point on shape is inside sphere.
|
||||
bool Foam::dynamicTreeDataPoint::overlaps
|
||||
(
|
||||
const label index,
|
||||
const point& centre,
|
||||
const scalar radiusSqr
|
||||
) const
|
||||
{
|
||||
const point& p = points_[index];
|
||||
|
||||
const scalar distSqr = magSqr(p - centre);
|
||||
|
||||
if (distSqr <= radiusSqr)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
|
||||
// nearestPoint.
|
||||
void Foam::dynamicTreeDataPoint::findNearest
|
||||
(
|
||||
const labelUList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
forAll(indices, i)
|
||||
{
|
||||
const label index = indices[i];
|
||||
|
||||
const point& pt = points_[index];
|
||||
|
||||
scalar distSqr = magSqr(pt - sample);
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
nearestPoint = pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void Foam::dynamicTreeDataPoint::findNearest
|
||||
(
|
||||
const labelUList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
// Best so far
|
||||
scalar nearestDistSqr = magSqr(linePoint - nearestPoint);
|
||||
|
||||
forAll(indices, i)
|
||||
{
|
||||
const label index = indices[i];
|
||||
|
||||
const point& shapePt = points_[index];
|
||||
|
||||
if (tightest.contains(shapePt))
|
||||
{
|
||||
// Nearest point on line
|
||||
pointHit pHit = ln.nearestDist(shapePt);
|
||||
scalar distSqr = sqr(pHit.distance());
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
linePoint = pHit.rawPoint();
|
||||
nearestPoint = shapePt;
|
||||
|
||||
{
|
||||
point& minPt = tightest.min();
|
||||
minPt = min(ln.start(), ln.end());
|
||||
minPt.x() -= pHit.distance();
|
||||
minPt.y() -= pHit.distance();
|
||||
minPt.z() -= pHit.distance();
|
||||
}
|
||||
{
|
||||
point& maxPt = tightest.max();
|
||||
maxPt = max(ln.start(), ln.end());
|
||||
maxPt.x() += pHit.distance();
|
||||
maxPt.y() += pHit.distance();
|
||||
maxPt.z() += pHit.distance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,172 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2012-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::dynamicTreeDataPoint
|
||||
|
||||
Description
|
||||
Holds (reference to) pointField. Encapsulation of data needed for
|
||||
octree searches.
|
||||
Used for searching for nearest point. No bounding boxes around points.
|
||||
Only overlaps and calcNearest are implemented, rest makes little sense.
|
||||
|
||||
Optionally works on subset of points.
|
||||
|
||||
SourceFiles
|
||||
dynamicTreeDataPoint.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef dynamicTreeDataPoint_H
|
||||
#define dynamicTreeDataPoint_H
|
||||
|
||||
#include "pointField.H"
|
||||
#include "treeBoundBox.H"
|
||||
#include "linePointRef.H"
|
||||
#include "volumeType.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
template<class Type> class dynamicIndexedOctree;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class dynamicTreeDataPoint Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class dynamicTreeDataPoint
|
||||
{
|
||||
// Private data
|
||||
|
||||
const DynamicList<point>& points_;
|
||||
|
||||
public:
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("dynamicTreeDataPoint");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from List. Holds reference!
|
||||
dynamicTreeDataPoint(const DynamicList<point>& points);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
inline label size() const
|
||||
{
|
||||
return points_.size();
|
||||
}
|
||||
|
||||
//- Get representative point cloud for all shapes inside
|
||||
// (one point per shape)
|
||||
const DynamicList<point>& shapePoints() const;
|
||||
|
||||
|
||||
// Search
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
volumeType getVolumeType
|
||||
(
|
||||
const dynamicIndexedOctree<dynamicTreeDataPoint>&,
|
||||
const point&
|
||||
) const;
|
||||
|
||||
//- Does (bb of) shape at index overlap bb
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& sampleBb
|
||||
) const;
|
||||
|
||||
//- Check if any point on shape is inside sphere.
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const point& centre,
|
||||
const scalar radiusSqr
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to sample) point in shape.
|
||||
// Returns actual point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelUList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestIndex,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculates nearest (to line) point in shape.
|
||||
// Returns point and distance (squared)
|
||||
void findNearest
|
||||
(
|
||||
const labelUList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
//- Calculate intersection of shape with ray. Sets result
|
||||
// accordingly
|
||||
bool intersects
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& result
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"dynamicTreeDataPoint::intersects"
|
||||
"(const label, const point&, const point&, point&)"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
3077
src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C
Normal file
3077
src/OpenFOAM/algorithms/indexedOctree/indexedOctree.C
Normal file
File diff suppressed because it is too large
Load Diff
707
src/OpenFOAM/algorithms/indexedOctree/indexedOctree.H
Normal file
707
src/OpenFOAM/algorithms/indexedOctree/indexedOctree.H
Normal file
@ -0,0 +1,707 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::indexedOctree
|
||||
|
||||
Description
|
||||
Non-pointer based hierarchical recursive searching
|
||||
|
||||
SourceFiles
|
||||
indexedOctree.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef indexedOctree_H
|
||||
#define indexedOctree_H
|
||||
|
||||
#include "treeBoundBox.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "FixedList.H"
|
||||
#include "Ostream.H"
|
||||
#include "HashSet.H"
|
||||
#include "labelBits.H"
|
||||
#include "PackedList.H"
|
||||
#include "volumeType.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
template<class Type> class indexedOctree;
|
||||
template<class Type> Ostream& operator<<(Ostream&, const indexedOctree<Type>&);
|
||||
class Istream;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedOctreeName Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
TemplateName(indexedOctree);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedOctree Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
class indexedOctree
|
||||
:
|
||||
public indexedOctreeName
|
||||
{
|
||||
public:
|
||||
|
||||
// Data types
|
||||
|
||||
//- Tree node. Has up pointer and down pointers.
|
||||
class node
|
||||
{
|
||||
public:
|
||||
|
||||
//- Bounding box of this node
|
||||
treeBoundBox bb_;
|
||||
|
||||
//- parent node (index into nodes_ of tree)
|
||||
label parent_;
|
||||
|
||||
//- IDs of the 8 nodes on all sides of the mid point
|
||||
FixedList<labelBits, 8> subNodes_;
|
||||
|
||||
friend Ostream& operator<< (Ostream& os, const node& n)
|
||||
{
|
||||
return os << n.bb_ << token::SPACE
|
||||
<< n.parent_ << token::SPACE << n.subNodes_;
|
||||
}
|
||||
|
||||
friend Istream& operator>> (Istream& is, node& n)
|
||||
{
|
||||
return is >> n.bb_ >> n.parent_ >> n.subNodes_;
|
||||
}
|
||||
|
||||
friend bool operator==(const node& a, const node& b)
|
||||
{
|
||||
return
|
||||
a.bb_ == b.bb_
|
||||
&& a.parent_ == b.parent_
|
||||
&& a.subNodes_ == b.subNodes_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const node& a, const node& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Static data
|
||||
|
||||
//- Relative peturbation tolerance. Determines when point is
|
||||
// considered to be close to face/edge of bb of node.
|
||||
// The tolerance is relative to the bounding box of the smallest
|
||||
// node.
|
||||
static scalar perturbTol_;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Underlying shapes for geometric queries.
|
||||
const Type shapes_;
|
||||
|
||||
//- List of all nodes
|
||||
List<node> nodes_;
|
||||
|
||||
//- List of all contents (referenced by those nodes that are contents)
|
||||
labelListList contents_;
|
||||
|
||||
//- Per node per octant whether is fully inside/outside/mixed.
|
||||
mutable PackedList<2> nodeTypes_;
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Helper: does bb intersect a sphere around sample? Or is any
|
||||
// corner point of bb closer than nearestDistSqr to sample.
|
||||
// (bb is implicitly provided as parent bb + octant)
|
||||
static bool overlaps
|
||||
(
|
||||
const treeBoundBox& parentBb,
|
||||
const direction octant,
|
||||
const scalar nearestDistSqr,
|
||||
const point& sample
|
||||
);
|
||||
|
||||
// Construction
|
||||
|
||||
//- Split list of indices into 8 bins
|
||||
// according to where they are in relation to mid.
|
||||
void divide
|
||||
(
|
||||
const labelList& indices,
|
||||
const treeBoundBox& bb,
|
||||
labelListList& result
|
||||
) const;
|
||||
|
||||
//- Subdivide the contents node at position contentI.
|
||||
// Appends to contents.
|
||||
node divide
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
DynamicList<labelList>& contents,
|
||||
const label contentI
|
||||
) const;
|
||||
|
||||
//- Split any contents node with more than minSize elements.
|
||||
void splitNodes
|
||||
(
|
||||
const label minSize,
|
||||
DynamicList<node>& nodes,
|
||||
DynamicList<labelList>& contents
|
||||
) const;
|
||||
|
||||
static label compactContents
|
||||
(
|
||||
DynamicList<node>& nodes,
|
||||
DynamicList<labelList>& contents,
|
||||
const label compactLevel,
|
||||
const label nodeI,
|
||||
const label level,
|
||||
List<labelList>& compactedContents,
|
||||
label& compactI
|
||||
);
|
||||
|
||||
//- Determine inside/outside per node (mixed if cannot be
|
||||
// determined). Only valid for closed shapes.
|
||||
volumeType calcVolumeType(const label nodeI) const;
|
||||
|
||||
//- Search cached volume type.
|
||||
volumeType getVolumeType(const label nodeI, const point&) const;
|
||||
|
||||
|
||||
// Query
|
||||
|
||||
//- Find nearest point to line.
|
||||
template<class FindNearestOp>
|
||||
void findNearest
|
||||
(
|
||||
const label nodeI,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& nearestShapeI,
|
||||
point& linePoint,
|
||||
point& nearestPoint,
|
||||
|
||||
const FindNearestOp& fnOp
|
||||
) const;
|
||||
|
||||
//- Return bbox of octant
|
||||
treeBoundBox subBbox
|
||||
(
|
||||
const label parentNodeI,
|
||||
const direction octant
|
||||
) const;
|
||||
|
||||
//- Helper: take a point on/close to face of bb and push it
|
||||
// inside or outside of bb.
|
||||
static point pushPoint
|
||||
(
|
||||
const treeBoundBox&,
|
||||
const point&,
|
||||
const bool pushInside
|
||||
);
|
||||
|
||||
//- Helper: take a point on face of bb and push it
|
||||
// inside or outside of bb.
|
||||
static point pushPoint
|
||||
(
|
||||
const treeBoundBox&,
|
||||
const direction,
|
||||
const point&,
|
||||
const bool pushInside
|
||||
);
|
||||
|
||||
//- Helper: take point on face(s) of bb and push it away from
|
||||
// edges of face.
|
||||
static point pushPointIntoFace
|
||||
(
|
||||
const treeBoundBox& bb,
|
||||
const vector& dir, // end-start
|
||||
const point& pt
|
||||
);
|
||||
|
||||
////- Push point on multiple faces away from any corner/edge.
|
||||
//static void checkMultipleFaces
|
||||
//(
|
||||
// const treeBoundBox& bb,
|
||||
// const vector& dir, // end-start
|
||||
// pointIndexHit& faceHitInfo,
|
||||
// direction& faceID
|
||||
//);
|
||||
|
||||
//- Walk to parent of node+octant.
|
||||
bool walkToParent
|
||||
(
|
||||
const label nodeI,
|
||||
const direction octant,
|
||||
|
||||
label& parentNodeI,
|
||||
label& parentOctant
|
||||
) const;
|
||||
|
||||
//- Walk tree to neighbouring node. Return false if edge of tree
|
||||
// hit.
|
||||
bool walkToNeighbour
|
||||
(
|
||||
const point& facePoint,
|
||||
const direction faceID, // direction to walk in
|
||||
label& nodeI,
|
||||
direction& octant
|
||||
) const;
|
||||
|
||||
//- Debug: return verbose the bounding box faces
|
||||
static word faceString(const direction faceID);
|
||||
|
||||
//- Traverse a node. If intersects a triangle return first
|
||||
// intersection point.
|
||||
// findAny=true : return any intersection
|
||||
// findAny=false: return nearest (to start) intersection
|
||||
template<class FindIntersectOp>
|
||||
void traverseNode
|
||||
(
|
||||
const bool findAny,
|
||||
const point& treeStart,
|
||||
const vector& treeVec,
|
||||
|
||||
const point& start,
|
||||
const point& end,
|
||||
const label nodeI,
|
||||
const direction octantI,
|
||||
|
||||
pointIndexHit& hitInfo,
|
||||
direction& faceID,
|
||||
|
||||
const FindIntersectOp& fiOp
|
||||
) const;
|
||||
|
||||
//- Find any or nearest intersection
|
||||
template<class FindIntersectOp>
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const bool findAny,
|
||||
const point& treeStart,
|
||||
const point& treeEnd,
|
||||
const label startNodeI,
|
||||
const direction startOctantI,
|
||||
const FindIntersectOp& fiOp,
|
||||
const bool verbose = false
|
||||
) const;
|
||||
|
||||
//- Find any or nearest intersection of line between start and end.
|
||||
template<class FindIntersectOp>
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const bool findAny,
|
||||
const point& start,
|
||||
const point& end,
|
||||
const FindIntersectOp& fiOp
|
||||
) const;
|
||||
|
||||
//- Find all elements intersecting box.
|
||||
void findBox
|
||||
(
|
||||
const label nodeI,
|
||||
const treeBoundBox& searchBox,
|
||||
labelHashSet& elements
|
||||
) const;
|
||||
|
||||
|
||||
//- Find all elements intersecting sphere.
|
||||
void findSphere
|
||||
(
|
||||
const label nodeI,
|
||||
const point& centre,
|
||||
const scalar radiusSqr,
|
||||
labelHashSet& elements
|
||||
) const;
|
||||
|
||||
|
||||
template<class CompareOp>
|
||||
static void findNear
|
||||
(
|
||||
const scalar nearDist,
|
||||
const bool okOrder,
|
||||
const indexedOctree<Type>& tree1,
|
||||
const labelBits index1,
|
||||
const treeBoundBox& bb1,
|
||||
const indexedOctree<Type>& tree2,
|
||||
const labelBits index2,
|
||||
const treeBoundBox& bb2,
|
||||
CompareOp& cop
|
||||
);
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Count number of elements on this and sublevels
|
||||
label countElements(const labelBits index) const;
|
||||
|
||||
//- Dump node+octant to an obj file
|
||||
void writeOBJ(const label nodeI, const direction octant) const;
|
||||
|
||||
//- From index into contents_ to subNodes_ entry
|
||||
static labelBits contentPlusOctant
|
||||
(
|
||||
const label i,
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(-i - 1, octant);
|
||||
}
|
||||
|
||||
//- From index into nodes_ to subNodes_ entry
|
||||
static labelBits nodePlusOctant
|
||||
(
|
||||
const label i,
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(i + 1, octant);
|
||||
}
|
||||
|
||||
//- From empty to subNodes_ entry
|
||||
static labelBits emptyPlusOctant
|
||||
(
|
||||
const direction octant
|
||||
)
|
||||
{
|
||||
return labelBits(0, octant);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
//- Get the perturbation tolerance
|
||||
static scalar& perturbTol();
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
indexedOctree(const Type& shapes);
|
||||
|
||||
//- Construct from components
|
||||
indexedOctree
|
||||
(
|
||||
const Type& shapes,
|
||||
const List<node>& nodes,
|
||||
const labelListList& contents
|
||||
);
|
||||
|
||||
//- Construct from shapes
|
||||
indexedOctree
|
||||
(
|
||||
const Type& shapes,
|
||||
const treeBoundBox& bb,
|
||||
const label maxLevels, // maximum number of levels
|
||||
const scalar maxLeafRatio, // how many elements per leaf
|
||||
const scalar maxDuplicity // in how many leaves is a shape on
|
||||
// average
|
||||
);
|
||||
|
||||
//- Construct from Istream
|
||||
indexedOctree(const Type& shapes, Istream& is);
|
||||
|
||||
//- Clone
|
||||
autoPtr<indexedOctree<Type> > clone() const
|
||||
{
|
||||
return autoPtr<indexedOctree<Type> >
|
||||
(
|
||||
new indexedOctree<Type>(*this)
|
||||
);
|
||||
}
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Reference to shape
|
||||
const Type& shapes() const
|
||||
{
|
||||
return shapes_;
|
||||
}
|
||||
|
||||
//- List of all nodes
|
||||
const List<node>& nodes() const
|
||||
{
|
||||
return nodes_;
|
||||
}
|
||||
|
||||
//- List of all contents (referenced by those nodes that are
|
||||
// contents)
|
||||
const labelListList& contents() const
|
||||
{
|
||||
return contents_;
|
||||
}
|
||||
|
||||
//- Top bounding box
|
||||
const treeBoundBox& bb() const
|
||||
{
|
||||
if (nodes_.empty())
|
||||
{
|
||||
FatalErrorIn("indexedOctree<Type>::bb() const")
|
||||
<< "Tree is empty" << abort(FatalError);
|
||||
}
|
||||
return nodes_[0].bb_;
|
||||
}
|
||||
|
||||
|
||||
// Conversions for entries in subNodes_.
|
||||
|
||||
static bool isContent(const labelBits i)
|
||||
{
|
||||
return i.val() < 0;
|
||||
}
|
||||
|
||||
static bool isEmpty(const labelBits i)
|
||||
{
|
||||
return i.val() == 0;
|
||||
}
|
||||
|
||||
static bool isNode(const labelBits i)
|
||||
{
|
||||
return i.val() > 0;
|
||||
}
|
||||
|
||||
static label getContent(const labelBits i)
|
||||
{
|
||||
if (!isContent(i))
|
||||
{
|
||||
FatalErrorIn("getContent(const label)")
|
||||
<< abort(FatalError);
|
||||
}
|
||||
return -i.val()-1;
|
||||
}
|
||||
|
||||
static label getNode(const labelBits i)
|
||||
{
|
||||
if (!isNode(i))
|
||||
{
|
||||
FatalErrorIn("getNode(const label)")
|
||||
<< abort(FatalError);
|
||||
}
|
||||
return i.val() - 1;
|
||||
}
|
||||
|
||||
static direction getOctant(const labelBits i)
|
||||
{
|
||||
return i.bits();
|
||||
}
|
||||
|
||||
|
||||
// Queries
|
||||
|
||||
pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr
|
||||
) const;
|
||||
|
||||
//- Calculate nearest point on nearest shape.
|
||||
// Returns
|
||||
// - bool : any point found nearer than nearestDistSqr
|
||||
// - label: index in shapes
|
||||
// - point: actual nearest point found
|
||||
template<class FindNearestOp>
|
||||
pointIndexHit findNearest
|
||||
(
|
||||
const point& sample,
|
||||
const scalar nearestDistSqr,
|
||||
|
||||
const FindNearestOp& fnOp
|
||||
) const;
|
||||
|
||||
//- Low level: calculate nearest starting from subnode.
|
||||
template<class FindNearestOp>
|
||||
void findNearest
|
||||
(
|
||||
const label nodeI,
|
||||
const point&,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& nearestShapeI,
|
||||
point& nearestPoint,
|
||||
|
||||
const FindNearestOp& fnOp
|
||||
) const;
|
||||
|
||||
//- Find nearest to line.
|
||||
// Returns
|
||||
// - bool : any point found?
|
||||
// - label: index in shapes
|
||||
// - point: actual nearest point found
|
||||
// sets:
|
||||
// - linePoint : corresponding nearest point on line
|
||||
pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint
|
||||
) const;
|
||||
|
||||
template<class FindNearestOp>
|
||||
pointIndexHit findNearest
|
||||
(
|
||||
const linePointRef& ln,
|
||||
treeBoundBox& tightest,
|
||||
point& linePoint,
|
||||
|
||||
const FindNearestOp& fnOp
|
||||
) const;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end
|
||||
) const;
|
||||
|
||||
//- Find nearest intersection of line between start and end.
|
||||
template<class FindIntersectOp>
|
||||
pointIndexHit findLine
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
const FindIntersectOp& fiOp
|
||||
) const;
|
||||
|
||||
//- Find any intersection of line between start and end.
|
||||
template<class FindIntersectOp>
|
||||
pointIndexHit findLineAny
|
||||
(
|
||||
const point& start,
|
||||
const point& end,
|
||||
const FindIntersectOp& fiOp
|
||||
) const;
|
||||
|
||||
//- Find (in no particular order) indices of all shapes inside or
|
||||
// overlapping bounding box (i.e. all shapes not outside box)
|
||||
labelList findBox(const treeBoundBox& bb) const;
|
||||
|
||||
//- Find (in no particular order) indices of all shapes inside or
|
||||
// overlapping a bounding sphere (i.e. all shapes not outside
|
||||
// sphere)
|
||||
labelList findSphere
|
||||
(
|
||||
const point& centre,
|
||||
const scalar radiusSqr
|
||||
) const;
|
||||
|
||||
//- Find deepest node (as parent+octant) containing point. Starts
|
||||
// off from starting index in nodes_ (use 0 to start from top)
|
||||
// Use getNode and getOctant to extract info, or call findIndices.
|
||||
labelBits findNode(const label nodeI, const point&) const;
|
||||
|
||||
//- Find shape containing point. Only implemented for certain
|
||||
// shapes.
|
||||
label findInside(const point&) const;
|
||||
|
||||
//- Find the shape indices that occupy the result of findNode
|
||||
const labelList& findIndices(const point&) const;
|
||||
|
||||
//- Determine type (inside/outside/mixed) for point. unknown if
|
||||
// cannot be determined (e.g. non-manifold surface)
|
||||
volumeType getVolumeType(const point&) const;
|
||||
|
||||
//- Helper function to return the side. Returns outside if
|
||||
// outsideNormal&vec >= 0, inside otherwise
|
||||
static volumeType getSide
|
||||
(
|
||||
const vector& outsideNormal,
|
||||
const vector& vec
|
||||
);
|
||||
|
||||
//- Helper: does bb intersect a sphere around sample? Or is any
|
||||
// corner point of bb closer than nearestDistSqr to sample.
|
||||
static bool overlaps
|
||||
(
|
||||
const point& bbMin,
|
||||
const point& bbMax,
|
||||
const scalar nearestDistSqr,
|
||||
const point& sample
|
||||
);
|
||||
|
||||
//- Find near pairs and apply CompareOp to them.
|
||||
// tree2 can be *this or different tree.
|
||||
template<class CompareOp>
|
||||
void findNear
|
||||
(
|
||||
const scalar nearDist,
|
||||
const indexedOctree<Type>& tree2,
|
||||
CompareOp& cop
|
||||
) const;
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- Print tree. Either print all indices (printContent = true) or
|
||||
// just size of contents nodes.
|
||||
void print
|
||||
(
|
||||
prefixOSstream&,
|
||||
const bool printContents,
|
||||
const label
|
||||
) const;
|
||||
|
||||
bool write(Ostream& os) const;
|
||||
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
friend Ostream& operator<< <Type>(Ostream&, const indexedOctree<Type>&);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
# include "indexedOctree.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
36
src/OpenFOAM/algorithms/indexedOctree/indexedOctreeName.C
Normal file
36
src/OpenFOAM/algorithms/indexedOctree/indexedOctreeName.C
Normal file
@ -0,0 +1,36 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "indexedOctree.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(indexedOctreeName, 0);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
155
src/OpenFOAM/algorithms/indexedOctree/labelBits.H
Normal file
155
src/OpenFOAM/algorithms/indexedOctree/labelBits.H
Normal file
@ -0,0 +1,155 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::labelBits
|
||||
|
||||
Description
|
||||
A 29bits label and 3bits direction packed into single label
|
||||
|
||||
SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef labelBits_H
|
||||
#define labelBits_H
|
||||
|
||||
#include "label.H"
|
||||
//#include "uLabel.H"
|
||||
#include "direction.H"
|
||||
#include "error.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class labelBits Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class labelBits
|
||||
{
|
||||
// Private data
|
||||
|
||||
label data_;
|
||||
|
||||
inline static label pack(const label val, const direction bits)
|
||||
{
|
||||
# ifdef FULLDEBUG
|
||||
if (bits > 7 || (((val<<3)>>3) != val))
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"labelBits::pack(const label, const direction)"
|
||||
) << "Direction " << bits << " outside range 0..7"
|
||||
<< " or value " << val << " negative or larger than "
|
||||
<< label(8*sizeof(label)-3) << " bit representation"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
# endif
|
||||
|
||||
return (val<<3) | bits;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
inline labelBits()
|
||||
{}
|
||||
|
||||
//- Construct from components
|
||||
inline labelBits(const label val, const direction bits)
|
||||
:
|
||||
data_(pack(val, bits))
|
||||
{}
|
||||
|
||||
//- Construct from Istream
|
||||
inline labelBits(Istream& is)
|
||||
{
|
||||
is >> data_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
inline label val() const
|
||||
{
|
||||
return data_ >> 3;
|
||||
}
|
||||
|
||||
inline direction bits() const
|
||||
{
|
||||
return data_ & 7;
|
||||
}
|
||||
|
||||
inline void setVal(const label val)
|
||||
{
|
||||
data_ = pack(val, bits());
|
||||
}
|
||||
|
||||
inline void setBits(const direction bits)
|
||||
{
|
||||
data_ = pack(val(), bits);
|
||||
}
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
inline friend bool operator==(const labelBits& a, const labelBits& b)
|
||||
{
|
||||
return a.data_ == b.data_;
|
||||
}
|
||||
|
||||
inline friend bool operator!=(const labelBits& a, const labelBits& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// IOstream Operators
|
||||
|
||||
inline friend Istream& operator>>(Istream& is, labelBits& lb)
|
||||
{
|
||||
return is >> lb.data_;
|
||||
}
|
||||
|
||||
inline friend Ostream& operator<<(Ostream& os, const labelBits& lb)
|
||||
{
|
||||
return os << lb.data_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
325
src/OpenFOAM/algorithms/indexedOctree/treeDataCell.C
Normal file
325
src/OpenFOAM/algorithms/indexedOctree/treeDataCell.C
Normal file
@ -0,0 +1,325 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "treeDataCell.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "polyMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(treeDataCell, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::treeBoundBox Foam::treeDataCell::calcCellBb(const label cellI) const
|
||||
{
|
||||
const cellList& cells = mesh_.cells();
|
||||
const faceList& faces = mesh_.faces();
|
||||
const pointField& points = mesh_.points();
|
||||
|
||||
treeBoundBox cellBb
|
||||
(
|
||||
vector(GREAT, GREAT, GREAT),
|
||||
vector(-GREAT, -GREAT, -GREAT)
|
||||
);
|
||||
|
||||
const cell& cFaces = cells[cellI];
|
||||
|
||||
forAll(cFaces, cFaceI)
|
||||
{
|
||||
const face& f = faces[cFaces[cFaceI]];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
const point& p = points[f[fp]];
|
||||
|
||||
cellBb.min() = min(cellBb.min(), p);
|
||||
cellBb.max() = max(cellBb.max(), p);
|
||||
}
|
||||
}
|
||||
return cellBb;
|
||||
}
|
||||
|
||||
|
||||
void Foam::treeDataCell::update()
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
bbs_.setSize(cellLabels_.size());
|
||||
|
||||
forAll(cellLabels_, i)
|
||||
{
|
||||
bbs_[i] = calcCellBb(cellLabels_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::treeDataCell::treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh& mesh,
|
||||
const labelUList& cellLabels,
|
||||
const polyMesh::cellRepresentation decompMode
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
cellLabels_(cellLabels),
|
||||
cacheBb_(cacheBb),
|
||||
decompMode_(decompMode)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
Foam::treeDataCell::treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh& mesh,
|
||||
const Xfer<labelList>& cellLabels,
|
||||
const polyMesh::cellRepresentation decompMode
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
cellLabels_(cellLabels),
|
||||
cacheBb_(cacheBb),
|
||||
decompMode_(decompMode)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
Foam::treeDataCell::treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh& mesh,
|
||||
const polyMesh::cellRepresentation decompMode
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
cellLabels_(identity(mesh_.nCells())),
|
||||
cacheBb_(cacheBb),
|
||||
decompMode_(decompMode)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
Foam::treeDataCell::findNearestOp::findNearestOp
|
||||
(
|
||||
const indexedOctree<treeDataCell>& tree
|
||||
)
|
||||
:
|
||||
tree_(tree)
|
||||
{}
|
||||
|
||||
|
||||
Foam::treeDataCell::findIntersectOp::findIntersectOp
|
||||
(
|
||||
const indexedOctree<treeDataCell>& tree
|
||||
)
|
||||
:
|
||||
tree_(tree)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::treeDataCell::shapePoints() const
|
||||
{
|
||||
pointField cc(cellLabels_.size());
|
||||
|
||||
forAll(cellLabels_, i)
|
||||
{
|
||||
cc[i] = mesh_.cellCentres()[cellLabels_[i]];
|
||||
}
|
||||
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::treeDataCell::overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& cubeBb
|
||||
) const
|
||||
{
|
||||
if (cacheBb_)
|
||||
{
|
||||
return cubeBb.overlaps(bbs_[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return cubeBb.overlaps(calcCellBb(cellLabels_[index]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::treeDataCell::contains
|
||||
(
|
||||
const label index,
|
||||
const point& sample
|
||||
) const
|
||||
{
|
||||
return mesh_.pointInCell(sample, cellLabels_[index], decompMode_);
|
||||
}
|
||||
|
||||
|
||||
void Foam::treeDataCell::findNearestOp::operator()
|
||||
(
|
||||
const labelUList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
const treeDataCell& shape = tree_.shapes();
|
||||
|
||||
forAll(indices, i)
|
||||
{
|
||||
label index = indices[i];
|
||||
label cellI = shape.cellLabels()[index];
|
||||
scalar distSqr = magSqr(sample - shape.mesh().cellCentres()[cellI]);
|
||||
|
||||
if (distSqr < nearestDistSqr)
|
||||
{
|
||||
nearestDistSqr = distSqr;
|
||||
minIndex = index;
|
||||
nearestPoint = shape.mesh().cellCentres()[cellI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::treeDataCell::findNearestOp::operator()
|
||||
(
|
||||
const labelUList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataCell::findNearestOp::operator()"
|
||||
"("
|
||||
" const labelUList&,"
|
||||
" const linePointRef&,"
|
||||
" treeBoundBox&,"
|
||||
" label&,"
|
||||
" point&,"
|
||||
" point&"
|
||||
") const"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::treeDataCell::findIntersectOp::operator()
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& intersectionPoint
|
||||
) const
|
||||
{
|
||||
const treeDataCell& shape = tree_.shapes();
|
||||
|
||||
// Do quick rejection test
|
||||
if (shape.cacheBb_)
|
||||
{
|
||||
const treeBoundBox& cellBb = shape.bbs_[index];
|
||||
|
||||
if ((cellBb.posBits(start) & cellBb.posBits(end)) != 0)
|
||||
{
|
||||
// start and end in same block outside of cellBb.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const treeBoundBox cellBb = shape.calcCellBb(shape.cellLabels_[index]);
|
||||
|
||||
if ((cellBb.posBits(start) & cellBb.posBits(end)) != 0)
|
||||
{
|
||||
// start and end in same block outside of cellBb.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do intersection with all faces of cell
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// Disable picking up intersections behind us.
|
||||
scalar oldTol = intersection::setPlanarTol(0.0);
|
||||
|
||||
const cell& cFaces = shape.mesh_.cells()[shape.cellLabels_[index]];
|
||||
|
||||
const vector dir(end - start);
|
||||
scalar minDistSqr = magSqr(dir);
|
||||
bool hasMin = false;
|
||||
|
||||
forAll(cFaces, i)
|
||||
{
|
||||
const face& f = shape.mesh_.faces()[cFaces[i]];
|
||||
|
||||
pointHit inter = f.ray
|
||||
(
|
||||
start,
|
||||
dir,
|
||||
shape.mesh_.points(),
|
||||
intersection::HALF_RAY
|
||||
);
|
||||
|
||||
if (inter.hit() && sqr(inter.distance()) <= minDistSqr)
|
||||
{
|
||||
// Note: no extra test on whether intersection is in front of us
|
||||
// since using half_ray AND zero tolerance. (note that tolerance
|
||||
// is used to look behind us)
|
||||
minDistSqr = sqr(inter.distance());
|
||||
intersectionPoint = inter.hitPoint();
|
||||
hasMin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore picking tolerance
|
||||
intersection::setPlanarTol(oldTol);
|
||||
|
||||
return hasMin;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
239
src/OpenFOAM/algorithms/indexedOctree/treeDataCell.H
Normal file
239
src/OpenFOAM/algorithms/indexedOctree/treeDataCell.H
Normal file
@ -0,0 +1,239 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::treeDataCell
|
||||
|
||||
Description
|
||||
Encapsulation of data needed to search in/for cells. Used to find the
|
||||
cell containing a point (e.g. cell-cell mapping).
|
||||
|
||||
SourceFiles
|
||||
treeDataCell.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef treeDataCell_H
|
||||
#define treeDataCell_H
|
||||
|
||||
#include "polyMesh.H"
|
||||
#include "treeBoundBoxList.H"
|
||||
#include "volumeType.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of classes
|
||||
template<class Type> class indexedOctree;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class treeDataCell Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class treeDataCell
|
||||
{
|
||||
// Private data
|
||||
|
||||
const polyMesh& mesh_;
|
||||
|
||||
//- Subset of cells to work on
|
||||
const labelList cellLabels_;
|
||||
|
||||
//- Whether to precalculate and store cell bounding box
|
||||
const bool cacheBb_;
|
||||
|
||||
//- How to decide if point is inside cell
|
||||
const polyMesh::cellRepresentation decompMode_;
|
||||
|
||||
//- cell bounding boxes (valid only if cacheBb_)
|
||||
treeBoundBoxList bbs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Calculate cell bounding box
|
||||
treeBoundBox calcCellBb(const label cellI) const;
|
||||
|
||||
//- Initialise all member data
|
||||
void update();
|
||||
|
||||
public:
|
||||
|
||||
|
||||
class findNearestOp
|
||||
{
|
||||
const indexedOctree<treeDataCell>& tree_;
|
||||
|
||||
public:
|
||||
|
||||
findNearestOp(const indexedOctree<treeDataCell>& tree);
|
||||
|
||||
void operator()
|
||||
(
|
||||
const labelUList& indices,
|
||||
const point& sample,
|
||||
|
||||
scalar& nearestDistSqr,
|
||||
label& minIndex,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
|
||||
void operator()
|
||||
(
|
||||
const labelUList& indices,
|
||||
const linePointRef& ln,
|
||||
|
||||
treeBoundBox& tightest,
|
||||
label& minIndex,
|
||||
point& linePoint,
|
||||
point& nearestPoint
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
class findIntersectOp
|
||||
{
|
||||
const indexedOctree<treeDataCell>& tree_;
|
||||
|
||||
public:
|
||||
|
||||
findIntersectOp(const indexedOctree<treeDataCell>& tree);
|
||||
|
||||
bool operator()
|
||||
(
|
||||
const label index,
|
||||
const point& start,
|
||||
const point& end,
|
||||
point& intersectionPoint
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// Declare name of the class and its debug switch
|
||||
ClassName("treeDataCell");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from mesh and subset of cells.
|
||||
treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh&,
|
||||
const labelUList&,
|
||||
const polyMesh::cellRepresentation decompMode
|
||||
);
|
||||
|
||||
//- Construct from mesh and subset of cells, transferring contents
|
||||
treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh&,
|
||||
const Xfer<labelList>&,
|
||||
const polyMesh::cellRepresentation decompMode
|
||||
);
|
||||
|
||||
//- Construct from mesh. Uses all cells in mesh.
|
||||
treeDataCell
|
||||
(
|
||||
const bool cacheBb,
|
||||
const polyMesh&,
|
||||
const polyMesh::cellRepresentation decompMode
|
||||
);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
inline const labelList& cellLabels() const
|
||||
{
|
||||
return cellLabels_;
|
||||
}
|
||||
|
||||
inline const polyMesh& mesh() const
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
inline polyMesh::cellRepresentation decompMode() const
|
||||
{
|
||||
return decompMode_;
|
||||
}
|
||||
|
||||
inline label size() const
|
||||
{
|
||||
return cellLabels_.size();
|
||||
}
|
||||
|
||||
//- Get representative point cloud for all shapes inside
|
||||
// (one point per shape)
|
||||
pointField shapePoints() const;
|
||||
|
||||
|
||||
// Search
|
||||
|
||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||
// Only makes sense for closed surfaces.
|
||||
volumeType getVolumeType
|
||||
(
|
||||
const indexedOctree<treeDataCell>&,
|
||||
const point&
|
||||
) const
|
||||
{
|
||||
notImplemented
|
||||
(
|
||||
"treeDataCell::getVolumeType"
|
||||
"(const indexedOctree<treeDataCell>&, const point&)"
|
||||
);
|
||||
return volumeType::UNKNOWN;
|
||||
}
|
||||
|
||||
//- Does (bb of) shape at index overlap bb
|
||||
bool overlaps
|
||||
(
|
||||
const label index,
|
||||
const treeBoundBox& sampleBb
|
||||
) const;
|
||||
|
||||
//- Does shape at index contain sample
|
||||
bool contains
|
||||
(
|
||||
const label index,
|
||||
const point& sample
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
79
src/OpenFOAM/algorithms/indexedOctree/volumeType.C
Normal file
79
src/OpenFOAM/algorithms/indexedOctree/volumeType.C
Normal file
@ -0,0 +1,79 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "volumeType.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
template<>
|
||||
const char* Foam::NamedEnum
|
||||
<
|
||||
Foam::volumeType,
|
||||
4
|
||||
>::names[] =
|
||||
{
|
||||
"unknown",
|
||||
"mixed",
|
||||
"inside",
|
||||
"outside"
|
||||
};
|
||||
}
|
||||
|
||||
const Foam::NamedEnum<Foam::volumeType, 4> Foam::volumeType::names;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
Foam::Istream& Foam::operator>>(Istream& is, volumeType& vt)
|
||||
{
|
||||
// Read beginning of volumeType
|
||||
is.readBegin("volumeType");
|
||||
|
||||
int type;
|
||||
is >> type;
|
||||
|
||||
vt.t_ = static_cast<volumeType::type>(type);
|
||||
|
||||
// Read end of volumeType
|
||||
is.readEnd("volumeType");
|
||||
|
||||
// Check state of Istream
|
||||
is.check("operator>>(Istream&, volumeType&)");
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::operator<<(Ostream& os, const volumeType& vt)
|
||||
{
|
||||
os << static_cast<int>(vt.t_);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
127
src/OpenFOAM/algorithms/indexedOctree/volumeType.H
Normal file
127
src/OpenFOAM/algorithms/indexedOctree/volumeType.H
Normal file
@ -0,0 +1,127 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::volumeType
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
volumeType.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef volumeType_H
|
||||
#define volumeType_H
|
||||
|
||||
#include "NamedEnum.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declaration of friend functions and operators
|
||||
|
||||
class volumeType;
|
||||
Istream& operator>>(Istream& is, volumeType&);
|
||||
Ostream& operator<<(Ostream& os, const volumeType& C);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class volumeType Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class volumeType
|
||||
{
|
||||
public:
|
||||
|
||||
//- Volume types
|
||||
enum type
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
MIXED = 1,
|
||||
INSIDE = 2,
|
||||
OUTSIDE = 3
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- Volume type
|
||||
type t_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Static data
|
||||
|
||||
static const NamedEnum<volumeType, 4> names;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct null
|
||||
volumeType()
|
||||
:
|
||||
t_(UNKNOWN)
|
||||
{}
|
||||
|
||||
//- Construct from components
|
||||
volumeType(type t)
|
||||
:
|
||||
t_(t)
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
operator type() const
|
||||
{
|
||||
return t_;
|
||||
}
|
||||
|
||||
|
||||
// IOstream operators
|
||||
|
||||
friend Istream& operator>>(Istream& is, volumeType& vt);
|
||||
friend Ostream& operator<<(Ostream& os, const volumeType& vt);
|
||||
};
|
||||
|
||||
|
||||
//- Data associated with volumeType type are contiguous
|
||||
template<>
|
||||
inline bool contiguous<volumeType>() {return true;}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
153
src/OpenFOAM/algorithms/subCycle/subCycle.H
Normal file
153
src/OpenFOAM/algorithms/subCycle/subCycle.H
Normal file
@ -0,0 +1,153 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::subCycle
|
||||
|
||||
Description
|
||||
Perform a subCycleTime on a field
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef subCycle_H
|
||||
#define subCycle_H
|
||||
|
||||
#include "subCycleTime.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class subCycleField Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class GeometricField>
|
||||
class subCycleField
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Reference to the field being sub-cycled
|
||||
GeometricField& gf_;
|
||||
|
||||
//- Reference to the field old-time field being sub-cycled
|
||||
// Needed to avoid calls to oldTime() which may cause
|
||||
// unexpected updates of the old-time field
|
||||
GeometricField& gf0_;
|
||||
|
||||
//- Copy of the "real" old-time value of the field
|
||||
GeometricField gf_0_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct field and number of sub-cycles
|
||||
subCycleField(GeometricField& gf)
|
||||
:
|
||||
gf_(gf),
|
||||
gf0_(gf.oldTime()),
|
||||
gf_0_(gf0_.name() + "_", gf0_)
|
||||
{}
|
||||
|
||||
|
||||
//- Destructor
|
||||
~subCycleField()
|
||||
{
|
||||
// Reset the old-time field
|
||||
gf0_ = gf_0_;
|
||||
|
||||
// Correct the time index of the field to correspond to the global time
|
||||
gf_.timeIndex() = gf_.time().timeIndex();
|
||||
gf0_.timeIndex() = gf_.time().timeIndex();
|
||||
}
|
||||
|
||||
|
||||
//- Correct the time index of the field to correspond to
|
||||
// the sub-cycling time.
|
||||
//
|
||||
// The time index is incremented to protect the old-time value from
|
||||
// being updated at the beginning of the time-loop in the case of
|
||||
// outer iteration
|
||||
void updateTimeIndex()
|
||||
{
|
||||
gf_.timeIndex() = gf_.time().timeIndex() + 1;
|
||||
gf0_.timeIndex() = gf_.time().timeIndex() + 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class subCycle Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class GeometricField>
|
||||
class subCycle
|
||||
:
|
||||
public subCycleField<GeometricField>,
|
||||
public subCycleTime
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
subCycle(const subCycle<GeometricField>&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const subCycle<GeometricField>&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct field and number of sub-cycles
|
||||
subCycle(GeometricField& gf, const label nSubCycles)
|
||||
:
|
||||
subCycleField<GeometricField>(gf),
|
||||
subCycleTime(const_cast<Time&>(gf.time()), nSubCycles)
|
||||
{
|
||||
// Update the field time index to correspond to the sub-cycle time
|
||||
this->updateTimeIndex();
|
||||
}
|
||||
|
||||
|
||||
//- Destructor
|
||||
// End the subCycleTime, which restores the time state
|
||||
~subCycle()
|
||||
{
|
||||
endSubCycle();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user