ENH: adjustments to searchable surfaces

- code reduction, documentation, code stubs for spheroid (#1901)

- make searchableSurfaceCollection available as 'collection'
  for consistency with other objects
This commit is contained in:
Mark Olesen
2020-10-15 09:25:51 +02:00
parent f999013f41
commit 4258f8059f
26 changed files with 744 additions and 230 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -77,7 +77,8 @@ void Foam::searchableBox::projectOntoCoordPlane
FatalErrorInFunction
<< "Point on plane " << planePt
<< " is not on coordinate " << min()[dir]
<< " nor " << max()[dir] << abort(FatalError);
<< " nor " << max()[dir] << nl
<< abort(FatalError);
}
}
@ -135,31 +136,26 @@ Foam::pointIndexHit Foam::searchableBox::findNearest
// using the three near distances. Project onto the nearest plane.
if (!outside)
{
vector dist(cmptMag(info.rawPoint() - near));
const vector dist(cmptMag(info.point() - near));
direction projNorm(vector::Z);
if (dist.x() < dist.y())
{
if (dist.x() < dist.z())
{
// Project onto x plane
projectOntoCoordPlane(vector::X, near, info);
}
else
{
projectOntoCoordPlane(vector::Z, near, info);
projNorm = vector::X;
}
}
else
{
if (dist.y() < dist.z())
{
projectOntoCoordPlane(vector::Y, near, info);
}
else
{
projectOntoCoordPlane(vector::Z, near, info);
projNorm = vector::Y;
}
}
projectOntoCoordPlane(projNorm, near, info);
}
@ -194,7 +190,7 @@ Foam::searchableBox::searchableBox
<< exit(FatalError);
}
bounds() = static_cast<boundBox>(*this);
bounds() = static_cast<treeBoundBox>(*this);
}
@ -204,19 +200,12 @@ Foam::searchableBox::searchableBox
const dictionary& dict
)
:
searchableSurface(io),
treeBoundBox(dict.get<point>("min"), dict.get<point>("max"))
{
if (!treeBoundBox::valid())
{
FatalErrorInFunction
<< "Illegal bounding box specification : "
<< static_cast<const treeBoundBox>(*this) << nl
<< exit(FatalError);
}
bounds() = static_cast<boundBox>(*this);
}
searchableBox
(
io,
treeBoundBox(dict.get<point>("min"), dict.get<point>("max"))
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -257,7 +246,7 @@ void Foam::searchableBox::boundingSpheres
{
centres.setSize(size());
radiusSqr.setSize(size());
radiusSqr = 0.0;
radiusSqr = Zero;
const pointField pts(treeBoundBox::points());
const faceList& fcs = treeBoundBox::faces;
@ -527,8 +516,7 @@ void Foam::searchableBox::findLineAll
const scalarField magSqrDirVec(magSqr(dirVec));
const vectorField smallVec
(
ROOTSMALL*dirVec
+ vector(ROOTVSMALL,ROOTVSMALL,ROOTVSMALL)
ROOTSMALL*dirVec + vector::uniform(ROOTVSMALL)
);
forAll(start, pointi)

View File

@ -33,11 +33,14 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | box / searchableBox | selector |
type | box | selector |
min | minimum point for bounding box | yes |
max | maximum point for bounding box | yes |
\endtable
Note
Longer type name : \c searchableBox
SourceFiles
searchableBox.C
@ -115,6 +118,7 @@ public:
const dictionary& dict
);
//- Destructor
virtual ~searchableBox() = default;

View File

@ -122,11 +122,11 @@ void Foam::searchableCone::findNearestAndNormal
// Nearest and normal on cone. Initialise to far-away point so if not
// set it picks one of the disk points
point nearCone(GREAT, GREAT, GREAT);
point nearCone(point::uniform(GREAT));
vector normalCone(1, 0, 0);
// Nearest and normal on inner cone. Initialise to far-away point
point iCnearCone(GREAT, GREAT, GREAT);
point iCnearCone(point::uniform(GREAT));
vector iCnormalCone(1, 0, 0);
point projPt1 = point1_+ radius1_*v;

View File

@ -32,7 +32,7 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | cone / searchableCone | selector |
type | cone | selector |
point1 | coordinate of endpoint | yes |
radius1 | radius at point1 | yes |
innerRadius1| inner radius at point1 | no | 0
@ -44,6 +44,9 @@ Description
Note
Initial implementation, might suffer from robustness (e.g. radius1==radius2)
Note
Longer type name : \c searchableCone
SourceFiles
searchableCone.C

View File

@ -33,12 +33,15 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | cylinder / searchableCylinder | selector |
type | cylinder | selector |
point1 | coordinate of endpoint | yes |
point2 | coordinate of endpoint | yes |
radius | cylinder radius | yes |
\endtable
Note
Longer type name : \c searchableCylinder
SourceFiles
searchableCylinder.C

View File

@ -34,12 +34,15 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | disk / searchableDisk | selector |
type | disk | selector |
origin | centre of disk | yes |
normal | normal vector | yes |
radius | disk radius | yes |
\endtable
Note
Longer type name : \c searchableDisk
SourceFiles
searchableDisk.C

View File

@ -32,7 +32,7 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | extrudedCircle / searchableExtrudedCircle | selector |
type | extrudedCircle | selector |
file | The name of the edge mesh | yes |
radius | Search radius around the edges | yes |
\endtable
@ -42,6 +42,9 @@ Note
- Can not be used with snappyHexMesh since only implements nearest
searching.
Note
Longer type name : \c searchableExtrudedCircle
SourceFiles
searchableExtrudedCircle.C

View File

@ -80,21 +80,19 @@ Foam::pointIndexHit Foam::searchablePlane::findLine
Foam::boundBox Foam::searchablePlane::calcBounds() const
{
point max(VGREAT, VGREAT, VGREAT);
boundBox bb(boundBox::greatBox);
for (direction dir = 0; dir < vector::nComponents; dir++)
{
if (mag(normal()[dir]) - 1 < SMALL)
{
max[dir] = 0;
bb.min()[dir] = 0;
bb.max()[dir] = 0;
break;
}
}
point min = -max;
return boundBox(min, max);
return bb;
}
@ -146,10 +144,10 @@ void Foam::searchablePlane::boundingSpheres
scalarField& radiusSqr
) const
{
centres.setSize(1);
centres[0] = origin();
centres.resize(1);
radiusSqr.resize(1);
radiusSqr.setSize(1);
centres[0] = origin();
radiusSqr[0] = Foam::sqr(GREAT);
}

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,9 +35,12 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | plane / searchablePlane | selector |
type | plane | selector |
\endtable
Note
Longer type name : \c searchablePlane
SourceFiles
searchablePlane.C
@ -111,6 +115,7 @@ public:
const dictionary& dict
);
//- Destructor
virtual ~searchablePlane() = default;

View File

@ -61,30 +61,29 @@ Foam::direction Foam::searchablePlate::calcNormal(const point& span)
{
if (span[dir] < 0)
{
FatalErrorInFunction
<< "Span should have two positive and one zero entry. Now:"
<< span << exit(FatalError);
// Negative entry. Flag and exit.
normalDir = 3;
break;
}
else if (span[dir] < VSMALL)
{
if (normalDir == 3)
{
normalDir = dir;
}
else
if (normalDir != 3)
{
// Multiple zero entries. Flag and exit.
normalDir = 3;
break;
}
normalDir = dir;
}
}
if (normalDir == 3)
{
FatalErrorInFunction
<< "Span should have two positive and one zero entry. Now:"
<< span << exit(FatalError);
<< "Span should have two positive and one zero entry: "
<< span << nl
<< exit(FatalError);
}
return normalDir;
@ -246,18 +245,8 @@ Foam::searchablePlate::searchablePlate
const dictionary& dict
)
:
searchableSurface(io),
origin_(dict.get<point>("origin")),
span_(dict.get<vector>("span")),
normalDir_(calcNormal(span_))
{
DebugInFunction
<< " origin:" << origin_
<< " origin+span:" << origin_+span_
<< " normal:" << vector::componentNames[normalDir_] << nl;
bounds() = boundBox(origin_, origin_ + span_);
}
searchablePlate(io, dict.get<point>("origin"), dict.get<vector>("span"))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -266,8 +255,8 @@ const Foam::wordList& Foam::searchablePlate::regions() const
{
if (regions_.empty())
{
regions_.setSize(1);
regions_[0] = "region0";
regions_.resize(1);
regions_.first() = "region0";
}
return regions_;
}
@ -285,10 +274,10 @@ void Foam::searchablePlate::boundingSpheres
scalarField& radiusSqr
) const
{
centres.setSize(1);
centres[0] = origin_ + 0.5*span_;
centres.resize(1);
radiusSqr.resize(1);
radiusSqr.setSize(1);
centres[0] = origin_ + 0.5*span_;
radiusSqr[0] = Foam::magSqr(0.5*span_);
// Add a bit to make sure all points are tested inside
@ -298,26 +287,25 @@ void Foam::searchablePlate::boundingSpheres
Foam::tmp<Foam::pointField> Foam::searchablePlate::points() const
{
auto tpts = tmp<pointField>::New(4);
auto tpts = tmp<pointField>::New(4, origin_);
auto& pts = tpts.ref();
pts[0] = origin_;
pts[2] = origin_ + span_;
pts[2] += span_;
if (span_.x() < span_.y() && span_.x() < span_.z())
{
pts[1] = origin_ + point(0, span_.y(), 0);
pts[3] = origin_ + point(0, 0, span_.z());
pts[1].y() += span_.y();
pts[3].z() += span_.z();
}
else if (span_.y() < span_.z())
{
pts[1] = origin_ + point(span_.x(), 0, 0);
pts[3] = origin_ + point(0, 0, span_.z());
pts[1].x() += span_.x();
pts[3].z() += span_.z();
}
else
{
pts[1] = origin_ + point(span_.x(), 0, 0);
pts[3] = origin_ + point(0, span_.y(), 0);
pts[1].x() += span_.x();
pts[3].y() += span_.y();
}
return tpts;
@ -326,15 +314,7 @@ Foam::tmp<Foam::pointField> Foam::searchablePlate::points() const
bool Foam::searchablePlate::overlaps(const boundBox& bb) const
{
return
(
(origin_.x() + span_.x()) >= bb.min().x()
&& origin_.x() <= bb.max().x()
&& (origin_.y() + span_.y()) >= bb.min().y()
&& origin_.y() <= bb.max().y()
&& (origin_.z() + span_.z()) >= bb.min().z()
&& origin_.z() <= bb.max().z()
);
return bb.overlaps(bounds());
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -43,11 +43,14 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | plate / searchablePlate | selector |
origin | centre of the plate | yes |
span | The plate dimensions | yes |
type | plate | selector |
origin | The minimum corner of the plate | yes |
span | The plate dimensions | yes |
\endtable
Note
Longer type name : \c searchablePlate
SourceFiles
searchablePlate.C
@ -72,12 +75,12 @@ class searchablePlate
:
public searchableSurface
{
private:
// Private Member Data
//- The minimum corner of the plate
const point origin_;
//- The span size of the plate
const vector span_;
//- Coordinate direction which is normal
@ -144,6 +147,12 @@ public:
// Member Functions
//- The centre (origin) of the plate
inline const point& centre() const noexcept
{
return origin_;
}
//- Names of regions
virtual const wordList& regions() const;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2014 OpenFOAM Foundation
Copyright (C) 2015-2018 OpenCFD Ltd.
Copyright (C) 2015-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -55,7 +55,8 @@ namespace Foam
Foam::searchableRotatedBox::searchableRotatedBox
(
const IOobject& io,
const dictionary& dict
const vector& span,
const coordSystem::cartesian& csys
)
:
searchableSurface(io),
@ -69,21 +70,36 @@ Foam::searchableRotatedBox::searchableRotatedBox
io.db(),
io.readOpt(),
io.writeOpt(),
false //io.registerObject(),
false // never register
),
treeBoundBox(Zero, dict.get<vector>("span"))
treeBoundBox(Zero, span)
),
transform_
(
dict.get<point>("origin"),
dict.get<vector>("e3"),
dict.get<vector>("e1")
)
transform_(csys.origin(), csys.e3(), csys.e1())
{
points_ = transform_.globalPosition(box_.points());
}
Foam::searchableRotatedBox::searchableRotatedBox
(
const IOobject& io,
const dictionary& dict
)
:
searchableRotatedBox
(
io,
dict.get<vector>("span"),
coordSystem::cartesian
(
dict.get<point>("origin"),
dict.get<vector>("e3"),
dict.get<vector>("e1")
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::wordList& Foam::searchableRotatedBox::regions() const
@ -125,14 +141,10 @@ bool Foam::searchableRotatedBox::overlaps(const boundBox& bb) const
return false;
}
// 2. Check if one or more face points inside
const faceList& fcs = treeBoundBox::faces;
forAll(fcs, faceI)
// 2. Check if any corner points inside
if (bb.containsAny(points_))
{
if (bb.containsAny(points_))
{
return true;
}
return true;
}
// 3. Difficult case: all points are outside but connecting edges might
@ -141,8 +153,7 @@ bool Foam::searchableRotatedBox::overlaps(const boundBox& bb) const
const treeBoundBox treeBb(bb);
// 3a. my edges through bb faces
const edgeList& edges = treeBoundBox::edges;
for (const edge& e : edges)
for (const edge& e : treeBoundBox::edges)
{
point inter;
if (treeBb.intersects(points_[e[0]], points_[e[1]], inter))
@ -155,11 +166,11 @@ bool Foam::searchableRotatedBox::overlaps(const boundBox& bb) const
const pointField bbPoints(bb.points());
for (const face& f : fcs)
for (const face& f : treeBoundBox::faces)
{
point fc = f.centre(points_);
const point fc = f.centre(points_);
for (const edge& e : edges)
for (const edge& e : treeBoundBox::edges)
{
pointHit inter = f.intersection
(

View File

@ -46,13 +46,16 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | rotatedBox / searchableRotatedBox | selector |
type | rotatedBox | selector |
span | The box dimensions | yes |
origin | The box corner | yes |
e1 | Local x-axis of the box | yes |
e3 | Local z-axis of the box | yes |
\endtable
Note
Longer type name : \c searchableRotatedBox
SourceFiles
searchableRotatedBox.C
@ -78,8 +81,6 @@ class searchableRotatedBox
:
public searchableSurface
{
private:
// Private Member Data
//- Box in local coordinate system
@ -109,6 +110,14 @@ public:
// Constructors
//- Construct from components
searchableRotatedBox
(
const IOobject& io,
const vector& span,
const coordSystem::cartesian& csys = coordSystem::cartesian{}
);
//- Construct from dictionary (used by searchableSurface)
searchableRotatedBox
(

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -50,6 +50,95 @@ namespace Foam
}
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
// General handling
namespace Foam
{
// Dictionary entry with single scalar or vector quantity
inline static vector getRadius(const word& name, const dictionary& dict)
{
if (token(dict.lookup(name)).isNumber())
{
return vector::uniform(dict.get<scalar>(name));
}
return dict.get<vector>(name);
}
// Test point for negative components, return the sign-changes
inline static unsigned getOctant(const point& p)
{
unsigned octant = 0;
if (p.x() < 0) { octant |= 1; }
if (p.y() < 0) { octant |= 2; }
if (p.z() < 0) { octant |= 4; }
return octant;
}
// Apply sign-changes to point
inline static void applyOctant(point& p, unsigned octant)
{
if (octant & 1) { p.x() = -p.x(); }
if (octant & 2) { p.y() = -p.y(); }
if (octant & 4) { p.z() = -p.z(); }
}
} // End namespace Foam
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
inline Foam::searchableSphere::componentOrder
Foam::searchableSphere::getOrdering(const vector& radii)
{
#ifdef FULLDEBUG
for (direction cmpt = 0; cmpt < vector::nComponents; ++cmpt)
{
if (radii[cmpt] <= 0)
{
FatalErrorInFunction
<< "Radii must be positive, non-zero: " << radii << endl
<< exit(FatalError);
}
}
#endif
std::array<direction, 3> idx{0, 1, 2};
// Reverse sort by magnitude (largest first...)
// Radii are positive (checked above, or just always true)
std::stable_sort
(
idx.begin(),
idx.end(),
[&](direction a, direction b){ return radii[a] > radii[b]; }
);
componentOrder order{idx[0], idx[1], idx[2], shapeType::GENERAL};
if (equal(radii[order.major], radii[order.minor]))
{
order.shape = shapeType::SPHERE;
}
else if (equal(radii[order.major], radii[order.mezzo]))
{
order.shape = shapeType::OBLATE;
}
else if (equal(radii[order.mezzo], radii[order.minor]))
{
order.shape = shapeType::PROLATE;
}
return order;
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::pointIndexHit Foam::searchableSphere::findNearest
@ -60,23 +149,33 @@ Foam::pointIndexHit Foam::searchableSphere::findNearest
{
pointIndexHit info(false, sample, -1);
const vector n(sample - origin_);
scalar magN = mag(n);
// Handle special cases first
if (nearestDistSqr >= sqr(magN - radius_))
// if (order_.shape == shapeType::SPHERE)
if (true)
{
if (magN < ROOTVSMALL)
// Point relative to origin, simultaneously the normal on the sphere
const vector n(sample - origin_);
const scalar magN = mag(n);
// It is a sphere, all radii are identical
if (nearestDistSqr >= sqr(magN - radii_[0]))
{
info.rawPoint() = origin_ + vector(1,0,0)*radius_;
info.setPoint
(
origin_
+ (magN < ROOTVSMALL ? vector(radii_[0],0,0) : (radii_[0]*n/magN))
);
info.setHit();
info.setIndex(0);
}
else
{
info.rawPoint() = origin_ + n/magN*radius_;
}
info.setHit();
info.setIndex(0);
return info;
}
//[code]
return info;
}
@ -93,43 +192,47 @@ void Foam::searchableSphere::findLineAll
near.setMiss();
far.setMiss();
vector dir(end-start);
scalar magSqrDir = magSqr(dir);
if (magSqrDir > ROOTVSMALL)
// if (order_.shape == shapeType::SPHERE)
if (true)
{
const vector toCentre(origin_ - start);
scalar magSqrToCentre = magSqr(toCentre);
vector dir(end-start);
const scalar magSqrDir = magSqr(dir);
dir /= Foam::sqrt(magSqrDir);
scalar v = (toCentre & dir);
scalar disc = sqr(radius_) - (magSqrToCentre - sqr(v));
if (disc >= 0)
if (magSqrDir > ROOTVSMALL)
{
scalar d = Foam::sqrt(disc);
dir /= Foam::sqrt(magSqrDir);
scalar nearParam = v-d;
const vector relStart(start - origin_);
if (nearParam >= 0 && sqr(nearParam) <= magSqrDir)
const scalar v = -(relStart & dir);
const scalar disc = sqr(radius()) - (magSqr(relStart) - sqr(v));
if (disc >= 0)
{
near.setHit();
near.setPoint(start + nearParam*dir);
near.setIndex(0);
}
const scalar d = Foam::sqrt(disc);
scalar farParam = v+d;
const scalar nearParam = v - d;
const scalar farParam = v + d;
if (farParam >= 0 && sqr(farParam) <= magSqrDir)
{
far.setHit();
far.setPoint(start + farParam*dir);
far.setIndex(0);
if (nearParam >= 0 && sqr(nearParam) <= magSqrDir)
{
near.setHit();
near.setPoint(start + nearParam*dir);
near.setIndex(0);
}
if (farParam >= 0 && sqr(farParam) <= magSqrDir)
{
far.setHit();
far.setPoint(start + farParam*dir);
far.setIndex(0);
}
}
}
}
//[code]
}
@ -141,16 +244,26 @@ Foam::searchableSphere::searchableSphere
const point& origin,
const scalar radius
)
:
searchableSphere(io, origin, vector::uniform(radius))
{}
Foam::searchableSphere::searchableSphere
(
const IOobject& io,
const point& origin,
const vector& radii
)
:
searchableSurface(io),
origin_(origin),
radius_(radius)
// radii_(radii),
radii_(vector::uniform(cmptMax(radii))) /* Transition */,
order_{getOrdering(radii_)}
{
bounds() = boundBox
(
origin_ - radius_*vector::one,
origin_ + radius_*vector::one
);
bounds().min() = (centre() - radii_);
bounds().max() = (centre() + radii_);
}
@ -164,16 +277,61 @@ Foam::searchableSphere::searchableSphere
(
io,
dict.getCompat<vector>("origin", {{"centre", -1806}}),
dict.get<scalar>("radius")
getRadius("radius", dict)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::point Foam::searchableSphere::surfacePoint
(
const scalar theta,
const scalar phi
) const
{
return point
(
origin_.x() + radii_.x() * cos(theta)*sin(phi),
origin_.y() + radii_.y() * sin(theta)*sin(phi),
origin_.z() + radii_.z() * cos(phi)
);
}
Foam::vector Foam::searchableSphere::surfaceNormal
(
const scalar theta,
const scalar phi
) const
{
// Normal is (x0/r0^2, x1/r1^2, x2/r2^2)
return vector
(
cos(theta)*sin(phi) / radii_.x(),
sin(theta)*sin(phi) / radii_.y(),
cos(phi) / radii_.z()
).normalise();
}
bool Foam::searchableSphere::overlaps(const boundBox& bb) const
{
return bb.overlaps(origin_, sqr(radius_));
// if (order_.shape == shapeType::SPHERE)
if (true)
{
return bb.overlaps(origin_, sqr(radius()));
}
if (!bb.valid())
{
return false;
}
//[code]
return true;
}
@ -188,7 +346,6 @@ const Foam::wordList& Foam::searchableSphere::regions() const
}
void Foam::searchableSphere::boundingSpheres
(
pointField& centres,
@ -196,10 +353,10 @@ void Foam::searchableSphere::boundingSpheres
) const
{
centres.resize(1);
centres[0] = origin_;
radiusSqr.resize(1);
radiusSqr[0] = Foam::sqr(radius_);
centres[0] = origin_;
radiusSqr[0] = Foam::sqr(radius());
// Add a bit to make sure all points are tested inside
radiusSqr += Foam::sqr(SMALL);
@ -213,7 +370,7 @@ void Foam::searchableSphere::findNearest
List<pointIndexHit>& info
) const
{
info.setSize(samples.size());
info.resize(samples.size());
forAll(samples, i)
{
@ -229,14 +386,17 @@ void Foam::searchableSphere::findLine
List<pointIndexHit>& info
) const
{
info.setSize(start.size());
info.resize(start.size());
pointIndexHit b;
forAll(start, i)
{
// Pick nearest intersection. If none intersected take second one.
// Pick nearest intersection.
// If none intersected take second one.
findLineAll(start[i], end[i], info[i], b);
if (!info[i].hit() && b.hit())
{
info[i] = b;
@ -252,14 +412,17 @@ void Foam::searchableSphere::findLineAny
List<pointIndexHit>& info
) const
{
info.setSize(start.size());
info.resize(start.size());
pointIndexHit b;
forAll(start, i)
{
// Pick nearest intersection.
// Discard far intersection
findLineAll(start[i], end[i], info[i], b);
if (!info[i].hit() && b.hit())
{
info[i] = b;
@ -275,24 +438,25 @@ void Foam::searchableSphere::findLineAll
List<List<pointIndexHit>>& info
) const
{
info.setSize(start.size());
info.resize(start.size());
forAll(start, i)
{
pointIndexHit near, far;
findLineAll(start[i], end[i], near, far);
if (near.hit())
{
if (far.hit())
{
info[i].setSize(2);
info[i].resize(2);
info[i][0] = near;
info[i][1] = far;
}
else
{
info[i].setSize(1);
info[i].resize(1);
info[i][0] = near;
}
}
@ -300,7 +464,7 @@ void Foam::searchableSphere::findLineAll
{
if (far.hit())
{
info[i].setSize(1);
info[i].resize(1);
info[i][0] = far;
}
else
@ -318,7 +482,7 @@ void Foam::searchableSphere::getRegion
labelList& region
) const
{
region.setSize(info.size());
region.resize(info.size());
region = 0;
}
@ -329,18 +493,18 @@ void Foam::searchableSphere::getNormal
vectorField& normal
) const
{
normal.setSize(info.size());
normal = Zero;
normal.resize(info.size());
forAll(info, i)
{
if (info[i].hit())
{
normal[i] = normalised(info[i].hitPoint() - origin_);
normal[i] = normalised(info[i].point() - origin_);
}
else
{
// Set to what?
normal[i] = Zero;
}
}
}
@ -352,20 +516,26 @@ void Foam::searchableSphere::getVolumeType
List<volumeType>& volType
) const
{
volType.setSize(points.size());
volType.resize(points.size());
const scalar rad2 = sqr(radius_);
forAll(points, pointi)
// if (order_.shape == shapeType::SPHERE)
if (true)
{
const point& pt = points[pointi];
const scalar rad2 = sqr(radius());
volType[pointi] =
(
(magSqr(pt - origin_) <= rad2)
? volumeType::INSIDE : volumeType::OUTSIDE
);
forAll(points, pointi)
{
const point& p = points[pointi];
volType[pointi] =
(
(magSqr(p - origin_) <= rad2)
? volumeType::INSIDE : volumeType::OUTSIDE
);
}
}
//[code]
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,12 +33,15 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | sphere / searchableSphere | selector |
origin | The origin (centre) of the sphere | yes |
radius | The (outside) radius of sphere | yes |
centre | Alternative for 'origin' | no |
type | sphere | selector |
origin | The origin (centre) of the sphere | yes |
radius | The (outside) radius of sphere | yes |
centre | Alternative name for 'origin' | no |
\endtable
Note
Longer type name : \c searchableSphere
SourceFiles
searchableSphere.C
@ -63,15 +66,44 @@ class searchableSphere
:
public searchableSurface
{
public:
// Public Types
//- The type of shape
enum shapeType : uint8_t
{
SPHERE = 0, //!< Sphere (all components equal)
OBLATE = 1, //!< Oblate (major = mezzo > minor)
PROLATE = 2, //!< Prolate (major > mezzo = minor)
GENERAL = 3 //!< General spheroid
};
private:
// Private Member Data
// Private Types
//- Component order (largest to smallest)
struct componentOrder
{
uint8_t major; //!< Component with major radius
uint8_t mezzo; //!< Component with intermediate radius
uint8_t minor; //!< Component with minor radius
shapeType shape; //!< The type of shape
};
// Private Data
//- Centre point of the sphere
const point origin_;
//- The outer radius of the sphere
const scalar radius_;
//- The outer radii of the spheroid
const vector radii_;
//- The canonical (sorted) order and shape
const struct componentOrder order_;
//- Names of regions
mutable wordList regions_;
@ -79,6 +111,9 @@ private:
// Private Member Functions
//- Determine sorted order and classify the shape
inline static componentOrder getOrdering(const vector& radii);
//- Inherit findNearest from searchableSurface
using searchableSurface::findNearest;
@ -114,12 +149,20 @@ public:
// Constructors
//- Construct from components
//- Construct a sphere from components
searchableSphere
(
const IOobject& io,
const point& origin,
const scalar radius
);
//- Construct a spheroid from components
searchableSphere
(
const IOobject& io,
const point& centre,
const scalar radius
const vector& radii
);
//- Construct from dictionary (used by searchableSurface)
@ -136,6 +179,44 @@ public:
// Member Functions
// Geometric
//- The centre (origin) of the sphere
const point& centre() const noexcept
{
return origin_;
}
//- The radius of the sphere, or major radius of the spheroid
scalar radius() const noexcept
{
return radii_[order_.major];
}
//- The radii of the spheroid
const vector& radii() const noexcept
{
return radii_;
}
//- The type of shape
enum shapeType shape() const noexcept
{
return shapeType::SPHERE;
}
//- A point on the sphere at given location
// theta [-pi,pi], phi [0,pi]
point surfacePoint(const scalar theta, const scalar phi) const;
//- Surface normal on the sphere at given location
// theta [-pi,pi], phi [0,pi]
vector surfaceNormal(const scalar theta, const scalar phi) const;
// Searching
//- Names of regions
virtual const wordList& regions() const;
@ -228,7 +309,6 @@ public:
) const;
//- Determine type (inside/outside/mixed) for point.
// Unknown if cannot be determined (e.g. non-manifold surface)
virtual void getVolumeType
(
const pointField& points,
@ -236,14 +316,14 @@ public:
) const;
// regIOobject implementation
bool writeData(Ostream&) const
{
NotImplemented;
return false;
}
// Output
// Implementation for regIOobject. NotImplemented
bool writeData(Ostream&) const
{
NotImplemented;
return false;
}
};

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2018 OpenCFD Ltd.
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -43,6 +43,13 @@ namespace Foam
searchableSurfaceCollection,
dict
);
addNamedToRunTimeSelectionTable
(
searchableSurface,
searchableSurfaceCollection,
dict,
collection
);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015 OpenCFD Ltd.
Copyright (C) 2015-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,10 +34,13 @@ Description
\heading Dictionary parameters
\table
Property | Description | Required | Default
type | searchableSurfaceCollection | selector |
type | collection | selector |
mergeSubRegions | boolean | yes |
\endtable
Note
Longer type name : \c searchableSurfaceCollection
SourceFiles
searchableSurfaceCollection.C