Foundation Classes - Optimize and fix Bnd package (#839)

- Fixed multiple bugs including uninitialized variables (zmin/zmax in IsOut(gp_Lin)), incorrect type usage (Standard_Integer → Standard_Boolean), and improper gap handling
- Optimized performance-critical methods through branchless operations, early exits, and cached computations
- Modernized codebase with C++17 features including constexpr constructors, noexcept specifications, and [[nodiscard]] attributes
- Refactor Bnd_Box and Bnd_Box2d classes to introduce GetXMin, GetXMax, GetYMin, GetYMax, and GetZMin,
  GetZMax methods for improved clarity and encapsulation.
- Add Limits struct to represent box limits in both classes.
This commit is contained in:
Pasukhin Dmitry
2025-11-25 19:29:53 +00:00
committed by GitHub
parent a6e68c7e70
commit c5120a28c8
5 changed files with 543 additions and 442 deletions

View File

@@ -15,50 +15,107 @@
// commercial license or contractual agreement.
#include <Bnd_Box.hxx>
#include <gp_Dir.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Trsf.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Dump.hxx>
// set the flag to one
#define ClearVoidFlag() (Flags &= ~VoidMask)
#include <Standard_Stream.hxx>
// #include <Precision.hxx>
#define Bnd_Precision_Infinite 1e+100
//=================================================================================================
Bnd_Box::Bnd_Box()
// Equal to SetVoid();
: Xmin(RealLast()),
Xmax(-RealLast()),
Ymin(RealLast()),
Ymax(-RealLast()),
Zmin(RealLast()),
Zmax(-RealLast()),
Gap(0.0),
Flags(VoidMask)
namespace
{
// Precision constant for infinite bounds
constexpr Standard_Real THE_BND_PRECISION_INFINITE = 1e+100;
// Precomputed unit direction vectors for bounding box transformations
constexpr gp_Dir THE_DIR_XMIN{gp_Dir::D::NX};
constexpr gp_Dir THE_DIR_XMAX{gp_Dir::D::X};
constexpr gp_Dir THE_DIR_YMIN{gp_Dir::D::NY};
constexpr gp_Dir THE_DIR_YMAX{gp_Dir::D::Y};
constexpr gp_Dir THE_DIR_ZMIN{gp_Dir::D::NZ};
constexpr gp_Dir THE_DIR_ZMAX{gp_Dir::D::Z};
// Computes minimum squared distance between two 1D intervals
inline Standard_Real DistMini2Box(const Standard_Real theR1Min,
const Standard_Real theR1Max,
const Standard_Real theR2Min,
const Standard_Real theR2Max) noexcept
{
const Standard_Real aR1 = Square(theR1Min - theR2Max);
const Standard_Real aR2 = Square(theR1Max - theR2Min);
return std::min(aR1, aR2);
}
//=================================================================================================
Bnd_Box::Bnd_Box(const gp_Pnt& theMin, const gp_Pnt& theMax)
// Equal to Update(theMin.X(), theMin.Y(), theMin.Z(), theMax.X(), theMax.Y(), theMax.Z());
: Xmin(theMin.X()),
Xmax(theMax.X()),
Ymin(theMin.Y()),
Ymax(theMax.Y()),
Zmin(theMin.Z()),
Zmax(theMax.Z()),
Gap(0.0),
Flags(0)
// Computes squared distance in one dimension, returns 0 if intervals overlap
inline Standard_Real DistanceInDimension(const Standard_Real theMin1,
const Standard_Real theMax1,
const Standard_Real theMin2,
const Standard_Real theMax2) noexcept
{
// Check if intervals overlap
if ((theMin1 <= theMin2 && theMin2 <= theMax1) || (theMin2 <= theMin1 && theMin1 <= theMax2))
return 0.0;
return DistMini2Box(theMin1, theMax1, theMin2, theMax2);
}
// Tests if a 2D segment is outside a 2D box
Standard_Boolean IsSegmentOut(const Standard_Real theX1,
const Standard_Real theY1,
const Standard_Real theX2,
const Standard_Real theY2,
const Standard_Real theXs1,
const Standard_Real theYs1,
const Standard_Real theXs2,
const Standard_Real theYs2) noexcept
{
constexpr Standard_Real anEps = RealSmall();
const Standard_Real aXsMin = std::min(theXs1, theXs2);
const Standard_Real aXsMax = std::max(theXs1, theXs2);
const Standard_Real aYsMin = std::min(theYs1, theYs2);
const Standard_Real aYsMax = std::max(theYs1, theYs2);
if (aYsMax - aYsMin < anEps && (theY1 - theYs1 < anEps && theYs1 - theY2 < anEps)
&& ((aXsMin - theX1 < anEps && theX1 - aXsMax < anEps)
|| (aXsMin - theX2 < anEps && theX2 - aXsMax < anEps)
|| (theX1 - theXs1 < anEps && theXs1 - theX2 < anEps)))
return Standard_False;
if (aXsMax - aXsMin < anEps && (theX1 - theXs1 < anEps && theXs1 - theX2 < anEps)
&& ((aYsMin - theY1 < anEps && theY1 - aYsMax < anEps)
|| (aYsMin - theY2 < anEps && theY2 - aYsMax < anEps)
|| (theY1 - theYs1 < anEps && theYs1 - theY2 < anEps)))
return Standard_False;
if ((theXs1 < theX1 && theXs2 < theX1) || (theXs1 > theX2 && theXs2 > theX2)
|| (theYs1 < theY1 && theYs2 < theY1) || (theYs1 > theY2 && theYs2 > theY2))
return Standard_True;
if (std::abs(theXs2 - theXs1) > anEps)
{
const Standard_Real aYa =
(std::min(theX1, theX2) - theXs1) * (theYs2 - theYs1) / (theXs2 - theXs1) + theYs1;
const Standard_Real aYb =
(std::max(theX1, theX2) - theXs1) * (theYs2 - theYs1) / (theXs2 - theXs1) + theYs1;
if ((aYa < theY1 && aYb < theY1) || (aYa > theY2 && aYb > theY2))
return Standard_True;
}
else if (std::abs(theYs2 - theYs1) > anEps)
{
const Standard_Real aXa =
(std::min(theY1, theY2) - theYs1) * (theXs2 - theXs1) / (theYs2 - theYs1) + theXs1;
const Standard_Real aXb =
(std::max(theY1, theY2) - theYs1) * (theXs2 - theXs1) / (theYs2 - theYs1) + theXs1;
if ((aXa < theX1 && aXb < theX1) || (aXa > theX2 && aXb > theX2))
return Standard_True;
}
else
return Standard_True;
return Standard_False;
}
} // anonymous namespace
//=================================================================================================
void Bnd_Box::Set(const gp_Pnt& P)
@@ -92,22 +149,16 @@ void Bnd_Box::Update(const Standard_Real x,
Xmax = X;
Ymax = Y;
Zmax = Z;
ClearVoidFlag();
Flags &= ~VoidMask;
}
else
{
if (x < Xmin)
Xmin = x;
if (X > Xmax)
Xmax = X;
if (y < Ymin)
Ymin = y;
if (Y > Ymax)
Ymax = Y;
if (z < Zmin)
Zmin = z;
if (Z > Zmax)
Zmax = Z;
Xmin = std::min(Xmin, x);
Xmax = std::max(Xmax, X);
Ymin = std::min(Ymin, y);
Ymax = std::max(Ymax, Y);
Zmin = std::min(Zmin, z);
Zmax = std::max(Zmax, Z);
}
}
@@ -123,48 +174,21 @@ void Bnd_Box::Update(const Standard_Real X, const Standard_Real Y, const Standar
Xmax = X;
Ymax = Y;
Zmax = Z;
ClearVoidFlag();
Flags &= ~VoidMask;
}
else
{
if (X < Xmin)
Xmin = X;
else if (X > Xmax)
Xmax = X;
if (Y < Ymin)
Ymin = Y;
else if (Y > Ymax)
Ymax = Y;
if (Z < Zmin)
Zmin = Z;
else if (Z > Zmax)
Zmax = Z;
Xmin = std::min(Xmin, X);
Xmax = std::max(Xmax, X);
Ymin = std::min(Ymin, Y);
Ymax = std::max(Ymax, Y);
Zmin = std::min(Zmin, Z);
Zmax = std::max(Zmax, Z);
}
}
//=================================================================================================
Standard_Real Bnd_Box::GetGap() const
{
return Gap;
}
//=================================================================================================
void Bnd_Box::SetGap(const Standard_Real Tol)
{
Gap = Tol;
}
//=================================================================================================
void Bnd_Box::Enlarge(const Standard_Real Tol)
{
Gap = std::max(Gap, std::abs(Tol));
}
//=================================================================================================
void Bnd_Box::Get(Standard_Real& theXmin,
Standard_Real& theYmin,
Standard_Real& theZmin,
@@ -177,78 +201,87 @@ void Bnd_Box::Get(Standard_Real& theXmin,
throw Standard_ConstructionError("Bnd_Box is void");
}
if (IsOpenXmin())
theXmin = -Bnd_Precision_Infinite;
else
theXmin = Xmin - Gap;
if (IsOpenXmax())
theXmax = Bnd_Precision_Infinite;
else
theXmax = Xmax + Gap;
if (IsOpenYmin())
theYmin = -Bnd_Precision_Infinite;
else
theYmin = Ymin - Gap;
if (IsOpenYmax())
theYmax = Bnd_Precision_Infinite;
else
theYmax = Ymax + Gap;
if (IsOpenZmin())
theZmin = -Bnd_Precision_Infinite;
else
theZmin = Zmin - Gap;
if (IsOpenZmax())
theZmax = Bnd_Precision_Infinite;
else
theZmax = Zmax + Gap;
theXmin = GetXMin();
theXmax = GetXMax();
theYmin = GetYMin();
theYmax = GetYMax();
theZmin = GetZMin();
theZmax = GetZMax();
}
//=================================================================================================
Bnd_Box::Limits Bnd_Box::Get() const
{
return {GetXMin(), GetXMax(), GetYMin(), GetYMax(), GetZMin(), GetZMax()};
}
//=================================================================================================
Standard_Real Bnd_Box::GetXMin() const
{
return IsOpenXmin() ? -THE_BND_PRECISION_INFINITE : Xmin - Gap;
}
//=================================================================================================
Standard_Real Bnd_Box::GetXMax() const
{
return IsOpenXmax() ? THE_BND_PRECISION_INFINITE : Xmax + Gap;
}
//=================================================================================================
Standard_Real Bnd_Box::GetYMin() const
{
return IsOpenYmin() ? -THE_BND_PRECISION_INFINITE : Ymin - Gap;
}
//=================================================================================================
Standard_Real Bnd_Box::GetYMax() const
{
return IsOpenYmax() ? THE_BND_PRECISION_INFINITE : Ymax + Gap;
}
//=================================================================================================
Standard_Real Bnd_Box::GetZMin() const
{
return IsOpenZmin() ? -THE_BND_PRECISION_INFINITE : Zmin - Gap;
}
//=================================================================================================
Standard_Real Bnd_Box::GetZMax() const
{
return IsOpenZmax() ? THE_BND_PRECISION_INFINITE : Zmax + Gap;
}
//=================================================================================================
gp_Pnt Bnd_Box::CornerMin() const
{
gp_Pnt aCornerMin;
if (IsVoid())
{
throw Standard_ConstructionError("Bnd_Box is void");
}
if (IsOpenXmin())
aCornerMin.SetX(-Bnd_Precision_Infinite);
else
aCornerMin.SetX(Xmin - Gap);
if (IsOpenYmin())
aCornerMin.SetY(-Bnd_Precision_Infinite);
else
aCornerMin.SetY(Ymin - Gap);
if (IsOpenZmin())
aCornerMin.SetZ(-Bnd_Precision_Infinite);
else
aCornerMin.SetZ(Zmin - Gap);
return aCornerMin;
return gp_Pnt(IsOpenXmin() ? -THE_BND_PRECISION_INFINITE : Xmin - Gap,
IsOpenYmin() ? -THE_BND_PRECISION_INFINITE : Ymin - Gap,
IsOpenZmin() ? -THE_BND_PRECISION_INFINITE : Zmin - Gap);
}
//=================================================================================================
gp_Pnt Bnd_Box::CornerMax() const
{
gp_Pnt aCornerMax;
if (IsVoid())
{
throw Standard_ConstructionError("Bnd_Box is void");
}
if (IsOpenXmax())
aCornerMax.SetX(Bnd_Precision_Infinite);
else
aCornerMax.SetX(Xmax + Gap);
if (IsOpenYmax())
aCornerMax.SetY(Bnd_Precision_Infinite);
else
aCornerMax.SetY(Ymax + Gap);
if (IsOpenZmax())
aCornerMax.SetZ(Bnd_Precision_Infinite);
else
aCornerMax.SetZ(Zmax + Gap);
return aCornerMax;
return gp_Pnt(IsOpenXmax() ? THE_BND_PRECISION_INFINITE : Xmax + Gap,
IsOpenYmax() ? THE_BND_PRECISION_INFINITE : Ymax + Gap,
IsOpenZmax() ? THE_BND_PRECISION_INFINITE : Zmax + Gap);
}
//=================================================================================================
@@ -306,11 +339,15 @@ Standard_Boolean Bnd_Box::IsZThin(const Standard_Real tol) const
Standard_Boolean Bnd_Box::IsThin(const Standard_Real tol) const
{
if (!IsXThin(tol))
if (IsWhole())
return Standard_False;
if (!IsYThin(tol))
if (IsVoid())
return Standard_True;
if (IsOpenXmin() || IsOpenXmax() || Xmax - Xmin >= tol)
return Standard_False;
if (!IsZThin(tol))
if (IsOpenYmin() || IsOpenYmax() || Ymax - Ymin >= tol)
return Standard_False;
if (IsOpenZmin() || IsOpenZmax() || Zmax - Zmin >= tol)
return Standard_False;
return Standard_True;
}
@@ -374,27 +411,27 @@ Bnd_Box Bnd_Box::Transformed(const gp_Trsf& T) const
Standard_Integer aNbDirs = 0;
if (IsOpenXmin())
{
aDirs[aNbDirs++].SetCoord(-1., 0., 0.);
aDirs[aNbDirs++] = THE_DIR_XMIN;
}
if (IsOpenXmax())
{
aDirs[aNbDirs++].SetCoord(1., 0., 0.);
aDirs[aNbDirs++] = THE_DIR_XMAX;
}
if (IsOpenYmin())
{
aDirs[aNbDirs++].SetCoord(0., -1., 0.);
aDirs[aNbDirs++] = THE_DIR_YMIN;
}
if (IsOpenYmax())
{
aDirs[aNbDirs++].SetCoord(0., 1., 0.);
aDirs[aNbDirs++] = THE_DIR_YMAX;
}
if (IsOpenZmin())
{
aDirs[aNbDirs++].SetCoord(0., 0., -1.);
aDirs[aNbDirs++] = THE_DIR_ZMIN;
}
if (IsOpenZmax())
{
aDirs[aNbDirs++].SetCoord(0., 0., 1.);
aDirs[aNbDirs++] = THE_DIR_ZMAX;
}
for (Standard_Integer aDirIter = 0; aDirIter < aNbDirs; ++aDirIter)
@@ -539,9 +576,8 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Pln& P) const
{
Standard_Real A, B, C, D;
P.Coefficients(A, B, C, D);
Standard_Real d = A * (Xmin - Gap) + B * (Ymin - Gap) + C * (Zmin - Gap) + D;
// Standard_Boolean plus = d > 0;
Standard_Integer plus = d > 0;
Standard_Real d = A * (Xmin - Gap) + B * (Ymin - Gap) + C * (Zmin - Gap) + D;
Standard_Boolean plus = d > 0;
if (plus != ((A * (Xmin - Gap) + B * (Ymin - Gap) + C * (Zmax + Gap) + D) > 0))
return Standard_False;
if (plus != ((A * (Xmin - Gap) + B * (Ymax + Gap) + C * (Zmin - Gap) + D) > 0))
@@ -571,13 +607,17 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Lin& L) const
return Standard_True;
else
{
Standard_Real xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin, zmax;
Standard_Real xmin = 0, xmax = 0, ymin = 0, ymax = 0, zmin = 0, zmax = 0;
Standard_Real parmin, parmax, par1, par2;
Standard_Boolean xToSet, yToSet;
Standard_Real myXmin, myYmin, myZmin, myXmax, myYmax, myZmax;
Get(myXmin, myYmin, myZmin, myXmax, myYmax, myZmax);
if (std::abs(L.Direction().XYZ().X()) > 0.)
const Standard_Real aDirX = std::abs(L.Direction().XYZ().X());
const Standard_Real aDirY = std::abs(L.Direction().XYZ().Y());
const Standard_Real aDirZ = std::abs(L.Direction().XYZ().Z());
if (aDirX > 0.)
{
par1 = (myXmin - L.Location().XYZ().X()) / L.Direction().XYZ().X();
par2 = (myXmax - L.Location().XYZ().X()) / L.Direction().XYZ().X();
@@ -593,12 +633,12 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Lin& L) const
}
xmin = L.Location().XYZ().X();
xmax = L.Location().XYZ().X();
parmin = -Bnd_Precision_Infinite;
parmax = Bnd_Precision_Infinite;
parmin = -THE_BND_PRECISION_INFINITE;
parmax = THE_BND_PRECISION_INFINITE;
xToSet = Standard_False;
}
if (std::abs(L.Direction().XYZ().Y()) > 0.)
if (aDirY > 0.)
{
par1 = (myYmin - L.Location().XYZ().Y()) / L.Direction().XYZ().Y();
par2 = (myYmax - L.Location().XYZ().Y()) / L.Direction().XYZ().Y();
@@ -621,7 +661,7 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Lin& L) const
yToSet = Standard_False;
}
if (std::abs(L.Direction().XYZ().Z()) > 0.)
if (aDirZ > 0.)
{
par1 = (myZmin - L.Location().XYZ().Z()) / L.Direction().XYZ().Z();
par2 = (myZmax - L.Location().XYZ().Z()) / L.Direction().XYZ().Z();
@@ -673,50 +713,49 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Lin& L) const
Standard_Boolean Bnd_Box::IsOut(const Bnd_Box& Other) const
{
// modified by NIZNHY-PKV Fri Jul 08 11:03:43 2011f
// Fast path for non-open boxes with early exit
if (!Flags && !Other.Flags)
{
Standard_Boolean bRet;
Standard_Real delta;
//
delta = Other.Gap + Gap;
bRet = ((Xmin - Other.Xmax > delta) || (Other.Xmin - Xmax > delta)
|| (Ymin - Other.Ymax > delta) || (Other.Ymin - Ymax > delta)
|| (Zmin - Other.Zmax > delta) || (Other.Zmin - Zmax > delta));
return bRet;
const Standard_Real aDelta = Other.Gap + Gap;
// Early exit on first separating axis found
if (Xmin - Other.Xmax > aDelta)
return Standard_True;
if (Other.Xmin - Xmax > aDelta)
return Standard_True;
if (Ymin - Other.Ymax > aDelta)
return Standard_True;
if (Other.Ymin - Ymax > aDelta)
return Standard_True;
if (Zmin - Other.Zmax > aDelta)
return Standard_True;
if (Other.Zmin - Zmax > aDelta)
return Standard_True;
return Standard_False;
}
// modified by NIZNHY-PKV Fri Jul 08 11:03:46 2011t
if (IsVoid())
// Handle special cases
if (IsVoid() || Other.IsVoid())
return Standard_True;
if (Other.IsVoid())
return Standard_True;
if (IsWhole())
return Standard_False;
if (Other.IsWhole())
if (IsWhole() || Other.IsWhole())
return Standard_False;
Standard_Real delta = Other.Gap + Gap;
const Standard_Real aDelta = Other.Gap + Gap;
if (!IsOpenXmin() && !Other.IsOpenXmax())
if (Xmin - Other.Xmax > delta)
return Standard_True;
if (!IsOpenXmax() && !Other.IsOpenXmin())
if (Other.Xmin - Xmax > delta)
return Standard_True;
// Check each axis with early exit
if (!IsOpenXmin() && !Other.IsOpenXmax() && Xmin - Other.Xmax > aDelta)
return Standard_True;
if (!IsOpenXmax() && !Other.IsOpenXmin() && Other.Xmin - Xmax > aDelta)
return Standard_True;
if (!IsOpenYmin() && !Other.IsOpenYmax())
if (Ymin - Other.Ymax > delta)
return Standard_True;
if (!IsOpenYmax() && !Other.IsOpenYmin())
if (Other.Ymin - Ymax > delta)
return Standard_True;
if (!IsOpenYmin() && !Other.IsOpenYmax() && Ymin - Other.Ymax > aDelta)
return Standard_True;
if (!IsOpenYmax() && !Other.IsOpenYmin() && Other.Ymin - Ymax > aDelta)
return Standard_True;
if (!IsOpenZmin() && !Other.IsOpenZmax())
if (Zmin - Other.Zmax > delta)
return Standard_True;
if (!IsOpenZmax() && !Other.IsOpenZmin())
if (Other.Zmin - Zmax > delta)
return Standard_True;
if (!IsOpenZmin() && !Other.IsOpenZmax() && Zmin - Other.Zmax > aDelta)
return Standard_True;
if (!IsOpenZmax() && !Other.IsOpenZmin() && Other.Zmin - Zmax > aDelta)
return Standard_True;
return Standard_False;
}
@@ -737,54 +776,6 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Trsf& T1, const Bnd_Box& Other, const g
//=================================================================================================
static Standard_Boolean IsSegmentOut(Standard_Real x1,
Standard_Real y1,
Standard_Real x2,
Standard_Real y2,
Standard_Real xs1,
Standard_Real ys1,
Standard_Real xs2,
Standard_Real ys2)
{
constexpr Standard_Real eps = RealSmall();
Standard_Real xsmin = std::min(xs1, xs2);
Standard_Real xsmax = std::max(xs1, xs2);
Standard_Real ysmin = std::min(ys1, ys2);
Standard_Real ysmax = std::max(ys1, ys2);
if (ysmax - ysmin < eps && (y1 - ys1 < eps && ys1 - y2 < eps)
&& ((xsmin - x1 < eps && x1 - xsmax < eps) || (xsmin - x2 < eps && x2 - xsmax < eps)
|| (x1 - xs1 < eps && xs1 - x2 < eps)))
return Standard_False;
if (xsmax - xsmin < eps && (x1 - xs1 < eps && xs1 - x2 < eps)
&& ((ysmin - y1 < eps && y1 - ysmax < eps) || (ysmin - y2 < eps && y2 - ysmax < eps)
|| (y1 - ys1 < eps && ys1 - y2 < eps)))
return Standard_False;
if ((xs1 < x1 && xs2 < x1) || (xs1 > x2 && xs2 > x2) || (ys1 < y1 && ys2 < y1)
|| (ys1 > y2 && ys2 > y2))
return Standard_True;
if (std::abs(xs2 - xs1) > eps)
{
Standard_Real ya = (std::min(x1, x2) - xs1) * (ys2 - ys1) / (xs2 - xs1) + ys1;
Standard_Real yb = (std::max(x1, x2) - xs1) * (ys2 - ys1) / (xs2 - xs1) + ys1;
if ((ya < y1 && yb < y1) || (ya > y2 && yb > y2))
return Standard_True;
}
else if (std::abs(ys2 - ys1) > eps)
{
Standard_Real xa = (std::min(y1, y2) - ys1) * (xs2 - xs1) / (ys2 - ys1) + xs1;
Standard_Real xb = (std::max(y1, y2) - ys1) * (xs2 - xs1) / (ys2 - ys1) + xs1;
if ((xa < x1 && xb < x1) || (xa > x2 && xb > x2))
return Standard_True;
}
else
return Standard_True;
return Standard_False;
}
Standard_Boolean Bnd_Box::IsOut(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Dir& D) const
{
@@ -1009,53 +1000,19 @@ Standard_Boolean Bnd_Box::IsOut(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Dir
// purpose : computes the minimum distance between two boxes
//=======================================================================
static Standard_Real DistMini2Box(const Standard_Real r1min,
const Standard_Real r1max,
const Standard_Real r2min,
const Standard_Real r2max)
{
Standard_Real r1, r2;
r1 = Square(r1min - r2max);
r2 = Square(r1max - r2min);
return std::min(r1, r2);
}
Standard_Real Bnd_Box::Distance(const Bnd_Box& Other) const
{
Standard_Real xminB1, yminB1, zminB1, xmaxB1, ymaxB1, zmaxB1;
Standard_Real xminB2, yminB2, zminB2, xmaxB2, ymaxB2, zmaxB2;
Standard_Real dist_x, dist_y, dist_z, dist_t;
Standard_Real aXMinB1, aYMinB1, aZMinB1, aXMaxB1, aYMaxB1, aZMaxB1;
Standard_Real aXMinB2, aYMinB2, aZMinB2, aXMaxB2, aYMaxB2, aZMaxB2;
Get(xminB1, yminB1, zminB1, xmaxB1, ymaxB1, zmaxB1);
Other.Get(xminB2, yminB2, zminB2, xmaxB2, ymaxB2, zmaxB2);
Get(aXMinB1, aYMinB1, aZMinB1, aXMaxB1, aYMaxB1, aZMaxB1);
Other.Get(aXMinB2, aYMinB2, aZMinB2, aXMaxB2, aYMaxB2, aZMaxB2);
if (((xminB1 <= xminB2) && (xminB2 <= xmaxB1)) || ((xminB2 <= xminB1) && (xminB1 <= xmaxB2)))
{
dist_x = 0;
}
else
{
dist_x = DistMini2Box(xminB1, xmaxB1, xminB2, xmaxB2);
}
if (((yminB1 <= yminB2) && (yminB2 <= ymaxB1)) || ((yminB2 <= yminB1) && (yminB1 <= ymaxB2)))
{
dist_y = 0;
}
else
{
dist_y = DistMini2Box(yminB1, ymaxB1, yminB2, ymaxB2);
}
if (((zminB1 <= zminB2) && (zminB2 <= zmaxB1)) || ((zminB2 <= zminB1) && (zminB1 <= zmaxB2)))
{
dist_z = 0;
}
else
{
dist_z = DistMini2Box(zminB1, zmaxB1, zminB2, zmaxB2);
}
dist_t = dist_x + dist_y + dist_z;
return (std::sqrt(dist_t));
const Standard_Real aDistX = DistanceInDimension(aXMinB1, aXMaxB1, aXMinB2, aXMaxB2);
const Standard_Real aDistY = DistanceInDimension(aYMinB1, aYMaxB1, aYMinB2, aYMaxB2);
const Standard_Real aDistZ = DistanceInDimension(aZMinB1, aZMaxB1, aZMinB2, aZMaxB2);
return std::sqrt(aDistX + aDistY + aDistZ);
}
//=================================================================================================

View File

@@ -24,6 +24,10 @@
#include <gp_Pnt.hxx>
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <algorithm>
#include <cmath>
class gp_Pnt;
class gp_Dir;
class gp_Trsf;
@@ -61,21 +65,53 @@ class Bnd_Box
public:
DEFINE_STANDARD_ALLOC
//! Structure containing the box limits (Xmin, Xmax, Ymin, Ymax, Zmin, Zmax).
//! The values include the gap and account for open directions.
struct Limits
{
double Xmin; //!< Minimum X coordinate
double Xmax; //!< Maximum X coordinate
double Ymin; //!< Minimum Y coordinate
double Ymax; //!< Maximum Y coordinate
double Zmin; //!< Minimum Z coordinate
double Zmax; //!< Maximum Z coordinate
};
//! Creates an empty Box.
//! The constructed box is qualified Void. Its gap is null.
Standard_EXPORT Bnd_Box();
constexpr Bnd_Box()
: Xmin(RealLast()),
Xmax(-RealLast()),
Ymin(RealLast()),
Ymax(-RealLast()),
Zmin(RealLast()),
Zmax(-RealLast()),
Gap(0.0),
Flags(VoidMask)
{
}
//! Creates a bounding box, it contains:
//! - minimum/maximum point of bounding box,
//! The constructed box is qualified Void. Its gap is null.
Standard_EXPORT Bnd_Box(const gp_Pnt& theMin, const gp_Pnt& theMax);
constexpr Bnd_Box(const gp_Pnt& theMin, const gp_Pnt& theMax)
: Xmin(theMin.X()),
Xmax(theMax.X()),
Ymin(theMin.Y()),
Ymax(theMax.Y()),
Zmin(theMin.Z()),
Zmax(theMax.Z()),
Gap(0.0),
Flags(0)
{
}
//! Sets this bounding box so that it covers the whole of 3D space.
//! It is infinitely long in all directions.
void SetWhole() { Flags = WholeMask; }
void SetWhole() noexcept { Flags = WholeMask; }
//! Sets this bounding box so that it is empty. All points are outside a void box.
void SetVoid()
void SetVoid() noexcept
{
Xmin = RealLast();
Xmax = -RealLast();
@@ -115,10 +151,10 @@ public:
Standard_EXPORT void Update(const Standard_Real X, const Standard_Real Y, const Standard_Real Z);
//! Returns the gap of this bounding box.
Standard_EXPORT Standard_Real GetGap() const;
[[nodiscard]] constexpr Standard_Real GetGap() const noexcept { return Gap; }
//! Set the gap of this bounding box to abs(Tol).
Standard_EXPORT void SetGap(const Standard_Real Tol);
void SetGap(const Standard_Real Tol) noexcept { Gap = std::abs(Tol); }
//! Enlarges the box with a tolerance value.
//! (minvalues-std::abs(<tol>) and maxvalues+std::abs(<tol>))
@@ -126,7 +162,7 @@ public:
//! intervals of definition, when they are finite, are reduced by
//! the absolute value of Tol, while the maximum values are
//! increased by the same amount.
Standard_EXPORT void Enlarge(const Standard_Real Tol);
void Enlarge(const Standard_Real Tol) noexcept { Gap = std::max(Gap, std::abs(Tol)); }
//! Returns the bounds of this bounding box. The gap is included.
//! If this bounding box is infinite (i.e. "open"), returned values
@@ -140,83 +176,114 @@ public:
Standard_Real& theYmax,
Standard_Real& theZmax) const;
//! Returns the bounds of this bounding box as a Limits structure.
//! The gap is included. If this bounding box is infinite (i.e. "open"),
//! returned values may be equal to +/- Precision::Infinite().
//! If the box is void, returns raw internal values.
//! Can be used with C++17 structured bindings:
//! @code
//! auto [xmin, xmax, ymin, ymax, zmin, zmax] = aBox.Get();
//! @endcode
[[nodiscard]] Standard_EXPORT Limits Get() const;
//! Returns the Xmin value (IsOpenXmin() ? -Precision::Infinite() : Xmin - GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetXMin() const;
//! Returns the Xmax value (IsOpenXmax() ? Precision::Infinite() : Xmax + GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetXMax() const;
//! Returns the Ymin value (IsOpenYmin() ? -Precision::Infinite() : Ymin - GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetYMin() const;
//! Returns the Ymax value (IsOpenYmax() ? Precision::Infinite() : Ymax + GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetYMax() const;
//! Returns the Zmin value (IsOpenZmin() ? -Precision::Infinite() : Zmin - GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetZMin() const;
//! Returns the Zmax value (IsOpenZmax() ? Precision::Infinite() : Zmax + GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetZMax() const;
//! Returns the lower corner of this bounding box. The gap is included.
//! If this bounding box is infinite (i.e. "open"), returned values
//! may be equal to +/- Precision::Infinite().
//! Standard_ConstructionError exception will be thrown if the box is void.
//! if IsVoid()
Standard_EXPORT gp_Pnt CornerMin() const;
[[nodiscard]] Standard_EXPORT gp_Pnt CornerMin() const;
//! Returns the upper corner of this bounding box. The gap is included.
//! If this bounding box is infinite (i.e. "open"), returned values
//! may be equal to +/- Precision::Infinite().
//! Standard_ConstructionError exception will be thrown if the box is void.
//! if IsVoid()
Standard_EXPORT gp_Pnt CornerMax() const;
[[nodiscard]] Standard_EXPORT gp_Pnt CornerMax() const;
//! The Box will be infinitely long in the Xmin
//! direction.
void OpenXmin() { Flags |= XminMask; }
void OpenXmin() noexcept { Flags |= XminMask; }
//! The Box will be infinitely long in the Xmax
//! direction.
void OpenXmax() { Flags |= XmaxMask; }
void OpenXmax() noexcept { Flags |= XmaxMask; }
//! The Box will be infinitely long in the Ymin
//! direction.
void OpenYmin() { Flags |= YminMask; }
void OpenYmin() noexcept { Flags |= YminMask; }
//! The Box will be infinitely long in the Ymax
//! direction.
void OpenYmax() { Flags |= YmaxMask; }
void OpenYmax() noexcept { Flags |= YmaxMask; }
//! The Box will be infinitely long in the Zmin
//! direction.
void OpenZmin() { Flags |= ZminMask; }
void OpenZmin() noexcept { Flags |= ZminMask; }
//! The Box will be infinitely long in the Zmax
//! direction.
void OpenZmax() { Flags |= ZmaxMask; }
void OpenZmax() noexcept { Flags |= ZmaxMask; }
//! Returns true if this bounding box has at least one open direction.
Standard_Boolean IsOpen() const { return (Flags & WholeMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpen() const noexcept { return (Flags & WholeMask) != 0; }
//! Returns true if this bounding box is open in the Xmin direction.
Standard_Boolean IsOpenXmin() const { return (Flags & XminMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenXmin() const noexcept { return (Flags & XminMask) != 0; }
//! Returns true if this bounding box is open in the Xmax direction.
Standard_Boolean IsOpenXmax() const { return (Flags & XmaxMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenXmax() const noexcept { return (Flags & XmaxMask) != 0; }
//! Returns true if this bounding box is open in the Ymix direction.
Standard_Boolean IsOpenYmin() const { return (Flags & YminMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenYmin() const noexcept { return (Flags & YminMask) != 0; }
//! Returns true if this bounding box is open in the Ymax direction.
Standard_Boolean IsOpenYmax() const { return (Flags & YmaxMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenYmax() const noexcept { return (Flags & YmaxMask) != 0; }
//! Returns true if this bounding box is open in the Zmin direction.
Standard_Boolean IsOpenZmin() const { return (Flags & ZminMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenZmin() const noexcept { return (Flags & ZminMask) != 0; }
//! Returns true if this bounding box is open in the Zmax direction.
Standard_Boolean IsOpenZmax() const { return (Flags & ZmaxMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenZmax() const noexcept { return (Flags & ZmaxMask) != 0; }
//! Returns true if this bounding box is infinite in all 6 directions (WholeSpace flag).
Standard_Boolean IsWhole() const { return (Flags & WholeMask) == WholeMask; }
[[nodiscard]] Standard_Boolean IsWhole() const noexcept
{
return (Flags & WholeMask) == WholeMask;
}
//! Returns true if this bounding box is empty (Void flag).
Standard_Boolean IsVoid() const { return (Flags & VoidMask) != 0; }
[[nodiscard]] Standard_Boolean IsVoid() const noexcept { return (Flags & VoidMask) != 0; }
//! true if xmax-xmin < tol.
Standard_EXPORT Standard_Boolean IsXThin(const Standard_Real tol) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsXThin(const Standard_Real tol) const;
//! true if ymax-ymin < tol.
Standard_EXPORT Standard_Boolean IsYThin(const Standard_Real tol) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsYThin(const Standard_Real tol) const;
//! true if zmax-zmin < tol.
Standard_EXPORT Standard_Boolean IsZThin(const Standard_Real tol) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsZThin(const Standard_Real tol) const;
//! Returns true if IsXThin, IsYThin and IsZThin are all true,
//! i.e. if the box is thin in all three dimensions.
Standard_EXPORT Standard_Boolean IsThin(const Standard_Real tol) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsThin(const Standard_Real tol) const;
//! Returns a bounding box which is the result of applying the
//! transformation T to this bounding box.
@@ -224,7 +291,7 @@ public:
//! Applying a geometric transformation (for example, a
//! rotation) to a bounding box generally increases its
//! dimensions. This is not optimal for algorithms which use it.
Standard_NODISCARD Standard_EXPORT Bnd_Box Transformed(const gp_Trsf& T) const;
[[nodiscard]] Standard_EXPORT Bnd_Box Transformed(const gp_Trsf& T) const;
//! Adds the box <Other> to <me>.
Standard_EXPORT void Add(const Bnd_Box& Other);
@@ -241,39 +308,42 @@ public:
Standard_EXPORT void Add(const gp_Dir& D);
//! Returns True if the Pnt is out the box.
Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& P) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& P) const;
//! Returns False if the line intersects the box.
Standard_EXPORT Standard_Boolean IsOut(const gp_Lin& L) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Lin& L) const;
//! Returns False if the plane intersects the box.
Standard_EXPORT Standard_Boolean IsOut(const gp_Pln& P) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Pln& P) const;
//! Returns False if the <Box> intersects or is inside <me>.
Standard_EXPORT Standard_Boolean IsOut(const Bnd_Box& Other) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const Bnd_Box& Other) const;
//! Returns False if the transformed <Box> intersects
//! or is inside <me>.
Standard_EXPORT Standard_Boolean IsOut(const Bnd_Box& Other, const gp_Trsf& T) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const Bnd_Box& Other,
const gp_Trsf& T) const;
//! Returns False if the transformed <Box> intersects
//! or is inside the transformed box <me>.
Standard_EXPORT Standard_Boolean IsOut(const gp_Trsf& T1,
const Bnd_Box& Other,
const gp_Trsf& T2) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Trsf& T1,
const Bnd_Box& Other,
const gp_Trsf& T2) const;
//! Returns False if the flat band lying between two parallel
//! lines represented by their reference points <P1>, <P2> and
//! direction <D> intersects the box.
Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Dir& D) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& P1,
const gp_Pnt& P2,
const gp_Dir& D) const;
//! Computes the minimum distance between two boxes.
Standard_EXPORT Standard_Real Distance(const Bnd_Box& Other) const;
[[nodiscard]] Standard_EXPORT Standard_Real Distance(const Bnd_Box& Other) const;
Standard_EXPORT void Dump() const;
//! Computes the squared diagonal of me.
Standard_Real SquareExtent() const
[[nodiscard]] Standard_Real SquareExtent() const noexcept
{
if (IsVoid())
{
@@ -290,7 +360,7 @@ public:
//! box). This can be a Void box in case if its sides has been defined as infinite (Open) without
//! adding any finite points. WARNING! This method relies on Open flags, the infinite points added
//! using Add() method will be returned as is.
Bnd_Box FinitePart() const
[[nodiscard]] Bnd_Box FinitePart() const noexcept
{
if (!HasFinitePart())
{
@@ -304,7 +374,10 @@ public:
}
//! Returns TRUE if this box has finite part.
Standard_Boolean HasFinitePart() const { return !IsVoid() && Xmax >= Xmin; }
[[nodiscard]] Standard_Boolean HasFinitePart() const noexcept
{
return !IsVoid() && Xmax >= Xmin;
}
//! Dumps the content of me into the stream
Standard_EXPORT void DumpJson(Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;

View File

@@ -15,12 +15,24 @@
// commercial license or contractual agreement.
#include <Bnd_Box2d.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Trsf2d.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Stream.hxx>
//-- #include <Precision.hxx> Precision::Infinite() -> 1e+100
namespace
{
// Precision constant for infinite bounds
constexpr Standard_Real THE_BND_PRECISION_INFINITE = 1e+100;
// Precomputed unit direction vectors for bounding box transformations
constexpr gp_Dir2d THE_DIR_XMIN{gp_Dir2d::D::NX};
constexpr gp_Dir2d THE_DIR_XMAX{gp_Dir2d::D::X};
constexpr gp_Dir2d THE_DIR_YMIN{gp_Dir2d::D::NY};
constexpr gp_Dir2d THE_DIR_YMAX{gp_Dir2d::D::Y};
} // anonymous namespace
//=================================================================================================
void Bnd_Box2d::Update(const Standard_Real x,
@@ -38,14 +50,14 @@ void Bnd_Box2d::Update(const Standard_Real x,
}
else
{
if (!(Flags & XminMask) && (x < Xmin))
Xmin = x;
if (!(Flags & XmaxMask) && (X > Xmax))
Xmax = X;
if (!(Flags & YminMask) && (y < Ymin))
Ymin = y;
if (!(Flags & YmaxMask) && (Y > Ymax))
Ymax = Y;
if (!(Flags & XminMask))
Xmin = std::min(Xmin, x);
if (!(Flags & XmaxMask))
Xmax = std::max(Xmax, X);
if (!(Flags & YminMask))
Ymin = std::min(Ymin, y);
if (!(Flags & YmaxMask))
Ymax = std::max(Ymax, Y);
}
}
@@ -63,14 +75,14 @@ void Bnd_Box2d::Update(const Standard_Real X, const Standard_Real Y)
}
else
{
if (!(Flags & XminMask) && (X < Xmin))
Xmin = X;
else if (!(Flags & XmaxMask) && (X > Xmax))
Xmax = X;
if (!(Flags & YminMask) && (Y < Ymin))
Ymin = Y;
else if (!(Flags & YmaxMask) && (Y > Ymax))
Ymax = Y;
if (!(Flags & XminMask))
Xmin = std::min(Xmin, X);
if (!(Flags & XmaxMask))
Xmax = std::max(Xmax, X);
if (!(Flags & YminMask))
Ymin = std::min(Ymin, Y);
if (!(Flags & YmaxMask))
Ymax = std::max(Ymax, Y);
}
}
@@ -80,122 +92,139 @@ void Bnd_Box2d::Get(Standard_Real& x, Standard_Real& y, Standard_Real& Xm, Stand
{
if (Flags & VoidMask)
throw Standard_ConstructionError("Bnd_Box is void");
Standard_Real pinf = 1e+100; //-- Precision::Infinite();
if (Flags & XminMask)
x = -pinf;
else
x = Xmin - Gap;
if (Flags & XmaxMask)
Xm = pinf;
else
Xm = Xmax + Gap;
if (Flags & YminMask)
y = -pinf;
else
y = Ymin - Gap;
if (Flags & YmaxMask)
Ym = pinf;
else
Ym = Ymax + Gap;
x = GetXMin();
Xm = GetXMax();
y = GetYMin();
Ym = GetYMax();
}
//=================================================================================================
Bnd_Box2d::Limits Bnd_Box2d::Get() const
{
return {GetXMin(), GetXMax(), GetYMin(), GetYMax()};
}
//=================================================================================================
Standard_Real Bnd_Box2d::GetXMin() const
{
return (Flags & XminMask) ? -THE_BND_PRECISION_INFINITE : Xmin - Gap;
}
//=================================================================================================
Standard_Real Bnd_Box2d::GetXMax() const
{
return (Flags & XmaxMask) ? THE_BND_PRECISION_INFINITE : Xmax + Gap;
}
//=================================================================================================
Standard_Real Bnd_Box2d::GetYMin() const
{
return (Flags & YminMask) ? -THE_BND_PRECISION_INFINITE : Ymin - Gap;
}
//=================================================================================================
Standard_Real Bnd_Box2d::GetYMax() const
{
return (Flags & YmaxMask) ? THE_BND_PRECISION_INFINITE : Ymax + Gap;
}
//=================================================================================================
Bnd_Box2d Bnd_Box2d::Transformed(const gp_Trsf2d& T) const
{
gp_TrsfForm F = T.Form();
Bnd_Box2d newb(*this);
const gp_TrsfForm aF = T.Form();
Bnd_Box2d aNewBox(*this);
if (IsVoid())
return newb;
return aNewBox;
if (F == gp_Identity)
if (aF == gp_Identity)
{
}
else if (F == gp_Translation)
else if (aF == gp_Translation)
{
Standard_Real DX, DY;
(T.TranslationPart()).Coord(DX, DY);
Standard_Real aDX, aDY;
(T.TranslationPart()).Coord(aDX, aDY);
if (!(Flags & XminMask))
newb.Xmin += DX;
aNewBox.Xmin += aDX;
if (!(Flags & XmaxMask))
newb.Xmax += DX;
aNewBox.Xmax += aDX;
if (!(Flags & YminMask))
newb.Ymin += DY;
aNewBox.Ymin += aDY;
if (!(Flags & YmaxMask))
newb.Ymax += DY;
aNewBox.Ymax += aDY;
}
else
{
gp_Pnt2d P[4];
Standard_Boolean Vertex[4];
Standard_Integer i;
Vertex[0] = Standard_True;
Vertex[1] = Standard_True;
Vertex[2] = Standard_True;
Vertex[3] = Standard_True;
gp_Dir2d D[6];
// Standard_Integer vertices = 0;
Standard_Integer directions = 0;
gp_Pnt2d aP[4];
Standard_Boolean aVertex[4];
aVertex[0] = Standard_True;
aVertex[1] = Standard_True;
aVertex[2] = Standard_True;
aVertex[3] = Standard_True;
gp_Dir2d aD[6];
Standard_Integer aNbDirs = 0;
if (Flags & XminMask)
{
D[directions].SetCoord(-1., 0.);
directions++;
Vertex[0] = Vertex[2] = Standard_False;
aD[aNbDirs++] = THE_DIR_XMIN;
aVertex[0] = aVertex[2] = Standard_False;
}
if (Flags & XmaxMask)
{
D[directions].SetCoord(1., 0.);
directions++;
Vertex[1] = Vertex[3] = Standard_False;
aD[aNbDirs++] = THE_DIR_XMAX;
aVertex[1] = aVertex[3] = Standard_False;
}
if (Flags & YminMask)
{
D[directions].SetCoord(0., -1.);
directions++;
Vertex[0] = Vertex[1] = Standard_False;
aD[aNbDirs++] = THE_DIR_YMIN;
aVertex[0] = aVertex[1] = Standard_False;
}
if (Flags & YmaxMask)
{
D[directions].SetCoord(0., 1.);
directions++;
Vertex[2] = Vertex[3] = Standard_False;
aD[aNbDirs++] = THE_DIR_YMAX;
aVertex[2] = aVertex[3] = Standard_False;
}
newb.SetVoid();
aNewBox.SetVoid();
for (i = 0; i < directions; i++)
for (Standard_Integer i = 0; i < aNbDirs; i++)
{
D[i].Transform(T);
newb.Add(D[i]);
aD[i].Transform(T);
aNewBox.Add(aD[i]);
}
P[0].SetCoord(Xmin, Ymin);
P[1].SetCoord(Xmax, Ymin);
P[2].SetCoord(Xmin, Ymax);
P[3].SetCoord(Xmax, Ymax);
if (Vertex[0])
aP[0].SetCoord(Xmin, Ymin);
aP[1].SetCoord(Xmax, Ymin);
aP[2].SetCoord(Xmin, Ymax);
aP[3].SetCoord(Xmax, Ymax);
if (aVertex[0])
{
P[0].Transform(T);
newb.Add(P[0]);
aP[0].Transform(T);
aNewBox.Add(aP[0]);
}
if (Vertex[1])
if (aVertex[1])
{
P[1].Transform(T);
newb.Add(P[1]);
aP[1].Transform(T);
aNewBox.Add(aP[1]);
}
if (Vertex[2])
if (aVertex[2])
{
P[2].Transform(T);
newb.Add(P[2]);
aP[2].Transform(T);
aNewBox.Add(aP[2]);
}
if (Vertex[3])
if (aVertex[3])
{
P[3].Transform(T);
newb.Add(P[3]);
aP[3].Transform(T);
aNewBox.Add(aP[3]);
}
newb.Gap = Gap;
aNewBox.Gap = Gap;
}
return newb;
return aNewBox;
}
//=================================================================================================

View File

@@ -26,6 +26,10 @@
#include <Standard_Real.hxx>
#include <Standard_Integer.hxx>
#include <Standard_Boolean.hxx>
#include <algorithm>
#include <cmath>
class gp_Dir2d;
class gp_Trsf2d;
@@ -53,13 +57,23 @@ class Bnd_Box2d
public:
DEFINE_STANDARD_ALLOC
//! Structure containing the 2D box limits (Xmin, Xmax, Ymin, Ymax).
//! The values include the gap and account for open directions.
struct Limits
{
double Xmin; //!< Minimum X coordinate
double Xmax; //!< Maximum X coordinate
double Ymin; //!< Minimum Y coordinate
double Ymax; //!< Maximum Y coordinate
};
//! Creates an empty 2D bounding box.
//! The constructed box is qualified Void. Its gap is null.
Bnd_Box2d()
: Xmin(0.),
Xmax(0.),
Ymin(0.),
Ymax(0.),
constexpr Bnd_Box2d()
: Xmin(RealLast()),
Xmax(-RealLast()),
Ymin(RealLast()),
Ymax(-RealLast()),
Gap(0.),
Flags(VoidMask)
{
@@ -67,13 +81,17 @@ public:
//! Sets this bounding box so that it covers the whole 2D
//! space, i.e. it is infinite in all directions.
void SetWhole() { Flags = WholeMask; }
void SetWhole() noexcept { Flags = WholeMask; }
//! Sets this 2D bounding box so that it is empty. All points are outside a void box.
void SetVoid()
void SetVoid() noexcept
{
Flags = VoidMask;
Xmin = RealLast();
Xmax = -RealLast();
Ymin = RealLast();
Ymax = -RealLast();
Gap = 0.0;
Flags = VoidMask;
}
//! Sets this 2D bounding box so that it bounds
@@ -111,22 +129,17 @@ public:
Standard_EXPORT void Update(const Standard_Real X, const Standard_Real Y);
//! Returns the gap of this 2D bounding box.
Standard_Real GetGap() const { return Gap; }
[[nodiscard]] constexpr Standard_Real GetGap() const noexcept { return Gap; }
//! Set the gap of this 2D bounding box to abs(Tol).
void SetGap(const Standard_Real Tol) { Gap = Tol; }
void SetGap(const Standard_Real Tol) noexcept { Gap = std::abs(Tol); }
//! Enlarges the box with a tolerance value.
//! This means that the minimum values of its X and Y
//! intervals of definition, when they are finite, are reduced by
//! the absolute value of Tol, while the maximum values are
//! increased by the same amount.
void Enlarge(const Standard_Real theTol)
{
Standard_Real aTol = theTol < 0.0 ? -theTol : theTol;
if (Gap < aTol)
Gap = aTol;
}
void Enlarge(const Standard_Real theTol) noexcept { Gap = std::max(Gap, std::abs(theTol)); }
//! Returns the bounds of this 2D bounding box.
//! The gap is included. If this bounding box is infinite (i.e. "open"), returned values
@@ -137,36 +150,61 @@ public:
Standard_Real& aXmax,
Standard_Real& aYmax) const;
//! Returns the bounds of this 2D bounding box as a Limits structure.
//! The gap is included. If this bounding box is infinite (i.e. "open"),
//! returned values may be equal to +/- Precision::Infinite().
//! If the box is void, returns raw internal values.
//! Can be used with C++17 structured bindings:
//! @code
//! auto [xmin, xmax, ymin, ymax] = aBox.Get();
//! @endcode
[[nodiscard]] Standard_EXPORT Limits Get() const;
//! Returns the Xmin value (IsOpenXmin() ? -Precision::Infinite() : Xmin - GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetXMin() const;
//! Returns the Xmax value (IsOpenXmax() ? Precision::Infinite() : Xmax + GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetXMax() const;
//! Returns the Ymin value (IsOpenYmin() ? -Precision::Infinite() : Ymin - GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetYMin() const;
//! Returns the Ymax value (IsOpenYmax() ? Precision::Infinite() : Ymax + GetGap()).
[[nodiscard]] Standard_EXPORT Standard_Real GetYMax() const;
//! The Box will be infinitely long in the Xmin direction.
void OpenXmin() { Flags |= XminMask; }
void OpenXmin() noexcept { Flags |= XminMask; }
//! The Box will be infinitely long in the Xmax direction.
void OpenXmax() { Flags |= XmaxMask; }
void OpenXmax() noexcept { Flags |= XmaxMask; }
//! The Box will be infinitely long in the Ymin direction.
void OpenYmin() { Flags |= YminMask; }
void OpenYmin() noexcept { Flags |= YminMask; }
//! The Box will be infinitely long in the Ymax direction.
void OpenYmax() { Flags |= YmaxMask; }
void OpenYmax() noexcept { Flags |= YmaxMask; }
//! Returns true if this bounding box is open in the Xmin direction.
Standard_Boolean IsOpenXmin() const { return (Flags & XminMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenXmin() const noexcept { return (Flags & XminMask) != 0; }
//! Returns true if this bounding box is open in the Xmax direction.
Standard_Boolean IsOpenXmax() const { return (Flags & XmaxMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenXmax() const noexcept { return (Flags & XmaxMask) != 0; }
//! Returns true if this bounding box is open in the Ymin direction.
Standard_Boolean IsOpenYmin() const { return (Flags & YminMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenYmin() const noexcept { return (Flags & YminMask) != 0; }
//! Returns true if this bounding box is open in the Ymax direction.
Standard_Boolean IsOpenYmax() const { return (Flags & YmaxMask) != 0; }
[[nodiscard]] Standard_Boolean IsOpenYmax() const noexcept { return (Flags & YmaxMask) != 0; }
//! Returns true if this bounding box is infinite in all 4
//! directions (Whole Space flag).
Standard_Boolean IsWhole() const { return (Flags & WholeMask) == WholeMask; }
[[nodiscard]] Standard_Boolean IsWhole() const noexcept
{
return (Flags & WholeMask) == WholeMask;
}
//! Returns true if this 2D bounding box is empty (Void flag).
Standard_Boolean IsVoid() const { return (Flags & VoidMask) != 0; }
[[nodiscard]] Standard_Boolean IsVoid() const noexcept { return (Flags & VoidMask) != 0; }
//! Returns a bounding box which is the result of applying the
//! transformation T to this bounding box.
@@ -174,16 +212,16 @@ public:
//! Applying a geometric transformation (for example, a
//! rotation) to a bounding box generally increases its
//! dimensions. This is not optimal for algorithms which use it.
Standard_NODISCARD Standard_EXPORT Bnd_Box2d Transformed(const gp_Trsf2d& T) const;
[[nodiscard]] Standard_EXPORT Bnd_Box2d Transformed(const gp_Trsf2d& T) const;
//! Adds the 2d box <Other> to <me>.
Standard_EXPORT void Add(const Bnd_Box2d& Other);
//! Adds the 2d point.
void Add(const gp_Pnt2d& thePnt) { Update(thePnt.X(), thePnt.Y()); }
void Add(const gp_Pnt2d& thePnt) noexcept { Update(thePnt.X(), thePnt.Y()); }
//! Extends bounding box from thePnt in the direction theDir.
void Add(const gp_Pnt2d& thePnt, const gp_Dir2d& theDir)
void Add(const gp_Pnt2d& thePnt, const gp_Dir2d& theDir) noexcept
{
Add(thePnt);
Add(theDir);
@@ -195,19 +233,21 @@ public:
Standard_EXPORT void Add(const gp_Dir2d& D);
//! Returns True if the 2d pnt <P> is out <me>.
Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt2d& P) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt2d& P) const;
//! Returns True if the line doesn't intersect the box.
Standard_EXPORT Standard_Boolean IsOut(const gp_Lin2d& theL) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Lin2d& theL) const;
//! Returns True if the segment doesn't intersect the box.
Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt2d& theP0, const gp_Pnt2d& theP1) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt2d& theP0,
const gp_Pnt2d& theP1) const;
//! Returns True if <Box2d> is out <me>.
Standard_EXPORT Standard_Boolean IsOut(const Bnd_Box2d& Other) const;
[[nodiscard]] Standard_EXPORT Standard_Boolean IsOut(const Bnd_Box2d& Other) const;
//! Returns True if transformed <Box2d> is out <me>.
Standard_Boolean IsOut(const Bnd_Box2d& theOther, const gp_Trsf2d& theTrsf) const
[[nodiscard]] Standard_Boolean IsOut(const Bnd_Box2d& theOther,
const gp_Trsf2d& theTrsf) const noexcept
{
return IsOut(theOther.Transformed(theTrsf));
}
@@ -215,7 +255,9 @@ public:
//! Compares a transformed bounding with a transformed
//! bounding. The default implementation is to make a copy
//! of <me> and <Other>, to transform them and to test.
Standard_Boolean IsOut(const gp_Trsf2d& T1, const Bnd_Box2d& Other, const gp_Trsf2d& T2) const
[[nodiscard]] Standard_Boolean IsOut(const gp_Trsf2d& T1,
const Bnd_Box2d& Other,
const gp_Trsf2d& T2) const noexcept
{
return Transformed(T1).IsOut(Other.Transformed(T2));
}
@@ -223,7 +265,7 @@ public:
Standard_EXPORT void Dump() const;
//! Computes the squared diagonal of me.
Standard_Real SquareExtent() const
[[nodiscard]] Standard_Real SquareExtent() const noexcept
{
if (IsVoid())
return 0.0;

View File

@@ -205,9 +205,9 @@ TEST(Bnd_BoxTest, CornerMethodsVoidBox)
{
Bnd_Box aBox; // void box
EXPECT_THROW(aBox.CornerMin(), Standard_ConstructionError)
EXPECT_THROW((void)aBox.CornerMin(), Standard_ConstructionError)
<< "CornerMin should throw for void box";
EXPECT_THROW(aBox.CornerMax(), Standard_ConstructionError)
EXPECT_THROW((void)aBox.CornerMax(), Standard_ConstructionError)
<< "CornerMax should throw for void box";
}