From 4df229f2c4422d7346f50f1e57e81ca7acb7cd78 Mon Sep 17 00:00:00 2001 From: Pasukhin Dmitry Date: Thu, 12 Feb 2026 23:02:36 +0000 Subject: [PATCH] Foundation Classes - Bnd package improvements (#1051) Bug fixes: - Bnd_Box::Add(Bnd_Box) - fix unconditional bounds merge before open direction check - Bnd_Box::IsOut(gp_Pln) - use GetXMin()/GetXMax() accessors (include Gap) instead of raw fields - Bnd_Box::Distance() - add void box check to avoid invalid results - Bnd_Range::Common() - add missing return statement - Bnd_Sphere::SquareDistances() - fix radius comparison (was comparing distance vs radius instead of squared values) - Bnd_OBB: OBBTool::ProcessTriangle - add safety check for degenerate cross products before normalization - Bnd_OBB: OBBTool::ProcessDiTetrahedron - fix off-by-one in bounds check (use < instead of <=) Performance optimizations: - Bnd_Box::IsOut(Bnd_Box) - add early return fast path for non-open boxes - Bnd_Box2d::IsOut(Bnd_Box2d) - add early return fast path for non-open boxes API improvements: - Add Contains()/Intersects() semantic wrappers (inverse of IsOut) to Bnd_Box, Bnd_Box2d, Bnd_OBB, Bnd_Range - Add Center() returning std::optional to Bnd_Box, Bnd_Box2d, Bnd_Range - Add Min()/Max()/Get() returning std::optional to Bnd_Range - Add Bnd_Range::Bounds struct for C++17 structured bindings via Get() - Add Bnd_OBB::HalfSizes struct and GetHalfSizes() for structured bindings - Add Bnd_Box2d::Distance() method - Replace Bnd_Range::IsIntersected magic int returns with IntersectStatus enum Code modernization: - Add [[nodiscard]] and noexcept annotations across all Bnd classes - Migrate Bnd_Sphere inline methods from .lxx to header, delete Bnd_Sphere.lxx - Remove unused includes (iomanip, fstream, legacy Standard_*.hxx headers) - Fix Bnd_Box.hxx "Ymix" typo in IsOpenYmin() comment - Clean up DET-style comments in Bnd_Box.cxx - Update IntPatch_WLineTool.cxx to use IntersectStatus enum --- src/FoundationClasses/TKMath/Bnd/Bnd_Box.cxx | 123 +++-- src/FoundationClasses/TKMath/Bnd/Bnd_Box.hxx | 17 +- .../TKMath/Bnd/Bnd_Box2d.cxx | 92 +++- .../TKMath/Bnd/Bnd_Box2d.hxx | 20 +- src/FoundationClasses/TKMath/Bnd/Bnd_OBB.cxx | 20 +- src/FoundationClasses/TKMath/Bnd/Bnd_OBB.hxx | 60 +- .../TKMath/Bnd/Bnd_Range.cxx | 22 +- .../TKMath/Bnd/Bnd_Range.hxx | 111 +++- .../TKMath/Bnd/Bnd_Sphere.cxx | 7 +- .../TKMath/Bnd/Bnd_Sphere.hxx | 16 +- .../TKMath/Bnd/Bnd_Sphere.lxx | 42 -- src/FoundationClasses/TKMath/Bnd/FILES.cmake | 1 - .../TKMath/GTests/Bnd_Box2d_Test.cxx | 443 +++++++++++++++ .../TKMath/GTests/Bnd_Box_Test.cxx | 34 ++ .../TKMath/GTests/Bnd_OBB_Test.cxx | 27 + .../TKMath/GTests/Bnd_Range_Test.cxx | 511 ++++++++++++++++++ .../TKMath/GTests/Bnd_Sphere_Test.cxx | 224 ++++++++ .../TKMath/GTests/FILES.cmake | 3 + .../IntPatch/IntPatch_WLineTool.cxx | 6 +- 19 files changed, 1607 insertions(+), 172 deletions(-) delete mode 100644 src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.lxx create mode 100644 src/FoundationClasses/TKMath/GTests/Bnd_Box2d_Test.cxx create mode 100644 src/FoundationClasses/TKMath/GTests/Bnd_Range_Test.cxx create mode 100644 src/FoundationClasses/TKMath/GTests/Bnd_Sphere_Test.cxx diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Box.cxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Box.cxx index e05e7f3a6d..488ddcd471 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Box.cxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Box.cxx @@ -24,8 +24,6 @@ #include #include #include -#include -#include namespace { @@ -289,6 +287,19 @@ gp_Pnt Bnd_Box::CornerMax() const //================================================================================================= +std::optional Bnd_Box::Center() const +{ + if (IsVoid()) + { + return std::nullopt; + } + return gp_Pnt(0.5 * (GetXMin() + GetXMax()), + 0.5 * (GetYMin() + GetYMax()), + 0.5 * (GetZMin() + GetZMax())); +} + +//================================================================================================= + bool Bnd_Box::IsXThin(const double tol) const { if (IsWhole()) @@ -460,18 +471,6 @@ void Bnd_Box::Add(const Bnd_Box& Other) return; } - if (Xmin > Other.Xmin) - Xmin = Other.Xmin; - if (Xmax < Other.Xmax) - Xmax = Other.Xmax; - if (Ymin > Other.Ymin) - Ymin = Other.Ymin; - if (Ymax < Other.Ymax) - Ymax = Other.Ymax; - if (Zmin > Other.Zmin) - Zmin = Other.Zmin; - if (Zmax < Other.Zmax) - Zmax = Other.Zmax; Gap = std::max(Gap, Other.Gap); if (IsWhole()) @@ -484,18 +483,48 @@ void Bnd_Box::Add(const Bnd_Box& Other) return; } - if (Other.IsOpenXmin()) - OpenXmin(); - if (Other.IsOpenXmax()) - OpenXmax(); - if (Other.IsOpenYmin()) - OpenYmin(); - if (Other.IsOpenYmax()) - OpenYmax(); - if (Other.IsOpenZmin()) - OpenZmin(); - if (Other.IsOpenZmax()) - OpenZmax(); + if (!IsOpenXmin()) + { + if (Other.IsOpenXmin()) + OpenXmin(); + else if (Xmin > Other.Xmin) + Xmin = Other.Xmin; + } + if (!IsOpenXmax()) + { + if (Other.IsOpenXmax()) + OpenXmax(); + else if (Xmax < Other.Xmax) + Xmax = Other.Xmax; + } + if (!IsOpenYmin()) + { + if (Other.IsOpenYmin()) + OpenYmin(); + else if (Ymin > Other.Ymin) + Ymin = Other.Ymin; + } + if (!IsOpenYmax()) + { + if (Other.IsOpenYmax()) + OpenYmax(); + else if (Ymax < Other.Ymax) + Ymax = Other.Ymax; + } + if (!IsOpenZmin()) + { + if (Other.IsOpenZmin()) + OpenZmin(); + else if (Zmin > Other.Zmin) + Zmin = Other.Zmin; + } + if (!IsOpenZmax()) + { + if (Other.IsOpenZmax()) + OpenZmax(); + else if (Zmax < Other.Zmax) + Zmax = Other.Zmax; + } } //================================================================================================= @@ -579,21 +608,27 @@ bool Bnd_Box::IsOut(const gp_Pln& P) const { double A, B, C, D; P.Coefficients(A, B, C, D); - double d = A * (Xmin - Gap) + B * (Ymin - Gap) + C * (Zmin - Gap) + D; - bool plus = d > 0; - if (plus != ((A * (Xmin - Gap) + B * (Ymin - Gap) + C * (Zmax + Gap) + D) > 0)) + const double aXmin = GetXMin(); + const double aXmax = GetXMax(); + const double aYmin = GetYMin(); + const double aYmax = GetYMax(); + const double aZmin = GetZMin(); + const double aZmax = GetZMax(); + double d = A * aXmin + B * aYmin + C * aZmin + D; + bool plus = d > 0; + if (plus != ((A * aXmin + B * aYmin + C * aZmax + D) > 0)) return false; - if (plus != ((A * (Xmin - Gap) + B * (Ymax + Gap) + C * (Zmin - Gap) + D) > 0)) + if (plus != ((A * aXmin + B * aYmax + C * aZmin + D) > 0)) return false; - if (plus != ((A * (Xmin - Gap) + B * (Ymax + Gap) + C * (Zmax + Gap) + D) > 0)) + if (plus != ((A * aXmin + B * aYmax + C * aZmax + D) > 0)) return false; - if (plus != ((A * (Xmax + Gap) + B * (Ymin - Gap) + C * (Zmin - Gap) + D) > 0)) + if (plus != ((A * aXmax + B * aYmin + C * aZmin + D) > 0)) return false; - if (plus != ((A * (Xmax + Gap) + B * (Ymin - Gap) + C * (Zmax + Gap) + D) > 0)) + if (plus != ((A * aXmax + B * aYmin + C * aZmax + D) > 0)) return false; - if (plus != ((A * (Xmax + Gap) + B * (Ymax + Gap) + C * (Zmin - Gap) + D) > 0)) + if (plus != ((A * aXmax + B * aYmax + C * aZmin + D) > 0)) return false; - return plus == ((A * (Xmax + Gap) + B * (Ymax + Gap) + C * (Zmax + Gap) + D) > 0); + return plus == ((A * aXmax + B * aYmax + C * aZmax + D) > 0); } } @@ -642,10 +677,10 @@ bool Bnd_Box::IsOut(const gp_Lin& L) const { par1 = (myYmin - L.Location().XYZ().Y()) / L.Direction().XYZ().Y(); par2 = (myYmax - L.Location().XYZ().Y()) / L.Direction().XYZ().Y(); - //=================DET change 06/03/01==================== + // Check if parameter ranges from this axis are disjoint (early exit) if (parmax < std::min(par1, par2) || parmin > std::max(par1, par2)) return true; - //======================================================== + parmin = std::max(parmin, std::min(par1, par2)); parmax = std::min(parmax, std::max(par1, par2)); yToSet = true; @@ -665,10 +700,10 @@ bool Bnd_Box::IsOut(const gp_Lin& L) const { par1 = (myZmin - L.Location().XYZ().Z()) / L.Direction().XYZ().Z(); par2 = (myZmax - L.Location().XYZ().Z()) / L.Direction().XYZ().Z(); - //=================DET change 06/03/01==================== + // Check if parameter ranges from this axis are disjoint (early exit) if (parmax < std::min(par1, par2) || parmin > std::max(par1, par2)) return true; - //======================================================== + parmin = std::max(parmin, std::min(par1, par2)); parmax = std::min(parmax, std::max(par1, par2)); par1 = L.Location().XYZ().Z() + parmin * L.Direction().XYZ().Z(); @@ -995,13 +1030,15 @@ bool Bnd_Box::IsOut(const gp_Pnt& P1, const gp_Pnt& P2, const gp_Dir& D) const return true; } -//======================================================================= -// function : Distance -// purpose : computes the minimum distance between two boxes -//======================================================================= +//================================================================================================= double Bnd_Box::Distance(const Bnd_Box& Other) const { + if (IsVoid() || Other.IsVoid()) + { + return 0.0; + } + double aXMinB1, aYMinB1, aZMinB1, aXMaxB1, aYMaxB1, aZMaxB1; double aXMinB2, aYMinB2, aZMinB2, aXMaxB2, aYMaxB2, aZMaxB2; diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Box.hxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Box.hxx index ac79ed51d0..3243e11a29 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Box.hxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Box.hxx @@ -22,11 +22,10 @@ #include #include -#include -#include #include #include +#include class gp_Pnt; class gp_Dir; @@ -218,6 +217,12 @@ public: //! if IsVoid() [[nodiscard]] Standard_EXPORT gp_Pnt CornerMax() const; + //! Returns the center 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(). + //! Returns std::nullopt if the box is void. + [[nodiscard]] Standard_EXPORT std::optional Center() const; + //! The Box will be infinitely long in the Xmin //! direction. void OpenXmin() noexcept { Flags |= XminMask; } @@ -251,7 +256,7 @@ public: //! Returns true if this bounding box is open in the Xmax direction. [[nodiscard]] bool IsOpenXmax() const noexcept { return (Flags & XmaxMask) != 0; } - //! Returns true if this bounding box is open in the Ymix direction. + //! Returns true if this bounding box is open in the Ymin direction. [[nodiscard]] bool IsOpenYmin() const noexcept { return (Flags & YminMask) != 0; } //! Returns true if this bounding box is open in the Ymax direction. @@ -333,6 +338,12 @@ public: const gp_Pnt& P2, const gp_Dir& D) const; + //! Returns True if the point is inside or on the boundary of this box. + [[nodiscard]] bool Contains(const gp_Pnt& theP) const { return !IsOut(theP); } + + //! Returns True if the other box intersects or is inside this box. + [[nodiscard]] bool Intersects(const Bnd_Box& theOther) const { return !IsOut(theOther); } + //! Computes the minimum distance between two boxes. [[nodiscard]] Standard_EXPORT double Distance(const Bnd_Box& Other) const; diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.cxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.cxx index 7679a66668..9eddb1ccdd 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.cxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.cxx @@ -21,8 +21,6 @@ #include #include #include -#include -#include namespace { @@ -383,32 +381,92 @@ bool Bnd_Box2d::IsOut(const gp_Pnt2d& theP0, const gp_Pnt2d& theP1) const bool Bnd_Box2d::IsOut(const Bnd_Box2d& Other) const { - if (IsWhole()) - return false; - else if (IsVoid()) - return true; - else if (Other.IsWhole()) - return false; - else if (Other.IsVoid()) - return true; - else + // Fast path for non-open, non-void, non-whole boxes (most common case) + if (!Flags && !Other.Flags) { - double OXmin, OXmax, OYmin, OYmax; - Other.Get(OXmin, OYmin, OXmax, OYmax); - if (!(Flags & XminMask) && (OXmax < (Xmin - Gap))) + const double aDelta = Other.Gap + Gap; + if (Xmin - Other.Xmax > aDelta) return true; - else if (!(Flags & XmaxMask) && (OXmin > (Xmax + Gap))) + if (Other.Xmin - Xmax > aDelta) return true; - else if (!(Flags & YminMask) && (OYmax < (Ymin - Gap))) + if (Ymin - Other.Ymax > aDelta) return true; - else if (!(Flags & YmaxMask) && (OYmin > (Ymax + Gap))) + if (Other.Ymin - Ymax > aDelta) return true; + return false; } + + // Handle special cases + if (IsVoid() || Other.IsVoid()) + return true; + if (IsWhole() || Other.IsWhole()) + return false; + + double OXmin, OXmax, OYmin, OYmax; + Other.Get(OXmin, OYmin, OXmax, OYmax); + if (!(Flags & XminMask) && (OXmax < (Xmin - Gap))) + return true; + if (!(Flags & XmaxMask) && (OXmin > (Xmax + Gap))) + return true; + if (!(Flags & YminMask) && (OYmax < (Ymin - Gap))) + return true; + if (!(Flags & YmaxMask) && (OYmin > (Ymax + Gap))) + return true; return false; } //================================================================================================= +std::optional Bnd_Box2d::Center() const +{ + if (IsVoid()) + { + return std::nullopt; + } + return gp_Pnt2d(0.5 * (GetXMin() + GetXMax()), 0.5 * (GetYMin() + GetYMax())); +} + +//================================================================================================= + +double Bnd_Box2d::Distance(const Bnd_Box2d& theOther) const +{ + if (IsVoid() || theOther.IsVoid()) + { + return 0.0; + } + + double aXMin1, aYMin1, aXMax1, aYMax1; + double aXMin2, aYMin2, aXMax2, aYMax2; + + Get(aXMin1, aYMin1, aXMax1, aYMax1); + theOther.Get(aXMin2, aYMin2, aXMax2, aYMax2); + + // Compute squared distance per axis + auto distAxis = [](const double theMin1, + const double theMax1, + const double theMin2, + const double theMax2) -> double { + if (theMin1 > theMax2) + { + const double aD = theMin1 - theMax2; + return aD * aD; + } + if (theMin2 > theMax1) + { + const double aD = theMin2 - theMax1; + return aD * aD; + } + return 0.0; + }; + + const double aDx = distAxis(aXMin1, aXMax1, aXMin2, aXMax2); + const double aDy = distAxis(aYMin1, aYMax1, aYMin2, aYMax2); + + return std::sqrt(aDx + aDy); +} + +//================================================================================================= + void Bnd_Box2d::Dump() const { std::cout << "Box2d : "; diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.hxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.hxx index b4b091f3db..026a3f8041 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.hxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Box2d.hxx @@ -23,12 +23,9 @@ #include #include -#include -#include -#include - #include #include +#include class gp_Dir2d; class gp_Trsf2d; @@ -169,6 +166,12 @@ public: //! Returns the Ymax value (IsOpenYmax() ? Precision::Infinite() : Ymax + GetGap()). [[nodiscard]] Standard_EXPORT double GetYMax() const; + //! Returns the center of this 2D bounding box. The gap is included. + //! If this bounding box is infinite (i.e. "open"), returned values + //! may be equal to +/- Precision::Infinite(). + //! Returns std::nullopt if the box is void. + [[nodiscard]] Standard_EXPORT std::optional Center() const; + //! The Box will be infinitely long in the Xmin direction. void OpenXmin() noexcept { Flags |= XminMask; } @@ -238,6 +241,15 @@ public: //! Returns True if is out . [[nodiscard]] Standard_EXPORT bool IsOut(const Bnd_Box2d& Other) const; + //! Returns True if the 2d point is inside or on the boundary of this box. + [[nodiscard]] bool Contains(const gp_Pnt2d& theP) const { return !IsOut(theP); } + + //! Returns True if the other 2d box intersects or is inside this box. + [[nodiscard]] bool Intersects(const Bnd_Box2d& theOther) const { return !IsOut(theOther); } + + //! Computes the minimum distance between two 2D boxes. + [[nodiscard]] Standard_EXPORT double Distance(const Bnd_Box2d& theOther) const; + //! Returns True if transformed is out . [[nodiscard]] bool IsOut(const Bnd_Box2d& theOther, const gp_Trsf2d& theTrsf) const noexcept { diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.cxx b/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.cxx index ecf985ccb4..79284da0e6 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.cxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.cxx @@ -596,8 +596,19 @@ void OBBTool::ProcessTriangle(const int theIdx1, aZAxis /= std::sqrt(aSqMod); gp_XYZ aXAxis[aNbAxes]; + bool aXAxisValid[aNbAxes]; for (int i = 0; i < aNbAxes; i++) - aXAxis[i] = aYAxis[i].Crossed(aZAxis).Normalized(); + { + const gp_XYZ aCross = aYAxis[i].Crossed(aZAxis); + const double aCrossSqMod = aCross.SquareModulus(); + if (aCrossSqMod < Precision::SquareConfusion()) + { + aXAxisValid[i] = false; + continue; + } + aXAxis[i] = aCross / std::sqrt(aCrossSqMod); + aXAxisValid[i] = true; + } if (theIsBuiltTrg) FillToTriangle5(aZAxis, myLExtremalPoints[theIdx1]); @@ -612,6 +623,9 @@ void OBBTool::ProcessTriangle(const int theIdx1, int aMinIdx = -1; for (int anAxeInd = 0; anAxeInd < aNbAxes; anAxeInd++) { + if (!aXAxisValid[anAxeInd]) + continue; + const gp_XYZ& aAX = aXAxis[anAxeInd]; // Compute params on XAxis FindMinMax(aAX, aParams[0], aParams[1]); @@ -662,14 +676,14 @@ void OBBTool::ProcessDiTetrahedron() // Use the standard DiTo approach ProcessTriangle(myTriIdx[0], myTriIdx[1], myTriIdx[2], true); - if (myTriIdx[3] <= myNbExtremalPoints) + if (myTriIdx[3] < myNbExtremalPoints) { ProcessTriangle(myTriIdx[0], myTriIdx[1], myTriIdx[3], false); ProcessTriangle(myTriIdx[1], myTriIdx[2], myTriIdx[3], false); ProcessTriangle(myTriIdx[0], myTriIdx[2], myTriIdx[3], false); } - if (myTriIdx[4] <= myNbExtremalPoints) + if (myTriIdx[4] < myNbExtremalPoints) { ProcessTriangle(myTriIdx[0], myTriIdx[1], myTriIdx[4], false); ProcessTriangle(myTriIdx[1], myTriIdx[2], myTriIdx[4], false); diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.hxx b/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.hxx index e53a9840d0..fa192cc8a2 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.hxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_OBB.hxx @@ -18,7 +18,6 @@ #include #include #include -#include #include #include @@ -39,6 +38,18 @@ class Bnd_OBB public: DEFINE_STANDARD_ALLOC + //! Structure containing the OBB half-size dimensions. + //! Can be used with C++17 structured bindings: + //! @code + //! auto [aHX, aHY, aHZ] = anOBB.GetHalfSizes(); + //! @endcode + struct HalfSizes + { + double X; //!< Half-size along X axis + double Y; //!< Half-size along Y axis + double Z; //!< Half-size along Z axis + }; + //! Empty constructor Bnd_OBB() : myIsAABox(false) @@ -144,31 +155,44 @@ public: //! gp_Trsf aLoc; //! aLoc.SetTransformation (theOBB.Position(), gp::XOY()); //! @endcode - gp_Ax3 Position() const { return gp_Ax3(myCenter, ZDirection(), XDirection()); } + [[nodiscard]] gp_Ax3 Position() const { return gp_Ax3(myCenter, ZDirection(), XDirection()); } //! Returns the center of OBB - const gp_XYZ& Center() const { return myCenter; } + [[nodiscard]] const gp_XYZ& Center() const noexcept { return myCenter; } //! Returns the X Direction of OBB - const gp_XYZ& XDirection() const { return myAxes[0]; } + [[nodiscard]] const gp_XYZ& XDirection() const noexcept { return myAxes[0]; } //! Returns the Y Direction of OBB - const gp_XYZ& YDirection() const { return myAxes[1]; } + [[nodiscard]] const gp_XYZ& YDirection() const noexcept { return myAxes[1]; } //! Returns the Z Direction of OBB - const gp_XYZ& ZDirection() const { return myAxes[2]; } + [[nodiscard]] const gp_XYZ& ZDirection() const noexcept { return myAxes[2]; } //! Returns the X Dimension of OBB - double XHSize() const { return myHDims[0]; } + [[nodiscard]] double XHSize() const noexcept { return myHDims[0]; } //! Returns the Y Dimension of OBB - double YHSize() const { return myHDims[1]; } + [[nodiscard]] double YHSize() const noexcept { return myHDims[1]; } //! Returns the Z Dimension of OBB - double ZHSize() const { return myHDims[2]; } + [[nodiscard]] double ZHSize() const noexcept { return myHDims[2]; } + + //! Returns the half-size dimensions of the OBB as a HalfSizes structure. + //! Can be used with C++17 structured bindings: + //! @code + //! auto [aHX, aHY, aHZ] = anOBB.GetHalfSizes(); + //! @endcode + [[nodiscard]] HalfSizes GetHalfSizes() const noexcept + { + return {myHDims[0], myHDims[1], myHDims[2]}; + } //! Checks if the box is empty. - bool IsVoid() const { return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0)); } + [[nodiscard]] bool IsVoid() const noexcept + { + return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0)); + } //! Clears this box void SetVoid() @@ -182,7 +206,7 @@ public: void SetAABox(const bool& theFlag) { myIsAABox = theFlag; } //! Returns TRUE if the box is axes aligned - bool IsAABox() const { return myIsAABox; } + [[nodiscard]] bool IsAABox() const noexcept { return myIsAABox; } //! Enlarges the box with the given value void Enlarge(const double theGapAdd) @@ -230,19 +254,25 @@ public: } //! Returns square diagonal of this box - double SquareExtent() const + [[nodiscard]] double SquareExtent() const noexcept { return 4.0 * (myHDims[0] * myHDims[0] + myHDims[1] * myHDims[1] + myHDims[2] * myHDims[2]); } //! Check if the box do not interfere the other box. - Standard_EXPORT bool IsOut(const Bnd_OBB& theOther) const; + [[nodiscard]] Standard_EXPORT bool IsOut(const Bnd_OBB& theOther) const; //! Check if the point is inside of . - Standard_EXPORT bool IsOut(const gp_Pnt& theP) const; + [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Pnt& theP) const; + + //! Returns True if the point is inside or on the boundary of this OBB. + [[nodiscard]] bool Contains(const gp_Pnt& theP) const { return !IsOut(theP); } + + //! Returns True if the other OBB intersects or is inside this OBB. + [[nodiscard]] bool Intersects(const Bnd_OBB& theOther) const { return !IsOut(theOther); } //! Check if the theOther is completely inside *this. - Standard_EXPORT bool IsCompletelyInside(const Bnd_OBB& theOther) const; + [[nodiscard]] Standard_EXPORT bool IsCompletelyInside(const Bnd_OBB& theOther) const; //! Rebuilds this in order to include all previous objects //! (which it was created from) and theOther. diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Range.cxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Range.cxx index eeb19b9305..db74adb589 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Range.cxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Range.cxx @@ -23,6 +23,7 @@ void Bnd_Range::Common(const Bnd_Range& theOther) if (theOther.IsVoid()) { SetVoid(); + return; } if (IsVoid()) @@ -55,10 +56,11 @@ bool Bnd_Range::Union(const Bnd_Range& theOther) //================================================================================================= -int Bnd_Range::IsIntersected(const double theVal, const double thePeriod) const +Bnd_Range::IntersectStatus Bnd_Range::IsIntersected(const double theVal, + const double thePeriod) const { if (IsVoid()) - return false; + return IntersectStatus_Out; const double aPeriod = std::abs(thePeriod); const double aDF = myFirst - theVal, aDL = myLast - theVal; @@ -67,12 +69,12 @@ int Bnd_Range::IsIntersected(const double theVal, const double thePeriod) const { const double aDelta = aDF * aDL; if (IsEqual(aDelta, 0.0)) - return 2; + return IntersectStatus_Boundary; if (aDelta > 0.0) - return 0; + return IntersectStatus_Out; - return 1; + return IntersectStatus_In; } // If intersects theVal then there exists an integer @@ -97,20 +99,20 @@ int Bnd_Range::IsIntersected(const double theVal, const double thePeriod) const { // Interval (myFirst, myLast] intersects seam-edge if (IsEqual(aVal2, static_cast(aPar2))) { // aVal2 is an integer number => myLast lies ON the "seam-edge" - return 2; + return IntersectStatus_Boundary; } - return 1; + return IntersectStatus_In; } // Here, aPar1 == aPar2. if (IsEqual(aVal1, static_cast(aPar1))) { // aVal1 is an integer number => myFirst lies ON the "seam-edge" - return 2; + return IntersectStatus_Boundary; } - return 0; + return IntersectStatus_Out; } //================================================================================================= @@ -120,7 +122,7 @@ void Bnd_Range::Split(const double theVal, const double thePeriod) const { const double aPeriod = std::abs(thePeriod); - if (IsIntersected(theVal, aPeriod) != 1) + if (IsIntersected(theVal, aPeriod) != IntersectStatus_In) { theList.Append(*this); return; diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Range.hxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Range.hxx index 4bdab4d1f1..dd9cce3387 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Range.hxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Range.hxx @@ -20,12 +20,25 @@ #include +#include + //! This class describes a range in 1D space restricted //! by two real values. //! A range can be void indicating there is no point included in the range. class Bnd_Range { public: + //! Structure containing the range bounds (Min, Max). + //! Can be used with C++17 structured bindings: + //! @code + //! auto [aMin, aMax] = aRange.Get(); + //! @endcode + struct Bounds + { + double Min; //!< Minimum value of the range + double Max; //!< Maximum value of the range + }; + //! Default constructor. Creates VOID range. Bnd_Range() : myFirst(0.0), @@ -50,7 +63,7 @@ public: //! Returns false if the operation cannot be done (e.g. //! input arguments are empty or separated). //! @sa use method ::Add() to merge two ranges unconditionally - Standard_EXPORT bool Union(const Bnd_Range& theOther); + [[nodiscard]] Standard_EXPORT bool Union(const Bnd_Range& theOther); //! Splits to several sub-ranges by theVal value //! (e.g. range [3, 15] will be split by theVal==5 to the two @@ -66,16 +79,22 @@ public: NCollection_List& theList, const double thePeriod = 0.0) const; + //! Status of intersection check with a periodic value. + //! @sa IsIntersected() + enum IntersectStatus + { + IntersectStatus_Out = 0, //!< No intersection with theVal+k*thePeriod + IntersectStatus_In = 1, //!< Range strictly contains theVal+k*thePeriod + IntersectStatus_Boundary = 2 //!< Range boundary coincides with theVal+k*thePeriod + }; + //! Checks if intersects values like //! theVal+k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...). - //! Returns: - //! 0 - if does not intersect the theVal+k*thePeriod. - //! 1 - if intersects theVal+k*thePeriod. - //! 2 - if myFirst or/and myLast are equal to theVal+k*thePeriod. //! //! ATTENTION!!! - //! If (myFirst == myLast) then this function will return only either 0 or 2. - Standard_EXPORT int IsIntersected(const double theVal, const double thePeriod = 0.0) const; + //! If (myFirst == myLast) then this function will return only either Out or Boundary. + Standard_EXPORT IntersectStatus IsIntersected(const double theVal, + const double thePeriod = 0.0) const; //! Extends to include theParameter void Add(const double theParameter) @@ -101,6 +120,7 @@ public: else if (IsVoid()) { *this = theRange; + return; } myFirst = (std::min)(myFirst, theRange.myFirst); myLast = (std::max)(myLast, theRange.myLast); @@ -146,6 +166,22 @@ public: return true; } + //! Returns the bounds of this range as a Bounds structure. + //! Returns std::nullopt if IsVoid(). + //! Can be used with C++17 structured bindings: + //! @code + //! if (auto aBounds = aRange.Get()) + //! { + //! auto [aMin, aMax] = *aBounds; + //! } + //! @endcode + [[nodiscard]] std::optional Get() const noexcept + { + if (IsVoid()) + return std::nullopt; + return Bounds{myFirst, myLast}; + } + //! Obtain theParameter satisfied to the equation //! (theParameter-MIN)/(MAX-MIN) == theLambda. //! * theLambda == 0 --> MIN boundary will be returned; @@ -165,21 +201,30 @@ public: return true; } + //! Returns the center of this range ((Min + Max) / 2). + //! Returns std::nullopt if IsVoid(). + [[nodiscard]] std::optional Center() const noexcept + { + if (IsVoid()) + return std::nullopt; + return 0.5 * (myFirst + myLast); + } + //! Returns range value (MAX-MIN). Returns negative value for VOID range. - double Delta() const { return (myLast - myFirst); } + [[nodiscard]] double Delta() const noexcept { return (myLast - myFirst); } //! Is initialized. - bool IsVoid() const { return (myLast < myFirst); } + [[nodiscard]] bool IsVoid() const noexcept { return (myLast < myFirst); } //! Initializes by default parameters. Makes VOID. - void SetVoid() + void SetVoid() noexcept { myLast = -1.0; myFirst = 0.0; } //! Extends this to the given value (in both side) - void Enlarge(const double theDelta) + void Enlarge(const double theDelta) noexcept { if (IsVoid()) { @@ -191,13 +236,13 @@ public: } //! Returns the copy of <*this> shifted by theVal - Bnd_Range Shifted(const double theVal) const + [[nodiscard]] Bnd_Range Shifted(const double theVal) const { return !IsVoid() ? Bnd_Range(myFirst + theVal, myLast + theVal) : Bnd_Range(); } //! Shifts <*this> by theVal - void Shift(const double theVal) + void Shift(const double theVal) noexcept { if (!IsVoid()) { @@ -208,7 +253,7 @@ public: //! Trims the First value in range by the given lower limit. //! Marks range as Void if the given Lower value is greater than range Max. - void TrimFrom(const double theValLower) + void TrimFrom(const double theValLower) noexcept { if (!IsVoid()) { @@ -218,7 +263,7 @@ public: //! Trim the Last value in range by the given Upper limit. //! Marks range as Void if the given Upper value is smaller than range Max. - void TrimTo(const double theValUpper) + void TrimTo(const double theValUpper) noexcept { if (!IsVoid()) { @@ -227,16 +272,46 @@ public: } //! Returns True if the value is out of this range. - bool IsOut(double theValue) const { return IsVoid() || theValue < myFirst || theValue > myLast; } + [[nodiscard]] bool IsOut(double theValue) const noexcept + { + return IsVoid() || theValue < myFirst || theValue > myLast; + } //! Returns True if the given range is out of this range. - bool IsOut(const Bnd_Range& theRange) const + [[nodiscard]] bool IsOut(const Bnd_Range& theRange) const noexcept { return IsVoid() || theRange.IsVoid() || theRange.myLast < myFirst || theRange.myFirst > myLast; } + //! Returns True if the value is within this range. + [[nodiscard]] bool Contains(double theValue) const noexcept { return !IsOut(theValue); } + + //! Returns True if the given range intersects (overlaps with) this range. + [[nodiscard]] bool Intersects(const Bnd_Range& theRange) const noexcept + { + return !IsOut(theRange); + } + + //! Returns the MIN boundary of . + //! Returns std::nullopt if IsVoid(). + [[nodiscard]] std::optional Min() const noexcept + { + if (IsVoid()) + return std::nullopt; + return myFirst; + } + + //! Returns the MAX boundary of . + //! Returns std::nullopt if IsVoid(). + [[nodiscard]] std::optional Max() const noexcept + { + if (IsVoid()) + return std::nullopt; + return myLast; + } + //! Returns TRUE if theOther is equal to <*this> - bool operator==(const Bnd_Range& theOther) const + [[nodiscard]] bool operator==(const Bnd_Range& theOther) const noexcept { return ((myFirst == theOther.myFirst) && (myLast == theOther.myLast)); } diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.cxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.cxx index 6224864d59..440f3648a9 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.cxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.cxx @@ -36,9 +36,10 @@ Bnd_Sphere::Bnd_Sphere(const gp_XYZ& theCenter, void Bnd_Sphere::SquareDistances(const gp_XYZ& theXYZ, double& theMin, double& theMax) const { - theMax = (theXYZ - myCenter).SquareModulus(); - theMin = (theMax - myRadius < 0 ? 0.0 : theMax - myRadius * myRadius); - theMax += myRadius * myRadius; + theMax = (theXYZ - myCenter).SquareModulus(); + const double aRadSq = myRadius * myRadius; + theMin = (theMax < aRadSq ? 0.0 : theMax - aRadSq); + theMax += aRadSq; } void Bnd_Sphere::Distances(const gp_XYZ& theXYZ, double& theMin, double& theMax) const diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.hxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.hxx index 3f68cc4aed..1357ac3450 100644 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.hxx +++ b/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.hxx @@ -21,8 +21,6 @@ #include #include -#include -#include //! This class represents a bounding sphere of a geometric entity //! (triangle, segment of line or whatever else). @@ -41,22 +39,22 @@ public: const int theV); //! Returns the U parameter on shape - int U() const; + int U() const noexcept { return myU; } //! Returns the V parameter on shape - int V() const; + int V() const noexcept { return myV; } //! Returns validity status, indicating that this //! sphere corresponds to a real entity - bool IsValid() const; + bool IsValid() const noexcept { return myIsValid; } - void SetValid(const bool isValid); + void SetValid(const bool isValid) noexcept { myIsValid = isValid; } //! Returns center of sphere object - const gp_XYZ& Center() const; + const gp_XYZ& Center() const noexcept { return myCenter; } //! Returns the radius value - double Radius() const; + double Radius() const noexcept { return myRadius; } //! Calculate and return minimal and maximal distance to sphere. //! NOTE: This function is tightly optimized; any modifications @@ -95,6 +93,4 @@ private: int myV; }; -#include - #endif // _Bnd_Sphere_HeaderFile diff --git a/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.lxx b/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.lxx deleted file mode 100644 index 8675e88a29..0000000000 --- a/src/FoundationClasses/TKMath/Bnd/Bnd_Sphere.lxx +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -inline int Bnd_Sphere::U() const -{ - return myU; -} - -inline int Bnd_Sphere::V() const -{ - return myV; -} - -inline bool Bnd_Sphere::IsValid() const -{ - return myIsValid; -} - -inline void Bnd_Sphere::SetValid(const bool isValid) -{ - myIsValid = isValid; -} - -inline const gp_XYZ& Bnd_Sphere::Center() const -{ - return myCenter; -} - -inline double Bnd_Sphere::Radius() const -{ - return myRadius; -} diff --git a/src/FoundationClasses/TKMath/Bnd/FILES.cmake b/src/FoundationClasses/TKMath/Bnd/FILES.cmake index 31f1cf32da..bf2ff44980 100644 --- a/src/FoundationClasses/TKMath/Bnd/FILES.cmake +++ b/src/FoundationClasses/TKMath/Bnd/FILES.cmake @@ -18,6 +18,5 @@ set(OCCT_Bnd_FILES Bnd_Range.hxx Bnd_Sphere.cxx Bnd_Sphere.hxx - Bnd_Sphere.lxx Bnd_Tools.hxx ) diff --git a/src/FoundationClasses/TKMath/GTests/Bnd_Box2d_Test.cxx b/src/FoundationClasses/TKMath/GTests/Bnd_Box2d_Test.cxx new file mode 100644 index 0000000000..a6b7ef2ebc --- /dev/null +++ b/src/FoundationClasses/TKMath/GTests/Bnd_Box2d_Test.cxx @@ -0,0 +1,443 @@ +// Copyright (c) 2025 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include + +#include + +TEST(Bnd_Box2dTest, DefaultConstructor) +{ + Bnd_Box2d aBox; + EXPECT_TRUE(aBox.IsVoid()); + EXPECT_FALSE(aBox.IsWhole()); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 0.0); +} + +TEST(Bnd_Box2dTest, SetVoid) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + EXPECT_FALSE(aBox.IsVoid()); + aBox.SetVoid(); + EXPECT_TRUE(aBox.IsVoid()); +} + +TEST(Bnd_Box2dTest, SetWhole) +{ + Bnd_Box2d aBox; + aBox.SetWhole(); + EXPECT_TRUE(aBox.IsWhole()); + EXPECT_FALSE(aBox.IsVoid()); +} + +TEST(Bnd_Box2dTest, Update_Bounds) +{ + Bnd_Box2d aBox; + aBox.Update(1.0, 2.0, 10.0, 20.0); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 1.0); + EXPECT_DOUBLE_EQ(aYmin, 2.0); + EXPECT_DOUBLE_EQ(aXmax, 10.0); + EXPECT_DOUBLE_EQ(aYmax, 20.0); +} + +TEST(Bnd_Box2dTest, Update_SinglePoint) +{ + Bnd_Box2d aBox; + aBox.Update(5.0, 7.0); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 5.0); + EXPECT_DOUBLE_EQ(aYmin, 7.0); + EXPECT_DOUBLE_EQ(aXmax, 5.0); + EXPECT_DOUBLE_EQ(aYmax, 7.0); +} + +TEST(Bnd_Box2dTest, Update_Expansion) +{ + Bnd_Box2d aBox; + aBox.Update(1.0, 2.0, 10.0, 20.0); + aBox.Update(0.0, 0.0, 15.0, 25.0); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 0.0); + EXPECT_DOUBLE_EQ(aYmin, 0.0); + EXPECT_DOUBLE_EQ(aXmax, 15.0); + EXPECT_DOUBLE_EQ(aYmax, 25.0); +} + +TEST(Bnd_Box2dTest, GapOperations) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 0.0); + aBox.SetGap(2.0); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 2.0); + aBox.SetGap(-3.0); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 3.0); +} + +TEST(Bnd_Box2dTest, Enlarge) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + aBox.Enlarge(5.0); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 5.0); + aBox.Enlarge(3.0); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 5.0); // max(5, 3) = 5 + aBox.Enlarge(7.0); + EXPECT_DOUBLE_EQ(aBox.GetGap(), 7.0); // max(5, 7) = 7 +} + +TEST(Bnd_Box2dTest, Get_WithGap) +{ + Bnd_Box2d aBox; + aBox.Update(1.0, 2.0, 10.0, 20.0); + aBox.SetGap(0.5); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 0.5); + EXPECT_DOUBLE_EQ(aYmin, 1.5); + EXPECT_DOUBLE_EQ(aXmax, 10.5); + EXPECT_DOUBLE_EQ(aYmax, 20.5); +} + +TEST(Bnd_Box2dTest, Get_StructuredBindings) +{ + Bnd_Box2d aBox; + aBox.Update(1.0, 2.0, 10.0, 20.0); + const auto [aXmin, aXmax, aYmin, aYmax] = aBox.Get(); + EXPECT_DOUBLE_EQ(aXmin, 1.0); + EXPECT_DOUBLE_EQ(aXmax, 10.0); + EXPECT_DOUBLE_EQ(aYmin, 2.0); + EXPECT_DOUBLE_EQ(aYmax, 20.0); +} + +TEST(Bnd_Box2dTest, Set_Point) +{ + Bnd_Box2d aBox; + aBox.Set(gp_Pnt2d(5.0, 7.0)); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 5.0); + EXPECT_DOUBLE_EQ(aYmin, 7.0); + EXPECT_DOUBLE_EQ(aXmax, 5.0); + EXPECT_DOUBLE_EQ(aYmax, 7.0); +} + +TEST(Bnd_Box2dTest, Add_Point) +{ + Bnd_Box2d aBox; + aBox.Add(gp_Pnt2d(1.0, 2.0)); + aBox.Add(gp_Pnt2d(10.0, 20.0)); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 1.0); + EXPECT_DOUBLE_EQ(aYmin, 2.0); + EXPECT_DOUBLE_EQ(aXmax, 10.0); + EXPECT_DOUBLE_EQ(aYmax, 20.0); +} + +TEST(Bnd_Box2dTest, Add_Box) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 5.0, 5.0); + Bnd_Box2d aBox2; + aBox2.Update(3.0, 3.0, 10.0, 10.0); + aBox1.Add(aBox2); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox1.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 0.0); + EXPECT_DOUBLE_EQ(aYmin, 0.0); + EXPECT_DOUBLE_EQ(aXmax, 10.0); + EXPECT_DOUBLE_EQ(aYmax, 10.0); +} + +TEST(Bnd_Box2dTest, Add_VoidBox) +{ + Bnd_Box2d aBox; + aBox.Update(1.0, 2.0, 5.0, 6.0); + Bnd_Box2d aVoidBox; + aBox.Add(aVoidBox); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 1.0); + EXPECT_DOUBLE_EQ(aYmin, 2.0); +} + +TEST(Bnd_Box2dTest, Add_ToVoidBox) +{ + Bnd_Box2d aVoidBox; + Bnd_Box2d aBox; + aBox.Update(1.0, 2.0, 5.0, 6.0); + aVoidBox.Add(aBox); + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aVoidBox.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 1.0); + EXPECT_DOUBLE_EQ(aYmin, 2.0); + EXPECT_DOUBLE_EQ(aXmax, 5.0); + EXPECT_DOUBLE_EQ(aYmax, 6.0); +} + +TEST(Bnd_Box2dTest, OpenDirections) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + EXPECT_FALSE(aBox.IsOpenXmin()); + EXPECT_FALSE(aBox.IsOpenXmax()); + EXPECT_FALSE(aBox.IsOpenYmin()); + EXPECT_FALSE(aBox.IsOpenYmax()); + + aBox.OpenXmin(); + EXPECT_TRUE(aBox.IsOpenXmin()); + aBox.OpenYmax(); + EXPECT_TRUE(aBox.IsOpenYmax()); + EXPECT_FALSE(aBox.IsWhole()); +} + +TEST(Bnd_Box2dTest, IsOut_Point) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + EXPECT_FALSE(aBox.IsOut(gp_Pnt2d(5.0, 5.0))); + EXPECT_TRUE(aBox.IsOut(gp_Pnt2d(15.0, 5.0))); + EXPECT_TRUE(aBox.IsOut(gp_Pnt2d(-1.0, 5.0))); +} + +TEST(Bnd_Box2dTest, IsOut_Box_Overlapping) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 10.0, 10.0); + Bnd_Box2d aBox2; + aBox2.Update(5.0, 5.0, 15.0, 15.0); + EXPECT_FALSE(aBox1.IsOut(aBox2)); +} + +TEST(Bnd_Box2dTest, IsOut_Box_Separated) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 5.0, 5.0); + Bnd_Box2d aBox2; + aBox2.Update(10.0, 10.0, 15.0, 15.0); + EXPECT_TRUE(aBox1.IsOut(aBox2)); +} + +TEST(Bnd_Box2dTest, IsOut_Box_FastPath) +{ + // Both non-void, non-whole, non-open -> fast path + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 10.0, 10.0); + Bnd_Box2d aBox2; + aBox2.Update(5.0, 5.0, 15.0, 15.0); + EXPECT_FALSE(aBox1.IsOut(aBox2)); + + Bnd_Box2d aBox3; + aBox3.Update(20.0, 20.0, 30.0, 30.0); + EXPECT_TRUE(aBox1.IsOut(aBox3)); +} + +TEST(Bnd_Box2dTest, IsOut_Box_FastPath_WithGap) +{ + // Boxes separated by 1.0, but gap bridges it + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 5.0, 5.0); + aBox1.SetGap(1.0); + Bnd_Box2d aBox2; + aBox2.Update(6.0, 0.0, 10.0, 5.0); + // Gap from box1 = 1.0, gap from box2 = 0.0, total = 1.0 + // Xmin1 - Xmax2 = 0 - 10 = -10 (not > 1.0) -> not out in X + // Xmin2 - Xmax1 = 6 - 5 = 1 (not > 1.0, equal) -> not out + EXPECT_FALSE(aBox1.IsOut(aBox2)); + + // Now increase separation + Bnd_Box2d aBox3; + aBox3.Update(7.0, 0.0, 10.0, 5.0); + // Xmin3 - Xmax1 = 7 - 5 = 2 > 1.0 -> out + EXPECT_TRUE(aBox1.IsOut(aBox3)); +} + +TEST(Bnd_Box2dTest, IsOut_VoidBox) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + Bnd_Box2d aVoid; + EXPECT_TRUE(aBox.IsOut(aVoid)); + EXPECT_TRUE(aVoid.IsOut(aBox)); +} + +TEST(Bnd_Box2dTest, IsOut_WholeBox) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + Bnd_Box2d aWhole; + aWhole.SetWhole(); + EXPECT_FALSE(aBox.IsOut(aWhole)); + EXPECT_FALSE(aWhole.IsOut(aBox)); +} + +TEST(Bnd_Box2dTest, IsOut_OpenBox) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 10.0, 10.0); + aBox1.OpenXmin(); // extends to -infinity in X + + Bnd_Box2d aBox2; + aBox2.Update(-100.0, 0.0, -50.0, 10.0); + + // aBox1 is open in Xmin, so extends to -infinity: should overlap + EXPECT_FALSE(aBox1.IsOut(aBox2)); +} + +TEST(Bnd_Box2dTest, IsOut_Line) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + + // Line that intersects + gp_Lin2d aLinInside(gp_Pnt2d(5.0, -5.0), gp_Dir2d(0.0, 1.0)); + EXPECT_FALSE(aBox.IsOut(aLinInside)); + + // Line that doesn't intersect + gp_Lin2d aLinOutside(gp_Pnt2d(20.0, -5.0), gp_Dir2d(0.0, 1.0)); + EXPECT_TRUE(aBox.IsOut(aLinOutside)); +} + +TEST(Bnd_Box2dTest, IsOut_Segment) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + + // Segment that crosses + EXPECT_FALSE(aBox.IsOut(gp_Pnt2d(5.0, -5.0), gp_Pnt2d(5.0, 15.0))); + + // Segment fully outside + EXPECT_TRUE(aBox.IsOut(gp_Pnt2d(20.0, 0.0), gp_Pnt2d(20.0, 10.0))); +} + +TEST(Bnd_Box2dTest, Transformed) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + + gp_Trsf2d aTrsf; + aTrsf.SetTranslation(gp_Pnt2d(0.0, 0.0), gp_Pnt2d(5.0, 5.0)); + Bnd_Box2d aTransformed = aBox.Transformed(aTrsf); + + double aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; + aTransformed.Get(aXmin, aYmin, aXmax, aYmax); + EXPECT_DOUBLE_EQ(aXmin, 5.0); + EXPECT_DOUBLE_EQ(aYmin, 5.0); + EXPECT_DOUBLE_EQ(aXmax, 15.0); + EXPECT_DOUBLE_EQ(aYmax, 15.0); +} + +TEST(Bnd_Box2dTest, SquareExtent) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 3.0, 4.0); + // Diagonal^2 = 3^2 + 4^2 = 25 + EXPECT_DOUBLE_EQ(aBox.SquareExtent(), 25.0); +} + +TEST(Bnd_Box2dTest, SquareExtent_Void) +{ + Bnd_Box2d aBox; + EXPECT_DOUBLE_EQ(aBox.SquareExtent(), 0.0); +} + +TEST(Bnd_Box2dTest, Add_Direction) +{ + Bnd_Box2d aBox; + aBox.Set(gp_Pnt2d(5.0, 5.0)); + aBox.Add(gp_Dir2d(1.0, 0.0)); + EXPECT_TRUE(aBox.IsOpenXmax()); + EXPECT_FALSE(aBox.IsOpenXmin()); +} + +TEST(Bnd_Box2dTest, Contains_Point) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 10.0); + EXPECT_TRUE(aBox.Contains(gp_Pnt2d(5.0, 5.0))); + EXPECT_TRUE(aBox.Contains(gp_Pnt2d(0.0, 0.0))); + EXPECT_FALSE(aBox.Contains(gp_Pnt2d(-1.0, 5.0))); + EXPECT_FALSE(aBox.Contains(gp_Pnt2d(5.0, 11.0))); +} + +TEST(Bnd_Box2dTest, Intersects_Box) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 10.0, 10.0); + Bnd_Box2d aBox2; + aBox2.Update(5.0, 5.0, 15.0, 15.0); + Bnd_Box2d aBox3; + aBox3.Update(20.0, 20.0, 30.0, 30.0); + EXPECT_TRUE(aBox1.Intersects(aBox2)); + EXPECT_FALSE(aBox1.Intersects(aBox3)); +} + +TEST(Bnd_Box2dTest, Distance_Separated) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 1.0, 1.0); + Bnd_Box2d aBox2; + aBox2.Update(4.0, 0.0, 5.0, 1.0); + EXPECT_NEAR(aBox1.Distance(aBox2), 3.0, 1e-10); +} + +TEST(Bnd_Box2dTest, Distance_Overlapping) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 10.0, 10.0); + Bnd_Box2d aBox2; + aBox2.Update(5.0, 5.0, 15.0, 15.0); + EXPECT_DOUBLE_EQ(aBox1.Distance(aBox2), 0.0); +} + +TEST(Bnd_Box2dTest, Distance_Diagonal) +{ + Bnd_Box2d aBox1; + aBox1.Update(0.0, 0.0, 1.0, 1.0); + Bnd_Box2d aBox2; + aBox2.Update(4.0, 4.0, 5.0, 5.0); + EXPECT_NEAR(aBox1.Distance(aBox2), std::sqrt(18.0), 1e-10); +} + +TEST(Bnd_Box2dTest, Distance_Void) +{ + Bnd_Box2d aBox1; + Bnd_Box2d aBox2; + aBox2.Update(0.0, 0.0, 1.0, 1.0); + EXPECT_DOUBLE_EQ(aBox1.Distance(aBox2), 0.0); +} + +TEST(Bnd_Box2dTest, Center) +{ + Bnd_Box2d aBox; + aBox.Update(0.0, 0.0, 10.0, 20.0); + auto aCenter = aBox.Center(); + ASSERT_TRUE(aCenter.has_value()); + EXPECT_DOUBLE_EQ(aCenter->X(), 5.0); + EXPECT_DOUBLE_EQ(aCenter->Y(), 10.0); +} + +TEST(Bnd_Box2dTest, Center_VoidNullopt) +{ + Bnd_Box2d aVoid; + EXPECT_FALSE(aVoid.Center().has_value()); +} diff --git a/src/FoundationClasses/TKMath/GTests/Bnd_Box_Test.cxx b/src/FoundationClasses/TKMath/GTests/Bnd_Box_Test.cxx index 459349cac4..77081b285f 100644 --- a/src/FoundationClasses/TKMath/GTests/Bnd_Box_Test.cxx +++ b/src/FoundationClasses/TKMath/GTests/Bnd_Box_Test.cxx @@ -845,4 +845,38 @@ TEST(Bnd_BoxTest, OCC16485_CumulativeEnlargeTolerance) // Verify that Xmin is approximately -tolerance (not growing with iterations) EXPECT_NEAR(-aTol, aXmin, 1e-10) << "Xmin should be equal to -tolerance"; EXPECT_NEAR(aNbStep + aTol, aXmax, 1e-10) << "Xmax should be equal to nbstep + tolerance"; +} + +TEST(Bnd_BoxTest, Contains_Point) +{ + Bnd_Box aBox(gp_Pnt(0, 0, 0), gp_Pnt(10, 10, 10)); + EXPECT_TRUE(aBox.Contains(gp_Pnt(5, 5, 5))); + EXPECT_TRUE(aBox.Contains(gp_Pnt(0, 0, 0))); + EXPECT_FALSE(aBox.Contains(gp_Pnt(-1, 5, 5))); + EXPECT_FALSE(aBox.Contains(gp_Pnt(5, 5, 11))); +} + +TEST(Bnd_BoxTest, Intersects_Box) +{ + Bnd_Box aBox1(gp_Pnt(0, 0, 0), gp_Pnt(10, 10, 10)); + Bnd_Box aBox2(gp_Pnt(5, 5, 5), gp_Pnt(15, 15, 15)); + Bnd_Box aBox3(gp_Pnt(20, 20, 20), gp_Pnt(30, 30, 30)); + EXPECT_TRUE(aBox1.Intersects(aBox2)); + EXPECT_FALSE(aBox1.Intersects(aBox3)); +} + +TEST(Bnd_BoxTest, Center) +{ + Bnd_Box aBox(gp_Pnt(0, 0, 0), gp_Pnt(10, 20, 30)); + auto aCenter = aBox.Center(); + ASSERT_TRUE(aCenter.has_value()); + EXPECT_DOUBLE_EQ(aCenter->X(), 5.0); + EXPECT_DOUBLE_EQ(aCenter->Y(), 10.0); + EXPECT_DOUBLE_EQ(aCenter->Z(), 15.0); +} + +TEST(Bnd_BoxTest, Center_VoidNullopt) +{ + Bnd_Box aVoid; + EXPECT_FALSE(aVoid.Center().has_value()); } \ No newline at end of file diff --git a/src/FoundationClasses/TKMath/GTests/Bnd_OBB_Test.cxx b/src/FoundationClasses/TKMath/GTests/Bnd_OBB_Test.cxx index d865f73a15..68396243a9 100644 --- a/src/FoundationClasses/TKMath/GTests/Bnd_OBB_Test.cxx +++ b/src/FoundationClasses/TKMath/GTests/Bnd_OBB_Test.cxx @@ -77,3 +77,30 @@ TEST(Bnd_OBB_Test, OCC30704_AddPointToVoidBox) EXPECT_DOUBLE_EQ(aCenter.Y(), 200.0); EXPECT_DOUBLE_EQ(aCenter.Z(), 300.0); } + +TEST(Bnd_OBB_Test, Contains_Point) +{ + Bnd_OBB anOBB(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0), gp_Dir(0, 1, 0), gp_Dir(0, 0, 1), 5.0, 5.0, 5.0); + EXPECT_TRUE(anOBB.Contains(gp_Pnt(0, 0, 0))); + EXPECT_TRUE(anOBB.Contains(gp_Pnt(4, 4, 4))); + EXPECT_FALSE(anOBB.Contains(gp_Pnt(10, 0, 0))); +} + +TEST(Bnd_OBB_Test, Intersects_OBB) +{ + Bnd_OBB anOBB1(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0), gp_Dir(0, 1, 0), gp_Dir(0, 0, 1), 5.0, 5.0, 5.0); + Bnd_OBB anOBB2(gp_Pnt(8, 0, 0), gp_Dir(1, 0, 0), gp_Dir(0, 1, 0), gp_Dir(0, 0, 1), 5.0, 5.0, 5.0); + Bnd_OBB + anOBB3(gp_Pnt(20, 0, 0), gp_Dir(1, 0, 0), gp_Dir(0, 1, 0), gp_Dir(0, 0, 1), 5.0, 5.0, 5.0); + EXPECT_TRUE(anOBB1.Intersects(anOBB2)); + EXPECT_FALSE(anOBB1.Intersects(anOBB3)); +} + +TEST(Bnd_OBB_Test, GetHalfSizes_StructuredBindings) +{ + Bnd_OBB anOBB(gp_Pnt(0, 0, 0), gp_Dir(1, 0, 0), gp_Dir(0, 1, 0), gp_Dir(0, 0, 1), 3.0, 5.0, 7.0); + const auto [aHX, aHY, aHZ] = anOBB.GetHalfSizes(); + EXPECT_DOUBLE_EQ(aHX, 3.0); + EXPECT_DOUBLE_EQ(aHY, 5.0); + EXPECT_DOUBLE_EQ(aHZ, 7.0); +} diff --git a/src/FoundationClasses/TKMath/GTests/Bnd_Range_Test.cxx b/src/FoundationClasses/TKMath/GTests/Bnd_Range_Test.cxx new file mode 100644 index 0000000000..193c17e854 --- /dev/null +++ b/src/FoundationClasses/TKMath/GTests/Bnd_Range_Test.cxx @@ -0,0 +1,511 @@ +// Copyright (c) 2025 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include + +#include + +TEST(Bnd_RangeTest, DefaultConstructor_IsVoid) +{ + Bnd_Range aRange; + EXPECT_TRUE(aRange.IsVoid()); + EXPECT_LT(aRange.Delta(), 0.0); +} + +TEST(Bnd_RangeTest, ParameterizedConstructor) +{ + Bnd_Range aRange(3.0, 15.0); + EXPECT_FALSE(aRange.IsVoid()); + EXPECT_DOUBLE_EQ(aRange.Delta(), 12.0); +} + +TEST(Bnd_RangeTest, ParameterizedConstructor_InvalidRange) +{ + EXPECT_THROW(Bnd_Range(10.0, 5.0), Standard_ConstructionError); +} + +TEST(Bnd_RangeTest, ParameterizedConstructor_PointRange) +{ + Bnd_Range aRange(5.0, 5.0); + EXPECT_FALSE(aRange.IsVoid()); + EXPECT_DOUBLE_EQ(aRange.Delta(), 0.0); +} + +TEST(Bnd_RangeTest, GetMin_GetMax_GetBounds) +{ + Bnd_Range aRange(2.0, 8.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetMin(aMin)); + EXPECT_DOUBLE_EQ(aMin, 2.0); + EXPECT_TRUE(aRange.GetMax(aMax)); + EXPECT_DOUBLE_EQ(aMax, 8.0); + + double aFirst = 0.0, aLast = 0.0; + EXPECT_TRUE(aRange.GetBounds(aFirst, aLast)); + EXPECT_DOUBLE_EQ(aFirst, 2.0); + EXPECT_DOUBLE_EQ(aLast, 8.0); +} + +TEST(Bnd_RangeTest, GetMin_GetMax_Void) +{ + Bnd_Range aRange; + double aVal = 0.0; + EXPECT_FALSE(aRange.GetMin(aVal)); + EXPECT_FALSE(aRange.GetMax(aVal)); + + double aFirst = 0.0, aLast = 0.0; + EXPECT_FALSE(aRange.GetBounds(aFirst, aLast)); +} + +TEST(Bnd_RangeTest, GetIntermediatePoint) +{ + Bnd_Range aRange(10.0, 20.0); + double aPar = 0.0; + EXPECT_TRUE(aRange.GetIntermediatePoint(0.0, aPar)); + EXPECT_DOUBLE_EQ(aPar, 10.0); + EXPECT_TRUE(aRange.GetIntermediatePoint(0.5, aPar)); + EXPECT_DOUBLE_EQ(aPar, 15.0); + EXPECT_TRUE(aRange.GetIntermediatePoint(1.0, aPar)); + EXPECT_DOUBLE_EQ(aPar, 20.0); +} + +TEST(Bnd_RangeTest, GetIntermediatePoint_Void) +{ + Bnd_Range aRange; + double aPar = 0.0; + EXPECT_FALSE(aRange.GetIntermediatePoint(0.5, aPar)); +} + +TEST(Bnd_RangeTest, SetVoid) +{ + Bnd_Range aRange(1.0, 5.0); + EXPECT_FALSE(aRange.IsVoid()); + aRange.SetVoid(); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, Add_Double_ToVoid) +{ + Bnd_Range aRange; + aRange.Add(5.0); + EXPECT_FALSE(aRange.IsVoid()); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 5.0); + EXPECT_DOUBLE_EQ(aMax, 5.0); +} + +TEST(Bnd_RangeTest, Add_Double_Extends) +{ + Bnd_Range aRange(3.0, 7.0); + aRange.Add(1.0); + aRange.Add(10.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 1.0); + EXPECT_DOUBLE_EQ(aMax, 10.0); +} + +TEST(Bnd_RangeTest, Add_Range_ToVoid) +{ + Bnd_Range aRange; + Bnd_Range anOther(3.0, 7.0); + aRange.Add(anOther); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 7.0); +} + +TEST(Bnd_RangeTest, Add_VoidRange) +{ + Bnd_Range aRange(3.0, 7.0); + Bnd_Range aVoid; + aRange.Add(aVoid); + // Should remain unchanged + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 7.0); +} + +TEST(Bnd_RangeTest, Add_Range_VoidToVoid) +{ + Bnd_Range aRange; + Bnd_Range aVoid; + aRange.Add(aVoid); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, Add_Range_Extends) +{ + Bnd_Range aRange(3.0, 7.0); + Bnd_Range anOther(1.0, 10.0); + aRange.Add(anOther); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 1.0); + EXPECT_DOUBLE_EQ(aMax, 10.0); +} + +TEST(Bnd_RangeTest, Common_Overlapping) +{ + Bnd_Range aRange(1.0, 10.0); + Bnd_Range anOther(5.0, 15.0); + aRange.Common(anOther); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 5.0); + EXPECT_DOUBLE_EQ(aMax, 10.0); +} + +TEST(Bnd_RangeTest, Common_NoOverlap) +{ + Bnd_Range aRange(1.0, 5.0); + Bnd_Range anOther(7.0, 10.0); + aRange.Common(anOther); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, Common_WithVoid) +{ + Bnd_Range aRange(1.0, 5.0); + Bnd_Range aVoid; + aRange.Common(aVoid); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, Union_Overlapping) +{ + Bnd_Range aRange(1.0, 7.0); + Bnd_Range anOther(5.0, 15.0); + EXPECT_TRUE(aRange.Union(anOther)); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 1.0); + EXPECT_DOUBLE_EQ(aMax, 15.0); +} + +TEST(Bnd_RangeTest, Union_Separated) +{ + Bnd_Range aRange(1.0, 5.0); + Bnd_Range anOther(7.0, 10.0); + EXPECT_FALSE(aRange.Union(anOther)); + // aRange should remain unchanged + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 1.0); + EXPECT_DOUBLE_EQ(aMax, 5.0); +} + +TEST(Bnd_RangeTest, Union_WithVoid) +{ + Bnd_Range aRange(1.0, 5.0); + Bnd_Range aVoid; + EXPECT_FALSE(aRange.Union(aVoid)); +} + +TEST(Bnd_RangeTest, IsIntersected_Void) +{ + Bnd_Range aRange; + EXPECT_EQ(aRange.IsIntersected(5.0), Bnd_Range::IntersectStatus_Out); +} + +TEST(Bnd_RangeTest, IsIntersected_Contains) +{ + Bnd_Range aRange(3.0, 15.0); + EXPECT_EQ(aRange.IsIntersected(5.0), Bnd_Range::IntersectStatus_In); +} + +TEST(Bnd_RangeTest, IsIntersected_Outside) +{ + Bnd_Range aRange(3.0, 15.0); + EXPECT_EQ(aRange.IsIntersected(20.0), Bnd_Range::IntersectStatus_Out); + EXPECT_EQ(aRange.IsIntersected(1.0), Bnd_Range::IntersectStatus_Out); +} + +TEST(Bnd_RangeTest, IsIntersected_OnBoundary) +{ + Bnd_Range aRange(3.0, 15.0); + EXPECT_EQ(aRange.IsIntersected(3.0), Bnd_Range::IntersectStatus_Boundary); + EXPECT_EQ(aRange.IsIntersected(15.0), Bnd_Range::IntersectStatus_Boundary); +} + +TEST(Bnd_RangeTest, IsIntersected_PointRange) +{ + // When myFirst == myLast, only Out or Boundary possible + Bnd_Range aRange(5.0, 5.0); + EXPECT_EQ(aRange.IsIntersected(5.0), Bnd_Range::IntersectStatus_Boundary); + EXPECT_EQ(aRange.IsIntersected(3.0), Bnd_Range::IntersectStatus_Out); +} + +TEST(Bnd_RangeTest, IsIntersected_Periodic_Contains) +{ + // Range [3, 15], period 4, val 1 + // Check: val + k*period in [3, 15] + // k=1: 1+4=5, inside [3,15] -> In + Bnd_Range aRange(3.0, 15.0); + EXPECT_EQ(aRange.IsIntersected(1.0, 4.0), Bnd_Range::IntersectStatus_In); +} + +TEST(Bnd_RangeTest, IsIntersected_Periodic_OnBoundary) +{ + // Range [3, 15], period 4, val 3 -> val + 0*4 = 3 exactly + Bnd_Range aRange(3.0, 15.0); + EXPECT_EQ(aRange.IsIntersected(3.0, 4.0), Bnd_Range::IntersectStatus_Boundary); +} + +TEST(Bnd_RangeTest, IsIntersected_Periodic_Outside) +{ + // Range [3.5, 3.9], period 4, val 0 + // Check: 0 + k*4 in [3.5, 3.9] -> k=1 gives 4.0, not in range + Bnd_Range aRange(3.5, 3.9); + EXPECT_EQ(aRange.IsIntersected(0.0, 4.0), Bnd_Range::IntersectStatus_Out); +} + +TEST(Bnd_RangeTest, Split_NoIntersection) +{ + Bnd_Range aRange(3.0, 15.0); + NCollection_List aList; + aRange.Split(20.0, aList); + EXPECT_EQ(aList.Size(), 1); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aList.First().GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 15.0); +} + +TEST(Bnd_RangeTest, Split_AtInteriorPoint) +{ + Bnd_Range aRange(3.0, 15.0); + NCollection_List aList; + aRange.Split(5.0, aList); + EXPECT_EQ(aList.Size(), 2); + double aMin1 = 0.0, aMax1 = 0.0; + EXPECT_TRUE(aList.First().GetBounds(aMin1, aMax1)); + EXPECT_DOUBLE_EQ(aMin1, 3.0); + EXPECT_DOUBLE_EQ(aMax1, 5.0); + double aMin2 = 0.0, aMax2 = 0.0; + EXPECT_TRUE(aList.Last().GetBounds(aMin2, aMax2)); + EXPECT_DOUBLE_EQ(aMin2, 5.0); + EXPECT_DOUBLE_EQ(aMax2, 15.0); +} + +TEST(Bnd_RangeTest, Split_Periodic) +{ + // Range [3, 15], split at val=5, period=4 + // Split points: 5, 9, 13 -> sub-ranges: [3,5], [5,9], [9,13], [13,15] + Bnd_Range aRange(3.0, 15.0); + NCollection_List aList; + aRange.Split(5.0, aList, 4.0); + EXPECT_EQ(aList.Size(), 4); +} + +TEST(Bnd_RangeTest, Enlarge) +{ + Bnd_Range aRange(5.0, 10.0); + aRange.Enlarge(2.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 12.0); +} + +TEST(Bnd_RangeTest, Enlarge_Void) +{ + Bnd_Range aRange; + aRange.Enlarge(2.0); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, Shifted) +{ + Bnd_Range aRange(3.0, 7.0); + Bnd_Range aShifted = aRange.Shifted(10.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aShifted.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 13.0); + EXPECT_DOUBLE_EQ(aMax, 17.0); + // Original unchanged + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 7.0); +} + +TEST(Bnd_RangeTest, Shifted_Void) +{ + Bnd_Range aRange; + Bnd_Range aShifted = aRange.Shifted(10.0); + EXPECT_TRUE(aShifted.IsVoid()); +} + +TEST(Bnd_RangeTest, Shift) +{ + Bnd_Range aRange(3.0, 7.0); + aRange.Shift(10.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 13.0); + EXPECT_DOUBLE_EQ(aMax, 17.0); +} + +TEST(Bnd_RangeTest, TrimFrom) +{ + Bnd_Range aRange(3.0, 10.0); + aRange.TrimFrom(5.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 5.0); + EXPECT_DOUBLE_EQ(aMax, 10.0); +} + +TEST(Bnd_RangeTest, TrimFrom_MakesVoid) +{ + Bnd_Range aRange(3.0, 10.0); + aRange.TrimFrom(15.0); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, TrimTo) +{ + Bnd_Range aRange(3.0, 10.0); + aRange.TrimTo(7.0); + double aMin = 0.0, aMax = 0.0; + EXPECT_TRUE(aRange.GetBounds(aMin, aMax)); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 7.0); +} + +TEST(Bnd_RangeTest, TrimTo_MakesVoid) +{ + Bnd_Range aRange(3.0, 10.0); + aRange.TrimTo(1.0); + EXPECT_TRUE(aRange.IsVoid()); +} + +TEST(Bnd_RangeTest, IsOut_Value) +{ + Bnd_Range aRange(3.0, 10.0); + EXPECT_FALSE(aRange.IsOut(5.0)); + EXPECT_FALSE(aRange.IsOut(3.0)); + EXPECT_FALSE(aRange.IsOut(10.0)); + EXPECT_TRUE(aRange.IsOut(1.0)); + EXPECT_TRUE(aRange.IsOut(15.0)); +} + +TEST(Bnd_RangeTest, IsOut_Void) +{ + Bnd_Range aRange; + EXPECT_TRUE(aRange.IsOut(5.0)); +} + +TEST(Bnd_RangeTest, IsOut_Range) +{ + Bnd_Range aRange(3.0, 10.0); + EXPECT_FALSE(aRange.IsOut(Bnd_Range(5.0, 8.0))); + EXPECT_FALSE(aRange.IsOut(Bnd_Range(1.0, 5.0))); + EXPECT_TRUE(aRange.IsOut(Bnd_Range(11.0, 15.0))); +} + +TEST(Bnd_RangeTest, IsOut_Range_Void) +{ + Bnd_Range aRange(3.0, 10.0); + Bnd_Range aVoid; + EXPECT_TRUE(aRange.IsOut(aVoid)); + EXPECT_TRUE(aVoid.IsOut(aRange)); +} + +TEST(Bnd_RangeTest, Equality) +{ + Bnd_Range aRange1(3.0, 10.0); + Bnd_Range aRange2(3.0, 10.0); + Bnd_Range aRange3(3.0, 11.0); + EXPECT_TRUE(aRange1 == aRange2); + EXPECT_FALSE(aRange1 == aRange3); +} + +TEST(Bnd_RangeTest, Contains_Value) +{ + Bnd_Range aRange(3.0, 10.0); + EXPECT_TRUE(aRange.Contains(5.0)); + EXPECT_TRUE(aRange.Contains(3.0)); + EXPECT_TRUE(aRange.Contains(10.0)); + EXPECT_FALSE(aRange.Contains(2.0)); + EXPECT_FALSE(aRange.Contains(11.0)); + + Bnd_Range aVoid; + EXPECT_FALSE(aVoid.Contains(5.0)); +} + +TEST(Bnd_RangeTest, Intersects_Range) +{ + Bnd_Range aRange1(3.0, 10.0); + Bnd_Range aRange2(5.0, 15.0); + Bnd_Range aRange3(11.0, 20.0); + EXPECT_TRUE(aRange1.Intersects(aRange2)); + EXPECT_FALSE(aRange1.Intersects(aRange3)); + + Bnd_Range aVoid; + EXPECT_FALSE(aRange1.Intersects(aVoid)); +} + +TEST(Bnd_RangeTest, Min_Max_DirectAccess) +{ + Bnd_Range aRange(3.0, 10.0); + ASSERT_TRUE(aRange.Min().has_value()); + ASSERT_TRUE(aRange.Max().has_value()); + EXPECT_DOUBLE_EQ(*aRange.Min(), 3.0); + EXPECT_DOUBLE_EQ(*aRange.Max(), 10.0); +} + +TEST(Bnd_RangeTest, Min_Max_NulloptOnVoid) +{ + Bnd_Range aVoid; + EXPECT_FALSE(aVoid.Min().has_value()); + EXPECT_FALSE(aVoid.Max().has_value()); +} + +TEST(Bnd_RangeTest, Get_StructuredBindings) +{ + Bnd_Range aRange(3.0, 10.0); + auto aBounds = aRange.Get(); + ASSERT_TRUE(aBounds.has_value()); + const auto [aMin, aMax] = *aBounds; + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 10.0); +} + +TEST(Bnd_RangeTest, Get_NulloptOnVoid) +{ + Bnd_Range aVoid; + EXPECT_FALSE(aVoid.Get().has_value()); +} + +TEST(Bnd_RangeTest, Center) +{ + Bnd_Range aRange(2.0, 8.0); + ASSERT_TRUE(aRange.Center().has_value()); + EXPECT_DOUBLE_EQ(*aRange.Center(), 5.0); + + Bnd_Range aPoint(3.0, 3.0); + ASSERT_TRUE(aPoint.Center().has_value()); + EXPECT_DOUBLE_EQ(*aPoint.Center(), 3.0); +} + +TEST(Bnd_RangeTest, Center_NulloptOnVoid) +{ + Bnd_Range aVoid; + EXPECT_FALSE(aVoid.Center().has_value()); +} diff --git a/src/FoundationClasses/TKMath/GTests/Bnd_Sphere_Test.cxx b/src/FoundationClasses/TKMath/GTests/Bnd_Sphere_Test.cxx new file mode 100644 index 0000000000..ae857de20a --- /dev/null +++ b/src/FoundationClasses/TKMath/GTests/Bnd_Sphere_Test.cxx @@ -0,0 +1,224 @@ +// Copyright (c) 2025 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include + +TEST(Bnd_SphereTest, DefaultConstructor) +{ + Bnd_Sphere aSphere; + EXPECT_DOUBLE_EQ(aSphere.Center().X(), 0.0); + EXPECT_DOUBLE_EQ(aSphere.Center().Y(), 0.0); + EXPECT_DOUBLE_EQ(aSphere.Center().Z(), 0.0); + EXPECT_DOUBLE_EQ(aSphere.Radius(), 0.0); + EXPECT_FALSE(aSphere.IsValid()); + EXPECT_EQ(aSphere.U(), 0); + EXPECT_EQ(aSphere.V(), 0); +} + +TEST(Bnd_SphereTest, ParameterizedConstructor) +{ + const gp_XYZ aCenter(1.0, 2.0, 3.0); + Bnd_Sphere aSphere(aCenter, 5.0, 10, 20); + EXPECT_DOUBLE_EQ(aSphere.Center().X(), 1.0); + EXPECT_DOUBLE_EQ(aSphere.Center().Y(), 2.0); + EXPECT_DOUBLE_EQ(aSphere.Center().Z(), 3.0); + EXPECT_DOUBLE_EQ(aSphere.Radius(), 5.0); + EXPECT_EQ(aSphere.U(), 10); + EXPECT_EQ(aSphere.V(), 20); +} + +TEST(Bnd_SphereTest, Validity) +{ + Bnd_Sphere aSphere; + EXPECT_FALSE(aSphere.IsValid()); + aSphere.SetValid(true); + EXPECT_TRUE(aSphere.IsValid()); + aSphere.SetValid(false); + EXPECT_FALSE(aSphere.IsValid()); +} + +TEST(Bnd_SphereTest, Distance) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 1.0, 0, 0); + const gp_XYZ aPoint(3.0, 4.0, 0.0); + const double aDist = aSphere.Distance(aPoint); + EXPECT_DOUBLE_EQ(aDist, 5.0); +} + +TEST(Bnd_SphereTest, SquareDistance) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 1.0, 0, 0); + const gp_XYZ aPoint(3.0, 4.0, 0.0); + EXPECT_DOUBLE_EQ(aSphere.SquareDistance(aPoint), 25.0); +} + +TEST(Bnd_SphereTest, Distances_PointOutside) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 2.0, 0, 0); + const gp_XYZ aPoint(5.0, 0.0, 0.0); + double aMin = 0.0, aMax = 0.0; + aSphere.Distances(aPoint, aMin, aMax); + EXPECT_DOUBLE_EQ(aMin, 3.0); + EXPECT_DOUBLE_EQ(aMax, 7.0); +} + +TEST(Bnd_SphereTest, Distances_PointInside) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 5.0, 0, 0); + const gp_XYZ aPoint(1.0, 0.0, 0.0); + double aMin = 0.0, aMax = 0.0; + aSphere.Distances(aPoint, aMin, aMax); + EXPECT_DOUBLE_EQ(aMin, 0.0); + EXPECT_DOUBLE_EQ(aMax, 6.0); +} + +TEST(Bnd_SphereTest, SquareDistances_PointOutside) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 2.0, 0, 0); + const gp_XYZ aPoint(5.0, 0.0, 0.0); + double aMin = 0.0, aMax = 0.0; + aSphere.SquareDistances(aPoint, aMin, aMax); + // d^2 = 25, r^2 = 4 + // min = d^2 - r^2 = 21, max = d^2 + r^2 = 29 + EXPECT_DOUBLE_EQ(aMin, 21.0); + EXPECT_DOUBLE_EQ(aMax, 29.0); +} + +TEST(Bnd_SphereTest, SquareDistances_PointInside) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 5.0, 0, 0); + const gp_XYZ aPoint(1.0, 0.0, 0.0); + double aMin = 0.0, aMax = 0.0; + aSphere.SquareDistances(aPoint, aMin, aMax); + // d^2 = 1, r^2 = 25 + // d^2 < r^2 -> min = 0, max = d^2 + r^2 = 26 + EXPECT_DOUBLE_EQ(aMin, 0.0); + EXPECT_DOUBLE_EQ(aMax, 26.0); +} + +TEST(Bnd_SphereTest, SquareDistances_PointAtCenter) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 3.0, 0, 0); + const gp_XYZ aPoint(0.0, 0.0, 0.0); + double aMin = 0.0, aMax = 0.0; + aSphere.SquareDistances(aPoint, aMin, aMax); + // d^2 = 0, r^2 = 9 + // d^2 < r^2 -> min = 0, max = 0 + 9 = 9 + EXPECT_DOUBLE_EQ(aMin, 0.0); + EXPECT_DOUBLE_EQ(aMax, 9.0); +} + +TEST(Bnd_SphereTest, SquareDistances_PointOnSurface) +{ + const gp_XYZ aCenter(0.0, 0.0, 0.0); + Bnd_Sphere aSphere(aCenter, 3.0, 0, 0); + const gp_XYZ aPoint(3.0, 0.0, 0.0); + double aMin = 0.0, aMax = 0.0; + aSphere.SquareDistances(aPoint, aMin, aMax); + // d^2 = 9, r^2 = 9 + // d^2 < r^2 is false (equal), so min = d^2 - r^2 = 0, max = d^2 + r^2 = 18 + EXPECT_DOUBLE_EQ(aMin, 0.0); + EXPECT_DOUBLE_EQ(aMax, 18.0); +} + +TEST(Bnd_SphereTest, Project) +{ + const gp_XYZ aCenter(1.0, 2.0, 3.0); + Bnd_Sphere aSphere(aCenter, 5.0, 0, 0); + const gp_XYZ aNode(10.0, 20.0, 30.0); + gp_XYZ aProjNode; + double aDist = 0.0; + bool anInside = false; + const bool isOk = aSphere.Project(aNode, aProjNode, aDist, anInside); + EXPECT_TRUE(isOk); + EXPECT_TRUE(anInside); + EXPECT_DOUBLE_EQ(aProjNode.X(), aCenter.X()); + EXPECT_DOUBLE_EQ(aProjNode.Y(), aCenter.Y()); + EXPECT_DOUBLE_EQ(aProjNode.Z(), aCenter.Z()); +} + +TEST(Bnd_SphereTest, Add_EnclosingSphere) +{ + Bnd_Sphere aSphere1(gp_XYZ(0.0, 0.0, 0.0), 10.0, 0, 0); + Bnd_Sphere aSphere2(gp_XYZ(1.0, 0.0, 0.0), 2.0, 0, 0); + aSphere1.Add(aSphere2); + // aSphere1 already encloses aSphere2, should remain unchanged + EXPECT_DOUBLE_EQ(aSphere1.Radius(), 10.0); +} + +TEST(Bnd_SphereTest, Add_EnclosedBySphere) +{ + Bnd_Sphere aSphere1(gp_XYZ(0.0, 0.0, 0.0), 2.0, 0, 0); + Bnd_Sphere aSphere2(gp_XYZ(0.0, 0.0, 0.0), 10.0, 0, 0); + aSphere1.Add(aSphere2); + // aSphere2 encloses aSphere1, should take aSphere2 + EXPECT_DOUBLE_EQ(aSphere1.Radius(), 10.0); +} + +TEST(Bnd_SphereTest, Add_PartialOverlap) +{ + Bnd_Sphere aSphere1(gp_XYZ(0.0, 0.0, 0.0), 3.0, 0, 0); + Bnd_Sphere aSphere2(gp_XYZ(5.0, 0.0, 0.0), 3.0, 0, 0); + aSphere1.Add(aSphere2); + // Combined radius should be (5 + 3 + 3) / 2 = 5.5 + EXPECT_DOUBLE_EQ(aSphere1.Radius(), 5.5); +} + +TEST(Bnd_SphereTest, IsOut_Separated) +{ + Bnd_Sphere aSphere1(gp_XYZ(0.0, 0.0, 0.0), 1.0, 0, 0); + Bnd_Sphere aSphere2(gp_XYZ(10.0, 0.0, 0.0), 1.0, 0, 0); + EXPECT_TRUE(aSphere1.IsOut(aSphere2)); +} + +TEST(Bnd_SphereTest, IsOut_Overlapping) +{ + Bnd_Sphere aSphere1(gp_XYZ(0.0, 0.0, 0.0), 3.0, 0, 0); + Bnd_Sphere aSphere2(gp_XYZ(4.0, 0.0, 0.0), 3.0, 0, 0); + EXPECT_FALSE(aSphere1.IsOut(aSphere2)); +} + +TEST(Bnd_SphereTest, IsOut_PointWithMaxDist) +{ + Bnd_Sphere aSphere(gp_XYZ(0.0, 0.0, 0.0), 5.0, 0, 0); + const gp_XYZ aPoint(20.0, 0.0, 0.0); + double aMaxDist = 100.0; + aSphere.SetValid(true); + EXPECT_FALSE(aSphere.IsOut(aPoint, aMaxDist)); + // aMaxDist should be updated to aCurMaxDist = 20 + 5 = 25 + EXPECT_DOUBLE_EQ(aMaxDist, 25.0); +} + +TEST(Bnd_SphereTest, IsOut_PointTooFar) +{ + Bnd_Sphere aSphere(gp_XYZ(0.0, 0.0, 0.0), 1.0, 0, 0); + const gp_XYZ aPoint(20.0, 0.0, 0.0); + double aMaxDist = 10.0; + EXPECT_TRUE(aSphere.IsOut(aPoint, aMaxDist)); +} + +TEST(Bnd_SphereTest, SquareExtent) +{ + Bnd_Sphere aSphere(gp_XYZ(0.0, 0.0, 0.0), 3.0, 0, 0); + EXPECT_DOUBLE_EQ(aSphere.SquareExtent(), 36.0); +} diff --git a/src/FoundationClasses/TKMath/GTests/FILES.cmake b/src/FoundationClasses/TKMath/GTests/FILES.cmake index b513fafa0a..b02f1c30a7 100644 --- a/src/FoundationClasses/TKMath/GTests/FILES.cmake +++ b/src/FoundationClasses/TKMath/GTests/FILES.cmake @@ -6,7 +6,10 @@ set(OCCT_TKMath_GTests_FILES Bnd_B3_Test.cxx Bnd_BoundSortBox_Test.cxx Bnd_Box_Test.cxx + Bnd_Box2d_Test.cxx Bnd_OBB_Test.cxx + Bnd_Range_Test.cxx + Bnd_Sphere_Test.cxx BSplCLib_Cache_Test.cxx BSplCLib_Test.cxx BSplSLib_Cache_Test.cxx diff --git a/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_WLineTool.cxx b/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_WLineTool.cxx index d40eac7f3f..926ab2b332 100644 --- a/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_WLineTool.cxx +++ b/src/ModelingAlgorithms/TKGeomAlgo/IntPatch/IntPatch_WLineTool.cxx @@ -613,10 +613,10 @@ static bool IsSeamOrBound(const IntSurf_PntOn2S& thePtf, aBndR[i].Add(aParF[i]); aBndR[i].Add(aParL[i]); - if (aBndR[i].IsIntersected(theFBound[i], theArrPeriods[i]) == 1) + if (aBndR[i].IsIntersected(theFBound[i], theArrPeriods[i]) == Bnd_Range::IntersectStatus_In) return true; - if (aBndR[i].IsIntersected(theLBound[i], theArrPeriods[i]) == 1) + if (aBndR[i].IsIntersected(theLBound[i], theArrPeriods[i]) == Bnd_Range::IntersectStatus_In) return true; } @@ -635,7 +635,7 @@ static bool IsSeamOrBound(const IntSurf_PntOn2S& thePtf, return true; } - if (aBndR[i].IsIntersected(0.0, theArrPeriods[i]) == 1) + if (aBndR[i].IsIntersected(0.0, theArrPeriods[i]) == Bnd_Range::IntersectStatus_In) return true; }