Commit 47a63dc9 authored by mattijs's avatar mattijs
Browse files

ENH: indexedOctree: added find-inside query.

Adapted meshSearch and sampledTriSurfaceMesh to use it.
parent a2995ae0
......@@ -2495,6 +2495,59 @@ Foam::labelBits Foam::indexedOctree<Type>::findNode
}
template <class Type>
Foam::label Foam::indexedOctree<Type>::find(const point& sample) const
{
labelBits index = findNode(0, sample);
const node& nod = nodes_[getNode(index)];
labelBits contentIndex = nod.subNodes_[getOctant(index)];
// Need to check for the presence of content, in-case the node is empty
if (isContent(contentIndex))
{
labelList indices = contents_[getContent(contentIndex)];
forAll(indices, elemI)
{
label shapeI = indices[elemI];
if (shapes_.contains(shapeI, sample))
{
return shapeI;
}
}
}
return -1;
}
template <class Type>
Foam::labelList Foam::indexedOctree<Type>::findIndices
(
const point& sample
) const
{
labelBits index = findNode(0, sample);
const node& nod = nodes_[getNode(index)];
labelBits contentIndex = nod.subNodes_[getOctant(index)];
// Need to check for the presence of content, in-case the node is empty
if (isContent(contentIndex))
{
return contents_[getContent(contentIndex)];
}
else
{
return labelList(0);
}
}
// Determine type (inside/outside/mixed) per node.
template <class Type>
typename Foam::indexedOctree<Type>::volumeType
......
......@@ -549,9 +549,15 @@ public:
//- Find deepest node (as parent+octant) containing point. Starts
// off from starting index in nodes_ (use 0 to start from top)
// Use getNode, getOctant to extract info.
// Use getNode and getOctant to extract info, or call findIndices.
labelBits findNode(const label nodeI, const point&) const;
//- Find shape containing point in tree
label find(const point&) const;
//- Find the shape indices that occupy the result of findNode
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;
......
......@@ -145,6 +145,16 @@ bool Foam::treeDataCell::overlaps
}
bool Foam::treeDataCell::contains
(
const label index,
const point& sample
) const
{
return mesh_.pointInCell(sample, cellLabels_[index]);
}
// Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
// nearestPoint.
void Foam::treeDataCell::findNearest
......
......@@ -142,6 +142,13 @@ public:
const treeBoundBox& sampleBb
) const;
//- Does shape at index contain sample
bool contains
(
const label index,
const point& sample
) const;
//- Calculates nearest (to sample) point in shape.
// Returns actual point and distance (squared)
void findNearest
......
......@@ -103,6 +103,11 @@ public:
// Access
const labelList& edgeLabels() const
{
return edgeLabels_;
}
label size() const
{
return edgeLabels_.size();
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -99,7 +99,7 @@ bool Foam::meshSearch::findNearer
// tree based searching
Foam::label Foam::meshSearch::findNearestCellTree(const point& location) const
{
const indexedOctree<treeDataPoint>& tree = cellCentreTree();
const indexedOctree<treeDataCell>& tree = cellTree();
scalar span = tree.bb().mag();
......@@ -176,7 +176,7 @@ Foam::label Foam::meshSearch::findNearestCellWalk
Foam::label Foam::meshSearch::findNearestFaceTree(const point& location) const
{
// Search nearest cell centre.
const indexedOctree<treeDataPoint>& tree = cellCentreTree();
const indexedOctree<treeDataCell>& tree = cellTree();
scalar span = tree.bb().mag();
......@@ -320,6 +320,80 @@ Foam::label Foam::meshSearch::findCellLinear(const point& location) const
}
// walking from seed
Foam::label Foam::meshSearch::findCellWalk
(
const point& location,
const label seedCellI
) const
{
if (seedCellI < 0)
{
FatalErrorIn
(
"meshSearch::findCellWalk(const point&, const label)"
) << "illegal seedCell:" << seedCellI << exit(FatalError);
}
if (pointInCell(location, seedCellI))
{
return seedCellI;
}
// Walk in direction of face that decreases distance
label curCellI = seedCellI;
scalar nearestDistSqr = magSqr(mesh_.cellCentres()[curCellI] - location);
while(true)
{
// Try neighbours of curCellI
const cell& cFaces = mesh_.cells()[curCellI];
label nearestCellI = -1;
forAll(cFaces, i)
{
label faceI = cFaces[i];
if (mesh_.isInternalFace(faceI))
{
label cellI = mesh_.faceOwner()[faceI];
if (cellI == curCellI)
{
cellI = mesh_.faceNeighbour()[faceI];
}
// Check if this is the correct cell
if (pointInCell(location, cellI))
{
return cellI;
}
// Also calculate the nearest cell
scalar distSqr = magSqr(mesh_.cellCentres()[cellI] - location);
if (distSqr < nearestDistSqr)
{
nearestDistSqr = distSqr;
nearestCellI = cellI;
}
}
}
if (nearestCellI == -1)
{
return -1;
}
// Continue with the nearest cell
curCellI = nearestCellI;
}
return -1;
}
Foam::label Foam::meshSearch::findNearestBoundaryFaceWalk
(
const point& location,
......@@ -426,11 +500,7 @@ Foam::vector Foam::meshSearch::offset
Foam::meshSearch::meshSearch(const polyMesh& mesh, const bool faceDecomp)
:
mesh_(mesh),
faceDecomp_(faceDecomp),
cloud_(mesh_, "meshSearchCloud", IDLList<passiveParticle>()),
boundaryTreePtr_(NULL),
cellTreePtr_(NULL),
cellCentreTreePtr_(NULL)
faceDecomp_(faceDecomp)
{}
......@@ -447,7 +517,7 @@ Foam::meshSearch::~meshSearch()
const Foam::indexedOctree<Foam::treeDataFace>& Foam::meshSearch::boundaryTree()
const
{
if (!boundaryTreePtr_)
if (!boundaryTreePtr_.valid())
{
//
// Construct tree
......@@ -466,85 +536,59 @@ const Foam::indexedOctree<Foam::treeDataFace>& Foam::meshSearch::boundaryTree()
overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
boundaryTreePtr_ = new indexedOctree<treeDataFace>
boundaryTreePtr_.reset
(
treeDataFace // all information needed to search faces
new indexedOctree<treeDataFace>
(
false, // do not cache bb
mesh_,
bndFaces // boundary faces only
),
overallBb, // overall search domain
8, // maxLevel
10, // leafsize
3.0 // duplicity
treeDataFace // all information needed to search faces
(
false, // do not cache bb
mesh_,
bndFaces // boundary faces only
),
overallBb, // overall search domain
8, // maxLevel
10, // leafsize
3.0 // duplicity
)
);
}
return *boundaryTreePtr_;
return boundaryTreePtr_();
}
const Foam::indexedOctree<Foam::treeDataCell>& Foam::meshSearch::cellTree()
const
const
{
if (!cellTreePtr_)
if (!cellTreePtr_.valid())
{
//
// Construct tree
//
treeBoundBox overallBb(mesh_.points());
Random rndGen(123456);
overallBb = overallBb.extend(rndGen, 1E-4);
overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
cellTreePtr_ = new indexedOctree<treeDataCell>
(
treeDataCell
(
false, // not cache bb
mesh_
),
overallBb, // overall search domain
8, // maxLevel
10, // leafsize
3.0 // duplicity
);
}
return *cellTreePtr_;
}
Random rndGen(261782);
const Foam::indexedOctree<Foam::treeDataPoint>&
Foam::meshSearch::cellCentreTree() const
{
if (!cellCentreTreePtr_)
{
//
// Construct tree
//
treeBoundBox overallBb(mesh_.cellCentres());
Random rndGen(123456);
overallBb = overallBb.extend(rndGen, 1E-4);
overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
cellCentreTreePtr_ = new indexedOctree<treeDataPoint>
cellTreePtr_.reset
(
treeDataPoint(mesh_.cellCentres()),
overallBb, // overall search domain
10, // max levels
10.0, // maximum ratio of cubes v.s. cells
100.0 // max. duplicity; n/a since no bounding boxes.
new indexedOctree<treeDataCell>
(
treeDataCell
(
false, // not cache bb
mesh_
),
overallBb,
8, // maxLevel
10, // leafsize
3.0 // duplicity
)
);
}
return *cellCentreTreePtr_;
return cellTreePtr_();
}
......@@ -697,107 +741,21 @@ Foam::label Foam::meshSearch::findCell
) const
{
// Find the nearest cell centre to this location
label nearCellI = findNearestCell(location, seedCellI, useTreeSearch);
if (debug)
{
Pout<< "findCell : nearCellI:" << nearCellI
<< " ctr:" << mesh_.cellCentres()[nearCellI]
<< endl;
}
if (pointInCell(location, nearCellI))
{
return nearCellI;
}
else
if (seedCellI == -1)
{
if (useTreeSearch)
{
// Start searching from cell centre of nearCell
point curPoint = mesh_.cellCentres()[nearCellI];
vector edgeVec = location - curPoint;
edgeVec /= mag(edgeVec);
do
{
// Walk neighbours (using tracking) to get closer
passiveParticle tracker(cloud_, curPoint, nearCellI);
if (debug)
{
Pout<< "findCell : tracked from curPoint:" << curPoint
<< " nearCellI:" << nearCellI;
}
tracker.track(location);
if (debug)
{
Pout<< " to " << tracker.position()
<< " need:" << location
<< " onB:" << tracker.onBoundary()
<< " cell:" << tracker.cell()
<< " face:" << tracker.face() << endl;
}
if (!tracker.onBoundary())
{
// stopped not on boundary -> reached location
return tracker.cell();
}
// stopped on boundary face. Compare positions
scalar typDim = sqrt(mag(mesh_.faceAreas()[tracker.face()]));
if ((mag(tracker.position() - location)/typDim) < SMALL)
{
return tracker.cell();
}
// tracking stopped at boundary. Find next boundary
// intersection from current point (shifted out a little bit)
// in the direction of the destination
curPoint =
tracker.position()
+ offset(tracker.position(), tracker.face(), edgeVec);
if (debug)
{
Pout<< "Searching for next boundary from curPoint:"
<< curPoint
<< " to location:" << location << endl;
}
pointIndexHit curHit = intersection(curPoint, location);
if (debug)
{
Pout<< "Returned from line search with ";
curHit.write(Pout);
Pout<< endl;
}
if (!curHit.hit())
{
return -1;
}
else
{
nearCellI = mesh_.faceOwner()[curHit.index()];
curPoint =
curHit.hitPoint()
+ offset(curHit.hitPoint(), curHit.index(), edgeVec);
}
}
while (true);
return cellTree().find(location);
}
else
{
return findCellLinear(location);
}
}
return -1;
else
{
return findCellWalk(location, seedCellI);
}
}
......@@ -947,9 +905,8 @@ bool Foam::meshSearch::isInside(const point& p) const
// Delete all storage
void Foam::meshSearch::clearOut()
{
deleteDemandDrivenData(boundaryTreePtr_);
deleteDemandDrivenData(cellTreePtr_);
deleteDemandDrivenData(cellCentreTreePtr_);
boundaryTreePtr_.clear();
cellTreePtr_.clear();
}
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
\\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -37,7 +37,7 @@ SourceFiles
#define meshSearch_H
#include "pointIndexHit.H"
#include "passiveParticleCloud.H"
#include "pointField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -48,7 +48,6 @@ namespace Foam
class polyMesh;
class treeDataCell;
class treeDataFace;
class treeDataPoint;
template<class Type> class indexedOctree;
/*---------------------------------------------------------------------------*\
......@@ -65,14 +64,10 @@ class meshSearch
//- Whether to use face decomposition for all geometric tests
const bool faceDecomp_;
//- Dummy cloud to put particles on for tracking.
passiveParticleCloud cloud_;
//- demand driven octrees
mutable indexedOctree<treeDataFace>* boundaryTreePtr_;
mutable indexedOctree<treeDataCell>* cellTreePtr_;
mutable indexedOctree<treeDataPoint>* cellCentreTreePtr_;
mutable autoPtr<indexedOctree<treeDataFace> > boundaryTreePtr_;
mutable autoPtr<indexedOctree<treeDataCell> > cellTreePtr_;
// Private Member Functions
......@@ -112,8 +107,12 @@ class meshSearch
//- cell containing location. Linear search.
label findCellLinear(const point&) const;
//- walk from seed. Does not 'go around' boundary, just returns
// last cell before boundary.
label findCellWalk(const point&, const label) const;
// Cells
// Faces
label findNearestFaceTree(const point&) const;
......@@ -188,9 +187,6 @@ public:
//- Get (demand driven) reference to octree holding all cells
const indexedOctree<treeDataCell>& cellTree() const;
//- Get (demand driven) reference to octree holding all cell centres
const indexedOctree<treeDataPoint>& cellCentreTree() const;
// Queries
......
......@@ -28,6 +28,7 @@ License
#include "meshSearch.H"
#include "Tuple2.H"
#include "globalIndex.H"
#include "treeDataCell.H"
#include "addToRunTimeSelectionTable.H"
......@@ -166,8 +167,7 @@ bool Foam::sampledTriSurfaceMesh::update()
meshSearch meshSearcher(mesh(), false);
const indexedOctree<treeDataPoint>& cellCentreTree =
meshSearcher.cellCentreTree();
const indexedOctree<treeDataCell>& cellTree = meshSearcher.cellTree();
// Global numbering for cells - only used to uniquely identify local cells.
......@@ -182,7 +182,7 @@ bool Foam::sampledTriSurfaceMesh::update()
// Search triangles using nearest on local mesh
forAll(fc, triI)
{
pointIndexHit nearInfo = cellCentreTree.findNearest
pointIndexHit nearInfo = cellTree.findNearest
(
fc[triI],
sqr(GREAT)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment