/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016-2018 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 .
\*---------------------------------------------------------------------------*/
#include "boundBox.H"
#include "PstreamReduceOps.H"
#include "tmp.H"
#include "plane.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
const Foam::boundBox Foam::boundBox::greatBox
(
point::uniform(-ROOTVGREAT),
point::uniform(ROOTVGREAT)
);
const Foam::boundBox Foam::boundBox::invertedBox
(
point::uniform(ROOTVGREAT),
point::uniform(-ROOTVGREAT)
);
const Foam::faceList Foam::boundBox::faces
({
// Point and face order as per hex cellmodel
face({0, 4, 7, 3}), // 0: x-min, left
face({1, 2, 6, 5}), // 1: x-max, right
face({0, 1, 5, 4}), // 2: y-min, bottom
face({3, 7, 6, 2}), // 3: y-max, top
face({0, 3, 2, 1}), // 4: z-min, back
face({4, 5, 6, 7}) // 5: z-max, front
});
const Foam::FixedList Foam::boundBox::faceNormals
({
vector(-1, 0, 0), // 0: x-min, left
vector( 1, 0, 0), // 1: x-max, right
vector( 0, -1, 0), // 2: y-min, bottom
vector( 0, 1, 0), // 3: y-max, top
vector( 0, 0, -1), // 4: z-min, back
vector( 0, 0, 1) // 5: z-max, front
});
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::boundBox::boundBox(const UList& points, bool doReduce)
:
boundBox()
{
add(points);
if (doReduce)
{
reduce();
}
}
Foam::boundBox::boundBox(const tmp& tpoints, bool doReduce)
:
boundBox()
{
add(tpoints);
if (doReduce)
{
reduce();
}
}
Foam::boundBox::boundBox
(
const UList& points,
const labelUList& indices,
bool doReduce
)
:
boundBox()
{
add(points, indices);
if (doReduce)
{
reduce();
}
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
Foam::tmp Foam::boundBox::points() const
{
auto tpt = tmp::New(8);
auto& pt = tpt.ref();
pt[0] = min_; // min-x, min-y, min-z
pt[1] = point(max_.x(), min_.y(), min_.z()); // max-x, min-y, min-z
pt[2] = point(max_.x(), max_.y(), min_.z()); // max-x, max-y, min-z
pt[3] = point(min_.x(), max_.y(), min_.z()); // min-x, max-y, min-z
pt[4] = point(min_.x(), min_.y(), max_.z()); // min-x, min-y, max-z
pt[5] = point(max_.x(), min_.y(), max_.z()); // max-x, min-y, max-z
pt[6] = max_; // max-x, max-y, max-z
pt[7] = point(min_.x(), max_.y(), max_.z()); // min-x, max-y, max-z
return tpt;
}
Foam::tmp Foam::boundBox::faceCentres() const
{
auto tpts = tmp::New(6);
auto& pts = tpts.ref();
forAll(pts, facei)
{
pts[facei] = faceCentre(facei);
}
return tpts;
}
Foam::point Foam::boundBox::faceCentre(const direction facei) const
{
point pt = boundBox::midpoint();
if (facei > 5)
{
FatalErrorInFunction
<< "face should be [0..5]"
<< abort(FatalError);
}
switch (facei)
{
case 0: pt.x() = min().x(); break; // 0: x-min, left
case 1: pt.x() = max().x(); break; // 1: x-max, right
case 2: pt.y() = min().y(); break; // 2: y-min, bottom
case 3: pt.y() = max().y(); break; // 3: y-max, top
case 4: pt.z() = min().z(); break; // 4: z-min, back
case 5: pt.z() = max().z(); break; // 5: z-max, front
}
return pt;
}
void Foam::boundBox::inflate(const scalar s)
{
const vector ext = vector::one*s*mag();
min_ -= ext;
max_ += ext;
}
void Foam::boundBox::reduce()
{
Foam::reduce(min_, minOp());
Foam::reduce(max_, maxOp());
}
bool Foam::boundBox::intersect(const boundBox& bb)
{
min_ = ::Foam::max(min_, bb.min_);
max_ = ::Foam::min(max_, bb.max_);
return !empty();
}
bool Foam::boundBox::intersects(const plane& pln) const
{
// Require a full 3D box
if (nDim() != 3)
{
return false;
}
bool above = false;
bool below = false;
tmp tpts(points());
const auto& pts = tpts();
for (const point& p : pts)
{
if (pln.sideOfPlane(p) == plane::FRONT)
{
above = true;
}
else
{
below = true;
}
}
return (above && below);
}
bool Foam::boundBox::contains(const UList& points) const
{
if (points.empty())
{
return true;
}
for (const point& p : points)
{
if (!contains(p))
{
return false;
}
}
return true;
}
bool Foam::boundBox::containsAny(const UList& points) const
{
if (points.empty())
{
return true;
}
for (const point& p : points)
{
if (contains(p))
{
return true;
}
}
return false;
}
Foam::point Foam::boundBox::nearest(const point& pt) const
{
// Clip the point to the range of the bounding box
const scalar surfPtx = Foam::max(Foam::min(pt.x(), max_.x()), min_.x());
const scalar surfPty = Foam::max(Foam::min(pt.y(), max_.y()), min_.y());
const scalar surfPtz = Foam::max(Foam::min(pt.z(), max_.z()), min_.z());
return point(surfPtx, surfPty, surfPtz);
}
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const boundBox& bb)
{
if (os.format() == IOstream::ASCII)
{
os << bb.min_ << token::SPACE << bb.max_;
}
else
{
os.write
(
reinterpret_cast(&bb.min_),
sizeof(boundBox)
);
}
os.check(FUNCTION_NAME);
return os;
}
Foam::Istream& Foam::operator>>(Istream& is, boundBox& bb)
{
if (is.format() == IOstream::ASCII)
{
is >> bb.min_ >> bb.max_;
}
else
{
is.read
(
reinterpret_cast(&bb.min_),
sizeof(boundBox)
);
}
is.check(FUNCTION_NAME);
return is;
}
// ************************************************************************* //