mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: cleanup treeData items (#2609)
Changes / Improvements
- more consistent subsetting, interface
* Extend the use of subset and non-subset collections with uniform
internal getters to ensure that the subset/non-subset versions
are robustly handled.
* operator[](label) and objectIndex(label) for standardized access
to the underlying item, or the original index, regardless of
subsetting or not.
* centres() and centre(label) for representative point cloud
information.
* nDim() returns the object dimensionality (0: point, 1: line, etc)
these can be used to determine how 'fat' each shape may be
and whether bounds(labelList) may contribute any useful information.
* bounds(labelList) to return the full bound box required for
specific items. Eg, the overall bounds for various 3D cells.
- easier construction of non-caching versions. The bounding boxes are
rarely cached, so simpler constructors without the caching bool
are provided.
- expose findNearest (bound sphere) method to allow general use
since this does not actually need a tree.
- static helpers
The boxes() static methods can be used by callers that need to build
their own treeBoundBoxList of common shapes (edge, face, cell)
that are also available as treeData types.
The bounds() static methods can be used by callers to determine the
overall bound-box size prior to constructing an indexedOctree
without writing ad hoc code inplace.
Not implemented for treeDataPrimitivePatch since similiar
functionality is available directly from the PrimitivePatch::box()
method with less typing.
========
BREAKING: cellLabels(), faceLabels(), edgeLabel() access methods
- it was always unsafe to use the treeData xxxLabels() methods without
subsetting elements. However, since the various classes
(treeDataCell, treeDataEdge, etc) automatically provided
an identity lookup, this problem was not apparent.
Use objectIndex(label) to safely de-reference to the original index
and operator[](index) to de-reference to the original object.
This commit is contained in:
committed by
Andrew Heather
parent
f638db48c7
commit
ac4f580d09
@ -1807,23 +1807,25 @@ Foam::conformalVoronoiMesh::nearestFeatureEdgeLocations
|
|||||||
const Foam::point& pt
|
const Foam::point& pt
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
const auto& tree = edgeLocationTreePtr_();
|
||||||
|
|
||||||
const scalar exclusionRangeSqr = featureEdgeExclusionDistanceSqr(pt);
|
const scalar exclusionRangeSqr = featureEdgeExclusionDistanceSqr(pt);
|
||||||
|
|
||||||
labelList elems
|
labelList elems = tree.findSphere(pt, exclusionRangeSqr);
|
||||||
= edgeLocationTreePtr_().findSphere(pt, exclusionRangeSqr);
|
|
||||||
|
|
||||||
DynamicList<pointIndexHit> dynPointHit;
|
DynamicList<pointIndexHit> dynPointHit(elems.size());
|
||||||
|
|
||||||
forAll(elems, elemI)
|
for (const label index : elems)
|
||||||
{
|
{
|
||||||
label index = elems[elemI];
|
dynPointHit.append
|
||||||
|
(
|
||||||
const Foam::point& pointi
|
pointIndexHit
|
||||||
= edgeLocationTreePtr_().shapes().shapePoints()[index];
|
(
|
||||||
|
true,
|
||||||
pointIndexHit nearHit(true, pointi, index);
|
tree.shapes().centre(index),
|
||||||
|
index
|
||||||
dynPointHit.append(nearHit);
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dynPointHit;
|
return dynPointHit;
|
||||||
|
|||||||
@ -235,16 +235,14 @@ public:
|
|||||||
|
|
||||||
for (const label index : indices)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const label edgeIndex = shape.edgeLabels()[index];
|
const label edgeIndex = shape.objectIndex(index);
|
||||||
|
|
||||||
if (shapeMask_.found(edgeIndex))
|
if (shapeMask_.found(edgeIndex))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const edge& e = shape.edges()[edgeIndex];
|
pointHit nearHit = shape.line(index).nearestDist(sample);
|
||||||
|
|
||||||
pointHit nearHit = e.line(shape.points()).nearestDist(sample);
|
|
||||||
|
|
||||||
// Only register hit if closest point is not an edge point
|
// Only register hit if closest point is not an edge point
|
||||||
if (nearHit.hit())
|
if (nearHit.hit())
|
||||||
|
|||||||
@ -27,14 +27,13 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "dynamicTreeDataPoint.H"
|
#include "dynamicTreeDataPoint.H"
|
||||||
#include "treeBoundBox.H"
|
|
||||||
#include "dynamicIndexedOctree.H"
|
#include "dynamicIndexedOctree.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(dynamicTreeDataPoint, 0);
|
defineTypeName(dynamicTreeDataPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -51,10 +50,10 @@ Foam::dynamicTreeDataPoint::dynamicTreeDataPoint
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
const Foam::DynamicList<Foam::point>&
|
Foam::treeBoundBox
|
||||||
Foam::dynamicTreeDataPoint::shapePoints() const
|
Foam::dynamicTreeDataPoint::bounds(const labelUList& indices) const
|
||||||
{
|
{
|
||||||
return points_;
|
return treeBoundBox(points_, indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -71,10 +70,10 @@ Foam::volumeType Foam::dynamicTreeDataPoint::getVolumeType
|
|||||||
bool Foam::dynamicTreeDataPoint::overlaps
|
bool Foam::dynamicTreeDataPoint::overlaps
|
||||||
(
|
(
|
||||||
const label index,
|
const label index,
|
||||||
const treeBoundBox& cubeBb
|
const treeBoundBox& searchBox
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return cubeBb.contains(points_[index]);
|
return searchBox.contains(centre(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +84,7 @@ bool Foam::dynamicTreeDataPoint::overlaps
|
|||||||
const scalar radiusSqr
|
const scalar radiusSqr
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return (centre.distSqr(points_[index]) <= radiusSqr);
|
return (centre.distSqr(this->centre(index)) <= radiusSqr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,11 +98,9 @@ void Foam::dynamicTreeDataPoint::findNearest
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
forAll(indices, i)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const label index = indices[i];
|
const point& pt = centre(index);
|
||||||
|
|
||||||
const point& pt = points_[index];
|
|
||||||
|
|
||||||
const scalar distSqr = sample.distSqr(pt);
|
const scalar distSqr = sample.distSqr(pt);
|
||||||
|
|
||||||
@ -128,42 +125,30 @@ void Foam::dynamicTreeDataPoint::findNearest
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
const treeBoundBox lnBb(ln.box());
|
||||||
|
|
||||||
// Best so far
|
// Best so far
|
||||||
scalar nearestDistSqr = linePoint.distSqr(nearestPoint);
|
scalar nearestDistSqr = linePoint.distSqr(nearestPoint);
|
||||||
|
|
||||||
forAll(indices, i)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const label index = indices[i];
|
const point& pt = centre(index);
|
||||||
|
|
||||||
const point& shapePt = points_[index];
|
if (tightest.contains(pt))
|
||||||
|
|
||||||
if (tightest.contains(shapePt))
|
|
||||||
{
|
{
|
||||||
// Nearest point on line
|
// Nearest point on line
|
||||||
pointHit pHit = ln.nearestDist(shapePt);
|
pointHit pHit = ln.nearestDist(pt);
|
||||||
scalar distSqr = sqr(pHit.distance());
|
const scalar distSqr = sqr(pHit.distance());
|
||||||
|
|
||||||
if (distSqr < nearestDistSqr)
|
if (distSqr < nearestDistSqr)
|
||||||
{
|
{
|
||||||
nearestDistSqr = distSqr;
|
nearestDistSqr = distSqr;
|
||||||
minIndex = index;
|
minIndex = index;
|
||||||
linePoint = pHit.point();
|
linePoint = pHit.point();
|
||||||
nearestPoint = shapePt;
|
nearestPoint = pt;
|
||||||
|
|
||||||
{
|
tightest = lnBb;
|
||||||
point& minPt = tightest.min();
|
tightest.grow(pHit.distance());
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2012-2015 OpenFOAM Foundation
|
Copyright (C) 2012-2015 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -61,100 +62,126 @@ template<class Type> class dynamicIndexedOctree;
|
|||||||
|
|
||||||
class dynamicTreeDataPoint
|
class dynamicTreeDataPoint
|
||||||
{
|
{
|
||||||
// Private data
|
// Private Data
|
||||||
|
|
||||||
|
//- The point field
|
||||||
const DynamicList<point>& points_;
|
const DynamicList<point>& points_;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Declare name of the class and its debug switch
|
// Declare name of the class
|
||||||
ClassName("dynamicTreeDataPoint");
|
ClassNameNoDebug("dynamicTreeDataPoint");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors (non-caching)
|
||||||
|
|
||||||
//- Construct from List. Holds reference!
|
//- Construct from List. Holds reference!
|
||||||
dynamicTreeDataPoint(const DynamicList<point>& points);
|
explicit dynamicTreeDataPoint(const DynamicList<point>& points);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
//- Object dimension == 0 (point element)
|
||||||
|
int nDim() const noexcept { return 0; }
|
||||||
|
|
||||||
inline label size() const
|
//- Return bounding box for the specified point indices
|
||||||
{
|
treeBoundBox bounds(const labelUList& indices) const;
|
||||||
return points_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Get representative point cloud for all shapes inside
|
|
||||||
// (one point per shape)
|
|
||||||
const DynamicList<point>& shapePoints() const;
|
|
||||||
|
|
||||||
|
|
||||||
// Search
|
// Access
|
||||||
|
|
||||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
//- The original point field
|
||||||
// Only makes sense for closed surfaces.
|
const DynamicList<point>& points() const noexcept { return points_; }
|
||||||
volumeType getVolumeType
|
|
||||||
(
|
|
||||||
const dynamicIndexedOctree<dynamicTreeDataPoint>&,
|
|
||||||
const point&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does (bb of) shape at index overlap bb
|
//TDB //- The subset of point ids to use
|
||||||
bool overlaps
|
///const labelList& pointLabels() const noexcept { labelList::null(); }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const treeBoundBox& sampleBb
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Check if any point on shape is inside sphere.
|
//- Use a subset of points
|
||||||
bool overlaps
|
bool useSubset() const noexcept { return false; }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const point& centre,
|
|
||||||
const scalar radiusSqr
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Calculates nearest (to sample) point in shape.
|
//- Is the effective point field empty?
|
||||||
// Returns actual point and distance (squared)
|
bool empty() const noexcept { return points_.empty(); }
|
||||||
void findNearest
|
|
||||||
(
|
|
||||||
const labelUList& indices,
|
|
||||||
const point& sample,
|
|
||||||
|
|
||||||
scalar& nearestDistSqr,
|
//- The size of the effective point field
|
||||||
label& nearestIndex,
|
label size() const noexcept { return points_.size(); }
|
||||||
point& nearestPoint
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Calculates nearest (to line) point in shape.
|
//- Map from shape index to original (non-subset) point label
|
||||||
// Returns point and distance (squared)
|
label objectIndex(label index) const noexcept { return index; }
|
||||||
void findNearest
|
|
||||||
(
|
|
||||||
const labelUList& indices,
|
|
||||||
const linePointRef& ln,
|
|
||||||
|
|
||||||
treeBoundBox& tightest,
|
//- Point at specified shape index
|
||||||
label& minIndex,
|
const point& operator[](label index) const { return points_[index]; }
|
||||||
point& linePoint,
|
|
||||||
point& nearestPoint
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Calculate intersection of shape with ray. Sets result
|
//- Point at specified shape index
|
||||||
// accordingly
|
const point& centre(label index) const { return points_[index]; }
|
||||||
bool intersects
|
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const point& start,
|
|
||||||
const point& end,
|
|
||||||
point& result
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//- Representative point cloud
|
||||||
|
const DynamicList<point>& centres() const noexcept { return points_; }
|
||||||
|
|
||||||
|
|
||||||
|
// 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& searchBox
|
||||||
|
) 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;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -29,44 +29,119 @@ License
|
|||||||
#include "treeDataCell.H"
|
#include "treeDataCell.H"
|
||||||
#include "indexedOctree.H"
|
#include "indexedOctree.H"
|
||||||
#include "polyMesh.H"
|
#include "polyMesh.H"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(treeDataCell, 0);
|
defineTypeName(treeDataCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Bound boxes corresponding to specified cells
|
||||||
|
template<class ElementIds>
|
||||||
|
static treeBoundBoxList boxesImpl
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const ElementIds& elemIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBoxList bbs(elemIds.size());
|
||||||
|
|
||||||
|
if (mesh.hasCellPoints())
|
||||||
|
{
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
elemIds.cbegin(),
|
||||||
|
elemIds.cend(),
|
||||||
|
bbs.begin(),
|
||||||
|
[&](label celli)
|
||||||
|
{
|
||||||
|
return treeBoundBox(mesh.points(), mesh.cellPoints(celli));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
elemIds.cbegin(),
|
||||||
|
elemIds.cend(),
|
||||||
|
bbs.begin(),
|
||||||
|
[&](label celli)
|
||||||
|
{
|
||||||
|
return treeBoundBox(mesh.cells()[celli].box(mesh));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataCell::boxes(const primitiveMesh& mesh)
|
||||||
|
{
|
||||||
|
// All cells
|
||||||
|
return boxesImpl(mesh, labelRange(mesh.nCells()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataCell::boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& cellIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boxesImpl(mesh, cellIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataCell::bounds
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& cellIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
if (mesh.hasCellPoints())
|
||||||
|
{
|
||||||
|
for (const label celli : cellIds)
|
||||||
|
{
|
||||||
|
bb.add(mesh.points(), mesh.cellPoints(celli));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const label celli : cellIds)
|
||||||
|
{
|
||||||
|
bb.add(mesh.cells()[celli].box(mesh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::treeBoundBox Foam::treeDataCell::calcCellBb(const label celli) const
|
inline Foam::treeBoundBox
|
||||||
|
Foam::treeDataCell::getBounds(const label index) const
|
||||||
{
|
{
|
||||||
const cellList& cells = mesh_.cells();
|
return treeBoundBox(mesh_.cellBb(objectIndex(index)));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,11 +149,13 @@ void Foam::treeDataCell::update()
|
|||||||
{
|
{
|
||||||
if (cacheBb_)
|
if (cacheBb_)
|
||||||
{
|
{
|
||||||
bbs_.setSize(cellLabels_.size());
|
if (useSubset_)
|
||||||
|
|
||||||
forAll(cellLabels_, i)
|
|
||||||
{
|
{
|
||||||
bbs_[i] = calcCellBb(cellLabels_[i]);
|
bbs_ = treeDataCell::boxes(mesh_, cellLabels_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bbs_ = treeDataCell::boxes(mesh_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +163,23 @@ void Foam::treeDataCell::update()
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeDataCell::treeDataCell
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const polyMesh::cellDecomposition decompMode
|
||||||
|
)
|
||||||
|
:
|
||||||
|
mesh_(mesh),
|
||||||
|
cellLabels_(),
|
||||||
|
useSubset_(false),
|
||||||
|
cacheBb_(cacheBb),
|
||||||
|
decompMode_(decompMode)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataCell::treeDataCell
|
Foam::treeDataCell::treeDataCell
|
||||||
(
|
(
|
||||||
const bool cacheBb,
|
const bool cacheBb,
|
||||||
@ -96,6 +190,7 @@ Foam::treeDataCell::treeDataCell
|
|||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
cellLabels_(cellLabels),
|
cellLabels_(cellLabels),
|
||||||
|
useSubset_(true),
|
||||||
cacheBb_(cacheBb),
|
cacheBb_(cacheBb),
|
||||||
decompMode_(decompMode)
|
decompMode_(decompMode)
|
||||||
{
|
{
|
||||||
@ -113,6 +208,7 @@ Foam::treeDataCell::treeDataCell
|
|||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
cellLabels_(std::move(cellLabels)),
|
cellLabels_(std::move(cellLabels)),
|
||||||
|
useSubset_(true),
|
||||||
cacheBb_(cacheBb),
|
cacheBb_(cacheBb),
|
||||||
decompMode_(decompMode)
|
decompMode_(decompMode)
|
||||||
{
|
{
|
||||||
@ -120,22 +216,79 @@ Foam::treeDataCell::treeDataCell
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataCell::treeDataCell
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataCell::bounds(const labelUList& indices) const
|
||||||
|
{
|
||||||
|
if (useSubset_)
|
||||||
|
{
|
||||||
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
if (mesh_.hasCellPoints())
|
||||||
|
{
|
||||||
|
for (const label index : indices)
|
||||||
|
{
|
||||||
|
const label celli = cellLabels_[index];
|
||||||
|
|
||||||
|
bb.add(mesh_.points(), mesh_.cellPoints(celli));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const label index : indices)
|
||||||
|
{
|
||||||
|
const label celli = cellLabels_[index];
|
||||||
|
|
||||||
|
bb.add(mesh_.cells()[celli].box(mesh_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return treeDataCell::bounds(mesh_, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField> Foam::treeDataCell::centres() const
|
||||||
|
{
|
||||||
|
if (useSubset_)
|
||||||
|
{
|
||||||
|
return tmp<pointField>::New(mesh_.cellCentres(), cellLabels_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mesh_.cellCentres();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::treeDataCell::overlaps
|
||||||
(
|
(
|
||||||
const bool cacheBb,
|
const label index,
|
||||||
const polyMesh& mesh,
|
const treeBoundBox& searchBox
|
||||||
const polyMesh::cellDecomposition decompMode
|
) const
|
||||||
)
|
|
||||||
:
|
|
||||||
mesh_(mesh),
|
|
||||||
cellLabels_(identity(mesh_.nCells())),
|
|
||||||
cacheBb_(cacheBb),
|
|
||||||
decompMode_(decompMode)
|
|
||||||
{
|
{
|
||||||
update();
|
return
|
||||||
|
(
|
||||||
|
cacheBb_
|
||||||
|
? searchBox.overlaps(bbs_[index])
|
||||||
|
: searchBox.overlaps(getBounds(index))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::treeDataCell::contains
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const point& sample
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return mesh_.pointInCell(sample, objectIndex(index), decompMode_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Searching * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::treeDataCell::findNearestOp::findNearestOp
|
Foam::treeDataCell::findNearestOp::findNearestOp
|
||||||
(
|
(
|
||||||
const indexedOctree<treeDataCell>& tree
|
const indexedOctree<treeDataCell>& tree
|
||||||
@ -154,43 +307,29 @@ Foam::treeDataCell::findIntersectOp::findIntersectOp
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
void Foam::treeDataCell::findNearest
|
||||||
|
|
||||||
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 labelUList& indices,
|
||||||
const treeBoundBox& cubeBb
|
const point& sample,
|
||||||
|
|
||||||
|
scalar& nearestDistSqr,
|
||||||
|
label& minIndex,
|
||||||
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
if (cacheBb_)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
return cubeBb.overlaps(bbs_[index]);
|
const point& pt = centre(index);
|
||||||
|
|
||||||
|
const scalar distSqr = sample.distSqr(pt);
|
||||||
|
|
||||||
|
if (distSqr < nearestDistSqr)
|
||||||
|
{
|
||||||
|
nearestDistSqr = distSqr;
|
||||||
|
minIndex = index;
|
||||||
|
nearestPoint = pt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cubeBb.overlaps(calcCellBb(cellLabels_[index]));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::treeDataCell::contains
|
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const point& sample
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return mesh_.pointInCell(sample, cellLabels_[index], decompMode_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -204,23 +343,14 @@ void Foam::treeDataCell::findNearestOp::operator()
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const treeDataCell& shape = tree_.shapes();
|
tree_.shapes().findNearest
|
||||||
|
(
|
||||||
forAll(indices, i)
|
indices,
|
||||||
{
|
sample,
|
||||||
label index = indices[i];
|
nearestDistSqr,
|
||||||
label celli = shape.cellLabels()[index];
|
minIndex,
|
||||||
const point& pt = shape.mesh().cellCentres()[celli];
|
nearestPoint
|
||||||
|
);
|
||||||
scalar distSqr = sample.distSqr(pt);
|
|
||||||
|
|
||||||
if (distSqr < nearestDistSqr)
|
|
||||||
{
|
|
||||||
nearestDistSqr = distSqr;
|
|
||||||
minIndex = index;
|
|
||||||
nearestPoint = pt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -262,7 +392,7 @@ bool Foam::treeDataCell::findIntersectOp::operator()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const treeBoundBox cellBb = shape.calcCellBb(shape.cellLabels_[index]);
|
const treeBoundBox cellBb = shape.getBounds(index);
|
||||||
|
|
||||||
if ((cellBb.posBits(start) & cellBb.posBits(end)) != 0)
|
if ((cellBb.posBits(start) & cellBb.posBits(end)) != 0)
|
||||||
{
|
{
|
||||||
@ -276,23 +406,23 @@ bool Foam::treeDataCell::findIntersectOp::operator()
|
|||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
// Disable picking up intersections behind us.
|
// Disable picking up intersections behind us.
|
||||||
scalar oldTol = intersection::setPlanarTol(0.0);
|
const scalar oldTol = intersection::setPlanarTol(0);
|
||||||
|
|
||||||
const cell& cFaces = shape.mesh_.cells()[shape.cellLabels_[index]];
|
|
||||||
|
|
||||||
const vector dir(end - start);
|
const vector dir(end - start);
|
||||||
scalar minDistSqr = magSqr(dir);
|
scalar minDistSqr = magSqr(dir);
|
||||||
bool hasMin = false;
|
bool hasMin = false;
|
||||||
|
|
||||||
forAll(cFaces, i)
|
const label celli = shape.objectIndex(index);
|
||||||
|
|
||||||
|
for (const label facei : shape.mesh().cells()[celli])
|
||||||
{
|
{
|
||||||
const face& f = shape.mesh_.faces()[cFaces[i]];
|
const face& f = shape.mesh().faces()[facei];
|
||||||
|
|
||||||
pointHit inter = f.ray
|
pointHit inter = f.ray
|
||||||
(
|
(
|
||||||
start,
|
start,
|
||||||
dir,
|
dir,
|
||||||
shape.mesh_.points(),
|
shape.mesh().points(),
|
||||||
intersection::HALF_RAY
|
intersection::HALF_RAY
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -35,8 +36,8 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef treeDataCell_H
|
#ifndef Foam_treeDataCell_H
|
||||||
#define treeDataCell_H
|
#define Foam_treeDataCell_H
|
||||||
|
|
||||||
#include "polyMesh.H"
|
#include "polyMesh.H"
|
||||||
#include "treeBoundBoxList.H"
|
#include "treeBoundBoxList.H"
|
||||||
@ -47,7 +48,7 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
// Forward declaration of classes
|
// Forward Declarations
|
||||||
template<class Type> class indexedOctree;
|
template<class Type> class indexedOctree;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
@ -56,13 +57,17 @@ template<class Type> class indexedOctree;
|
|||||||
|
|
||||||
class treeDataCell
|
class treeDataCell
|
||||||
{
|
{
|
||||||
// Private data
|
// Private Data
|
||||||
|
|
||||||
|
//- Reference to the mesh
|
||||||
const polyMesh& mesh_;
|
const polyMesh& mesh_;
|
||||||
|
|
||||||
//- Subset of cells to work on
|
//- Subset of cells to work on
|
||||||
const labelList cellLabels_;
|
const labelList cellLabels_;
|
||||||
|
|
||||||
|
//- Use subset of cells (cellLabels)
|
||||||
|
const bool useSubset_;
|
||||||
|
|
||||||
//- Whether to precalculate and store cell bounding box
|
//- Whether to precalculate and store cell bounding box
|
||||||
const bool cacheBb_;
|
const bool cacheBb_;
|
||||||
|
|
||||||
@ -75,8 +80,8 @@ class treeDataCell
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Calculate cell bounding box
|
//- Get cell bounding box at specified index
|
||||||
treeBoundBox calcCellBb(const label celli) const;
|
inline treeBoundBox getBounds(const label index) const;
|
||||||
|
|
||||||
//- Initialise all member data
|
//- Initialise all member data
|
||||||
void update();
|
void update();
|
||||||
@ -133,11 +138,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Declare name of the class and its debug switch
|
// Declare name of the class
|
||||||
ClassName("treeDataCell");
|
ClassNameNoDebug("treeDataCell");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors (cachable versions)
|
||||||
|
|
||||||
|
//- Construct from mesh, using all cells in mesh.
|
||||||
|
treeDataCell
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const polyMesh& mesh,
|
||||||
|
polyMesh::cellDecomposition decompMode
|
||||||
|
);
|
||||||
|
|
||||||
//- Construct from mesh, copying subset of cells.
|
//- Construct from mesh, copying subset of cells.
|
||||||
treeDataCell
|
treeDataCell
|
||||||
@ -145,7 +158,7 @@ public:
|
|||||||
const bool cacheBb,
|
const bool cacheBb,
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const labelUList& cellLabels,
|
const labelUList& cellLabels,
|
||||||
const polyMesh::cellDecomposition decompMode
|
polyMesh::cellDecomposition decompMode
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from mesh, moving subset of cells
|
//- Construct from mesh, moving subset of cells
|
||||||
@ -154,74 +167,166 @@ public:
|
|||||||
const bool cacheBb,
|
const bool cacheBb,
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
labelList&& cellLabels,
|
labelList&& cellLabels,
|
||||||
const polyMesh::cellDecomposition decompMode
|
polyMesh::cellDecomposition decompMode
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from mesh. Uses all cells in mesh.
|
|
||||||
|
// Constructors (non-caching)
|
||||||
|
|
||||||
|
//- Construct from mesh, using all cells in mesh.
|
||||||
treeDataCell
|
treeDataCell
|
||||||
(
|
(
|
||||||
const bool cacheBb,
|
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const polyMesh::cellDecomposition decompMode
|
polyMesh::cellDecomposition decompMode
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataCell(false, mesh, decompMode)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from mesh, copying subset of cells.
|
||||||
|
treeDataCell
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const labelUList& cellLabels,
|
||||||
|
polyMesh::cellDecomposition decompMode
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataCell(false, mesh, cellLabels, decompMode)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from mesh, moving subset of cells
|
||||||
|
treeDataCell
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
labelList&& cellLabels,
|
||||||
|
polyMesh::cellDecomposition decompMode
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataCell(false, mesh, std::move(cellLabels), decompMode)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Static Functions
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for all mesh cells
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for specified mesh cells
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& cellIds
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return bounding box of specified mesh cells
|
||||||
|
static treeBoundBox bounds
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& cellIds
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
//- Object dimension == 3 (volume element)
|
||||||
|
int nDim() const noexcept { return 3; }
|
||||||
|
|
||||||
inline const labelList& cellLabels() const
|
//- Return bounding box for the specified cell indices
|
||||||
{
|
treeBoundBox bounds(const labelUList& indices) const;
|
||||||
return cellLabels_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const polyMesh& mesh() const
|
|
||||||
{
|
|
||||||
return mesh_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline polyMesh::cellDecomposition 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
|
// Access
|
||||||
|
|
||||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
//- Reference to the supporting mesh
|
||||||
// Only makes sense for closed surfaces.
|
const polyMesh& mesh() const noexcept { return mesh_; }
|
||||||
volumeType getVolumeType
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataCell>&,
|
|
||||||
const point&
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
NotImplemented;
|
|
||||||
return volumeType::UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Does (bb of) shape at index overlap bb
|
//- The cell decomposition mode used
|
||||||
bool overlaps
|
polyMesh::cellDecomposition decompMode() const noexcept
|
||||||
(
|
{
|
||||||
const label index,
|
return decompMode_;
|
||||||
const treeBoundBox& sampleBb
|
}
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does shape at index contain sample
|
//- The subset of cell ids to use
|
||||||
bool contains
|
const labelList& cellLabels() const noexcept { return cellLabels_; }
|
||||||
(
|
|
||||||
const label index,
|
//- Use a subset of cells
|
||||||
const point& sample
|
bool useSubset() const noexcept { return useSubset_; }
|
||||||
) const;
|
|
||||||
|
//- Is the effective cell selection empty?
|
||||||
|
bool empty() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? cellLabels_.empty() : !mesh_.nCells();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- The size of the cell selection
|
||||||
|
label size() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? cellLabels_.size() : mesh_.nCells();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Map from shape index to original (non-subset) cell label
|
||||||
|
label objectIndex(const label index) const
|
||||||
|
{
|
||||||
|
return useSubset_ && index >= 0 ? cellLabels_[index] : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TBD //- Cell at specified shape index
|
||||||
|
///const cell& operator[](const label index) const
|
||||||
|
///{ return mesh_.cells()[objectIndex(index)]; }
|
||||||
|
|
||||||
|
//- Representative point (cell centre) at shape index
|
||||||
|
const point& centre(const label index) const
|
||||||
|
{
|
||||||
|
return mesh_.cellCentres()[objectIndex(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Representative point cloud for contained shapes.
|
||||||
|
//- One point per shape, corresponding to the cell centres.
|
||||||
|
tmp<pointField> centres() 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;
|
||||||
|
return volumeType::UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Does (bb of) shape at index overlap searchBox
|
||||||
|
bool overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const treeBoundBox& searchBox
|
||||||
|
) 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
|
||||||
|
(
|
||||||
|
const labelUList& indices,
|
||||||
|
const point& sample,
|
||||||
|
|
||||||
|
scalar& nearestDistSqr,
|
||||||
|
label& nearestIndex,
|
||||||
|
point& nearestPoint
|
||||||
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -28,36 +28,173 @@ License
|
|||||||
|
|
||||||
#include "treeDataEdge.H"
|
#include "treeDataEdge.H"
|
||||||
#include "indexedOctree.H"
|
#include "indexedOctree.H"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(treeDataEdge, 0);
|
defineTypeName(treeDataEdge);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Bound boxes corresponding to specified edges
|
||||||
|
template<class ElementIds>
|
||||||
|
static treeBoundBoxList boxesImpl
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const ElementIds& elemIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBoxList bbs(elemIds.size());
|
||||||
|
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
elemIds.cbegin(),
|
||||||
|
elemIds.cend(),
|
||||||
|
bbs.begin(),
|
||||||
|
[&](label edgei)
|
||||||
|
{
|
||||||
|
return treeBoundBox(edges[edgei].box(points));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return bbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Overall bound box for specified edges
|
||||||
|
template<class ElementIds>
|
||||||
|
static treeBoundBox boundsImpl
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const ElementIds& elemIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
for (const label edgei : elemIds)
|
||||||
|
{
|
||||||
|
const edge& e = edges[edgei];
|
||||||
|
|
||||||
|
bb.add(points[e.first()], points[e.second()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataEdge::boxes
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBoxList bbs(edges.size());
|
||||||
|
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
edges.cbegin(),
|
||||||
|
edges.cend(),
|
||||||
|
bbs.begin(),
|
||||||
|
[&](const edge& e) { return treeBoundBox(e.box(points)); }
|
||||||
|
);
|
||||||
|
|
||||||
|
return bbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataEdge::boxes
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boxesImpl(edges, points, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataEdge::boxes
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelUList& edgeIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boxesImpl(edges, points, edgeIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataEdge::bounds
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
for (const edge& e : edges)
|
||||||
|
{
|
||||||
|
bb.add(points[e.first()], points[e.second()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataEdge::bounds
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boundsImpl(edges, points, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataEdge::bounds
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelUList& edgeIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boundsImpl(edges, points, edgeIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::treeBoundBox Foam::treeDataEdge::calcBb(const label edgeI) const
|
|
||||||
{
|
|
||||||
const edge& e = edges_[edgeI];
|
|
||||||
const point& p0 = points_[e[0]];
|
|
||||||
const point& p1 = points_[e[1]];
|
|
||||||
|
|
||||||
return treeBoundBox(min(p0, p1), max(p0, p1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataEdge::update()
|
void Foam::treeDataEdge::update()
|
||||||
{
|
{
|
||||||
if (cacheBb_)
|
if (cacheBb_)
|
||||||
{
|
{
|
||||||
bbs_.setSize(edgeLabels_.size());
|
if (useSubset_)
|
||||||
|
|
||||||
forAll(edgeLabels_, i)
|
|
||||||
{
|
{
|
||||||
bbs_[i] = calcBb(edgeLabels_[i]);
|
bbs_ = treeDataEdge::boxes(edges_, points_, edgeLabels_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bbs_ = treeDataEdge::boxes(edges_, points_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,6 +202,41 @@ void Foam::treeDataEdge::update()
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeDataEdge::treeDataEdge
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points
|
||||||
|
)
|
||||||
|
:
|
||||||
|
points_(points),
|
||||||
|
edges_(edges),
|
||||||
|
edgeLabels_(),
|
||||||
|
useSubset_(false),
|
||||||
|
cacheBb_(cacheBb)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeDataEdge::treeDataEdge
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
:
|
||||||
|
points_(points),
|
||||||
|
edges_(edges),
|
||||||
|
edgeLabels_(identity(range)),
|
||||||
|
useSubset_(true),
|
||||||
|
cacheBb_(cacheBb)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataEdge::treeDataEdge
|
Foam::treeDataEdge::treeDataEdge
|
||||||
(
|
(
|
||||||
const bool cacheBb,
|
const bool cacheBb,
|
||||||
@ -73,9 +245,10 @@ Foam::treeDataEdge::treeDataEdge
|
|||||||
const labelUList& edgeLabels
|
const labelUList& edgeLabels
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
edges_(edges),
|
|
||||||
points_(points),
|
points_(points),
|
||||||
|
edges_(edges),
|
||||||
edgeLabels_(edgeLabels),
|
edgeLabels_(edgeLabels),
|
||||||
|
useSubset_(true),
|
||||||
cacheBb_(cacheBb)
|
cacheBb_(cacheBb)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
@ -90,15 +263,107 @@ Foam::treeDataEdge::treeDataEdge
|
|||||||
labelList&& edgeLabels
|
labelList&& edgeLabels
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
edges_(edges),
|
|
||||||
points_(points),
|
points_(points),
|
||||||
|
edges_(edges),
|
||||||
edgeLabels_(std::move(edgeLabels)),
|
edgeLabels_(std::move(edgeLabels)),
|
||||||
|
useSubset_(true),
|
||||||
cacheBb_(cacheBb)
|
cacheBb_(cacheBb)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeBoundBox Foam::treeDataEdge::bounds(const labelUList& indices) const
|
||||||
|
{
|
||||||
|
if (useSubset_)
|
||||||
|
{
|
||||||
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
for (const label index : indices)
|
||||||
|
{
|
||||||
|
const edge& e = edges_[edgeLabels_[index]];
|
||||||
|
|
||||||
|
bb.add(points_[e.first()], points_[e.second()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return treeDataEdge::bounds(edges_, points_, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField> Foam::treeDataEdge::centres() const
|
||||||
|
{
|
||||||
|
tmp<pointField> tpts;
|
||||||
|
|
||||||
|
if (useSubset_)
|
||||||
|
{
|
||||||
|
tpts = tmp<pointField>::New(edgeLabels_.size());
|
||||||
|
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
edgeLabels_.cbegin(),
|
||||||
|
edgeLabels_.cend(),
|
||||||
|
tpts.ref().begin(),
|
||||||
|
[&](label edgei) { return edges_[edgei].centre(points_); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tpts = tmp<pointField>::New(edges_.size());
|
||||||
|
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
edges_.cbegin(),
|
||||||
|
edges_.cend(),
|
||||||
|
tpts.ref().begin(),
|
||||||
|
[&](const edge& e) { return e.centre(points_); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tpts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::volumeType Foam::treeDataEdge::getVolumeType
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataEdge>& oc,
|
||||||
|
const point& sample
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return volumeType::UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::treeDataEdge::overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const treeBoundBox& searchBox
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
point intersect;
|
||||||
|
return searchBox.intersects(this->line(index), intersect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::treeDataEdge::overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const point& centre,
|
||||||
|
const scalar radiusSqr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const pointHit nearHit = this->line(index).nearestDist(centre);
|
||||||
|
|
||||||
|
return (sqr(nearHit.distance()) <= radiusSqr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Searching * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::treeDataEdge::findNearestOp::findNearestOp
|
Foam::treeDataEdge::findNearestOp::findNearestOp
|
||||||
(
|
(
|
||||||
const indexedOctree<treeDataEdge>& tree
|
const indexedOctree<treeDataEdge>& tree
|
||||||
@ -115,67 +380,7 @@ Foam::treeDataEdge::findIntersectOp::findIntersectOp
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
void Foam::treeDataEdge::findNearest
|
||||||
|
|
||||||
Foam::pointField Foam::treeDataEdge::shapePoints() const
|
|
||||||
{
|
|
||||||
pointField eMids(edgeLabels_.size());
|
|
||||||
|
|
||||||
forAll(edgeLabels_, i)
|
|
||||||
{
|
|
||||||
const edge& e = edges_[edgeLabels_[i]];
|
|
||||||
|
|
||||||
eMids[i] = e.centre(points_);
|
|
||||||
}
|
|
||||||
return eMids;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::volumeType Foam::treeDataEdge::getVolumeType
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataEdge>& oc,
|
|
||||||
const point& sample
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return volumeType::UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::treeDataEdge::overlaps
|
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const treeBoundBox& cubeBb
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const edge& e = edges_[edgeLabels_[index]];
|
|
||||||
|
|
||||||
const point& start = points_[e.start()];
|
|
||||||
const point& end = points_[e.end()];
|
|
||||||
|
|
||||||
point intersect;
|
|
||||||
|
|
||||||
return cubeBb.intersects(start, end, intersect);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::treeDataEdge::overlaps
|
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const point& centre,
|
|
||||||
const scalar radiusSqr
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const edge& e = edges_[edgeLabels_[index]];
|
|
||||||
|
|
||||||
const pointHit nearHit = e.line(points_).nearestDist(centre);
|
|
||||||
|
|
||||||
const scalar distSqr = sqr(nearHit.distance());
|
|
||||||
|
|
||||||
return (distSqr <= radiusSqr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataEdge::findNearestOp::operator()
|
|
||||||
(
|
(
|
||||||
const labelUList& indices,
|
const labelUList& indices,
|
||||||
const point& sample,
|
const point& sample,
|
||||||
@ -185,13 +390,9 @@ void Foam::treeDataEdge::findNearestOp::operator()
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const treeDataEdge& shape = tree_.shapes();
|
|
||||||
|
|
||||||
for (const label index : indices)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const edge& e = shape.edges()[shape.edgeLabels()[index]];
|
pointHit nearHit = this->line(index).nearestDist(sample);
|
||||||
|
|
||||||
pointHit nearHit = e.line(shape.points()).nearestDist(sample);
|
|
||||||
|
|
||||||
const scalar distSqr = sqr(nearHit.distance());
|
const scalar distSqr = sqr(nearHit.distance());
|
||||||
|
|
||||||
@ -205,6 +406,27 @@ void Foam::treeDataEdge::findNearestOp::operator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::treeDataEdge::findNearestOp::operator()
|
||||||
|
(
|
||||||
|
const labelUList& indices,
|
||||||
|
const point& sample,
|
||||||
|
|
||||||
|
scalar& nearestDistSqr,
|
||||||
|
label& minIndex,
|
||||||
|
point& nearestPoint
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
tree_.shapes().findNearest
|
||||||
|
(
|
||||||
|
indices,
|
||||||
|
sample,
|
||||||
|
nearestDistSqr,
|
||||||
|
minIndex,
|
||||||
|
nearestPoint
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataEdge::findNearestOp::operator()
|
void Foam::treeDataEdge::findNearestOp::operator()
|
||||||
(
|
(
|
||||||
const labelUList& indices,
|
const labelUList& indices,
|
||||||
@ -218,19 +440,20 @@ void Foam::treeDataEdge::findNearestOp::operator()
|
|||||||
{
|
{
|
||||||
const treeDataEdge& shape = tree_.shapes();
|
const treeDataEdge& shape = tree_.shapes();
|
||||||
|
|
||||||
|
const treeBoundBox lnBb(ln.box());
|
||||||
|
|
||||||
// Best so far
|
// Best so far
|
||||||
scalar nearestDistSqr = linePoint.distSqr(nearestPoint);
|
scalar nearestDistSqr = linePoint.distSqr(nearestPoint);
|
||||||
|
|
||||||
for (const label index : indices)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const edge& e = shape.edges()[shape.edgeLabels()[index]];
|
|
||||||
|
|
||||||
// Note: could do bb test ? Worthwhile?
|
// Note: could do bb test ? Worthwhile?
|
||||||
|
|
||||||
// Nearest point on line
|
// Nearest point on line
|
||||||
point ePoint, lnPt;
|
point ePoint, lnPt;
|
||||||
scalar dist = e.line(shape.points()).nearestDist(ln, ePoint, lnPt);
|
const scalar dist = shape.line(index).nearestDist(ln, ePoint, lnPt);
|
||||||
scalar distSqr = sqr(dist);
|
|
||||||
|
const scalar distSqr = sqr(dist);
|
||||||
|
|
||||||
if (distSqr < nearestDistSqr)
|
if (distSqr < nearestDistSqr)
|
||||||
{
|
{
|
||||||
@ -239,20 +462,8 @@ void Foam::treeDataEdge::findNearestOp::operator()
|
|||||||
linePoint = lnPt;
|
linePoint = lnPt;
|
||||||
nearestPoint = ePoint;
|
nearestPoint = ePoint;
|
||||||
|
|
||||||
{
|
tightest = lnBb;
|
||||||
point& minPt = tightest.min();
|
tightest.grow(dist);
|
||||||
minPt = min(ln.start(), ln.end());
|
|
||||||
minPt.x() -= dist;
|
|
||||||
minPt.y() -= dist;
|
|
||||||
minPt.z() -= dist;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
point& maxPt = tightest.max();
|
|
||||||
maxPt = max(ln.start(), ln.end());
|
|
||||||
maxPt.x() += dist;
|
|
||||||
maxPt.y() += dist;
|
|
||||||
maxPt.z() += dist;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2015 OpenFOAM Foundation
|
Copyright (C) 2011-2015 OpenFOAM Foundation
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -39,6 +39,7 @@ SourceFiles
|
|||||||
#define Foam_treeDataEdge_H
|
#define Foam_treeDataEdge_H
|
||||||
|
|
||||||
#include "treeBoundBoxList.H"
|
#include "treeBoundBoxList.H"
|
||||||
|
#include "labelRange.H"
|
||||||
#include "line.H"
|
#include "line.H"
|
||||||
#include "volumeType.H"
|
#include "volumeType.H"
|
||||||
|
|
||||||
@ -56,41 +57,37 @@ template<class Type> class indexedOctree;
|
|||||||
|
|
||||||
class treeDataEdge
|
class treeDataEdge
|
||||||
{
|
{
|
||||||
// Static Data
|
|
||||||
|
|
||||||
//- Tolerance on linear dimensions
|
|
||||||
static scalar tol;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Data
|
// Private Data
|
||||||
|
|
||||||
|
//- Reference to the underlying support points
|
||||||
|
const pointField& points_;
|
||||||
|
|
||||||
//- Reference to edgeList
|
//- Reference to edgeList
|
||||||
const edgeList& edges_;
|
const edgeList& edges_;
|
||||||
|
|
||||||
//- Reference to points
|
//- Subset of edges to work on
|
||||||
const pointField& points_;
|
|
||||||
|
|
||||||
//- Labels of edges
|
|
||||||
const labelList edgeLabels_;
|
const labelList edgeLabels_;
|
||||||
|
|
||||||
//- Whether to precalculate and store face bounding box
|
//- Use subset of edges (edgeLabels)
|
||||||
|
const bool useSubset_;
|
||||||
|
|
||||||
|
//- Whether to precalculate and store edge bounding box
|
||||||
const bool cacheBb_;
|
const bool cacheBb_;
|
||||||
|
|
||||||
//- Bbs for all above edges (valid only if cacheBb_)
|
//- Edge bounding boxes (valid only if cacheBb_)
|
||||||
treeBoundBoxList bbs_;
|
treeBoundBoxList bbs_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Calculate edge bounding box
|
|
||||||
treeBoundBox calcBb(const label edgeI) const;
|
|
||||||
|
|
||||||
//- Initialise all member data
|
//- Initialise all member data
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
//- Forward to treeDataEdge findNearest operations
|
||||||
class findNearestOp
|
class findNearestOp
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataEdge>& tree_;
|
const indexedOctree<treeDataEdge>& tree_;
|
||||||
@ -122,6 +119,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- Forward to treeDataEdge findIntersect operations
|
||||||
class findIntersectOp
|
class findIntersectOp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -141,10 +139,29 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// Declare name of the class and its debug switch
|
// Declare name of the class and its debug switch
|
||||||
ClassName("treeDataEdge");
|
ClassNameNoDebug("treeDataEdge");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors (cachable versions)
|
||||||
|
|
||||||
|
//- Construct from all edges.
|
||||||
|
// \note Holds references to edges and points!
|
||||||
|
treeDataEdge
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from range of edges.
|
||||||
|
// \note Holds references to edges and points!
|
||||||
|
treeDataEdge
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
);
|
||||||
|
|
||||||
//- Construct from selected edges.
|
//- Construct from selected edges.
|
||||||
// \note Holds references to edges and points!
|
// \note Holds references to edges and points!
|
||||||
@ -167,59 +184,201 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors (non-caching)
|
||||||
|
|
||||||
|
//- Construct from all edges.
|
||||||
|
// \note Holds references to edges and points!
|
||||||
|
treeDataEdge(const edgeList& edges, const pointField& points)
|
||||||
|
:
|
||||||
|
treeDataEdge(false, edges, points)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from range of edges.
|
||||||
|
// \note Holds references to edges and points!
|
||||||
|
treeDataEdge
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataEdge(false, edges, points, range)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from selected edges.
|
||||||
|
// \note Holds references to edges and points!
|
||||||
|
treeDataEdge
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelUList& edgeLabels
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataEdge(false, edges, points, edgeLabels)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from selected edges, transferring contents.
|
||||||
|
// \note Holds references to edges and points!
|
||||||
|
treeDataEdge
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
labelList&& edgeLabels
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataEdge(false, edges, points, std::move(edgeLabels))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Static Functions
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for all edges
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for specified range of edges
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for specified edges
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelUList& edgeIds
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return bounding box of all edges
|
||||||
|
static treeBoundBox bounds
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return bounding box of specified range of edges
|
||||||
|
static treeBoundBox bounds
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelRange& range
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return bounding box of specified edges
|
||||||
|
static treeBoundBox bounds
|
||||||
|
(
|
||||||
|
const edgeList& edges,
|
||||||
|
const pointField& points,
|
||||||
|
const labelUList& edgeIds
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
//- Object dimension == 1 (line element)
|
||||||
|
int nDim() const noexcept { return 1; }
|
||||||
|
|
||||||
const edgeList& edges() const
|
//- Return bounding box for the specified edge indices
|
||||||
{
|
treeBoundBox bounds(const labelUList& indices) const;
|
||||||
return edges_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pointField& points() const
|
|
||||||
{
|
|
||||||
return points_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const labelList& edgeLabels() const
|
|
||||||
{
|
|
||||||
return edgeLabels_;
|
|
||||||
}
|
|
||||||
|
|
||||||
label size() const
|
|
||||||
{
|
|
||||||
return edgeLabels_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Representative point cloud for all shapes inside
|
|
||||||
//- (one point per shape)
|
|
||||||
pointField shapePoints() const;
|
|
||||||
|
|
||||||
|
|
||||||
// Search
|
// Access
|
||||||
|
|
||||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
//- The reference point field
|
||||||
// Only makes sense for closed surfaces.
|
const pointField& points() const noexcept { return points_; }
|
||||||
volumeType getVolumeType
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataEdge>&,
|
|
||||||
const point&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does (bb of) shape at index overlap bb
|
//- The original list of edges
|
||||||
bool overlaps
|
const edgeList& edges() const noexcept { return edges_; }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const treeBoundBox& sampleBb
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does (bb of) shape at index overlap bb
|
//- The subset of edge ids to use
|
||||||
bool overlaps
|
const labelList& edgeLabels() const noexcept { return edgeLabels_; }
|
||||||
(
|
|
||||||
const label index,
|
//- Use a subset of edges
|
||||||
const point& centre,
|
bool useSubset() const noexcept { return useSubset_; }
|
||||||
const scalar radiusSqr
|
|
||||||
) const;
|
//- Is the effective edge selection empty?
|
||||||
|
bool empty() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? edgeLabels_.empty() : edges_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- The size of edge selection
|
||||||
|
label size() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? edgeLabels_.size() : edges_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Map from shape index to original (non-subset) edge label
|
||||||
|
label objectIndex(const label index) const
|
||||||
|
{
|
||||||
|
return useSubset_ && index >= 0 ? edgeLabels_[index] : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Edge at specified shape index
|
||||||
|
const edge& operator[](const label index) const
|
||||||
|
{
|
||||||
|
return edges_[objectIndex(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Geometric line for edge at specified shape index. Frequently used
|
||||||
|
const linePointRef line(const label index) const
|
||||||
|
{
|
||||||
|
return edges_[objectIndex(index)].line(points_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Representative point (edge centre) at shape index
|
||||||
|
point centre(const label index) const
|
||||||
|
{
|
||||||
|
return edges_[objectIndex(index)].centre(points_);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Representative point cloud for contained shapes.
|
||||||
|
//- One point per shape, corresponding to the edge centres.
|
||||||
|
tmp<pointField> centres() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
|
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||||
|
// Only makes sense for closed surfaces.
|
||||||
|
volumeType getVolumeType
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataEdge>&,
|
||||||
|
const point&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does (bb of) shape at index searchBox
|
||||||
|
bool overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const treeBoundBox& searchBox
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does (bb of) shape at index overlap bb
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ License
|
|||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(treeDataPoint, 0);
|
defineTypeName(treeDataPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -72,29 +72,29 @@ Foam::treeDataPoint::treeDataPoint
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataPoint::findNearestOp::findNearestOp
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataPoint>& tree
|
|
||||||
)
|
|
||||||
:
|
|
||||||
tree_(tree)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataPoint::findIntersectOp::findIntersectOp
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataPoint>& tree
|
|
||||||
)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::pointField Foam::treeDataPoint::shapePoints() const
|
Foam::treeBoundBox Foam::treeDataPoint::bounds(const labelUList& indices) const
|
||||||
{
|
{
|
||||||
if (useSubset_)
|
if (useSubset_)
|
||||||
{
|
{
|
||||||
return pointField(points_, pointLabels_);
|
treeBoundBox bb;
|
||||||
|
for (const label index : indices)
|
||||||
|
{
|
||||||
|
bb.add(points_[pointLabels_[index]]);
|
||||||
|
}
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return treeBoundBox(points_, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField> Foam::treeDataPoint::centres() const
|
||||||
|
{
|
||||||
|
if (useSubset_)
|
||||||
|
{
|
||||||
|
return tmp<pointField>::New(points_, pointLabels_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return points_;
|
return points_;
|
||||||
@ -114,10 +114,10 @@ Foam::volumeType Foam::treeDataPoint::getVolumeType
|
|||||||
bool Foam::treeDataPoint::overlaps
|
bool Foam::treeDataPoint::overlaps
|
||||||
(
|
(
|
||||||
const label index,
|
const label index,
|
||||||
const treeBoundBox& cubeBb
|
const treeBoundBox& searchBox
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return cubeBb.contains(shapePoint(index));
|
return searchBox.contains(centre(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,11 +128,29 @@ bool Foam::treeDataPoint::overlaps
|
|||||||
const scalar radiusSqr
|
const scalar radiusSqr
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return (centre.distSqr(shapePoint(index)) <= radiusSqr);
|
return (centre.distSqr(this->centre(index)) <= radiusSqr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataPoint::findNearestOp::operator()
|
// * * * * * * * * * * * * * * * * Searching * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeDataPoint::findNearestOp::findNearestOp
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataPoint>& tree
|
||||||
|
)
|
||||||
|
:
|
||||||
|
tree_(tree)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeDataPoint::findIntersectOp::findIntersectOp
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataPoint>& tree
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::treeDataPoint::findNearest
|
||||||
(
|
(
|
||||||
const labelUList& indices,
|
const labelUList& indices,
|
||||||
const point& sample,
|
const point& sample,
|
||||||
@ -142,11 +160,9 @@ void Foam::treeDataPoint::findNearestOp::operator()
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const treeDataPoint& shape = tree_.shapes();
|
|
||||||
|
|
||||||
for (const label index : indices)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const point& pt = shape.shapePoint(index);
|
const point& pt = centre(index);
|
||||||
|
|
||||||
const scalar distSqr = sample.distSqr(pt);
|
const scalar distSqr = sample.distSqr(pt);
|
||||||
|
|
||||||
@ -160,6 +176,27 @@ void Foam::treeDataPoint::findNearestOp::operator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::treeDataPoint::findNearestOp::operator()
|
||||||
|
(
|
||||||
|
const labelUList& indices,
|
||||||
|
const point& sample,
|
||||||
|
|
||||||
|
scalar& nearestDistSqr,
|
||||||
|
label& minIndex,
|
||||||
|
point& nearestPoint
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
tree_.shapes().findNearest
|
||||||
|
(
|
||||||
|
indices,
|
||||||
|
sample,
|
||||||
|
nearestDistSqr,
|
||||||
|
minIndex,
|
||||||
|
nearestPoint
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataPoint::findNearestOp::operator()
|
void Foam::treeDataPoint::findNearestOp::operator()
|
||||||
(
|
(
|
||||||
const labelUList& indices,
|
const labelUList& indices,
|
||||||
@ -173,6 +210,8 @@ void Foam::treeDataPoint::findNearestOp::operator()
|
|||||||
{
|
{
|
||||||
const treeDataPoint& shape = tree_.shapes();
|
const treeDataPoint& shape = tree_.shapes();
|
||||||
|
|
||||||
|
const treeBoundBox lnBb(ln.box());
|
||||||
|
|
||||||
// Best so far
|
// Best so far
|
||||||
scalar nearestDistSqr = GREAT;
|
scalar nearestDistSqr = GREAT;
|
||||||
if (minIndex >= 0)
|
if (minIndex >= 0)
|
||||||
@ -182,12 +221,12 @@ void Foam::treeDataPoint::findNearestOp::operator()
|
|||||||
|
|
||||||
for (const label index : indices)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const point& shapePt = shape.shapePoint(index);
|
const point& pt = shape.centre(index);
|
||||||
|
|
||||||
if (tightest.contains(shapePt))
|
if (tightest.contains(pt))
|
||||||
{
|
{
|
||||||
// Nearest point on line
|
// Nearest point on line
|
||||||
pointHit pHit = ln.nearestDist(shapePt);
|
pointHit pHit = ln.nearestDist(pt);
|
||||||
const scalar distSqr = sqr(pHit.distance());
|
const scalar distSqr = sqr(pHit.distance());
|
||||||
|
|
||||||
if (distSqr < nearestDistSqr)
|
if (distSqr < nearestDistSqr)
|
||||||
@ -195,22 +234,10 @@ void Foam::treeDataPoint::findNearestOp::operator()
|
|||||||
nearestDistSqr = distSqr;
|
nearestDistSqr = distSqr;
|
||||||
minIndex = index;
|
minIndex = index;
|
||||||
linePoint = pHit.point();
|
linePoint = pHit.point();
|
||||||
nearestPoint = shapePt;
|
nearestPoint = pt;
|
||||||
|
|
||||||
{
|
tightest = lnBb;
|
||||||
point& minPt = tightest.min();
|
tightest.grow(pHit.distance());
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2013 OpenFOAM Foundation
|
Copyright (C) 2011-2013 OpenFOAM Foundation
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -64,16 +64,19 @@ class treeDataPoint
|
|||||||
{
|
{
|
||||||
// Private Data
|
// Private Data
|
||||||
|
|
||||||
|
//- Reference to the underlying point field
|
||||||
const pointField& points_;
|
const pointField& points_;
|
||||||
|
|
||||||
//- Subset of points to work on (or empty)
|
//- Subset of points to work on (or empty)
|
||||||
const labelList pointLabels_;
|
const labelList pointLabels_;
|
||||||
|
|
||||||
|
//- Use subset of points (pointLabels)
|
||||||
const bool useSubset_;
|
const bool useSubset_;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//- Forward to treeDataPoint findNearest operations
|
||||||
class findNearestOp
|
class findNearestOp
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataPoint>& tree_;
|
const indexedOctree<treeDataPoint>& tree_;
|
||||||
@ -105,6 +108,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//- Forward to treeDataPoint findIntersect operations (not possible)
|
||||||
class findIntersectOp
|
class findIntersectOp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -123,11 +127,11 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Declare name of the class and its debug switch
|
// Declare name of the class
|
||||||
ClassName("treeDataPoint");
|
ClassNameNoDebug("treeDataPoint");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors (non-caching)
|
||||||
|
|
||||||
//- Construct from pointField
|
//- Construct from pointField
|
||||||
// \note Holds reference to the points!
|
// \note Holds reference to the points!
|
||||||
@ -154,108 +158,101 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
//- Object dimension == 0 (point element)
|
||||||
|
int nDim() const noexcept { return 0; }
|
||||||
|
|
||||||
//- An empty effective point field?
|
//- Return bounding box for the specified point indices
|
||||||
inline bool empty() const
|
treeBoundBox bounds(const labelUList& indices) const;
|
||||||
{
|
|
||||||
return
|
|
||||||
(
|
|
||||||
useSubset_
|
|
||||||
? pointLabels_.empty()
|
|
||||||
: points_.empty()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- The effective point field size
|
|
||||||
inline label size() const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(
|
|
||||||
useSubset_
|
|
||||||
? pointLabels_.size()
|
|
||||||
: points_.size()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- The original point field
|
|
||||||
inline const pointField& points() const
|
|
||||||
{
|
|
||||||
return points_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- The original point ids
|
|
||||||
inline const labelList& pointLabels() const
|
|
||||||
{
|
|
||||||
return pointLabels_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Use a subset of points
|
|
||||||
inline bool useSubset() const
|
|
||||||
{
|
|
||||||
return useSubset_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- The original (non-subset) point label
|
|
||||||
inline label pointLabel(const label index) const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(
|
|
||||||
useSubset_ && index >= 0
|
|
||||||
? pointLabels_[index]
|
|
||||||
: index
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Point at specified index
|
|
||||||
inline const point& shapePoint(const label index) const
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(
|
|
||||||
useSubset_
|
|
||||||
? points_[pointLabels_[index]]
|
|
||||||
: points_[index]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Representative point cloud for all shapes inside
|
|
||||||
//- (one point per shape)
|
|
||||||
pointField shapePoints() const;
|
|
||||||
|
|
||||||
|
|
||||||
// Search
|
// Access
|
||||||
|
|
||||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
//- The original point field
|
||||||
// Only makes sense for closed surfaces.
|
const pointField& points() const noexcept { return points_; }
|
||||||
volumeType getVolumeType
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataPoint>& os,
|
|
||||||
const point& sample
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does (bb of) shape at index overlap bb
|
//- The subset of point ids to use
|
||||||
bool overlaps
|
const labelList& pointLabels() const noexcept { return pointLabels_; }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const treeBoundBox& sampleBb
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does shape at index overlap the sphere
|
//- Use a subset of points
|
||||||
bool overlaps
|
bool useSubset() const noexcept { return useSubset_; }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const point& centre,
|
|
||||||
const scalar radiusSqr
|
|
||||||
) const;
|
|
||||||
|
|
||||||
|
//- Is the effective point field empty?
|
||||||
// Member Operators
|
bool empty() const noexcept
|
||||||
|
|
||||||
//- The point at the specified index
|
|
||||||
inline const point& operator[](const label index) const
|
|
||||||
{
|
{
|
||||||
return shapePoint(index);
|
return useSubset_ ? pointLabels_.empty() : points_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//- The size of the effective point field
|
||||||
|
label size() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? pointLabels_.size() : points_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Map to the original (non-subset) point label
|
||||||
|
label objectIndex(const label index) const
|
||||||
|
{
|
||||||
|
return useSubset_ && index >= 0 ? pointLabels_[index] : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Point at specified shape index
|
||||||
|
const point& operator[](const label index) const
|
||||||
|
{
|
||||||
|
return points_[objectIndex(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Point at specified shape index
|
||||||
|
const point& centre(const label index) const
|
||||||
|
{
|
||||||
|
return points_[objectIndex(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Point cloud
|
||||||
|
tmp<pointField> centres() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
|
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||||
|
// Only makes sense for closed surfaces.
|
||||||
|
volumeType getVolumeType
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataPoint>& os,
|
||||||
|
const point& sample
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does (bb of) shape at index searchBox
|
||||||
|
bool overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const treeBoundBox& searchBox
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does shape at index overlap the 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;
|
||||||
|
|
||||||
|
|
||||||
|
// Housekeeping
|
||||||
|
|
||||||
|
//- Map to the original (non-subset) point label
|
||||||
|
///FOAM_DEPRECATED_FOR(2022-10, "objectIndex()")
|
||||||
|
label pointLabel(label index) const { return objectIndex(index); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1039,7 +1039,7 @@ void Foam::faceCoupleInfo::findSlavesCoveringMaster
|
|||||||
|
|
||||||
if (nearInfo.hit())
|
if (nearInfo.hit())
|
||||||
{
|
{
|
||||||
label mesh0Facei = tree.shapes().faceLabels()[nearInfo.index()];
|
label mesh0Facei = tree.shapes().objectIndex(nearInfo.index());
|
||||||
|
|
||||||
// Check if points of f1 actually lie on top of mesh0 face
|
// Check if points of f1 actually lie on top of mesh0 face
|
||||||
// This is the bit that might fail since if f0 is severely warped
|
// This is the bit that might fail since if f0 is severely warped
|
||||||
|
|||||||
@ -435,7 +435,7 @@ void Foam::functionObjects::propellerInfo::updateSampleDiskCells()
|
|||||||
// Kick the tet base points calculation to avoid parallel comms later
|
// Kick the tet base points calculation to avoid parallel comms later
|
||||||
(void)mesh_.tetBasePtIs();
|
(void)mesh_.tetBasePtIs();
|
||||||
|
|
||||||
const auto& cellLabels = tree.shapes().cellLabels();
|
const auto& treeData = tree.shapes();
|
||||||
|
|
||||||
forAll(points_, pointi)
|
forAll(points_, pointi)
|
||||||
{
|
{
|
||||||
@ -453,9 +453,11 @@ void Foam::functionObjects::propellerInfo::updateSampleDiskCells()
|
|||||||
if (proci >= 0)
|
if (proci >= 0)
|
||||||
{
|
{
|
||||||
cellIds_[pointi] =
|
cellIds_[pointi] =
|
||||||
|
(
|
||||||
proci == Pstream::myProcNo()
|
proci == Pstream::myProcNo()
|
||||||
? cellLabels[treeCelli]
|
? treeData.objectIndex(treeCelli)
|
||||||
: -1;
|
: -1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -67,19 +67,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
|
|||||||
extendedProcBbsOrigProc
|
extendedProcBbsOrigProc
|
||||||
);
|
);
|
||||||
|
|
||||||
treeBoundBoxList cellBbs(mesh_.nCells());
|
treeBoundBoxList cellBbs(treeDataCell::boxes(mesh_));
|
||||||
|
|
||||||
forAll(cellBbs, celli)
|
|
||||||
{
|
|
||||||
cellBbs[celli] = treeBoundBox
|
|
||||||
(
|
|
||||||
mesh_.cells()[celli].points
|
|
||||||
(
|
|
||||||
mesh_.faces(),
|
|
||||||
mesh_.points()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const globalIndexAndTransform& globalTransforms =
|
const globalIndexAndTransform& globalTransforms =
|
||||||
mesh_.globalData().globalTransforms();
|
mesh_.globalData().globalTransforms();
|
||||||
@ -214,7 +202,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
|
|||||||
// i.e. a more accurate bounding volume like a OBB or
|
// i.e. a more accurate bounding volume like a OBB or
|
||||||
// convex hull or an exact geometrical test.
|
// convex hull or an exact geometrical test.
|
||||||
|
|
||||||
label c = coupledPatchRangeTree.shapes().cellLabels()[elemI];
|
label c = coupledPatchRangeTree.shapes().objectIndex(elemI);
|
||||||
|
|
||||||
ril_[bbI][i] = c;
|
ril_[bbI][i] = c;
|
||||||
}
|
}
|
||||||
@ -237,7 +225,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
|
|||||||
// At this point, cellBbsToExchange does not need to be maintained
|
// At this point, cellBbsToExchange does not need to be maintained
|
||||||
// or distributed as it is not longer needed.
|
// or distributed as it is not longer needed.
|
||||||
|
|
||||||
cellBbsToExchange.setSize(0);
|
cellBbsToExchange.clearStorage();
|
||||||
|
|
||||||
cellMap().reverseDistribute
|
cellMap().reverseDistribute
|
||||||
(
|
(
|
||||||
@ -434,7 +422,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
|
|||||||
// i.e. a more accurate bounding volume like a OBB or
|
// i.e. a more accurate bounding volume like a OBB or
|
||||||
// convex hull or an exact geometrical test.
|
// convex hull or an exact geometrical test.
|
||||||
|
|
||||||
label c = coupledPatchRangeTree.shapes().cellLabels()[elemI];
|
label c = coupledPatchRangeTree.shapes().objectIndex(elemI);
|
||||||
|
|
||||||
rwfil_[bbI][i] = c;
|
rwfil_[bbI][i] = c;
|
||||||
}
|
}
|
||||||
@ -586,7 +574,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
|
|||||||
|
|
||||||
for (const label elemi : interactingElems)
|
for (const label elemi : interactingElems)
|
||||||
{
|
{
|
||||||
const label c = allCellsTree.shapes().cellLabels()[elemi];
|
const label c = allCellsTree.shapes().objectIndex(elemi);
|
||||||
|
|
||||||
// Here, a more detailed geometric test could be applied,
|
// Here, a more detailed geometric test could be applied,
|
||||||
// i.e. a more accurate bounding volume like a OBB or
|
// i.e. a more accurate bounding volume like a OBB or
|
||||||
@ -611,7 +599,7 @@ void Foam::InteractionLists<ParticleType>::buildInteractionLists()
|
|||||||
{
|
{
|
||||||
const label elemi = interactingElems[i];
|
const label elemi = interactingElems[i];
|
||||||
|
|
||||||
const label f = wallFacesTree.shapes().faceLabels()[elemi];
|
const label f = wallFacesTree.shapes().objectIndex(elemi);
|
||||||
|
|
||||||
dwfil_[celli][i] = f;
|
dwfil_[celli][i] = f;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2016-2021 OpenCFD Ltd.
|
Copyright (C) 2016-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -435,25 +435,23 @@ void Foam::lumpedPointMovement::setPatchControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
treeDataPoint treePoints
|
|
||||||
(
|
|
||||||
lumpedCentres0,
|
|
||||||
subsetPointIds.sortedToc(),
|
|
||||||
subsetPointIds.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
treeBoundBox bb(lumpedCentres0);
|
treeBoundBox bb(lumpedCentres0);
|
||||||
bb.inflate(0.01);
|
bb.inflate(0.01);
|
||||||
|
|
||||||
indexedOctree<treeDataPoint> ppTree
|
indexedOctree<treeDataPoint> ppTree
|
||||||
(
|
(
|
||||||
treePoints,
|
treeDataPoint
|
||||||
|
(
|
||||||
|
lumpedCentres0,
|
||||||
|
subsetPointIds.sortedToc(),
|
||||||
|
subsetPointIds.size() // subset is optional/required
|
||||||
|
),
|
||||||
bb, // overall search domain
|
bb, // overall search domain
|
||||||
8, // maxLevel
|
8, // maxLevel
|
||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treePoints = ppTree.shapes();
|
||||||
|
|
||||||
const scalar searchDistSqr(sqr(GREAT));
|
const scalar searchDistSqr(sqr(GREAT));
|
||||||
|
|
||||||
@ -464,7 +462,7 @@ void Foam::lumpedPointMovement::setPatchControl
|
|||||||
|
|
||||||
// Store the original pointId, not subset id
|
// Store the original pointId, not subset id
|
||||||
faceToPoint[patchFacei] =
|
faceToPoint[patchFacei] =
|
||||||
treePoints.pointLabel
|
treePoints.objectIndex
|
||||||
(
|
(
|
||||||
ppTree.findNearest(fc, searchDistSqr).index()
|
ppTree.findNearest(fc, searchDistSqr).index()
|
||||||
);
|
);
|
||||||
@ -655,24 +653,23 @@ void Foam::lumpedPointMovement::setInterpolator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
treeDataPoint treePoints
|
|
||||||
(
|
|
||||||
lumpedCentres0,
|
|
||||||
subsetPointIds.sortedToc(),
|
|
||||||
subsetPointIds.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
treeBoundBox bb(lumpedCentres0);
|
treeBoundBox bb(lumpedCentres0);
|
||||||
bb.inflate(0.01);
|
bb.inflate(0.01);
|
||||||
|
|
||||||
indexedOctree<treeDataPoint> ppTree
|
indexedOctree<treeDataPoint> ppTree
|
||||||
(
|
(
|
||||||
treePoints,
|
treeDataPoint
|
||||||
|
(
|
||||||
|
lumpedCentres0,
|
||||||
|
subsetPointIds.sortedToc(),
|
||||||
|
subsetPointIds.size() // subset is optional/required
|
||||||
|
),
|
||||||
bb, // overall search domain
|
bb, // overall search domain
|
||||||
8, // maxLevel
|
8, // maxLevel
|
||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treePoints = ppTree.shapes();
|
||||||
|
|
||||||
|
|
||||||
// Searching
|
// Searching
|
||||||
@ -692,7 +689,7 @@ void Foam::lumpedPointMovement::setInterpolator
|
|||||||
|
|
||||||
// Nearest (original) point id
|
// Nearest (original) point id
|
||||||
const label nearest =
|
const label nearest =
|
||||||
treePoints.pointLabel
|
treePoints.objectIndex
|
||||||
(
|
(
|
||||||
ppTree.findNearest(ptOnMesh, searchDistSqr).index()
|
ppTree.findNearest(ptOnMesh, searchDistSqr).index()
|
||||||
);
|
);
|
||||||
|
|||||||
@ -651,8 +651,9 @@ void Foam::refinementFeatures::findNearestEdge
|
|||||||
forAll(edgeTrees_, featI)
|
forAll(edgeTrees_, featI)
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataEdge>& tree = edgeTrees_[featI];
|
const indexedOctree<treeDataEdge>& tree = edgeTrees_[featI];
|
||||||
|
const treeDataEdge& treeData = tree.shapes();
|
||||||
|
|
||||||
if (tree.shapes().size() > 0)
|
if (!treeData.empty())
|
||||||
{
|
{
|
||||||
forAll(samples, sampleI)
|
forAll(samples, sampleI)
|
||||||
{
|
{
|
||||||
@ -677,13 +678,9 @@ void Foam::refinementFeatures::findNearestEdge
|
|||||||
(
|
(
|
||||||
info.hit(),
|
info.hit(),
|
||||||
info.point(),
|
info.point(),
|
||||||
tree.shapes().edgeLabels()[info.index()]
|
treeData.objectIndex(info.index())
|
||||||
);
|
);
|
||||||
|
nearNormal[sampleI] = treeData.line(info.index()).unitVec();
|
||||||
const treeDataEdge& td = tree.shapes();
|
|
||||||
const edge& e = td.edges()[nearInfo[sampleI].index()];
|
|
||||||
|
|
||||||
nearNormal[sampleI] = e.unitVec(td.points());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -714,6 +711,7 @@ void Foam::refinementFeatures::findNearestRegionEdge
|
|||||||
forAll(regionTrees, featI)
|
forAll(regionTrees, featI)
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataEdge>& regionTree = regionTrees[featI];
|
const indexedOctree<treeDataEdge>& regionTree = regionTrees[featI];
|
||||||
|
const treeDataEdge& treeData = regionTree.shapes();
|
||||||
|
|
||||||
forAll(samples, sampleI)
|
forAll(samples, sampleI)
|
||||||
{
|
{
|
||||||
@ -734,19 +732,14 @@ void Foam::refinementFeatures::findNearestRegionEdge
|
|||||||
|
|
||||||
if (info.hit())
|
if (info.hit())
|
||||||
{
|
{
|
||||||
const treeDataEdge& td = regionTree.shapes();
|
|
||||||
|
|
||||||
nearFeature[sampleI] = featI;
|
nearFeature[sampleI] = featI;
|
||||||
nearInfo[sampleI] = pointIndexHit
|
nearInfo[sampleI] = pointIndexHit
|
||||||
(
|
(
|
||||||
info.hit(),
|
info.hit(),
|
||||||
info.point(),
|
info.point(),
|
||||||
regionTree.shapes().edgeLabels()[info.index()]
|
treeData.objectIndex(info.index())
|
||||||
);
|
);
|
||||||
|
nearNormal[sampleI] = treeData.line(info.index()).unitVec();
|
||||||
const edge& e = td.edges()[nearInfo[sampleI].index()];
|
|
||||||
|
|
||||||
nearNormal[sampleI] = e.unitVec(td.points());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -770,7 +763,7 @@ void Foam::refinementFeatures::findNearestRegionEdge
|
|||||||
// {
|
// {
|
||||||
// const indexedOctree<treeDataPoint>& tree = pointTrees_[featI];
|
// const indexedOctree<treeDataPoint>& tree = pointTrees_[featI];
|
||||||
//
|
//
|
||||||
// if (tree.shapes().pointLabels().size() > 0)
|
// if (!tree.shapes().empty())
|
||||||
// {
|
// {
|
||||||
// forAll(samples, sampleI)
|
// forAll(samples, sampleI)
|
||||||
// {
|
// {
|
||||||
@ -779,14 +772,11 @@ void Foam::refinementFeatures::findNearestRegionEdge
|
|||||||
// scalar distSqr;
|
// scalar distSqr;
|
||||||
// if (nearFeature[sampleI] != -1)
|
// if (nearFeature[sampleI] != -1)
|
||||||
// {
|
// {
|
||||||
// label nearFeatI = nearFeature[sampleI];
|
// const nearTree = pointTrees_[nearFeature[sampleI]];
|
||||||
// const indexedOctree<treeDataPoint>& nearTree =
|
// distSqr = sample.distSqr
|
||||||
// pointTrees_[nearFeatI];
|
// (
|
||||||
// label featPointi =
|
// nearTree.shapes()[nearIndex[sampleI]]
|
||||||
// nearTree.shapes().pointLabels()[nearIndex[sampleI]];
|
// );
|
||||||
// const point& featPt =
|
|
||||||
// operator[](nearFeatI).points()[featPointi];
|
|
||||||
// distSqr = magSqr(featPt-sample);
|
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// {
|
// {
|
||||||
@ -822,8 +812,9 @@ void Foam::refinementFeatures::findNearestPoint
|
|||||||
forAll(pointTrees_, featI)
|
forAll(pointTrees_, featI)
|
||||||
{
|
{
|
||||||
const indexedOctree<treeDataPoint>& tree = pointTrees_[featI];
|
const indexedOctree<treeDataPoint>& tree = pointTrees_[featI];
|
||||||
|
const auto& treeData = tree.shapes();
|
||||||
|
|
||||||
if (tree.shapes().pointLabels().size() > 0)
|
if (!treeData.empty())
|
||||||
{
|
{
|
||||||
forAll(samples, sampleI)
|
forAll(samples, sampleI)
|
||||||
{
|
{
|
||||||
@ -848,7 +839,7 @@ void Foam::refinementFeatures::findNearestPoint
|
|||||||
(
|
(
|
||||||
info.hit(),
|
info.hit(),
|
||||||
info.point(),
|
info.point(),
|
||||||
tree.shapes().pointLabels()[info.index()]
|
treeData.objectIndex(info.index())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3296,8 +3296,13 @@ void Foam::snappySnapDriver::reverseAttractMeshPoints
|
|||||||
if (nearInfo.hit())
|
if (nearInfo.hit())
|
||||||
{
|
{
|
||||||
label pointi =
|
label pointi =
|
||||||
ppTree.shapes().pointLabels()[nearInfo.index()];
|
ppTree.shapes().objectIndex(nearInfo.index());
|
||||||
const point attraction = featPt-pp.localPoints()[pointi];
|
|
||||||
|
const point attraction
|
||||||
|
(
|
||||||
|
featPt
|
||||||
|
- ppTree.shapes()[nearInfo.index()]
|
||||||
|
);
|
||||||
|
|
||||||
// Check if this point is already being attracted. If so
|
// Check if this point is already being attracted. If so
|
||||||
// override it only if nearer.
|
// override it only if nearer.
|
||||||
@ -3368,10 +3373,13 @@ void Foam::snappySnapDriver::reverseAttractMeshPoints
|
|||||||
if (nearInfo.hit())
|
if (nearInfo.hit())
|
||||||
{
|
{
|
||||||
label pointi =
|
label pointi =
|
||||||
ppTree.shapes().pointLabels()[nearInfo.index()];
|
ppTree.shapes().objectIndex(nearInfo.index());
|
||||||
|
|
||||||
const point& pt = pp.localPoints()[pointi];
|
const point attraction
|
||||||
const point attraction = featPt-pt;
|
(
|
||||||
|
featPt
|
||||||
|
- ppTree.shapes()[nearInfo.index()]
|
||||||
|
);
|
||||||
|
|
||||||
// - already attracted to feature edge : point always wins
|
// - already attracted to feature edge : point always wins
|
||||||
// - already attracted to feature point: nearest wins
|
// - already attracted to feature point: nearest wins
|
||||||
|
|||||||
@ -211,7 +211,7 @@ Foam::boolList Foam::cellClassification::markFaces
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
label facei = faceTree.shapes().faceLabels()[pHit.index()];
|
label facei = faceTree.shapes().objectIndex(pHit.index());
|
||||||
|
|
||||||
if (!cutFace[facei])
|
if (!cutFace[facei])
|
||||||
{
|
{
|
||||||
|
|||||||
@ -709,29 +709,20 @@ void Foam::extendedEdgeMesh::nearestFeatureEdgeByType
|
|||||||
{
|
{
|
||||||
const PtrList<indexedOctree<treeDataEdge>>& edgeTrees = edgeTreesByType();
|
const PtrList<indexedOctree<treeDataEdge>>& edgeTrees = edgeTreesByType();
|
||||||
|
|
||||||
info.setSize(edgeTrees.size());
|
info.resize(edgeTrees.size());
|
||||||
|
|
||||||
labelList sliceStarts(edgeTrees.size());
|
|
||||||
|
|
||||||
sliceStarts[0] = externalStart_;
|
|
||||||
sliceStarts[1] = internalStart_;
|
|
||||||
sliceStarts[2] = flatStart_;
|
|
||||||
sliceStarts[3] = openStart_;
|
|
||||||
sliceStarts[4] = multipleStart_;
|
|
||||||
|
|
||||||
forAll(edgeTrees, i)
|
forAll(edgeTrees, i)
|
||||||
{
|
{
|
||||||
info[i] = edgeTrees[i].findNearest
|
const auto& tree = edgeTrees[i];
|
||||||
(
|
const auto& treeData = edgeTrees[i].shapes();
|
||||||
sample,
|
|
||||||
searchDistSqr[i]
|
info[i] = tree.findNearest(sample, searchDistSqr[i]);
|
||||||
);
|
|
||||||
|
|
||||||
// The index returned by the indexedOctree is local to the slice of
|
// The index returned by the indexedOctree is local to the slice of
|
||||||
// edges it was supplied with, return the index to the value in the
|
// edges it was supplied with, return the index to the value in the
|
||||||
// complete edge list
|
// complete edge list
|
||||||
|
|
||||||
info[i].setIndex(info[i].index() + sliceStarts[i]);
|
info[i].setIndex(treeData.objectIndex(info[i].index()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,11 +743,11 @@ void Foam::extendedEdgeMesh::allNearestFeaturePoints
|
|||||||
|
|
||||||
DynamicList<pointIndexHit> dynPointHit(elems.size());
|
DynamicList<pointIndexHit> dynPointHit(elems.size());
|
||||||
|
|
||||||
forAll(elems, elemI)
|
const auto& treeData = pointTree().shapes();
|
||||||
|
|
||||||
|
for (const label index : elems)
|
||||||
{
|
{
|
||||||
label index = elems[elemI];
|
const point& pt = treeData.centre(index);
|
||||||
label ptI = pointTree().shapes().pointLabels()[index];
|
|
||||||
const point& pt = points()[ptI];
|
|
||||||
|
|
||||||
pointIndexHit nearHit(true, pt, index);
|
pointIndexHit nearHit(true, pt, index);
|
||||||
|
|
||||||
@ -776,37 +767,25 @@ void Foam::extendedEdgeMesh::allNearestFeatureEdges
|
|||||||
{
|
{
|
||||||
const PtrList<indexedOctree<treeDataEdge>>& edgeTrees = edgeTreesByType();
|
const PtrList<indexedOctree<treeDataEdge>>& edgeTrees = edgeTreesByType();
|
||||||
|
|
||||||
info.setSize(edgeTrees.size());
|
|
||||||
|
|
||||||
labelList sliceStarts(edgeTrees.size());
|
|
||||||
|
|
||||||
sliceStarts[0] = externalStart_;
|
|
||||||
sliceStarts[1] = internalStart_;
|
|
||||||
sliceStarts[2] = flatStart_;
|
|
||||||
sliceStarts[3] = openStart_;
|
|
||||||
sliceStarts[4] = multipleStart_;
|
|
||||||
|
|
||||||
DynamicList<pointIndexHit> dynEdgeHit(edgeTrees.size()*3);
|
DynamicList<pointIndexHit> dynEdgeHit(edgeTrees.size()*3);
|
||||||
|
|
||||||
// Loop over all the feature edge types
|
// Loop over all the feature edge types
|
||||||
forAll(edgeTrees, i)
|
forAll(edgeTrees, i)
|
||||||
{
|
{
|
||||||
|
const auto& tree = edgeTrees[i];
|
||||||
|
const auto& treeData = tree.shapes();
|
||||||
|
|
||||||
// Pick up all the edges that intersect the search sphere
|
// Pick up all the edges that intersect the search sphere
|
||||||
labelList elems = edgeTrees[i].findSphere
|
labelList elems = tree.findSphere(sample, searchRadiusSqr);
|
||||||
(
|
|
||||||
sample,
|
|
||||||
searchRadiusSqr
|
|
||||||
);
|
|
||||||
|
|
||||||
forAll(elems, elemI)
|
for (const label index : elems)
|
||||||
{
|
{
|
||||||
label index = elems[elemI];
|
pointHit hitPoint = treeData.line(index).nearestDist(sample);
|
||||||
label edgeI = edgeTrees[i].shapes().edgeLabels()[index];
|
|
||||||
const edge& e = edges()[edgeI];
|
|
||||||
|
|
||||||
pointHit hitPoint = e.line(points()).nearestDist(sample);
|
// The index returned by indexedOctree is local its slice of
|
||||||
|
// edges. Return the index into the complete edge list
|
||||||
|
|
||||||
label hitIndex = index + sliceStarts[i];
|
const label hitIndex = treeData.objectIndex(index);
|
||||||
|
|
||||||
dynEdgeHit.append(pointIndexHit(hitPoint, hitIndex));
|
dynEdgeHit.append(pointIndexHit(hitPoint, hitIndex));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ License
|
|||||||
#include "treeDataFace.H"
|
#include "treeDataFace.H"
|
||||||
#include "polyMesh.H"
|
#include "polyMesh.H"
|
||||||
#include "triangleFuncs.H"
|
#include "triangleFuncs.H"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -40,25 +41,139 @@ namespace Foam
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Bound boxes corresponding to specified faces
|
||||||
|
template<class ElementIds>
|
||||||
|
static treeBoundBoxList boxesImpl
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const ElementIds& elemIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBoxList bbs(elemIds.size());
|
||||||
|
|
||||||
|
std::transform
|
||||||
|
(
|
||||||
|
elemIds.cbegin(),
|
||||||
|
elemIds.cend(),
|
||||||
|
bbs.begin(),
|
||||||
|
[&](label facei)
|
||||||
|
{
|
||||||
|
return treeBoundBox(mesh.points(), mesh.faces()[facei]);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return bbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Overall bound box for specified faces
|
||||||
|
template<class ElementIds>
|
||||||
|
static treeBoundBox boundsImpl
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const ElementIds& elemIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
for (const label facei : elemIds)
|
||||||
|
{
|
||||||
|
bb.add(mesh.points(), mesh.faces()[facei]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataFace::boxes(const primitiveMesh& mesh)
|
||||||
|
{
|
||||||
|
// All faces
|
||||||
|
return boxesImpl(mesh, labelRange(mesh.nFaces()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataFace::boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boxesImpl(mesh, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataFace::boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& faceIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boxesImpl(mesh, faceIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataFace::bounds
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boundsImpl(mesh, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataFace::bounds
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& faceIds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return boundsImpl(mesh, faceIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::treeBoundBox Foam::treeDataFace::calcBb(const label facei) const
|
inline bool
|
||||||
|
Foam::treeDataFace::usesFace(const label facei) const
|
||||||
{
|
{
|
||||||
|
return (!useSubset_ || isTreeFace_.test(facei));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::treeBoundBox
|
||||||
|
Foam::treeDataFace::getBounds(const label index) const
|
||||||
|
{
|
||||||
|
const label facei = objectIndex(index);
|
||||||
return treeBoundBox(mesh_.points(), mesh_.faces()[facei]);
|
return treeBoundBox(mesh_.points(), mesh_.faces()[facei]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataFace::update()
|
void Foam::treeDataFace::update()
|
||||||
{
|
{
|
||||||
isTreeFace_.set(faceLabels_);
|
|
||||||
|
|
||||||
if (cacheBb_)
|
if (cacheBb_)
|
||||||
{
|
{
|
||||||
bbs_.setSize(faceLabels_.size());
|
if (useSubset_)
|
||||||
|
|
||||||
forAll(faceLabels_, i)
|
|
||||||
{
|
{
|
||||||
bbs_[i] = calcBb(faceLabels_[i]);
|
bbs_ = treeDataFace::boxes(mesh_, faceLabels_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bbs_ = treeDataFace::boxes(mesh_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,6 +181,49 @@ void Foam::treeDataFace::update()
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeDataFace::treeDataFace
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const primitiveMesh& mesh
|
||||||
|
)
|
||||||
|
:
|
||||||
|
mesh_(mesh),
|
||||||
|
faceLabels_(),
|
||||||
|
isTreeFace_(),
|
||||||
|
useSubset_(false),
|
||||||
|
cacheBb_(cacheBb)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeDataFace::treeDataFace
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelRange& range
|
||||||
|
)
|
||||||
|
:
|
||||||
|
mesh_(mesh),
|
||||||
|
faceLabels_(identity(range)),
|
||||||
|
isTreeFace_(range),
|
||||||
|
useSubset_(true),
|
||||||
|
cacheBb_(cacheBb)
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeDataFace::treeDataFace
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const polyPatch& patch
|
||||||
|
)
|
||||||
|
:
|
||||||
|
treeDataFace(cacheBb, patch.boundaryMesh().mesh(), patch.range())
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataFace::treeDataFace
|
Foam::treeDataFace::treeDataFace
|
||||||
(
|
(
|
||||||
const bool cacheBb,
|
const bool cacheBb,
|
||||||
@ -75,7 +233,8 @@ Foam::treeDataFace::treeDataFace
|
|||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
faceLabels_(faceLabels),
|
faceLabels_(faceLabels),
|
||||||
isTreeFace_(mesh.nFaces(), false),
|
isTreeFace_(mesh_.nFaces(), faceLabels_),
|
||||||
|
useSubset_(true),
|
||||||
cacheBb_(cacheBb)
|
cacheBb_(cacheBb)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
@ -91,73 +250,45 @@ Foam::treeDataFace::treeDataFace
|
|||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
faceLabels_(std::move(faceLabels)),
|
faceLabels_(std::move(faceLabels)),
|
||||||
isTreeFace_(mesh.nFaces(), false),
|
isTreeFace_(mesh_.nFaces(), faceLabels_),
|
||||||
|
useSubset_(true),
|
||||||
cacheBb_(cacheBb)
|
cacheBb_(cacheBb)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataFace::treeDataFace
|
|
||||||
(
|
|
||||||
const bool cacheBb,
|
|
||||||
const primitiveMesh& mesh
|
|
||||||
)
|
|
||||||
:
|
|
||||||
mesh_(mesh),
|
|
||||||
faceLabels_(identity(mesh_.nFaces())),
|
|
||||||
isTreeFace_(mesh.nFaces(), false),
|
|
||||||
cacheBb_(cacheBb)
|
|
||||||
{
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataFace::treeDataFace
|
|
||||||
(
|
|
||||||
const bool cacheBb,
|
|
||||||
const polyPatch& patch
|
|
||||||
)
|
|
||||||
:
|
|
||||||
mesh_(patch.boundaryMesh().mesh()),
|
|
||||||
faceLabels_(identity(patch.range())),
|
|
||||||
isTreeFace_(mesh_.nFaces(), false),
|
|
||||||
cacheBb_(cacheBb)
|
|
||||||
{
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataFace::findNearestOp::findNearestOp
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataFace>& tree
|
|
||||||
)
|
|
||||||
:
|
|
||||||
tree_(tree)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::treeDataFace::findIntersectOp::findIntersectOp
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataFace>& tree
|
|
||||||
)
|
|
||||||
:
|
|
||||||
tree_(tree)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::pointField Foam::treeDataFace::shapePoints() const
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataFace::bounds(const labelUList& indices) const
|
||||||
{
|
{
|
||||||
pointField cc(faceLabels_.size());
|
if (useSubset_)
|
||||||
|
|
||||||
forAll(faceLabels_, i)
|
|
||||||
{
|
{
|
||||||
cc[i] = mesh_.faceCentres()[faceLabels_[i]];
|
treeBoundBox bb;
|
||||||
|
|
||||||
|
for (const label index : indices)
|
||||||
|
{
|
||||||
|
const label facei = faceLabels_[index];
|
||||||
|
|
||||||
|
bb.add(mesh_.points(), mesh_.faces()[facei]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cc;
|
return treeDataFace::bounds(mesh_, indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField> Foam::treeDataFace::centres() const
|
||||||
|
{
|
||||||
|
if (useSubset_)
|
||||||
|
{
|
||||||
|
return tmp<pointField>::New(mesh_.faceCentres(), faceLabels_);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mesh_.faceCentres();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -181,7 +312,9 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
// Find nearest face to sample
|
// Find nearest face to sample
|
||||||
pointIndexHit info = oc.findNearest(sample, sqr(GREAT));
|
pointIndexHit info = oc.findNearest(sample, sqr(GREAT));
|
||||||
|
|
||||||
if (info.index() == -1)
|
const label index = info.index();
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "Could not find " << sample << " in octree."
|
<< "Could not find " << sample << " in octree."
|
||||||
@ -190,7 +323,7 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
|
|
||||||
|
|
||||||
// Get actual intersection point on face
|
// Get actual intersection point on face
|
||||||
label facei = faceLabels_[info.index()];
|
const label facei = objectIndex(index);
|
||||||
|
|
||||||
if (debug & 2)
|
if (debug & 2)
|
||||||
{
|
{
|
||||||
@ -238,32 +371,32 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
|
|
||||||
const scalar typDimSqr = mag(area) + VSMALL;
|
const scalar typDimSqr = mag(area) + VSMALL;
|
||||||
|
|
||||||
forAll(f, fp)
|
for (const label fp : f)
|
||||||
{
|
{
|
||||||
if ((magSqr(points[f[fp]] - curPt)/typDimSqr) < tolSqr)
|
const scalar relDistSqr = (magSqr(points[fp] - curPt)/typDimSqr);
|
||||||
|
|
||||||
|
if (relDistSqr < tolSqr)
|
||||||
{
|
{
|
||||||
// Face intersection point equals face vertex fp
|
// Face intersection point equals face vertex
|
||||||
|
|
||||||
// Calculate point normal (wrong: uses face normals instead of
|
// Calculate point normal (wrong: uses face normals instead of
|
||||||
// triangle normals)
|
// triangle normals)
|
||||||
const labelList& pFaces = mesh_.pointFaces()[f[fp]];
|
|
||||||
|
|
||||||
vector pointNormal(Zero);
|
vector pointNormal(Zero);
|
||||||
|
|
||||||
for (const label facei : pFaces)
|
for (const label ptFacei : mesh_.pointFaces()[fp])
|
||||||
{
|
{
|
||||||
if (isTreeFace_.test(facei))
|
if (usesFace(ptFacei))
|
||||||
{
|
{
|
||||||
pointNormal += normalised(mesh_.faceAreas()[facei]);
|
pointNormal += normalised(mesh_.faceAreas()[ptFacei]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug & 2)
|
if (debug & 2)
|
||||||
{
|
{
|
||||||
Pout<< " -> face point hit :" << points[f[fp]]
|
Pout<< " -> face point hit :" << points[fp]
|
||||||
<< " point normal:" << pointNormal
|
<< " point normal:" << pointNormal
|
||||||
<< " distance:"
|
<< " distance:" << relDistSqr << endl;
|
||||||
<< magSqr(points[f[fp]] - curPt)/typDimSqr << endl;
|
|
||||||
}
|
}
|
||||||
return indexedOctree<treeDataFace>::getSide
|
return indexedOctree<treeDataFace>::getSide
|
||||||
(
|
(
|
||||||
@ -272,7 +405,10 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((magSqr(fc - curPt)/typDimSqr) < tolSqr)
|
|
||||||
|
const scalar relDistSqr = (magSqr(fc - curPt)/typDimSqr);
|
||||||
|
|
||||||
|
if (relDistSqr < tolSqr)
|
||||||
{
|
{
|
||||||
// Face intersection point equals face centre. Normal at face centre
|
// Face intersection point equals face centre. Normal at face centre
|
||||||
// is already average of face normals
|
// is already average of face normals
|
||||||
@ -280,47 +416,38 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
if (debug & 2)
|
if (debug & 2)
|
||||||
{
|
{
|
||||||
Pout<< " -> centre hit:" << fc
|
Pout<< " -> centre hit:" << fc
|
||||||
<< " distance:" << magSqr(fc - curPt)/typDimSqr << endl;
|
<< " distance:" << relDistSqr << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexedOctree<treeDataFace>::getSide(area, sample - curPt);
|
return indexedOctree<treeDataFace>::getSide(area, sample - curPt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 3] Get the 'real' edge the face intersection is on
|
// 3] Get the 'real' edge the face intersection is on
|
||||||
//
|
//
|
||||||
|
|
||||||
const labelList& myEdges = mesh_.faceEdges()[facei];
|
for (const label edgei : mesh_.faceEdges()[facei])
|
||||||
|
|
||||||
forAll(myEdges, myEdgeI)
|
|
||||||
{
|
{
|
||||||
const edge& e = mesh_.edges()[myEdges[myEdgeI]];
|
|
||||||
|
|
||||||
pointHit edgeHit =
|
pointHit edgeHit =
|
||||||
line<point, const point&>
|
mesh_.edges()[edgei].line(points).nearestDist(sample);
|
||||||
(
|
|
||||||
points[e.start()],
|
|
||||||
points[e.end()]
|
|
||||||
).nearestDist(sample);
|
|
||||||
|
|
||||||
|
const scalar relDistSqr = edgeHit.point().distSqr(curPt)/typDimSqr;
|
||||||
|
|
||||||
if ((edgeHit.point().distSqr(curPt)/typDimSqr) < tolSqr)
|
if (relDistSqr < tolSqr)
|
||||||
{
|
{
|
||||||
// Face intersection point lies on edge e
|
// Face intersection point lies on edge e
|
||||||
|
|
||||||
// Calculate edge normal (wrong: uses face normals instead of
|
// Calculate edge normal (wrong: uses face normals instead of
|
||||||
// triangle normals)
|
// triangle normals)
|
||||||
const labelList& eFaces = mesh_.edgeFaces()[myEdges[myEdgeI]];
|
|
||||||
|
|
||||||
vector edgeNormal(Zero);
|
vector edgeNormal(Zero);
|
||||||
|
|
||||||
for (const label facei : eFaces)
|
for (const label eFacei : mesh_.edgeFaces()[edgei])
|
||||||
{
|
{
|
||||||
if (isTreeFace_.test(facei))
|
if (usesFace(eFacei))
|
||||||
{
|
{
|
||||||
edgeNormal += normalised(mesh_.faceAreas()[facei]);
|
edgeNormal += normalised(mesh_.faceAreas()[eFacei]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,13 +475,11 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
|
|
||||||
forAll(f, fp)
|
forAll(f, fp)
|
||||||
{
|
{
|
||||||
pointHit edgeHit = line<point, const point&>
|
pointHit edgeHit = linePointRef(points[f[fp]], fc).nearestDist(sample);
|
||||||
(
|
|
||||||
points[f[fp]],
|
|
||||||
fc
|
|
||||||
).nearestDist(sample);
|
|
||||||
|
|
||||||
if ((edgeHit.point().distSqr(curPt)/typDimSqr) < tolSqr)
|
const scalar relDistSqr = edgeHit.point().distSqr(curPt)/typDimSqr;
|
||||||
|
|
||||||
|
if (relDistSqr < tolSqr)
|
||||||
{
|
{
|
||||||
// Face intersection point lies on edge between two face triangles
|
// Face intersection point lies on edge between two face triangles
|
||||||
|
|
||||||
@ -406,37 +531,32 @@ Foam::volumeType Foam::treeDataFace::getVolumeType
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if any point on shape is inside cubeBb.
|
// Check if any point on shape is inside searchBox.
|
||||||
bool Foam::treeDataFace::overlaps
|
bool Foam::treeDataFace::overlaps
|
||||||
(
|
(
|
||||||
const label index,
|
const label index,
|
||||||
const treeBoundBox& cubeBb
|
const treeBoundBox& searchBox
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// 1. Quick rejection: bb does not intersect face bb at all
|
// 1. Quick rejection: bb does not intersect face bb at all
|
||||||
if (cacheBb_)
|
if
|
||||||
|
(
|
||||||
|
cacheBb_
|
||||||
|
? !searchBox.overlaps(bbs_[index])
|
||||||
|
: !searchBox.overlaps(getBounds(index))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (!cubeBb.overlaps(bbs_[index]))
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!cubeBb.overlaps(calcBb(faceLabels_[index])))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const pointField& points = mesh_.points();
|
const pointField& points = mesh_.points();
|
||||||
|
|
||||||
|
|
||||||
// 2. Check if one or more face points inside
|
// 2. Check if one or more face points inside
|
||||||
label facei = faceLabels_[index];
|
const label facei = objectIndex(index);
|
||||||
|
|
||||||
const face& f = mesh_.faces()[facei];
|
const face& f = mesh_.faces()[facei];
|
||||||
if (cubeBb.containsAny(points, f))
|
if (searchBox.containsAny(points, f))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -452,7 +572,7 @@ bool Foam::treeDataFace::overlaps
|
|||||||
points[f[fp]],
|
points[f[fp]],
|
||||||
points[f[f.fcIndex(fp)]],
|
points[f[f.fcIndex(fp)]],
|
||||||
fc,
|
fc,
|
||||||
cubeBb
|
searchBox
|
||||||
);
|
);
|
||||||
|
|
||||||
if (triIntersects)
|
if (triIntersects)
|
||||||
@ -465,6 +585,89 @@ bool Foam::treeDataFace::overlaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check if any point on shape is inside sphere.
|
||||||
|
bool Foam::treeDataFace::overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const point& centre,
|
||||||
|
const scalar radiusSqr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// 1. Quick rejection: sphere does not intersect face bb at all
|
||||||
|
if
|
||||||
|
(
|
||||||
|
cacheBb_
|
||||||
|
? !bbs_[index].overlaps(centre, radiusSqr)
|
||||||
|
: !getBounds(index).overlaps(centre, radiusSqr)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const label facei = objectIndex(index);
|
||||||
|
|
||||||
|
const face& f = mesh().faces()[facei];
|
||||||
|
|
||||||
|
pointHit nearHit = f.nearestPoint(centre, mesh().points());
|
||||||
|
|
||||||
|
if (sqr(nearHit.distance()) < radiusSqr)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Searching * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::treeDataFace::findNearestOp::findNearestOp
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataFace>& tree
|
||||||
|
)
|
||||||
|
:
|
||||||
|
tree_(tree)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::treeDataFace::findIntersectOp::findIntersectOp
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataFace>& tree
|
||||||
|
)
|
||||||
|
:
|
||||||
|
tree_(tree)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::treeDataFace::findNearest
|
||||||
|
(
|
||||||
|
const labelUList& indices,
|
||||||
|
const point& sample,
|
||||||
|
|
||||||
|
scalar& nearestDistSqr,
|
||||||
|
label& minIndex,
|
||||||
|
point& nearestPoint
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
for (const label index : indices)
|
||||||
|
{
|
||||||
|
const label facei = objectIndex(index);
|
||||||
|
|
||||||
|
const face& f = mesh().faces()[facei];
|
||||||
|
|
||||||
|
pointHit nearHit = f.nearestPoint(sample, mesh().points());
|
||||||
|
scalar distSqr = sqr(nearHit.distance());
|
||||||
|
|
||||||
|
if (distSqr < nearestDistSqr)
|
||||||
|
{
|
||||||
|
nearestDistSqr = distSqr;
|
||||||
|
minIndex = index;
|
||||||
|
nearestPoint = nearHit.point();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::treeDataFace::findNearestOp::operator()
|
void Foam::treeDataFace::findNearestOp::operator()
|
||||||
(
|
(
|
||||||
const labelUList& indices,
|
const labelUList& indices,
|
||||||
@ -475,22 +678,14 @@ void Foam::treeDataFace::findNearestOp::operator()
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const treeDataFace& shape = tree_.shapes();
|
tree_.shapes().findNearest
|
||||||
|
(
|
||||||
for (const label index : indices)
|
indices,
|
||||||
{
|
sample,
|
||||||
const face& f = shape.mesh().faces()[shape.faceLabels()[index]];
|
nearestDistSqr,
|
||||||
|
minIndex,
|
||||||
pointHit nearHit = f.nearestPoint(sample, shape.mesh().points());
|
nearestPoint
|
||||||
scalar distSqr = sqr(nearHit.distance());
|
);
|
||||||
|
|
||||||
if (distSqr < nearestDistSqr)
|
|
||||||
{
|
|
||||||
nearestDistSqr = distSqr;
|
|
||||||
minIndex = index;
|
|
||||||
nearestPoint = nearHit.point();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -531,7 +726,7 @@ bool Foam::treeDataFace::findIntersectOp::operator()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const label facei = shape.faceLabels_[index];
|
const label facei = shape.objectIndex(index);
|
||||||
|
|
||||||
const vector dir(end - start);
|
const vector dir(end - start);
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -28,15 +28,15 @@ Class
|
|||||||
Foam::treeDataFace
|
Foam::treeDataFace
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Encapsulation of data needed to search for faces.
|
Encapsulation of data for searching on faces.
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
treeDataFace.C
|
treeDataFace.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef treeDataFace_H
|
#ifndef Foam_treeDataFace_H
|
||||||
#define treeDataFace_H
|
#define Foam_treeDataFace_H
|
||||||
|
|
||||||
#include "face.H"
|
#include "face.H"
|
||||||
#include "indexedOctree.H"
|
#include "indexedOctree.H"
|
||||||
@ -50,7 +50,7 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
// Forward declaration of classes
|
// Forward Declarations
|
||||||
class polyPatch;
|
class polyPatch;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
@ -67,6 +67,7 @@ class treeDataFace
|
|||||||
|
|
||||||
// Private Data
|
// Private Data
|
||||||
|
|
||||||
|
//- Reference to the mesh
|
||||||
const primitiveMesh& mesh_;
|
const primitiveMesh& mesh_;
|
||||||
|
|
||||||
//- Subset of faces to work on
|
//- Subset of faces to work on
|
||||||
@ -75,6 +76,9 @@ class treeDataFace
|
|||||||
//- Inverse of faceLabels. For every mesh whether face is in faceLabels.
|
//- Inverse of faceLabels. For every mesh whether face is in faceLabels.
|
||||||
bitSet isTreeFace_;
|
bitSet isTreeFace_;
|
||||||
|
|
||||||
|
//- Use subset of faces (faceLabels)
|
||||||
|
const bool useSubset_;
|
||||||
|
|
||||||
//- Whether to precalculate and store face bounding box
|
//- Whether to precalculate and store face bounding box
|
||||||
const bool cacheBb_;
|
const bool cacheBb_;
|
||||||
|
|
||||||
@ -84,8 +88,11 @@ class treeDataFace
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Calculate face bounding box
|
//- True if specified mesh facei is being used
|
||||||
treeBoundBox calcBb(const label celli) const;
|
inline bool usesFace(const label facei) const;
|
||||||
|
|
||||||
|
//- Get face bounding box at specified index
|
||||||
|
inline treeBoundBox getBounds(const label index) const;
|
||||||
|
|
||||||
//- Initialise all member data
|
//- Initialise all member data
|
||||||
void update();
|
void update();
|
||||||
@ -148,7 +155,25 @@ public:
|
|||||||
ClassName("treeDataFace");
|
ClassName("treeDataFace");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors (cachable versions)
|
||||||
|
|
||||||
|
//- Construct from mesh, using all faces
|
||||||
|
treeDataFace
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const primitiveMesh& mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from mesh, using polyPatch faces
|
||||||
|
treeDataFace(const bool cacheBb, const polyPatch& patch);
|
||||||
|
|
||||||
|
//- Construct from mesh, using specified range of faces
|
||||||
|
treeDataFace
|
||||||
|
(
|
||||||
|
const bool cacheBb,
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelRange& range
|
||||||
|
);
|
||||||
|
|
||||||
//- Construct from mesh, copying subset of faces
|
//- Construct from mesh, copying subset of faces
|
||||||
treeDataFace
|
treeDataFace
|
||||||
@ -166,53 +191,168 @@ public:
|
|||||||
labelList&& faceLabels
|
labelList&& faceLabels
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from mesh. Uses all faces in mesh.
|
|
||||||
treeDataFace(const bool cacheBb, const primitiveMesh& mesh);
|
|
||||||
|
|
||||||
//- Construct from mesh. Uses all faces in patch.
|
// Constructors (non-caching)
|
||||||
treeDataFace(const bool cacheBb, const polyPatch& patch);
|
|
||||||
|
//- Construct from mesh, using all faces
|
||||||
|
explicit treeDataFace(const primitiveMesh& mesh)
|
||||||
|
:
|
||||||
|
treeDataFace(false, mesh)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from mesh, using polyPatch faces
|
||||||
|
explicit treeDataFace(const polyPatch& patch)
|
||||||
|
:
|
||||||
|
treeDataFace(false, patch)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from mesh, using specified range of faces
|
||||||
|
treeDataFace(const primitiveMesh& mesh, const labelRange& range)
|
||||||
|
:
|
||||||
|
treeDataFace(false, mesh, range)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from mesh, copying subset of faces
|
||||||
|
treeDataFace(const primitiveMesh& mesh, const labelUList& faceLabels)
|
||||||
|
:
|
||||||
|
treeDataFace(false, mesh, faceLabels)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from mesh, moving subset of faces
|
||||||
|
treeDataFace(const primitiveMesh& mesh, labelList&& faceLabels)
|
||||||
|
:
|
||||||
|
treeDataFace(false, mesh, std::move(faceLabels))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Static Functions
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for all mesh faces
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for specified range of faces
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelRange& range
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for specified mesh faces
|
||||||
|
static treeBoundBoxList boxes
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& faceIds
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return bounding box of specified range of faces
|
||||||
|
static treeBoundBox bounds
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelRange& range
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return bounding box of specified mesh faces
|
||||||
|
static treeBoundBox bounds
|
||||||
|
(
|
||||||
|
const primitiveMesh& mesh,
|
||||||
|
const labelUList& faceIds
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
//- Object dimension == 2 (face element)
|
||||||
|
int nDim() const noexcept { return 2; }
|
||||||
|
|
||||||
inline const labelList& faceLabels() const
|
//- Return bounding box for the specified face indices
|
||||||
{
|
treeBoundBox bounds(const labelUList& indices) const;
|
||||||
return faceLabels_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const primitiveMesh& mesh() const
|
|
||||||
{
|
|
||||||
return mesh_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline label size() const
|
|
||||||
{
|
|
||||||
return faceLabels_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Representative point cloud for all shapes inside
|
|
||||||
//- (one point per shape)
|
|
||||||
pointField shapePoints() const;
|
|
||||||
|
|
||||||
|
|
||||||
// Search
|
// Access
|
||||||
|
|
||||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
//- Reference to the supporting mesh
|
||||||
// Only makes sense for closed surfaces.
|
const primitiveMesh& mesh() const noexcept { return mesh_; }
|
||||||
volumeType getVolumeType
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataFace>&,
|
|
||||||
const point&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does (bb of) shape at index overlap bb
|
//- The subset of face ids to use
|
||||||
bool overlaps
|
const labelList& faceLabels() const noexcept { return faceLabels_; }
|
||||||
(
|
|
||||||
const label index,
|
//- Use a subset of faces
|
||||||
const treeBoundBox& sampleBb
|
bool useSubset() const noexcept { return useSubset_; }
|
||||||
) const;
|
|
||||||
|
//- Is the effective face selection empty?
|
||||||
|
bool empty() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? faceLabels_.empty() : !mesh_.nFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- The size of the face selection
|
||||||
|
label size() const noexcept
|
||||||
|
{
|
||||||
|
return useSubset_ ? faceLabels_.size() : mesh_.nFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Map from shape index to original (non-subset) face label
|
||||||
|
label objectIndex(const label index) const
|
||||||
|
{
|
||||||
|
return useSubset_ && index >= 0 ? faceLabels_[index] : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Face at specified shape index
|
||||||
|
const face& operator[](const label index) const
|
||||||
|
{
|
||||||
|
return mesh_.faces()[objectIndex(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Representative point (face centre) at shape index
|
||||||
|
const point& centre(const label index) const
|
||||||
|
{
|
||||||
|
return mesh_.faceCentres()[objectIndex(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Representative point cloud for contained shapes.
|
||||||
|
//- One point per shape, corresponding to the face centres.
|
||||||
|
tmp<pointField> centres() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
|
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||||
|
// Only makes sense for closed surfaces.
|
||||||
|
volumeType getVolumeType
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataFace>&,
|
||||||
|
const point&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does (bb of) shape at index overlap searchBox
|
||||||
|
bool overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const treeBoundBox& searchBox
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does shape at index overlap 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -31,20 +31,51 @@ License
|
|||||||
#include "triangleFuncs.H"
|
#include "triangleFuncs.H"
|
||||||
#include "triSurfaceTools.H"
|
#include "triSurfaceTools.H"
|
||||||
#include "triFace.H"
|
#include "triFace.H"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class PatchType>
|
||||||
|
Foam::treeBoundBoxList
|
||||||
|
Foam::treeDataPrimitivePatch<PatchType>::boxes(const PatchType& pp)
|
||||||
|
{
|
||||||
|
const auto& points = pp.points();
|
||||||
|
|
||||||
|
treeBoundBoxList bbs(pp.size());
|
||||||
|
|
||||||
|
// Like std::transform with [&](const auto& f)
|
||||||
|
// which may not work with older C++ versions
|
||||||
|
|
||||||
|
{
|
||||||
|
auto iter = bbs.begin();
|
||||||
|
|
||||||
|
for (const auto& f : pp)
|
||||||
|
{
|
||||||
|
*iter = treeBoundBox(points, f);
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class PatchType>
|
||||||
|
inline Foam::treeBoundBox
|
||||||
|
Foam::treeDataPrimitivePatch<PatchType>::getBounds(const label patchFacei) const
|
||||||
|
{
|
||||||
|
return treeBoundBox(patch_.points(), patch_[patchFacei]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class PatchType>
|
template<class PatchType>
|
||||||
void Foam::treeDataPrimitivePatch<PatchType>::update()
|
void Foam::treeDataPrimitivePatch<PatchType>::update()
|
||||||
{
|
{
|
||||||
if (cacheBb_)
|
if (cacheBb_)
|
||||||
{
|
{
|
||||||
bbs_.setSize(patch_.size());
|
bbs_ = treeDataPrimitivePatch<PatchType>::boxes(patch_);
|
||||||
|
|
||||||
forAll(patch_, i)
|
|
||||||
{
|
|
||||||
bbs_[i] = treeBoundBox(patch_.points(), patch_[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,16 +146,20 @@ findSelfIntersectOp::findSelfIntersectOp
|
|||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class PatchType>
|
template<class PatchType>
|
||||||
Foam::pointField Foam::treeDataPrimitivePatch<PatchType>::shapePoints() const
|
Foam::treeBoundBox
|
||||||
|
Foam::treeDataPrimitivePatch<PatchType>::bounds
|
||||||
|
(
|
||||||
|
const labelUList& indices
|
||||||
|
) const
|
||||||
{
|
{
|
||||||
pointField cc(patch_.size());
|
treeBoundBox bb;
|
||||||
|
|
||||||
forAll(patch_, i)
|
for (const label patchFacei : indices)
|
||||||
{
|
{
|
||||||
cc[i] = patch_[i].centre(patch_.points());
|
bb.add(patch_.points(), patch_[patchFacei]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cc;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -168,7 +203,6 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
const typename PatchType::face_type& localF = patch_.localFaces()[facei];
|
const typename PatchType::face_type& localF = patch_.localFaces()[facei];
|
||||||
const typename PatchType::face_type& f = patch_[facei];
|
const typename PatchType::face_type& f = patch_[facei];
|
||||||
const pointField& points = patch_.points();
|
const pointField& points = patch_.points();
|
||||||
const labelList& mp = patch_.meshPoints();
|
|
||||||
|
|
||||||
// Retest to classify where on face info is. Note: could be improved. We
|
// Retest to classify where on face info is. Note: could be improved. We
|
||||||
// already have point.
|
// already have point.
|
||||||
@ -212,7 +246,9 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
|
|
||||||
forAll(f, fp)
|
forAll(f, fp)
|
||||||
{
|
{
|
||||||
if ((magSqr(points[f[fp]] - curPt)/typDimSqr) < planarTol_)
|
const scalar relDistSqr = (magSqr(points[f[fp]] - curPt)/typDimSqr);
|
||||||
|
|
||||||
|
if (relDistSqr < planarTol_)
|
||||||
{
|
{
|
||||||
// Face intersection point equals face vertex fp
|
// Face intersection point equals face vertex fp
|
||||||
|
|
||||||
@ -229,7 +265,9 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
|
|
||||||
const point fc(f.centre(points));
|
const point fc(f.centre(points));
|
||||||
|
|
||||||
if ((magSqr(fc - curPt)/typDimSqr) < planarTol_)
|
const scalar relDistSqr = (magSqr(fc - curPt)/typDimSqr);
|
||||||
|
|
||||||
|
if (relDistSqr < planarTol_)
|
||||||
{
|
{
|
||||||
// Face intersection point equals face centre. Normal at face centre
|
// Face intersection point equals face centre. Normal at face centre
|
||||||
// is already average of face normals
|
// is already average of face normals
|
||||||
@ -237,7 +275,7 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
if (debug & 2)
|
if (debug & 2)
|
||||||
{
|
{
|
||||||
Pout<< " -> centre hit:" << fc
|
Pout<< " -> centre hit:" << fc
|
||||||
<< " distance:" << magSqr(fc - curPt)/typDimSqr << endl;
|
<< " distance:" << relDistSqr << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexedOctree<treeDataPrimitivePatch>::getSide
|
return indexedOctree<treeDataPrimitivePatch>::getSide
|
||||||
@ -248,33 +286,28 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 3] Get the 'real' edge the face intersection is on
|
// 3] Get the 'real' edge the face intersection is on
|
||||||
//
|
//
|
||||||
|
|
||||||
const labelList& fEdges = patch_.faceEdges()[facei];
|
for (const label edgei : patch_.faceEdges()[facei])
|
||||||
|
|
||||||
forAll(fEdges, fEdgeI)
|
|
||||||
{
|
{
|
||||||
label edgeI = fEdges[fEdgeI];
|
pointHit edgeHit =
|
||||||
const edge& e = patch_.edges()[edgeI];
|
patch_.meshEdge(edgei).line(points).nearestDist(sample);
|
||||||
const linePointRef ln(points[mp[e.start()]], points[mp[e.end()]]);
|
|
||||||
pointHit edgeHit = ln.nearestDist(sample);
|
|
||||||
|
|
||||||
if ((edgeHit.point().distSqr(curPt)/typDimSqr) < planarTol_)
|
const scalar relDistSqr = (edgeHit.point().distSqr(curPt)/typDimSqr);
|
||||||
|
|
||||||
|
if (relDistSqr < planarTol_)
|
||||||
{
|
{
|
||||||
// Face intersection point lies on edge e
|
// Face intersection point lies on edge e
|
||||||
|
|
||||||
// Calculate edge normal (wrong: uses face normals instead of
|
// Calculate edge normal (wrong: uses face normals instead of
|
||||||
// triangle normals)
|
// triangle normals)
|
||||||
const labelList& eFaces = patch_.edgeFaces()[edgeI];
|
|
||||||
|
|
||||||
vector edgeNormal(Zero);
|
vector edgeNormal(Zero);
|
||||||
|
|
||||||
forAll(eFaces, i)
|
for (const label eFacei : patch_.edgeFaces()[edgei])
|
||||||
{
|
{
|
||||||
edgeNormal += patch_.faceNormals()[eFaces[i]];
|
edgeNormal += patch_.faceNormals()[eFacei];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug & 2)
|
if (debug & 2)
|
||||||
@ -303,7 +336,9 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
{
|
{
|
||||||
pointHit edgeHit = linePointRef(points[f[fp]], fc).nearestDist(sample);
|
pointHit edgeHit = linePointRef(points[f[fp]], fc).nearestDist(sample);
|
||||||
|
|
||||||
if ((edgeHit.point().distSqr(curPt)/typDimSqr) < planarTol_)
|
const scalar relDistSqr = (edgeHit.point().distSqr(curPt)/typDimSqr);
|
||||||
|
|
||||||
|
if (relDistSqr < planarTol_)
|
||||||
{
|
{
|
||||||
// Face intersection point lies on edge between two face triangles
|
// Face intersection point lies on edge between two face triangles
|
||||||
|
|
||||||
@ -356,20 +391,20 @@ Foam::volumeType Foam::treeDataPrimitivePatch<PatchType>::getVolumeType
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if any point on shape is inside cubeBb.
|
// Check if any point on shape is inside searchBox.
|
||||||
template<class PatchType>
|
template<class PatchType>
|
||||||
bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
||||||
(
|
(
|
||||||
const label index,
|
const label index,
|
||||||
const treeBoundBox& cubeBb
|
const treeBoundBox& searchBox
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// 1. Quick rejection: bb does not intersect face bb at all
|
// 1. Quick rejection: bb does not intersect face bb at all
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
cacheBb_
|
cacheBb_
|
||||||
? !cubeBb.overlaps(bbs_[index])
|
? !searchBox.overlaps(bbs_[index])
|
||||||
: !cubeBb.overlaps(treeBoundBox(patch_.points(), patch_[index]))
|
: !searchBox.overlaps(getBounds(index))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -381,7 +416,7 @@ bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
|||||||
const pointField& points = patch_.points();
|
const pointField& points = patch_.points();
|
||||||
const typename PatchType::face_type& f = patch_[index];
|
const typename PatchType::face_type& f = patch_[index];
|
||||||
|
|
||||||
if (cubeBb.containsAny(points, f))
|
if (searchBox.containsAny(points, f))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -397,7 +432,7 @@ bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
|||||||
points[f[0]],
|
points[f[0]],
|
||||||
points[f[1]],
|
points[f[1]],
|
||||||
points[f[2]],
|
points[f[2]],
|
||||||
cubeBb
|
searchBox
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -409,7 +444,7 @@ bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
|||||||
points[f[fp]],
|
points[f[fp]],
|
||||||
points[f[f.fcIndex(fp)]],
|
points[f[f.fcIndex(fp)]],
|
||||||
fc,
|
fc,
|
||||||
cubeBb
|
searchBox
|
||||||
);
|
);
|
||||||
|
|
||||||
if (triIntersects)
|
if (triIntersects)
|
||||||
@ -437,7 +472,7 @@ bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
|||||||
(
|
(
|
||||||
cacheBb_
|
cacheBb_
|
||||||
? !bbs_[index].overlaps(centre, radiusSqr)
|
? !bbs_[index].overlaps(centre, radiusSqr)
|
||||||
: !treeBoundBox(patch_.points(),patch_[index]).overlaps(centre, radiusSqr)
|
: !getBounds(index).overlaps(centre, radiusSqr)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -459,8 +494,10 @@ bool Foam::treeDataPrimitivePatch<PatchType>::overlaps
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Searching * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class PatchType>
|
template<class PatchType>
|
||||||
void Foam::treeDataPrimitivePatch<PatchType>::findNearestOp::operator()
|
void Foam::treeDataPrimitivePatch<PatchType>::findNearest
|
||||||
(
|
(
|
||||||
const labelUList& indices,
|
const labelUList& indices,
|
||||||
const point& sample,
|
const point& sample,
|
||||||
@ -470,14 +507,11 @@ void Foam::treeDataPrimitivePatch<PatchType>::findNearestOp::operator()
|
|||||||
point& nearestPoint
|
point& nearestPoint
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const treeDataPrimitivePatch<PatchType>& shape = tree_.shapes();
|
const pointField& points = patch_.points();
|
||||||
const PatchType& patch = shape.patch();
|
|
||||||
|
|
||||||
const pointField& points = patch.points();
|
|
||||||
|
|
||||||
for (const label index : indices)
|
for (const label index : indices)
|
||||||
{
|
{
|
||||||
const typename PatchType::face_type& f = patch[index];
|
const typename PatchType::face_type& f = patch_[index];
|
||||||
|
|
||||||
const pointHit nearHit = f.nearestPoint(sample, points);
|
const pointHit nearHit = f.nearestPoint(sample, points);
|
||||||
const scalar distSqr = sqr(nearHit.distance());
|
const scalar distSqr = sqr(nearHit.distance());
|
||||||
@ -492,6 +526,28 @@ void Foam::treeDataPrimitivePatch<PatchType>::findNearestOp::operator()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class PatchType>
|
||||||
|
void Foam::treeDataPrimitivePatch<PatchType>::findNearestOp::operator()
|
||||||
|
(
|
||||||
|
const labelUList& indices,
|
||||||
|
const point& sample,
|
||||||
|
|
||||||
|
scalar& nearestDistSqr,
|
||||||
|
label& minIndex,
|
||||||
|
point& nearestPoint
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
tree_.shapes().findNearest
|
||||||
|
(
|
||||||
|
indices,
|
||||||
|
sample,
|
||||||
|
nearestDistSqr,
|
||||||
|
minIndex,
|
||||||
|
nearestPoint
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class PatchType>
|
template<class PatchType>
|
||||||
void Foam::treeDataPrimitivePatch<PatchType>::findNearestOp::operator()
|
void Foam::treeDataPrimitivePatch<PatchType>::findNearestOp::operator()
|
||||||
(
|
(
|
||||||
|
|||||||
@ -82,6 +82,9 @@ class treeDataPrimitivePatch
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Get face bounding box
|
||||||
|
inline treeBoundBox getBounds(const label patchFacei) const;
|
||||||
|
|
||||||
//- Initialise all member data
|
//- Initialise all member data
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
@ -194,71 +197,126 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
// Constructors (cachable versions)
|
||||||
|
|
||||||
//- Construct from patch.
|
//- Construct from patch.
|
||||||
treeDataPrimitivePatch
|
treeDataPrimitivePatch
|
||||||
(
|
(
|
||||||
const bool cacheBb,
|
const bool cacheBb,
|
||||||
const PatchType&,
|
const PatchType& patch,
|
||||||
const scalar planarTol
|
const scalar planarTol
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors (non-caching)
|
||||||
|
|
||||||
|
//- Construct from patch.
|
||||||
|
treeDataPrimitivePatch(const PatchType& patch, const scalar planarTol)
|
||||||
|
:
|
||||||
|
treeDataPrimitivePatch(false, patch, planarTol)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Static Functions
|
||||||
|
|
||||||
|
//- Calculate and return bounding boxes for each patch face
|
||||||
|
static treeBoundBoxList boxes(const PatchType& patch);
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
//- Object dimension == 2 (face element)
|
||||||
|
int nDim() const noexcept { return 2; }
|
||||||
|
|
||||||
label size() const
|
//- Return bounding box for the specified face indices
|
||||||
{
|
treeBoundBox bounds(const labelUList& indices) const;
|
||||||
return patch_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Representative point cloud for all shapes inside
|
|
||||||
//- (one point per shape)
|
|
||||||
pointField shapePoints() const;
|
|
||||||
|
|
||||||
//- Return access to the underlying patch
|
|
||||||
const PatchType& patch() const
|
|
||||||
{
|
|
||||||
return patch_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Search
|
// Access
|
||||||
|
|
||||||
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
//- The underlying patch
|
||||||
// Only makes sense for closed surfaces.
|
const PatchType& patch() const noexcept { return patch_; }
|
||||||
volumeType getVolumeType
|
|
||||||
(
|
|
||||||
const indexedOctree<treeDataPrimitivePatch<PatchType>>&,
|
|
||||||
const point&
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does shape at index overlap bb
|
//TDB //- The subset of face ids to use
|
||||||
bool overlaps
|
///const labelList& faceLabels() const noexcept { labelList::null(); }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const treeBoundBox& sampleBb
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Does shape at index overlap sphere
|
//- Use a subset of the patch
|
||||||
bool overlaps
|
bool useSubset() const noexcept { return false; }
|
||||||
(
|
|
||||||
const label index,
|
|
||||||
const point& centre,
|
|
||||||
const scalar radiusSqr
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Helper: find intersection of line with shapes
|
//- Is the patch empty (no faces)?
|
||||||
static bool findIntersection
|
bool empty() const { return !patch_.size(); }
|
||||||
(
|
|
||||||
const indexedOctree<treeDataPrimitivePatch<PatchType>>& tree,
|
//- The patch size
|
||||||
const label index,
|
label size() const { return patch_.size(); }
|
||||||
const point& start,
|
|
||||||
const point& end,
|
//- Map from shape index to original (non-subset) face label
|
||||||
point& intersectionPoint
|
label objectIndex(const label index) const noexcept { return index; }
|
||||||
);
|
|
||||||
|
//TBD //- Face at specified shape index
|
||||||
|
///const typename PatchType::face_type&
|
||||||
|
///operator[](label index) const { return patch_[index]; }
|
||||||
|
|
||||||
|
//- Representative point (face centre) at shape index
|
||||||
|
const point& centre(const label index) const
|
||||||
|
{
|
||||||
|
return patch_.faceCentres()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Representative point cloud for contained shapes.
|
||||||
|
//- One point per shape, corresponding to the face centres.
|
||||||
|
tmp<pointField> centres() const
|
||||||
|
{
|
||||||
|
return patch_.faceCentres();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
|
//- Get type (inside,outside,mixed,unknown) of point w.r.t. surface.
|
||||||
|
// Only makes sense for closed surfaces.
|
||||||
|
volumeType getVolumeType
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataPrimitivePatch<PatchType>>&,
|
||||||
|
const point&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does shape at index overlap searchBox
|
||||||
|
bool overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const treeBoundBox& searchBox
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Does shape at index overlap sphere
|
||||||
|
bool overlaps
|
||||||
|
(
|
||||||
|
const label index,
|
||||||
|
const point& centre,
|
||||||
|
const scalar radiusSqr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Helper: find intersection of line with shapes
|
||||||
|
static bool findIntersection
|
||||||
|
(
|
||||||
|
const indexedOctree<treeDataPrimitivePatch<PatchType>>& tree,
|
||||||
|
const label index,
|
||||||
|
const point& start,
|
||||||
|
const point& end,
|
||||||
|
point& intersectionPoint
|
||||||
|
);
|
||||||
|
|
||||||
|
//- 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -414,6 +414,7 @@ void Foam::mappedPatchBase::findLocalSamples
|
|||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treeData = boundaryTree.shapes();
|
||||||
|
|
||||||
forAll(samples, sampleI)
|
forAll(samples, sampleI)
|
||||||
{
|
{
|
||||||
@ -435,7 +436,8 @@ void Foam::mappedPatchBase::findLocalSamples
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
point fc(pp[nearInfo.index()].centre(pp.points()));
|
const point& fc = treeData.centre(nearInfo.index());
|
||||||
|
|
||||||
nearInfo.setPoint(fc);
|
nearInfo.setPoint(fc);
|
||||||
near.first().second().first() = sample.distSqr(fc);
|
near.first().second().first() = sample.distSqr(fc);
|
||||||
near.first().second().second() = myRank;
|
near.first().second().second() = myRank;
|
||||||
|
|||||||
@ -84,7 +84,7 @@ namespace Foam
|
|||||||
// the new face shares a point with an existing hit face and the
|
// the new face shares a point with an existing hit face and the
|
||||||
// line passes through both faces in the same direction, then this
|
// line passes through both faces in the same direction, then this
|
||||||
// is also assumed to be a duplicate hit.
|
// is also assumed to be a duplicate hit.
|
||||||
const label newFacei = tree_.shapes().faceLabels()[index];
|
const label newFacei = tree_.shapes().objectIndex(index);
|
||||||
const face& newFace = mesh.faces()[newFacei];
|
const face& newFace = mesh.faces()[newFacei];
|
||||||
const scalar newDot = mesh.faceAreas()[newFacei] & (end - start);
|
const scalar newDot = mesh.faceAreas()[newFacei] & (end - start);
|
||||||
forAll(hits_, hiti)
|
forAll(hits_, hiti)
|
||||||
@ -161,10 +161,8 @@ bool Foam::meshSearch::findNearer
|
|||||||
{
|
{
|
||||||
bool nearer = false;
|
bool nearer = false;
|
||||||
|
|
||||||
forAll(indices, i)
|
for (const label pointi : indices)
|
||||||
{
|
{
|
||||||
label pointi = indices[i];
|
|
||||||
|
|
||||||
scalar distSqr = sample.distSqr(points[pointi]);
|
scalar distSqr = sample.distSqr(points[pointi]);
|
||||||
|
|
||||||
if (distSqr < nearestDistSqr)
|
if (distSqr < nearestDistSqr)
|
||||||
@ -620,9 +618,10 @@ Foam::meshSearch::boundaryTree() const
|
|||||||
if (!boundaryTreePtr_)
|
if (!boundaryTreePtr_)
|
||||||
{
|
{
|
||||||
// All boundary faces (not just walls)
|
// All boundary faces (not just walls)
|
||||||
labelList bndFaces
|
const labelRange bndFaces
|
||||||
(
|
(
|
||||||
identity(mesh_.nBoundaryFaces(), mesh_.nInternalFaces())
|
mesh_.nInternalFaces(),
|
||||||
|
mesh_.nBoundaryFaces()
|
||||||
);
|
);
|
||||||
|
|
||||||
boundaryTreePtr_.reset
|
boundaryTreePtr_.reset
|
||||||
@ -818,7 +817,7 @@ Foam::label Foam::meshSearch::findNearestBoundaryFace
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree.shapes().faceLabels()[info.index()];
|
return tree.shapes().objectIndex(info.index());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -867,7 +866,7 @@ Foam::pointIndexHit Foam::meshSearch::intersection
|
|||||||
if (curHit.hit())
|
if (curHit.hit())
|
||||||
{
|
{
|
||||||
// Change index into octreeData into face label
|
// Change index into octreeData into face label
|
||||||
curHit.setIndex(boundaryTree().shapes().faceLabels()[curHit.index()]);
|
curHit.setIndex(boundaryTree().shapes().objectIndex(curHit.index()));
|
||||||
}
|
}
|
||||||
return curHit;
|
return curHit;
|
||||||
}
|
}
|
||||||
@ -889,7 +888,7 @@ Foam::List<Foam::pointIndexHit> Foam::meshSearch::intersections
|
|||||||
if (!curHit.hit()) break;
|
if (!curHit.hit()) break;
|
||||||
|
|
||||||
// Change index into octreeData into face label
|
// Change index into octreeData into face label
|
||||||
curHit.setIndex(boundaryTree().shapes().faceLabels()[curHit.index()]);
|
curHit.setIndex(boundaryTree().shapes().objectIndex(curHit.index()));
|
||||||
|
|
||||||
hits.append(curHit);
|
hits.append(curHit);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -223,6 +223,7 @@ void Foam::searchableExtrudedCircle::findParametricNearest
|
|||||||
{
|
{
|
||||||
const edgeMesh& mesh = eMeshPtr_();
|
const edgeMesh& mesh = eMeshPtr_();
|
||||||
const indexedOctree<treeDataEdge>& tree = edgeTree_();
|
const indexedOctree<treeDataEdge>& tree = edgeTree_();
|
||||||
|
const auto& treeData = tree.shapes();
|
||||||
const edgeList& edges = mesh.edges();
|
const edgeList& edges = mesh.edges();
|
||||||
const pointField& points = mesh.points();
|
const pointField& points = mesh.points();
|
||||||
const labelListList& pointEdges = mesh.pointEdges();
|
const labelListList& pointEdges = mesh.pointEdges();
|
||||||
@ -243,11 +244,11 @@ void Foam::searchableExtrudedCircle::findParametricNearest
|
|||||||
|
|
||||||
const pointIndexHit startInfo = tree.findNearest(start, maxDistSqr);
|
const pointIndexHit startInfo = tree.findNearest(start, maxDistSqr);
|
||||||
curvePoints[0] = startInfo.hitPoint();
|
curvePoints[0] = startInfo.hitPoint();
|
||||||
axialVecs[0] = edges[startInfo.index()].vec(points);
|
axialVecs[0] = treeData.line(startInfo.index()).vec();
|
||||||
|
|
||||||
const pointIndexHit endInfo = tree.findNearest(end, maxDistSqr);
|
const pointIndexHit endInfo = tree.findNearest(end, maxDistSqr);
|
||||||
curvePoints.last() = endInfo.hitPoint();
|
curvePoints.last() = endInfo.hitPoint();
|
||||||
axialVecs.last() = edges[endInfo.index()].vec(points);
|
axialVecs.last() = treeData.line(endInfo.index()).vec();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -73,12 +73,11 @@ static bool onLine(const Foam::point& p, const linePointRef& line)
|
|||||||
|
|
||||||
Foam::pointIndexHit Foam::surfaceFeatures::edgeNearest
|
Foam::pointIndexHit Foam::surfaceFeatures::edgeNearest
|
||||||
(
|
(
|
||||||
const point& start,
|
const linePointRef& line,
|
||||||
const point& end,
|
|
||||||
const point& sample
|
const point& sample
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
pointHit eHit = linePointRef(start, end).nearestDist(sample);
|
pointHit eHit = line.nearestDist(sample);
|
||||||
|
|
||||||
// Classification of position on edge.
|
// Classification of position on edge.
|
||||||
label endPoint;
|
label endPoint;
|
||||||
@ -96,8 +95,8 @@ Foam::pointIndexHit Foam::surfaceFeatures::edgeNearest
|
|||||||
// which one.
|
// which one.
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
eHit.point().distSqr(start)
|
eHit.point().distSqr(line.start())
|
||||||
< eHit.point().distSqr(end)
|
< eHit.point().distSqr(line.end())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
endPoint = 0;
|
endPoint = 0;
|
||||||
@ -1255,6 +1254,7 @@ Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples
|
|||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treeData = ppTree.shapes();
|
||||||
|
|
||||||
// From patch point to surface point
|
// From patch point to surface point
|
||||||
Map<label> nearest(2*pointLabels.size());
|
Map<label> nearest(2*pointLabels.size());
|
||||||
@ -1283,7 +1283,7 @@ Foam::Map<Foam::label> Foam::surfaceFeatures::nearestSamples
|
|||||||
|
|
||||||
label sampleI = info.index();
|
label sampleI = info.index();
|
||||||
|
|
||||||
if (magSqr(samples[sampleI] - surfPt) < maxDistSqr[sampleI])
|
if (treeData.centre(sampleI).distSqr(surfPt) < maxDistSqr[sampleI])
|
||||||
{
|
{
|
||||||
nearest.insert(sampleI, surfPointi);
|
nearest.insert(sampleI, surfPointi);
|
||||||
}
|
}
|
||||||
@ -1537,7 +1537,7 @@ Foam::Map<Foam::pointIndexHit> Foam::surfaceFeatures::nearestEdges
|
|||||||
|
|
||||||
label index = info.index();
|
label index = info.index();
|
||||||
|
|
||||||
label sampleEdgeI = ppTree.shapes().edgeLabels()[index];
|
label sampleEdgeI = ppTree.shapes().objectIndex(index);
|
||||||
|
|
||||||
const edge& e = sampleEdges[sampleEdgeI];
|
const edge& e = sampleEdges[sampleEdgeI];
|
||||||
|
|
||||||
@ -1636,6 +1636,7 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
|||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treeData = ppTree.shapes();
|
||||||
|
|
||||||
forAll(samples, i)
|
forAll(samples, i)
|
||||||
{
|
{
|
||||||
@ -1653,18 +1654,14 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edgeLabel[i] = selectedEdges[info.index()];
|
|
||||||
|
|
||||||
// Need to recalculate to classify edgeEndPoint
|
// Need to recalculate to classify edgeEndPoint
|
||||||
const edge& e = surf_.edges()[edgeLabel[i]];
|
|
||||||
|
|
||||||
pointIndexHit pHit = edgeNearest
|
pointIndexHit pHit = edgeNearest
|
||||||
(
|
(
|
||||||
localPoints[e.start()],
|
treeData.line(info.index()),
|
||||||
localPoints[e.end()],
|
|
||||||
sample
|
sample
|
||||||
);
|
);
|
||||||
|
|
||||||
|
edgeLabel[i] = treeData.objectIndex(info.index());
|
||||||
edgePoint[i] = pHit.point();
|
edgePoint[i] = pHit.point();
|
||||||
edgeEndPoint[i] = pHit.index();
|
edgeEndPoint[i] = pHit.index();
|
||||||
}
|
}
|
||||||
@ -1707,6 +1704,7 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
|||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treeData = ppTree.shapes();
|
||||||
|
|
||||||
forAll(selectedSampleEdges, i)
|
forAll(selectedSampleEdges, i)
|
||||||
{
|
{
|
||||||
@ -1731,8 +1729,7 @@ void Foam::surfaceFeatures::nearestSurfEdge
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
edgeLabel[i] = selectedEdges[info.index()];
|
edgeLabel[i] = treeData.objectIndex(info.index());
|
||||||
|
|
||||||
pointOnFeature[i] = info.point();
|
pointOnFeature[i] = info.point();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1766,6 +1763,7 @@ void Foam::surfaceFeatures::nearestFeatEdge
|
|||||||
10, // leafsize
|
10, // leafsize
|
||||||
3.0 // duplicity
|
3.0 // duplicity
|
||||||
);
|
);
|
||||||
|
const auto& treeData = ppTree.shapes();
|
||||||
|
|
||||||
const edgeList& surfEdges = surf_.edges();
|
const edgeList& surfEdges = surf_.edges();
|
||||||
const pointField& surfLocalPoints = surf_.localPoints();
|
const pointField& surfLocalPoints = surf_.localPoints();
|
||||||
@ -1787,8 +1785,7 @@ void Foam::surfaceFeatures::nearestFeatEdge
|
|||||||
{
|
{
|
||||||
const vector surfEdgeDir = midPoint - startPoint;
|
const vector surfEdgeDir = midPoint - startPoint;
|
||||||
|
|
||||||
const edge& featEdge = edges[infoMid.index()];
|
const vector featEdgeDir = treeData.line(infoMid.index()).vec();
|
||||||
const vector featEdgeDir = featEdge.vec(points);
|
|
||||||
|
|
||||||
// Check that the edges are nearly parallel
|
// Check that the edges are nearly parallel
|
||||||
if (mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
|
if (mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
|
||||||
|
|||||||
@ -132,8 +132,7 @@ private:
|
|||||||
// index=1: nearest on edge.end().
|
// index=1: nearest on edge.end().
|
||||||
static pointIndexHit edgeNearest
|
static pointIndexHit edgeNearest
|
||||||
(
|
(
|
||||||
const point& start,
|
const linePointRef& line,
|
||||||
const point& end,
|
|
||||||
const point& sample
|
const point& sample
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -88,7 +88,7 @@ void Foam::meshToMesh0::calcAddressing()
|
|||||||
<< " bounding box (shifted) : " << shiftedBb << nl
|
<< " bounding box (shifted) : " << shiftedBb << nl
|
||||||
<< " typical dimension : " << shiftedBb.avgDim() << endl;
|
<< " typical dimension : " << shiftedBb.avgDim() << endl;
|
||||||
|
|
||||||
indexedOctree<treeDataCell> oc
|
indexedOctree<treeDataCell> cellTree
|
||||||
(
|
(
|
||||||
treeDataCell(false, fromMesh_, polyMesh::CELL_TETS),
|
treeDataCell(false, fromMesh_, polyMesh::CELL_TETS),
|
||||||
shiftedBb, // overall bounding box
|
shiftedBb, // overall bounding box
|
||||||
@ -99,7 +99,7 @@ void Foam::meshToMesh0::calcAddressing()
|
|||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
oc.print(Pout, false, 0);
|
cellTree.print(Pout, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cellAddresses
|
cellAddresses
|
||||||
@ -108,7 +108,7 @@ void Foam::meshToMesh0::calcAddressing()
|
|||||||
toMesh_.cellCentres(),
|
toMesh_.cellCentres(),
|
||||||
fromMesh_,
|
fromMesh_,
|
||||||
boundaryCell,
|
boundaryCell,
|
||||||
oc
|
cellTree
|
||||||
);
|
);
|
||||||
|
|
||||||
forAll(toMesh_.boundaryMesh(), patchi)
|
forAll(toMesh_.boundaryMesh(), patchi)
|
||||||
@ -125,7 +125,7 @@ void Foam::meshToMesh0::calcAddressing()
|
|||||||
toPatch.faceCentres(),
|
toPatch.faceCentres(),
|
||||||
fromMesh_,
|
fromMesh_,
|
||||||
boundaryCell,
|
boundaryCell,
|
||||||
oc
|
cellTree
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if
|
else if
|
||||||
@ -160,7 +160,7 @@ void Foam::meshToMesh0::calcAddressing()
|
|||||||
|
|
||||||
// Note: allow more levels than in meshSearch. Assume patch
|
// Note: allow more levels than in meshSearch. Assume patch
|
||||||
// is not as big as all boundary faces
|
// is not as big as all boundary faces
|
||||||
indexedOctree<treeDataFace> oc
|
indexedOctree<treeDataFace> faceTree
|
||||||
(
|
(
|
||||||
treeDataFace(false, fromPatch),
|
treeDataFace(false, fromPatch),
|
||||||
shiftedBb, // overall search domain
|
shiftedBb, // overall search domain
|
||||||
@ -178,7 +178,7 @@ void Foam::meshToMesh0::calcAddressing()
|
|||||||
|
|
||||||
forAll(toPatch, toi)
|
forAll(toPatch, toi)
|
||||||
{
|
{
|
||||||
boundaryAddressing_[patchi][toi] = oc.findNearest
|
boundaryAddressing_[patchi][toi] = faceTree.findNearest
|
||||||
(
|
(
|
||||||
centresToBoundary[toi],
|
centresToBoundary[toi],
|
||||||
distSqr
|
distSqr
|
||||||
@ -199,7 +199,7 @@ void Foam::meshToMesh0::cellAddresses
|
|||||||
const pointField& points,
|
const pointField& points,
|
||||||
const fvMesh& fromMesh,
|
const fvMesh& fromMesh,
|
||||||
const List<bool>& boundaryCell,
|
const List<bool>& boundaryCell,
|
||||||
const indexedOctree<treeDataCell>& oc
|
const indexedOctree<treeDataCell>& cellTree
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
// the implemented search method is a simple neighbour array search.
|
// the implemented search method is a simple neighbour array search.
|
||||||
@ -263,7 +263,7 @@ void Foam::meshToMesh0::cellAddresses
|
|||||||
// the octree search to find it.
|
// the octree search to find it.
|
||||||
if (boundaryCell[curCell])
|
if (boundaryCell[curCell])
|
||||||
{
|
{
|
||||||
cellAddressing_[toI] = oc.findInside(p);
|
cellAddressing_[toI] = cellTree.findInside(p);
|
||||||
|
|
||||||
if (cellAddressing_[toI] != -1)
|
if (cellAddressing_[toI] != -1)
|
||||||
{
|
{
|
||||||
@ -320,7 +320,7 @@ void Foam::meshToMesh0::cellAddresses
|
|||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
// Still not found so use the octree
|
// Still not found so use the octree
|
||||||
cellAddressing_[toI] = oc.findInside(p);
|
cellAddressing_[toI] = cellTree.findInside(p);
|
||||||
|
|
||||||
if (cellAddressing_[toI] != -1)
|
if (cellAddressing_[toI] != -1)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -116,7 +116,7 @@ class meshToMesh0
|
|||||||
const pointField& points,
|
const pointField& points,
|
||||||
const fvMesh& fromMesh,
|
const fvMesh& fromMesh,
|
||||||
const List<bool>& boundaryCell,
|
const List<bool>& boundaryCell,
|
||||||
const indexedOctree<treeDataCell>& oc
|
const indexedOctree<treeDataCell>& cellTree
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
void calculateInverseDistanceWeights() const;
|
void calculateInverseDistanceWeights() const;
|
||||||
|
|||||||
@ -107,14 +107,13 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
|
|||||||
|
|
||||||
forAll(probeLocations(), probei)
|
forAll(probeLocations(), probei)
|
||||||
{
|
{
|
||||||
|
const auto& treeData = boundaryTree.shapes();
|
||||||
const point sample = probeLocations()[probei];
|
const point sample = probeLocations()[probei];
|
||||||
|
|
||||||
const scalar span = boundaryTree.bb().mag();
|
|
||||||
|
|
||||||
pointIndexHit info = boundaryTree.findNearest
|
pointIndexHit info = boundaryTree.findNearest
|
||||||
(
|
(
|
||||||
sample,
|
sample,
|
||||||
Foam::sqr(span)
|
Foam::sqr(boundaryTree.bb().mag())
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!info.hit())
|
if (!info.hit())
|
||||||
@ -122,7 +121,7 @@ void Foam::patchProbes::findElements(const fvMesh& mesh)
|
|||||||
info = boundaryTree.findNearest(sample, Foam::sqr(GREAT));
|
info = boundaryTree.findNearest(sample, Foam::sqr(GREAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
label facei = boundaryTree.shapes().faceLabels()[info.index()];
|
const label facei = treeData.objectIndex(info.index());
|
||||||
|
|
||||||
const label patchi = bm.whichPatch(facei);
|
const label patchi = bm.whichPatch(facei);
|
||||||
|
|
||||||
|
|||||||
@ -115,9 +115,11 @@ void Foam::patchCloudSet::calcSamples
|
|||||||
|
|
||||||
forAll(sampleCoords_, sampleI)
|
forAll(sampleCoords_, sampleI)
|
||||||
{
|
{
|
||||||
|
const auto& treeData = patchTree.shapes();
|
||||||
const point& sample = sampleCoords_[sampleI];
|
const point& sample = sampleCoords_[sampleI];
|
||||||
|
|
||||||
pointIndexHit& nearInfo = nearest[sampleI].first();
|
pointIndexHit& nearInfo = nearest[sampleI].first();
|
||||||
|
auto& distSqrProc = nearest[sampleI].second();
|
||||||
|
|
||||||
// Find the nearest locally
|
// Find the nearest locally
|
||||||
if (patchFaces.size())
|
if (patchFaces.size())
|
||||||
@ -133,17 +135,18 @@ void Foam::patchCloudSet::calcSamples
|
|||||||
// Fill in the distance field and the processor field
|
// Fill in the distance field and the processor field
|
||||||
if (!nearInfo.hit())
|
if (!nearInfo.hit())
|
||||||
{
|
{
|
||||||
nearest[sampleI].second().first() = Foam::sqr(GREAT);
|
distSqrProc.first() = Foam::sqr(GREAT);
|
||||||
nearest[sampleI].second().second() = Pstream::myProcNo();
|
distSqrProc.second() = Pstream::myProcNo();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Set nearest to mesh face label
|
// Set nearest to mesh face label
|
||||||
nearInfo.setIndex(patchFaces[nearInfo.index()]);
|
const label objectIndex = treeData.objectIndex(nearInfo.index());
|
||||||
|
|
||||||
nearest[sampleI].second().first() =
|
nearInfo.setIndex(objectIndex);
|
||||||
nearInfo.point().distSqr(sample);
|
|
||||||
nearest[sampleI].second().second() = Pstream::myProcNo();
|
distSqrProc.first() = sample.distSqr(nearInfo.point());
|
||||||
|
distSqrProc.second() = Pstream::myProcNo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -136,9 +136,12 @@ void Foam::patchSeedSet::calcSamples
|
|||||||
|
|
||||||
forAll(selectedLocations_, sampleI)
|
forAll(selectedLocations_, sampleI)
|
||||||
{
|
{
|
||||||
|
const auto& treeData = boundaryTree.shapes();
|
||||||
const point& sample = selectedLocations_[sampleI];
|
const point& sample = selectedLocations_[sampleI];
|
||||||
|
|
||||||
pointIndexHit& nearInfo = nearest[sampleI].first();
|
pointIndexHit& nearInfo = nearest[sampleI].first();
|
||||||
|
auto& distSqrProc = nearest[sampleI].second();
|
||||||
|
|
||||||
nearInfo = boundaryTree.findNearest
|
nearInfo = boundaryTree.findNearest
|
||||||
(
|
(
|
||||||
sample,
|
sample,
|
||||||
@ -147,17 +150,15 @@ void Foam::patchSeedSet::calcSamples
|
|||||||
|
|
||||||
if (!nearInfo.hit())
|
if (!nearInfo.hit())
|
||||||
{
|
{
|
||||||
nearest[sampleI].second().first() = Foam::sqr(GREAT);
|
distSqrProc.first() = Foam::sqr(GREAT);
|
||||||
nearest[sampleI].second().second() =
|
distSqrProc.second() = Pstream::myProcNo();
|
||||||
Pstream::myProcNo();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
point fc(pp[nearInfo.index()].centre(pp.points()));
|
nearInfo.setPoint(treeData.centre(nearInfo.index()));
|
||||||
nearInfo.setPoint(fc);
|
|
||||||
nearest[sampleI].second().first() = sample.magSqr(fc);
|
distSqrProc.first() = sample.distSqr(nearInfo.point());
|
||||||
nearest[sampleI].second().second() =
|
distSqrProc.second() = Pstream::myProcNo();
|
||||||
Pstream::myProcNo();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -159,7 +159,8 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher)
|
|||||||
{
|
{
|
||||||
// Search for nearest cell
|
// Search for nearest cell
|
||||||
|
|
||||||
const indexedOctree<treeDataCell>& cellTree = meshSearcher.cellTree();
|
const auto& cellTree = meshSearcher.cellTree();
|
||||||
|
const auto& treeData = cellTree.shapes();
|
||||||
|
|
||||||
forAll(fc, facei)
|
forAll(fc, facei)
|
||||||
{
|
{
|
||||||
@ -170,8 +171,10 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher)
|
|||||||
|
|
||||||
if (info.hit())
|
if (info.hit())
|
||||||
{
|
{
|
||||||
|
const label objectIndex = treeData.objectIndex(info.index());
|
||||||
|
|
||||||
near.first() = info.point().distSqr(pt);
|
near.first() = info.point().distSqr(pt);
|
||||||
near.second() = globalCells.toGlobal(info.index());
|
near.second() = globalCells.toGlobal(objectIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,6 +183,7 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher)
|
|||||||
// Search for cell containing point
|
// Search for cell containing point
|
||||||
|
|
||||||
const auto& cellTree = meshSearcher.cellTree();
|
const auto& cellTree = meshSearcher.cellTree();
|
||||||
|
const auto& treeData = cellTree.shapes();
|
||||||
|
|
||||||
forAll(fc, facei)
|
forAll(fc, facei)
|
||||||
{
|
{
|
||||||
@ -189,10 +193,13 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher)
|
|||||||
if (cellTree.bb().contains(pt))
|
if (cellTree.bb().contains(pt))
|
||||||
{
|
{
|
||||||
const label index = cellTree.findInside(pt);
|
const label index = cellTree.findInside(pt);
|
||||||
|
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
{
|
{
|
||||||
|
const label objectIndex = treeData.objectIndex(index);
|
||||||
|
|
||||||
near.first() = 0;
|
near.first() = 0;
|
||||||
near.second() = globalCells.toGlobal(index);
|
near.second() = globalCells.toGlobal(objectIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,6 +210,7 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher)
|
|||||||
// on all non-coupled boundary faces
|
// on all non-coupled boundary faces
|
||||||
|
|
||||||
const auto& bndTree = meshSearcher.nonCoupledBoundaryTree();
|
const auto& bndTree = meshSearcher.nonCoupledBoundaryTree();
|
||||||
|
const auto& treeData = bndTree.shapes();
|
||||||
|
|
||||||
forAll(fc, facei)
|
forAll(fc, facei)
|
||||||
{
|
{
|
||||||
@ -213,12 +221,10 @@ bool Foam::sampledMeshedSurface::update(const meshSearch& meshSearcher)
|
|||||||
|
|
||||||
if (info.hit())
|
if (info.hit())
|
||||||
{
|
{
|
||||||
|
const label objectIndex = treeData.objectIndex(info.index());
|
||||||
|
|
||||||
near.first() = info.point().distSqr(pt);
|
near.first() = info.point().distSqr(pt);
|
||||||
near.second() =
|
near.second() = globalCells.toGlobal(objectIndex);
|
||||||
globalCells.toGlobal
|
|
||||||
(
|
|
||||||
bndTree.shapes().faceLabels()[info.index()]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user