openfoam/src/OpenFOAM/meshes/primitiveShapes/line/lineI.H
Mark Olesen 81b1c5021f ENH: provide low-level bound box() methods for meshShapes
- box method on meshShapes (cell,edge,face,triangle,...)
  returns a Pair<point>.

  Can be used directly without dependency on boundBox,
  but the limits can also passed through to boundBox.

- Direct box calculation for cell, which walks the cell-faces and
  mesh-faces.  Direct calculation for face (#2609)
2022-10-12 12:54:39 +02:00

369 lines
9.0 KiB
C++

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "zero.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::linePoints::linePoints(const linePointRef& pts)
:
Pair<point>(pts.a(), pts.b())
{}
inline Foam::linePoints::linePoints
(
const UList<point>& points,
const FixedList<label, 2>& indices
)
:
Pair<point>(points[indices.first()], points[indices.last()])
{}
template<class Point, class PointRef>
inline Foam::line<Point, PointRef>::line
(
const Point& from,
const Point& to
)
:
a_(from),
b_(to)
{}
template<class Point, class PointRef>
inline Foam::line<Point, PointRef>::line
(
const UList<Point>& points,
const FixedList<label, 2>& indices
)
:
a_(points[indices.first()]),
b_(points[indices.last()])
{}
template<class Point, class PointRef>
inline Foam::line<Point, PointRef>::line(Istream& is)
{
is >> *this;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline Foam::linePointRef Foam::linePoints::ln() const
{
return linePointRef(a(), b());
}
template<class Point, class PointRef>
inline Point Foam::line<Point, PointRef>::centre() const
{
return 0.5*(a_ + b_);
}
inline Foam::point Foam::linePoints::centre() const
{
return 0.5*(a() + b());
}
template<class Point, class PointRef>
inline Foam::scalar Foam::line<Point, PointRef>::mag() const
{
return ::Foam::mag(b() - a());
}
inline Foam::scalar Foam::linePoints::mag() const
{
return ::Foam::mag(b() - a());
}
template<class Point, class PointRef>
inline Point Foam::line<Point, PointRef>::vec() const
{
return (b() - a());
}
inline Foam::vector Foam::linePoints::vec() const
{
return (b() - a());
}
template<class Point, class PointRef>
inline Point Foam::line<Point, PointRef>::unitVec() const
{
const Point v = (b_ - a_);
const scalar s(::Foam::mag(v));
return s < ROOTVSMALL ? Zero : v/s;
}
inline Foam::vector Foam::linePoints::unitVec() const
{
return normalised(b() - a());
}
template<class Point, class PointRef>
inline Foam::Pair<Point> Foam::line<Point, PointRef>::box
(
const Point& p0,
const Point& p1
)
{
return Pair<Point>(min(p0, p1), max(p0, p1));
}
template<class Point, class PointRef>
inline Foam::Pair<Point> Foam::line<Point, PointRef>::box() const
{
return line<Point, PointRef>::box(a_, b_);
}
inline Foam::Pair<Foam::point> Foam::linePoints::box() const
{
return linePointRef::box(a(), b());
}
template<class Point, class PointRef>
Foam::PointHit<Point> Foam::line<Point, PointRef>::nearestDist
(
const Point& p
) const
{
Point v = vec();
Point w(p - a_);
const scalar c1 = v & w;
if (c1 <= 0)
{
return PointHit<Point>(false, a_, Foam::mag(p - a_), true);
}
const scalar c2 = v & v;
if (c2 <= c1)
{
return PointHit<Point>(false, b_, Foam::mag(p - b_), true);
}
const scalar b = c1/c2;
Point pb(a_ + b*v);
return PointHit<Point>(true, pb, Foam::mag(p - pb), false);
}
template<class Point, class PointRef>
Foam::scalar Foam::line<Point, PointRef>::nearestDist
(
const line<Point, const Point&>& edge,
Point& thisPt,
Point& edgePt
) const
{
// From Mathworld Line-Line distance/(Gellert et al. 1989, p. 538).
Point a(end() - start());
Point b(edge.end() - edge.start());
Point c(edge.start() - start());
Point crossab = a ^ b;
const scalar magCrossSqr = Foam::magSqr(crossab);
if (magCrossSqr > VSMALL)
{
scalar s = ((c ^ b) & crossab)/magCrossSqr;
scalar t = ((c ^ a) & crossab)/magCrossSqr;
// Check for end points outside of range 0..1
if (s >= 0 && s <= 1 && t >= 0 && t <= 1)
{
// Both inside range 0..1
thisPt = start() + a*s;
edgePt = edge.start() + b*t;
}
else
{
// Do brute force. Distance of everything to everything.
// Can quite possibly be improved!
// From edge endpoints to *this
PointHit<Point> this0(nearestDist(edge.start()));
PointHit<Point> this1(nearestDist(edge.end()));
scalar thisDist = min(this0.distance(), this1.distance());
// From *this to edge
PointHit<Point> edge0(edge.nearestDist(start()));
PointHit<Point> edge1(edge.nearestDist(end()));
scalar edgeDist = min(edge0.distance(), edge1.distance());
if (thisDist < edgeDist)
{
if (this0.distance() < this1.distance())
{
thisPt = this0.point();
edgePt = edge.start();
}
else
{
thisPt = this1.point();
edgePt = edge.end();
}
}
else
{
if (edge0.distance() < edge1.distance())
{
thisPt = start();
edgePt = edge0.point();
}
else
{
thisPt = end();
edgePt = edge1.point();
}
}
}
}
else
{
// Parallel lines. Find overlap of both lines by projecting onto
// direction vector (now equal for both lines).
scalar edge0 = edge.start() & a;
scalar edge1 = edge.end() & a;
bool edgeOrder = edge0 < edge1;
scalar minEdge = (edgeOrder ? edge0 : edge1);
scalar maxEdge = (edgeOrder ? edge1 : edge0);
const Point& minEdgePt = (edgeOrder ? edge.start() : edge.end());
const Point& maxEdgePt = (edgeOrder ? edge.end() : edge.start());
scalar this0 = start() & a;
scalar this1 = end() & a;
bool thisOrder = this0 < this1;
scalar minThis = min(this0, this1);
scalar maxThis = max(this1, this0);
const Point& minThisPt = (thisOrder ? start() : end());
const Point& maxThisPt = (thisOrder ? end() : start());
if (maxEdge < minThis)
{
// edge completely below *this
edgePt = maxEdgePt;
thisPt = minThisPt;
}
else if (maxEdge < maxThis)
{
// maxEdge inside interval of *this
edgePt = maxEdgePt;
thisPt = nearestDist(edgePt).point();
}
else
{
// maxEdge outside. Check if minEdge inside.
if (minEdge < minThis)
{
// Edge completely envelops this. Take any this point and
// determine nearest on edge.
thisPt = minThisPt;
edgePt = edge.nearestDist(thisPt).point();
}
else if (minEdge < maxThis)
{
// minEdge inside this interval.
edgePt = minEdgePt;
thisPt = nearestDist(edgePt).point();
}
else
{
// minEdge outside this interval
edgePt = minEdgePt;
thisPt = maxThisPt;
}
}
}
return Foam::mag(thisPt - edgePt);
}
// * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * * //
template<class Point, class PointRef>
inline Foam::Istream& Foam::operator>>
(
Istream& is,
line<Point, PointRef>& l
)
{
is.readBegin("line");
is >> l.a_ >> l.b_;
is.readEnd("line");
is.check(FUNCTION_NAME);
return is;
}
template<class Point, class PointRef>
inline Foam::Ostream& Foam::operator<<
(
Ostream& os,
const line<Point, PointRef>& l
)
{
os << token::BEGIN_LIST
<< l.a_ << token::SPACE
<< l.b_
<< token::END_LIST;
return os;
}
// ************************************************************************* //