ENH: Expand triSurfaceSearch and add triSurfaceRegionSearch

+ Move most of the octree searching functionality from triSurfaceMesh into
  triSurfaceSearch. Much of it was duplicated anyway.
+ Add triSurfaceRegionSearch, which constructs an octree for each region in
  a surface and performs searches on specified regions only.
This commit is contained in:
laurence
2013-04-05 15:28:00 +01:00
parent 640b4e4325
commit bfd30ea006
13 changed files with 791 additions and 648 deletions

View File

@ -54,6 +54,7 @@ namespace Foam
class polyMesh; class polyMesh;
class PackedBoolList; class PackedBoolList;
class boundBox;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class PatchTools Declaration Class PatchTools Declaration
@ -140,6 +141,21 @@ public:
labelList& faceMap labelList& faceMap
); );
//-
template
<
class Face,
template<class> class FaceList,
class PointField,
class PointType
>
static void calcBounds
(
const PrimitivePatch<Face, FaceList, PointField, PointType>& p,
boundBox& bb,
label& nPoints
);
//- Return edge-face addressing sorted by angle around the edge. //- Return edge-face addressing sorted by angle around the edge.
// Orientation is anticlockwise looking from edge.vec(localPoints()) // Orientation is anticlockwise looking from edge.vec(localPoints())
template template
@ -271,7 +287,6 @@ public:
List<Face>& mergedFaces, List<Face>& mergedFaces,
labelList& pointMergeMap labelList& pointMergeMap
); );
}; };

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -27,6 +27,8 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "PatchTools.H" #include "PatchTools.H"
#include "PackedBoolList.H"
#include "boundBox.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -222,4 +224,45 @@ Foam::PatchTools::subsetMap
} }
template
<
class Face,
template<class> class FaceList,
class PointField,
class PointType
>
void Foam::PatchTools::calcBounds
(
const PrimitivePatch<Face, FaceList, PointField, PointType>& p,
boundBox& bb,
label& nPoints
)
{
// Unfortunately nPoints constructs meshPoints() so do compact version
// ourselves
const PointField& points = p.points();
PackedBoolList pointIsUsed(points.size());
nPoints = 0;
bb = boundBox::invertedBox;
forAll(p, faceI)
{
const Face& f = p[faceI];
forAll(f, fp)
{
label pointI = f[fp];
if (pointIsUsed.set(pointI, 1u))
{
bb.min() = ::Foam::min(bb.min(), points[pointI]);
bb.max() = ::Foam::max(bb.max(), points[pointI]);
nPoints++;
}
}
}
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -26,7 +26,7 @@ Class
Description Description
Geometric class that creates a 2D plane and can return the intersection Geometric class that creates a 2D plane and can return the intersection
point between a line and the plane. point between a line and the plane.
SourceFiles SourceFiles
plane.C plane.C
@ -62,6 +62,14 @@ class plane
{ {
public: public:
//- Side of the plane
enum side
{
NORMAL,
FLIP
};
//- A direction and a reference point //- A direction and a reference point
class ray class ray
{ {
@ -182,6 +190,10 @@ public:
//- Return the cutting point between this plane and two other planes //- Return the cutting point between this plane and two other planes
point planePlaneIntersect(const plane&, const plane&) const; point planePlaneIntersect(const plane&, const plane&) const;
//- Return the side of the plane that the point is on.
// If the point is on the plane, then returns NORMAL.
side sideOfPlane(const point& p) const;
//- Write to dictionary //- Write to dictionary
void writeDict(Ostream&) const; void writeDict(Ostream&) const;

View File

@ -160,6 +160,7 @@ $(intersectedSurface)/intersectedSurface.C
$(intersectedSurface)/edgeSurface.C $(intersectedSurface)/edgeSurface.C
triSurface/triSurfaceSearch/triSurfaceSearch.C triSurface/triSurfaceSearch/triSurfaceSearch.C
triSurface/triSurfaceSearch/triSurfaceRegionSearch.C
triSurface/triangleFuncs/triangleFuncs.C triSurface/triangleFuncs/triangleFuncs.C
triSurface/surfaceFeatures/surfaceFeatures.C triSurface/surfaceFeatures/surfaceFeatures.C
triSurface/triSurfaceTools/triSurfaceTools.C triSurface/triSurfaceTools/triSurfaceTools.C

View File

@ -29,7 +29,7 @@ License
#include "EdgeMap.H" #include "EdgeMap.H"
#include "triSurfaceFields.H" #include "triSurfaceFields.H"
#include "Time.H" #include "Time.H"
#include "PackedBoolList.H" #include "PatchTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -218,48 +218,6 @@ bool Foam::triSurfaceMesh::isSurfaceClosed() const
} }
void Foam::triSurfaceMesh::calcBounds(boundBox& bb, label& nPoints) const
{
const triSurface& s = static_cast<const triSurface&>(*this);
calcBounds(s, bb, nPoints);
}
template <class PatchType>
void Foam::triSurfaceMesh::calcBounds
(
const PatchType& patch,
boundBox& bb,
label& nPoints
) const
{
// Unfortunately nPoints constructs meshPoints() so do compact version
// ourselves
PackedBoolList pointIsUsed(points()().size());
nPoints = 0;
bb = boundBox::invertedBox;
forAll(patch, faceI)
{
const typename PatchType::FaceType& f = patch[faceI];
forAll(f, fp)
{
label pointI = f[fp];
if (pointIsUsed.set(pointI, 1u))
{
bb.min() = ::Foam::min(bb.min(), points()()[pointI]);
bb.max() = ::Foam::max(bb.max(), points()()[pointI]);
nPoints++;
}
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s) Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
@ -279,9 +237,8 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
) )
), ),
triSurface(s), triSurface(s),
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()), triSurfaceRegionSearch(s),
minQuality_(-1), minQuality_(-1),
maxTreeDepth_(10),
surfaceClosed_(-1) surfaceClosed_(-1)
{ {
bounds() = boundBox(points()); bounds() = boundBox(points());
@ -326,9 +283,8 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
searchableSurface::objectPath() searchableSurface::objectPath()
) )
), ),
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()), triSurfaceRegionSearch(static_cast<const triSurface&>(*this)),
minQuality_(-1), minQuality_(-1),
maxTreeDepth_(10),
surfaceClosed_(-1) surfaceClosed_(-1)
{ {
bounds() = boundBox(points()); bounds() = boundBox(points());
@ -376,9 +332,8 @@ Foam::triSurfaceMesh::triSurfaceMesh
searchableSurface::objectPath() searchableSurface::objectPath()
) )
), ),
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()), triSurfaceRegionSearch(static_cast<const triSurface&>(*this), dict),
minQuality_(-1), minQuality_(-1),
maxTreeDepth_(10),
surfaceClosed_(-1) surfaceClosed_(-1)
{ {
scalar scaleFactor = 0; scalar scaleFactor = 0;
@ -394,13 +349,6 @@ Foam::triSurfaceMesh::triSurfaceMesh
bounds() = boundBox(points()); bounds() = boundBox(points());
// Have optional non-standard search tolerance for gappy surfaces.
if (dict.readIfPresent("tolerance", tolerance_) && tolerance_ > 0)
{
Info<< searchableSurface::name() << " : using intersection tolerance "
<< tolerance_ << endl;
}
// Have optional minimum quality for normal calculation // Have optional minimum quality for normal calculation
if (dict.readIfPresent("minQuality", minQuality_) && minQuality_ > 0) if (dict.readIfPresent("minQuality", minQuality_) && minQuality_ > 0)
{ {
@ -408,13 +356,6 @@ Foam::triSurfaceMesh::triSurfaceMesh
<< " : ignoring triangles with quality < " << " : ignoring triangles with quality < "
<< minQuality_ << " for normals calculation." << endl; << minQuality_ << " for normals calculation." << endl;
} }
// Have optional non-standard tree-depth to limit storage.
if (dict.readIfPresent("maxTreeDepth", maxTreeDepth_) && maxTreeDepth_ > 0)
{
Info<< searchableSurface::name() << " : using maximum tree depth "
<< maxTreeDepth_ << endl;
}
} }
@ -428,7 +369,7 @@ Foam::triSurfaceMesh::~triSurfaceMesh()
void Foam::triSurfaceMesh::clearOut() void Foam::triSurfaceMesh::clearOut()
{ {
tree_.clear(); triSurfaceRegionSearch::clearOut();
edgeTree_.clear(); edgeTree_.clear();
triSurface::clearOut(); triSurface::clearOut();
} }
@ -470,176 +411,12 @@ bool Foam::triSurfaceMesh::overlaps(const boundBox& bb) const
void Foam::triSurfaceMesh::movePoints(const pointField& newPoints) void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
{ {
tree_.clear(); triSurfaceRegionSearch::clearOut();
edgeTree_.clear(); edgeTree_.clear();
triSurface::movePoints(newPoints); triSurface::movePoints(newPoints);
} }
const Foam::indexedOctree<Foam::treeDataTriSurface>&
Foam::triSurfaceMesh::tree() const
{
if (tree_.empty())
{
// Calculate bb without constructing local point numbering.
treeBoundBox bb;
label nPoints;
calcBounds(bb, nPoints);
if (nPoints != points()().size())
{
WarningIn("triSurfaceMesh::tree() const")
<< "Surface " << searchableSurface::name()
<< " does not have compact point numbering."
<< " Of " << points()().size() << " only " << nPoints
<< " are used. This might give problems in some routines."
<< endl;
}
// Random number generator. Bit dodgy since not exactly random ;-)
Random rndGen(65431);
// Slightly extended bb. Slightly off-centred just so on symmetric
// geometry there are less face/edge aligned items.
bb = bb.extend(rndGen, 1e-4);
bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_;
tree_.reset
(
new indexedOctree<treeDataTriSurface>
(
treeDataTriSurface(true, *this, tolerance_),
bb,
maxTreeDepth_, // maxLevel
10, // leafsize
3.0 // duplicity
)
);
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
}
return tree_();
}
const Foam::PtrList
<
Foam::indexedOctree
<
Foam::triSurfaceMesh::treeDataTriSurfacePrimitivePatch
>
>&
Foam::triSurfaceMesh::treeByRegion() const
{
if (treeByRegion_.empty())
{
Map<label> regionSizes;
forAll(*this, fI)
{
const label regionI = this->triSurface::operator[](fI).region();
regionSizes(regionI)++;
}
label nRegions = regionSizes.size();
indirectRegionPatches_.setSize(nRegions);
treeByRegion_.setSize(nRegions);
labelListList regionsAddressing(nRegions);
forAll(regionsAddressing, regionI)
{
regionsAddressing[regionI] = labelList(regionSizes[regionI], -1);
}
labelList nFacesInRegions(nRegions, 0);
forAll(*this, fI)
{
const label regionI = this->triSurface::operator[](fI).region();
regionsAddressing[regionI][nFacesInRegions[regionI]++] = fI;
}
forAll(regionsAddressing, regionI)
{
scalar oldTol =
indexedOctree<treeDataTriSurfacePrimitivePatch>::perturbTol();
indexedOctree<treeDataTriSurfacePrimitivePatch>::perturbTol() =
tolerance_;
indirectRegionPatches_.set
(
regionI,
new indirectTriSurfacePrimitivePatch
(
IndirectList<labelledTri>
(
*this,
regionsAddressing[regionI]
),
points()
)
);
// Calculate bb without constructing local point numbering.
treeBoundBox bb;
label nPoints;
calcBounds(indirectRegionPatches_[regionI], bb, nPoints);
if (nPoints != points()().size())
{
WarningIn("triSurfaceMesh::treeByRegion() const")
<< "Surface " << searchableSurface::name()
<< " does not have compact point numbering."
<< " Of " << points()().size() << " only " << nPoints
<< " are used. This might give problems in some routines."
<< endl;
}
// Random number generator. Bit dodgy since not exactly random ;-)
Random rndGen(65431);
// Slightly extended bb. Slightly off-centred just so on symmetric
// geometry there are fewer face/edge aligned items.
bb = bb.extend(rndGen, 1e-4);
bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
treeByRegion_.set
(
regionI,
new indexedOctree<treeDataTriSurfacePrimitivePatch>
(
treeDataTriSurfacePrimitivePatch
(
true,
indirectRegionPatches_[regionI],
tolerance_
),
bb,
maxTreeDepth_, // maxLevel
10, // leafsize
3.0 // duplicity
)
);
indexedOctree<treeDataTriSurfacePrimitivePatch>::perturbTol() =
oldTol;
}
}
return treeByRegion_;
}
const Foam::indexedOctree<Foam::treeDataEdge>& const Foam::indexedOctree<Foam::treeDataEdge>&
Foam::triSurfaceMesh::edgeTree() const Foam::triSurfaceMesh::edgeTree() const
{ {
@ -658,7 +435,12 @@ Foam::triSurfaceMesh::edgeTree() const
treeBoundBox bb; treeBoundBox bb;
label nPoints; label nPoints;
calcBounds(bb, nPoints); PatchTools::calcBounds
(
static_cast<const triSurface&>(*this),
bb,
nPoints
);
// Random number generator. Bit dodgy since not exactly random ;-) // Random number generator. Bit dodgy since not exactly random ;-)
Random rndGen(65431); Random rndGen(65431);
@ -671,7 +453,7 @@ Foam::triSurfaceMesh::edgeTree() const
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL); bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
scalar oldTol = indexedOctree<treeDataEdge>::perturbTol(); scalar oldTol = indexedOctree<treeDataEdge>::perturbTol();
indexedOctree<treeDataEdge>::perturbTol() = tolerance_; indexedOctree<treeDataEdge>::perturbTol() = tolerance();
edgeTree_.reset edgeTree_.reset
( (
@ -685,7 +467,7 @@ Foam::triSurfaceMesh::edgeTree() const
bEdges // selected edges bEdges // selected edges
), ),
bb, // bb bb, // bb
maxTreeDepth_, // maxLevel maxTreeDepth(), // maxLevel
10, // leafsize 10, // leafsize
3.0 // duplicity 3.0 // duplicity
) )
@ -697,12 +479,6 @@ Foam::triSurfaceMesh::edgeTree() const
} }
Foam::scalar Foam::triSurfaceMesh::tolerance() const
{
return tolerance_;
}
const Foam::wordList& Foam::triSurfaceMesh::regions() const const Foam::wordList& Foam::triSurfaceMesh::regions() const
{ {
if (regions_.empty()) if (regions_.empty())
@ -743,24 +519,7 @@ void Foam::triSurfaceMesh::findNearest
List<pointIndexHit>& info List<pointIndexHit>& info
) const ) const
{ {
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol(); triSurfaceSearch::findNearest(samples, nearestDistSqr, info);
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_;
const indexedOctree<treeDataTriSurface>& octree = tree();
info.setSize(samples.size());
forAll(samples, i)
{
static_cast<pointIndexHit&>(info[i]) = octree.findNearest
(
samples[i],
nearestDistSqr[i],
treeDataTriSurface::findNearestOp(octree)
);
}
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
} }
@ -772,67 +531,13 @@ void Foam::triSurfaceMesh::findNearest
List<pointIndexHit>& info List<pointIndexHit>& info
) const ) const
{ {
if (regionIndices.empty()) triSurfaceRegionSearch::findNearest
{ (
findNearest(samples, nearestDistSqr, info); samples,
} nearestDistSqr,
else regionIndices,
{ info
scalar oldTol = );
indexedOctree<treeDataTriSurfacePrimitivePatch>::perturbTol();
indexedOctree<treeDataTriSurfacePrimitivePatch>::perturbTol() =
tolerance_;
const PtrList<indexedOctree<treeDataTriSurfacePrimitivePatch> >&
octrees = treeByRegion();
info.setSize(samples.size());
forAll(octrees, treeI)
{
if (findIndex(regionIndices, treeI) == -1)
{
continue;
}
const indexedOctree<treeDataTriSurfacePrimitivePatch>& octree =
octrees[treeI];
forAll(samples, i)
{
// if (!octree.bb().contains(samples[i]))
// {
// continue;
// }
pointIndexHit currentRegionHit = octree.findNearest
(
samples[i],
nearestDistSqr[i],
treeDataTriSurfacePrimitivePatch::findNearestOp(octree)
);
if
(
currentRegionHit.hit()
&&
(
!info[i].hit()
||
(
magSqr(currentRegionHit.hitPoint() - samples[i])
< magSqr(info[i].hitPoint() - samples[i])
)
)
)
{
info[i] = currentRegionHit;
}
}
}
indexedOctree<treeDataTriSurfacePrimitivePatch>::perturbTol() = oldTol;
}
} }
@ -843,23 +548,7 @@ void Foam::triSurfaceMesh::findLine
List<pointIndexHit>& info List<pointIndexHit>& info
) const ) const
{ {
const indexedOctree<treeDataTriSurface>& octree = tree(); triSurfaceSearch::findLine(start, end, info);
info.setSize(start.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_;
forAll(start, i)
{
static_cast<pointIndexHit&>(info[i]) = octree.findLine
(
start[i],
end[i]
);
}
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
} }
@ -870,23 +559,7 @@ void Foam::triSurfaceMesh::findLineAny
List<pointIndexHit>& info List<pointIndexHit>& info
) const ) const
{ {
const indexedOctree<treeDataTriSurface>& octree = tree(); triSurfaceSearch::findLineAny(start, end, info);
info.setSize(start.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_;
forAll(start, i)
{
static_cast<pointIndexHit&>(info[i]) = octree.findLineAny
(
start[i],
end[i]
);
}
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
} }
@ -897,51 +570,7 @@ void Foam::triSurfaceMesh::findLineAll
List<List<pointIndexHit> >& info List<List<pointIndexHit> >& info
) const ) const
{ {
const indexedOctree<treeDataTriSurface>& octree = tree(); triSurfaceSearch::findLineAll(start, end, info);
info.setSize(start.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_;
// Work array
DynamicList<pointIndexHit, 1, 1> hits;
DynamicList<label> shapeMask;
treeDataTriSurface::findAllIntersectOp allIntersectOp(octree, shapeMask);
forAll(start, pointI)
{
hits.clear();
shapeMask.clear();
while (true)
{
// See if any intersection between pt and end
pointIndexHit inter = octree.findLine
(
start[pointI],
end[pointI],
allIntersectOp
);
if (inter.hit())
{
hits.append(inter);
shapeMask.append(inter.index());
}
else
{
break;
}
}
info[pointI].transfer(hits);
}
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
} }
@ -1103,7 +732,7 @@ void Foam::triSurfaceMesh::getVolumeType
volType.setSize(points.size()); volType.setSize(points.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol(); scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_; indexedOctree<treeDataTriSurface>::perturbTol() = tolerance();
forAll(points, pointI) forAll(points, pointI)
{ {

View File

@ -50,6 +50,7 @@ SourceFiles
#include "treeDataEdge.H" #include "treeDataEdge.H"
#include "EdgeMap.H" #include "EdgeMap.H"
#include "triSurface.H" #include "triSurface.H"
#include "triSurfaceRegionSearch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -64,44 +65,17 @@ class triSurfaceMesh
: :
public searchableSurface, public searchableSurface,
public objectRegistry, // so we can store fields public objectRegistry, // so we can store fields
public triSurface public triSurface,
public triSurfaceRegionSearch
{ {
private: private:
// Private typedefs
typedef PrimitivePatch
<
labelledTri,
IndirectList,
const pointField&
> indirectTriSurfacePrimitivePatch;
typedef treeDataPrimitivePatch<indirectTriSurfacePrimitivePatch>
treeDataTriSurfacePrimitivePatch;
// Private member data // Private member data
//- Optional tolerance to use in searches
scalar tolerance_;
//- Optional min triangle quality. Triangles below this get //- Optional min triangle quality. Triangles below this get
// ignored for normal calculation // ignored for normal calculation
scalar minQuality_; scalar minQuality_;
//- Optional max tree depth of octree
label maxTreeDepth_;
//- Search tree (triangles)
mutable autoPtr<indexedOctree<treeDataTriSurface> > tree_;
mutable PtrList<indirectTriSurfacePrimitivePatch>
indirectRegionPatches_;
//- Search tree for each region
mutable PtrList<indexedOctree<treeDataTriSurfacePrimitivePatch> >
treeByRegion_;
//- Search tree for boundary edges. //- Search tree for boundary edges.
mutable autoPtr<indexedOctree<treeDataEdge> > edgeTree_; mutable autoPtr<indexedOctree<treeDataEdge> > edgeTree_;
@ -157,20 +131,6 @@ private:
void operator=(const triSurfaceMesh&); void operator=(const triSurfaceMesh&);
protected:
//- Calculate (number of) used points and their bounding box
void calcBounds(boundBox& bb, label& nPoints) const;
template <class PatchType>
void calcBounds
(
const PatchType& patch,
boundBox& bb,
label& nPoints
) const;
public: public:
//- Runtime type information //- Runtime type information
@ -206,17 +166,9 @@ public:
//- Move points //- Move points
virtual void movePoints(const pointField&); virtual void movePoints(const pointField&);
//- Demand driven construction of octree
const indexedOctree<treeDataTriSurface>& tree() const;
//- Demand driven construction of octree by region
const PtrList<indexedOctree<treeDataTriSurfacePrimitivePatch> >&
treeByRegion() const;
//- Demand driven contruction of octree for boundary edges //- Demand driven contruction of octree for boundary edges
const indexedOctree<treeDataEdge>& edgeTree() const; const indexedOctree<treeDataEdge>& edgeTree() const;
scalar tolerance() const;
// searchableSurface implementation // searchableSurface implementation

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -258,7 +258,8 @@ void Foam::orientedSurface::findZoneSide
zoneFaceI = -1; zoneFaceI = -1;
isOutside = false; isOutside = false;
List<pointIndexHit> hits; pointField start(1, outsidePoint);
List<List<pointIndexHit> > hits(1, List<pointIndexHit>());
forAll(faceZone, faceI) forAll(faceZone, faceI)
{ {
@ -273,7 +274,7 @@ void Foam::orientedSurface::findZoneSide
// Check if normal different enough to decide upon // Check if normal different enough to decide upon
if (magD > SMALL && (mag(n & d/magD) > 1e-6)) if (magD > SMALL && (mag(n & d/magD) > 1e-6))
{ {
point end = fc + d; pointField end(1, fc + d);
//Info<< "Zone " << zoneI << " : Shooting ray" //Info<< "Zone " << zoneI << " : Shooting ray"
// << " from " << outsidePoint // << " from " << outsidePoint
@ -281,12 +282,13 @@ void Foam::orientedSurface::findZoneSide
// << " to pierce triangle " << faceI // << " to pierce triangle " << faceI
// << " with centre " << fc << endl; // << " with centre " << fc << endl;
surfSearches.findLineAll(outsidePoint, end, hits);
surfSearches.findLineAll(start, end, hits);
label zoneIndex = -1; label zoneIndex = -1;
forAll(hits, i) forAll(hits[0], i)
{ {
if (hits[i].index() == faceI) if (hits[0][i].index() == faceI)
{ {
zoneIndex = i; zoneIndex = i;
break; break;
@ -573,4 +575,19 @@ bool Foam::orientedSurface::orient
} }
bool Foam::orientedSurface::orientAll(triSurface& s)
{
if (orientConsistent(s))
{
Info<< "Some triangles are not oriented consistently. Aborting."
<< endl;
return false;
}
labelList flipState(s.size(), FLIP);
return flipSurface(s, flipState);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,246 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "triSurfaceRegionSearch.H"
#include "indexedOctree.H"
#include "triSurface.H"
#include "PatchTools.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::triSurfaceRegionSearch::triSurfaceRegionSearch(const triSurface& surface)
:
triSurfaceSearch(surface),
indirectRegionPatches_(),
treeByRegion_()
{}
Foam::triSurfaceRegionSearch::triSurfaceRegionSearch
(
const triSurface& surface,
const dictionary& dict
)
:
triSurfaceSearch(surface, dict),
indirectRegionPatches_(),
treeByRegion_()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::triSurfaceRegionSearch::~triSurfaceRegionSearch()
{
clearOut();
}
void Foam::triSurfaceRegionSearch::clearOut()
{
triSurfaceSearch::clearOut();
treeByRegion_.clear();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::PtrList<Foam::triSurfaceRegionSearch::treeType>&
Foam::triSurfaceRegionSearch::treeByRegion() const
{
if (treeByRegion_.empty())
{
Map<label> regionSizes;
forAll(surface(), fI)
{
const label regionI = surface()[fI].region();
regionSizes(regionI)++;
}
label nRegions = regionSizes.size();
indirectRegionPatches_.setSize(nRegions);
treeByRegion_.setSize(nRegions);
labelListList regionsAddressing(nRegions);
forAll(regionsAddressing, regionI)
{
regionsAddressing[regionI] = labelList(regionSizes[regionI], -1);
}
labelList nFacesInRegions(nRegions, 0);
forAll(surface(), fI)
{
const label regionI = surface()[fI].region();
regionsAddressing[regionI][nFacesInRegions[regionI]++] = fI;
}
forAll(regionsAddressing, regionI)
{
scalar oldTol = treeType::perturbTol();
treeType::perturbTol() = tolerance();
indirectRegionPatches_.set
(
regionI,
new indirectTriSurface
(
IndirectList<labelledTri>
(
surface(),
regionsAddressing[regionI]
),
surface().points()
)
);
// Calculate bb without constructing local point numbering.
treeBoundBox bb;
label nPoints;
PatchTools::calcBounds
(
indirectRegionPatches_[regionI],
bb,
nPoints
);
// if (nPoints != surface().points().size())
// {
// WarningIn("triSurfaceRegionSearch::treeByRegion() const")
// << "Surface does not have compact point numbering. "
// << "Of " << surface().points().size()
// << " only " << nPoints
// << " are used. This might give problems in some routines."
// << endl;
// }
// Random number generator. Bit dodgy since not exactly random ;-)
Random rndGen(65431);
// Slightly extended bb. Slightly off-centred just so on symmetric
// geometry there are fewer face/edge aligned items.
bb = bb.extend(rndGen, 1e-4);
bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
treeByRegion_.set
(
regionI,
new treeType
(
treeDataIndirectTriSurface
(
true,
indirectRegionPatches_[regionI],
tolerance()
),
bb,
maxTreeDepth(), // maxLevel
10, // leafsize
3.0 // duplicity
)
);
treeType::perturbTol() = oldTol;
}
}
return treeByRegion_;
}
void Foam::triSurfaceRegionSearch::findNearest
(
const pointField& samples,
const scalarField& nearestDistSqr,
const labelList& regionIndices,
List<pointIndexHit>& info
) const
{
if (regionIndices.empty())
{
triSurfaceSearch::findNearest(samples, nearestDistSqr, info);
}
else
{
scalar oldTol = treeType::perturbTol();
treeType::perturbTol() = tolerance();
const PtrList<treeType>& octrees = treeByRegion();
info.setSize(samples.size());
forAll(octrees, treeI)
{
if (findIndex(regionIndices, treeI) == -1)
{
continue;
}
const treeType& octree = octrees[treeI];
forAll(samples, i)
{
// if (!octree.bb().contains(samples[i]))
// {
// continue;
// }
pointIndexHit currentRegionHit = octree.findNearest
(
samples[i],
nearestDistSqr[i],
treeDataIndirectTriSurface::findNearestOp(octree)
);
if
(
currentRegionHit.hit()
&&
(
!info[i].hit()
||
(
magSqr(currentRegionHit.hitPoint() - samples[i])
< magSqr(info[i].hitPoint() - samples[i])
)
)
)
{
info[i] = currentRegionHit;
}
}
}
treeType::perturbTol() = oldTol;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,144 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::triSurfaceRegionSearch
Description
Helper class to search on triSurface. Creates an octree for each region of
the surface and only searches on the specified regions.
SourceFiles
triSurfaceRegionSearch.C
\*---------------------------------------------------------------------------*/
#ifndef triSurfaceRegionSearch_H
#define triSurfaceRegionSearch_H
#include "pointField.H"
#include "pointIndexHit.H"
#include "triSurfaceSearch.H"
#include "labelledTri.H"
#include "IndirectList.H"
#include "PtrList.H"
#include "indexedOctree.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class triSurfaceRegionSearch Declaration
\*---------------------------------------------------------------------------*/
class triSurfaceRegionSearch
:
public triSurfaceSearch
{
// Private typedefs
typedef PrimitivePatch
<
labelledTri,
IndirectList,
const pointField&
> indirectTriSurface;
typedef treeDataPrimitivePatch<indirectTriSurface>
treeDataIndirectTriSurface;
typedef indexedOctree<treeDataIndirectTriSurface> treeType;
// Private data
//- Surface is split into patches by region
mutable PtrList<indirectTriSurface> indirectRegionPatches_;
//- Search tree for each region
mutable PtrList<treeType> treeByRegion_;
// Private Member Functions
//- Disallow default bitwise copy construct
triSurfaceRegionSearch(const triSurfaceRegionSearch&);
//- Disallow default bitwise assignment
void operator=(const triSurfaceRegionSearch&);
public:
// Constructors
//- Construct from surface. Holds reference to surface!
explicit triSurfaceRegionSearch(const triSurface&);
//- Construct from surface and dictionary. Holds reference to surface!
triSurfaceRegionSearch(const triSurface&, const dictionary& dict);
//- Destructor
~triSurfaceRegionSearch();
//- Clear storage
void clearOut();
// Member Functions
// Access
//- Demand driven construction of octree for each region.
// @todo Currently creates a tree for each region; could optimise
// by only constructing trees when they are in regionIndices
const PtrList<treeType>& treeByRegion() const;
// Query
//- Find the nearest point on the surface out of the regions
// supplied in the list regionIndices. Ignores regions that are
// not specified
void findNearest
(
const pointField& samples,
const scalarField& nearestDistSqr,
const labelList& regionIndices,
List<pointIndexHit>& info
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -24,63 +24,126 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "triSurfaceSearch.H" #include "triSurfaceSearch.H"
#include "indexedOctree.H"
#include "boolList.H"
#include "treeDataTriSurface.H"
#include "triSurface.H" #include "triSurface.H"
#include "line.H" #include "PatchTools.H"
#include "cpuTime.H" #include "volumeType.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::point Foam::triSurfaceSearch::greatPoint(GREAT, GREAT, GREAT);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct from surface. Holds reference!
Foam::triSurfaceSearch::triSurfaceSearch(const triSurface& surface) Foam::triSurfaceSearch::triSurfaceSearch(const triSurface& surface)
: :
surface_(surface), surface_(surface),
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()),
maxTreeDepth_(10),
treePtr_(NULL)
{}
Foam::triSurfaceSearch::triSurfaceSearch
(
const triSurface& surface,
const dictionary& dict
)
:
surface_(surface),
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()),
maxTreeDepth_(10),
treePtr_(NULL) treePtr_(NULL)
{ {
// Random number generator. Bit dodgy since not exactly random ;-) // Have optional non-standard search tolerance for gappy surfaces.
Random rndGen(65431); if (dict.readIfPresent("tolerance", tolerance_) && tolerance_ > 0)
{
Info<< " using intersection tolerance " << tolerance_ << endl;
}
// Slightly extended bb. Slightly off-centred just so on symmetric // Have optional non-standard tree-depth to limit storage.
// geometry there are less face/edge aligned items. if (dict.readIfPresent("maxTreeDepth", maxTreeDepth_) && maxTreeDepth_ > 0)
treeBoundBox treeBb {
( Info<< " using maximum tree depth " << maxTreeDepth_ << endl;
treeBoundBox(surface_.points(), surface_.meshPoints()).extend }
( }
rndGen,
1e-4
)
);
treeBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
treeBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
treePtr_.reset
( Foam::triSurfaceSearch::triSurfaceSearch
new indexedOctree<treeDataTriSurface> (
( const triSurface& surface,
treeDataTriSurface const scalar tolerance,
( const label maxTreeDepth
true, )
surface_, :
indexedOctree<treeDataTriSurface>::perturbTol() surface_(surface),
), tolerance_(tolerance),
treeBb, maxTreeDepth_(maxTreeDepth),
8, // maxLevel treePtr_(NULL)
10, // leafsize {}
3.0 // duplicity
)
); // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::triSurfaceSearch::~triSurfaceSearch()
{
clearOut();
}
void Foam::triSurfaceSearch::clearOut()
{
treePtr_.clear();
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::indexedOctree<Foam::treeDataTriSurface>&
Foam::triSurfaceSearch::tree() const
{
if (treePtr_.empty())
{
// Calculate bb without constructing local point numbering.
treeBoundBox bb;
label nPoints;
PatchTools::calcBounds(surface(), bb, nPoints);
if (nPoints != surface().points().size())
{
WarningIn("triSurfaceSearch::tree() const")
<< "Surface does not have compact point numbering."
<< " Of " << surface().points().size() << " only " << nPoints
<< " are used. This might give problems in some routines."
<< endl;
}
// Random number generator. Bit dodgy since not exactly random ;-)
Random rndGen(65431);
// Slightly extended bb. Slightly off-centred just so on symmetric
// geometry there are less face/edge aligned items.
bb = bb.extend(rndGen, 1e-4);
bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance_;
treePtr_.reset
(
new indexedOctree<treeDataTriSurface>
(
treeDataTriSurface(true, surface_, tolerance_),
bb,
maxTreeDepth_, // maxLevel
10, // leafsize
3.0 // duplicity
)
);
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
}
return treePtr_();
}
// Determine inside/outside for samples // Determine inside/outside for samples
Foam::boolList Foam::triSurfaceSearch::calcInside Foam::boolList Foam::triSurfaceSearch::calcInside
( (
@ -97,11 +160,7 @@ Foam::boolList Foam::triSurfaceSearch::calcInside
{ {
inside[sampleI] = false; inside[sampleI] = false;
} }
else if else if (tree().getVolumeType(sample) == volumeType::INSIDE)
(
tree().getVolumeType(sample)
== indexedOctree<treeDataTriSurface>::INSIDE
)
{ {
inside[sampleI] = true; inside[sampleI] = true;
} }
@ -114,65 +173,31 @@ Foam::boolList Foam::triSurfaceSearch::calcInside
} }
Foam::labelList Foam::triSurfaceSearch::calcNearestTri void Foam::triSurfaceSearch::findNearest
( (
const pointField& samples, const pointField& samples,
const vector& span const scalarField& nearestDistSqr,
List<pointIndexHit>& info
) const ) const
{ {
labelList nearest(samples.size()); scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance();
const scalar nearestDistSqr = 0.25*magSqr(span); const indexedOctree<treeDataTriSurface>& octree = tree();
pointIndexHit hitInfo; info.setSize(samples.size());
forAll(samples, sampleI) forAll(samples, i)
{ {
hitInfo = tree().findNearest(samples[sampleI], nearestDistSqr); static_cast<pointIndexHit&>(info[i]) = octree.findNearest
(
if (hitInfo.hit()) samples[i],
{ nearestDistSqr[i],
nearest[sampleI] = hitInfo.index(); treeDataTriSurface::findNearestOp(octree)
} );
else
{
nearest[sampleI] = -1;
}
} }
return nearest; indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
}
// Nearest point on surface
Foam::tmp<Foam::pointField> Foam::triSurfaceSearch::calcNearest
(
const pointField& samples,
const vector& span
) const
{
const scalar nearestDistSqr = 0.25*magSqr(span);
tmp<pointField> tnearest(new pointField(samples.size()));
pointField& nearest = tnearest();
pointIndexHit hitInfo;
forAll(samples, sampleI)
{
hitInfo = tree().findNearest(samples[sampleI], nearestDistSqr);
if (hitInfo.hit())
{
nearest[sampleI] = hitInfo.hitPoint();
}
else
{
nearest[sampleI] = greatPoint;
}
}
return tnearest;
} }
@ -189,84 +214,112 @@ const
} }
void Foam::triSurfaceSearch::findLine
(
const pointField& start,
const pointField& end,
List<pointIndexHit>& info
) const
{
const indexedOctree<treeDataTriSurface>& octree = tree();
info.setSize(start.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance();
forAll(start, i)
{
static_cast<pointIndexHit&>(info[i]) = octree.findLine
(
start[i],
end[i]
);
}
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
}
void Foam::triSurfaceSearch::findLineAny
(
const pointField& start,
const pointField& end,
List<pointIndexHit>& info
) const
{
const indexedOctree<treeDataTriSurface>& octree = tree();
info.setSize(start.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance();
forAll(start, i)
{
static_cast<pointIndexHit&>(info[i]) = octree.findLineAny
(
start[i],
end[i]
);
}
indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
}
void Foam::triSurfaceSearch::findLineAll void Foam::triSurfaceSearch::findLineAll
( (
const point& start, const pointField& start,
const point& end, const pointField& end,
List<pointIndexHit>& hits List<List<pointIndexHit> >& info
) ) const
const
{ {
// See if any intersection between pt and end const indexedOctree<treeDataTriSurface>& octree = tree();
pointIndexHit inter = tree().findLine(start, end);
if (inter.hit()) info.setSize(start.size());
scalar oldTol = indexedOctree<treeDataTriSurface>::perturbTol();
indexedOctree<treeDataTriSurface>::perturbTol() = tolerance();
// Work array
DynamicList<pointIndexHit, 1, 1> hits;
DynamicList<label> shapeMask;
treeDataTriSurface::findAllIntersectOp allIntersectOp(octree, shapeMask);
forAll(start, pointI)
{ {
hits.setSize(1); hits.clear();
hits[0] = inter; shapeMask.clear();
const vector dirVec(end-start);
const scalar magSqrDirVec(magSqr(dirVec));
const vector smallVec
(
indexedOctree<treeDataTriSurface>::perturbTol()*dirVec
+ vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
);
// Initial perturbation amount
vector perturbVec(smallVec);
while (true) while (true)
{ {
// Start tracking from last hit.
point pt = hits.last().hitPoint() + perturbVec;
if (((pt-start)&dirVec) > magSqrDirVec)
{
return;
}
// See if any intersection between pt and end // See if any intersection between pt and end
pointIndexHit inter = tree().findLine(pt, end); pointIndexHit inter = octree.findLine
(
start[pointI],
end[pointI],
allIntersectOp
);
if (!inter.hit()) if (inter.hit())
{ {
return; hits.append(inter);
}
// Check if already found this intersection shapeMask.append(inter.index());
bool duplicateHit = false;
forAllReverse(hits, i)
{
if (hits[i].index() == inter.index())
{
duplicateHit = true;
break;
}
}
if (duplicateHit)
{
// Hit same triangle again. Increase perturbVec and try again.
perturbVec *= 2;
} }
else else
{ {
// Proper hit break;
label sz = hits.size();
hits.setSize(sz+1);
hits[sz] = inter;
// Restore perturbVec
perturbVec = smallVec;
} }
} }
info[pointI].transfer(hits);
} }
else
{ indexedOctree<treeDataTriSurface>::perturbTol() = oldTol;
hits.clear();
}
} }

View File

@ -48,7 +48,6 @@ namespace Foam
// Forward declaration of classes // Forward declaration of classes
class triSurface; class triSurface;
template<class Type> class indexedOctree;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class triSurfaceSearch Declaration Class triSurfaceSearch Declaration
@ -61,64 +60,82 @@ class triSurfaceSearch
//- Reference to surface to work on //- Reference to surface to work on
const triSurface& surface_; const triSurface& surface_;
//- Optional tolerance to use in searches
scalar tolerance_;
//- Optional max tree depth of octree
label maxTreeDepth_;
//- Octree for searches //- Octree for searches
autoPtr<indexedOctree<treeDataTriSurface> > treePtr_; mutable autoPtr<indexedOctree<treeDataTriSurface> > treePtr_;
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
triSurfaceSearch(const triSurfaceSearch&); triSurfaceSearch(const triSurfaceSearch&);
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const triSurfaceSearch&); void operator=(const triSurfaceSearch&);
public: public:
// Static data members
//- Point far away; used for illegal finds
static const point greatPoint;
// Constructors // Constructors
//- Construct from surface. Holds reference to surface! //- Construct from surface. Holds reference to surface!
triSurfaceSearch(const triSurface&); explicit triSurfaceSearch(const triSurface&);
//- Construct from surface and dictionary.
triSurfaceSearch(const triSurface&, const dictionary& dict);
//- Construct from components
triSurfaceSearch
(
const triSurface& surface,
const scalar tolerance,
const label maxTreeDepth
);
//- Destructor
~triSurfaceSearch();
//- Clear storage
void clearOut();
// Member Functions // Member Functions
const indexedOctree<treeDataTriSurface>& tree() const //- Demand driven construction of the octree
{ const indexedOctree<treeDataTriSurface>& tree() const;
return treePtr_();
}
//- Return reference to the surface.
const triSurface& surface() const const triSurface& surface() const
{ {
return surface_; return surface_;
} }
//- Return tolerance to use in searches
scalar tolerance() const
{
return tolerance_;
}
//- Return max tree depth of octree
label maxTreeDepth() const
{
return maxTreeDepth_;
}
//- Calculate for each searchPoint inside/outside status. //- Calculate for each searchPoint inside/outside status.
boolList calcInside(const pointField& searchPoints) const; boolList calcInside(const pointField& searchPoints) const;
//- Calculate index of nearest triangle (or -1) for each sample. void findNearest
// Looks only in box of size 2*span around sample.
labelList calcNearestTri
( (
const pointField& samples, const pointField& samples,
const vector& span const scalarField& nearestDistSqr,
) const; List<pointIndexHit>& info
//- Calculate nearest points (to searchPoints) on surface.
// Looks only in box of size 2*span around sample. Returns greatPoint
// if not found.
tmp<pointField> calcNearest
(
const pointField& samples,
const vector& span
) const; ) const;
//- Calculate nearest point on surface for single searchPoint. Returns //- Calculate nearest point on surface for single searchPoint. Returns
@ -128,14 +145,27 @@ public:
// - index() : surface triangle label // - index() : surface triangle label
pointIndexHit nearest(const point&, const vector& span) const; pointIndexHit nearest(const point&, const vector& span) const;
void findLine
(
const pointField& start,
const pointField& end,
List<pointIndexHit>& info
) const;
void findLineAny
(
const pointField& start,
const pointField& end,
List<pointIndexHit>& info
) const;
//- Calculate all intersections from start to end //- Calculate all intersections from start to end
void findLineAll void findLineAll
( (
const point& start, const pointField& start,
const point& end, const pointField& end,
List<pointIndexHit>& List<List<pointIndexHit> >& info
) const; ) const;
}; };

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -31,7 +31,7 @@ Description
and thus introduce a third dimension into a 2-D problem. and thus introduce a third dimension into a 2-D problem.
The operation is performed by looping through all edges approximately The operation is performed by looping through all edges approximately
normal to the plane and enforcing their orthoginality onto the plane by normal to the plane and enforcing their orthogonality onto the plane by
adjusting points on their ends. adjusting points on their ends.
SourceFiles SourceFiles

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -37,6 +37,7 @@ License
#include "geomDecomp.H" #include "geomDecomp.H"
#include "vectorList.H" #include "vectorList.H"
#include "PackedBoolList.H" #include "PackedBoolList.H"
#include "PatchTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -2356,7 +2357,7 @@ void Foam::distributedTriSurfaceMesh::writeStats(Ostream& os) const
{ {
boundBox bb; boundBox bb;
label nPoints; label nPoints;
calcBounds(bb, nPoints); PatchTools::calcBounds(static_cast<const triSurface&>(*this), bb, nPoints);
reduce(bb.min(), minOp<point>()); reduce(bb.min(), minOp<point>());
reduce(bb.max(), maxOp<point>()); reduce(bb.max(), maxOp<point>());