// Created on: 2005-09-08 // Created by: Alexander GRIGORIEV // Copyright (c) 2005-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. #ifndef _Bnd_B3_HeaderFile #define _Bnd_B3_HeaderFile #include "Standard.hxx" #include "Standard_DefineAlloc.hxx" #include "Standard_Real.hxx" #include "Standard_ShortReal.hxx" #include "gp.hxx" #include "gp_XYZ.hxx" #include "gp_Pnt.hxx" #include "gp_Trsf.hxx" #include "gp_Ax1.hxx" #include "gp_Ax3.hxx" #include //! Template class for 3D bounding box. //! This is a base template that is instantiated for double and float. template class Bnd_B3 { public: DEFINE_STANDARD_ALLOC //! Empty constructor. constexpr Bnd_B3() noexcept; //! Constructor. constexpr Bnd_B3(const gp_XYZ& theCenter, const gp_XYZ& theHSize) noexcept; //! Constructor. constexpr Bnd_B3(const std::array& theCenter, const std::array& theHSize) noexcept; //! Returns True if the box is void (non-initialized). constexpr bool IsVoid() const noexcept; //! Reset the box data. void Clear() noexcept; //! Update the box by a point. void Add(const gp_XYZ& thePnt); //! Update the box by a point. void Add(const gp_Pnt& thePnt); //! Update the box by another box. void Add(const Bnd_B3& theBox); //! Query the lower corner: (Center - HSize). You must make sure that //! the box is NOT VOID (see IsVoid()), otherwise the method returns //! irrelevant result. gp_XYZ CornerMin() const noexcept; //! Query the upper corner: (Center + HSize). You must make sure that //! the box is NOT VOID (see IsVoid()), otherwise the method returns //! irrelevant result. gp_XYZ CornerMax() const noexcept; //! Query the square diagonal. If the box is VOID (see method IsVoid()) //! then a very big real value is returned. constexpr double SquareExtent() const noexcept; //! Extend the Box by the absolute value of theDiff. void Enlarge(const double theDiff) noexcept; //! Limit the Box by the internals of theOtherBox. //! Returns True if the limitation takes place, otherwise False //! indicating that the boxes do not intersect. bool Limit(const Bnd_B3& theOtherBox); //! Transform the bounding box with the given transformation. //! The resulting box will be larger if theTrsf contains rotation. [[nodiscard]] Bnd_B3 Transformed(const gp_Trsf& theTrsf) const; //! Check the given point for the inclusion in the Box. //! Returns True if the point is outside. constexpr bool IsOut(const gp_XYZ& thePnt) const noexcept; //! Check a sphere for the intersection with the current box. //! Returns True if there is no intersection between boxes. If the //! parameter 'IsSphereHollow' is True, then the intersection is not //! reported for a box that is completely inside the sphere (otherwise //! this method would report an intersection). bool IsOut(const gp_XYZ& theCenter, const double theRadius, const bool isSphereHollow = false) const; //! Check the given box for the intersection with the current box. //! Returns True if there is no intersection between boxes. constexpr bool IsOut(const Bnd_B3& theOtherBox) const noexcept; //! Check the given box oriented by the given transformation //! for the intersection with the current box. //! Returns True if there is no intersection between boxes. bool IsOut(const Bnd_B3& theOtherBox, const gp_Trsf& theTrsf) const; //! Check the given Line for the intersection with the current box. //! Returns True if there is no intersection. //! isRay==True means intersection check with the positive half-line //! theOverthickness is the addition to the size of the current box //! (may be negative). If positive, it can be treated as the thickness //! of the line 'theLine' or the radius of the cylinder along 'theLine' bool IsOut(const gp_Ax1& theLine, const bool isRay = false, const double theOverthickness = 0.0) const; //! Check the given Plane for the intersection with the current box. //! Returns True if there is no intersection. bool IsOut(const gp_Ax3& thePlane) const; //! Check that the box 'this' is inside the given box 'theBox'. Returns //! True if 'this' box is fully inside 'theBox'. constexpr bool IsIn(const Bnd_B3& theBox) const noexcept; //! Check that the box 'this' is inside the given box 'theBox' //! transformed by 'theTrsf'. Returns True if 'this' box is fully //! inside the transformed 'theBox'. bool IsIn(const Bnd_B3& theBox, const gp_Trsf& theTrsf) const; //! Set the Center coordinates void SetCenter(const gp_XYZ& theCenter) noexcept; //! Set the Center coordinates void SetCenter(const std::array& theCenter) noexcept; //! Set the HSize (half-diagonal) coordinates. //! All components of theHSize must be non-negative. void SetHSize(const gp_XYZ& theHSize) noexcept; //! Set the HSize (half-diagonal) coordinates. //! All components of theHSize must be non-negative. void SetHSize(const std::array& theHSize) noexcept; //! Get the Center coordinates constexpr const std::array& Center() const noexcept; //! Get the HSize (half-diagonal) coordinates constexpr const std::array& HSize() const noexcept; protected: static constexpr bool compareDist(const RealType aHSize[3], const RealType aDist[3]) noexcept { return (std::abs(aDist[0]) > aHSize[0] || std::abs(aDist[1]) > aHSize[1] || std::abs(aDist[2]) > aHSize[2]); } static bool compareDistD(const gp_XYZ& aHSize, const gp_XYZ& aDist) noexcept { return (std::abs(aDist.X()) > aHSize.X() || std::abs(aDist.Y()) > aHSize.Y() || std::abs(aDist.Z()) > aHSize.Z()); } //! Constant representing a very large value for void box initialization static constexpr RealType THE_RealLast = RealType(1e30); private: std::array myCenter; std::array myHSize; }; //================================================================================================= template constexpr inline Bnd_B3::Bnd_B3() noexcept : myCenter{THE_RealLast, THE_RealLast, THE_RealLast}, myHSize{-THE_RealLast, -THE_RealLast, -THE_RealLast} { } //================================================================================================= template constexpr inline Bnd_B3::Bnd_B3(const gp_XYZ& theCenter, const gp_XYZ& theHSize) noexcept : myCenter{RealType(theCenter.X()), RealType(theCenter.Y()), RealType(theCenter.Z())}, myHSize{RealType(theHSize.X()), RealType(theHSize.Y()), RealType(theHSize.Z())} { } //================================================================================================= template constexpr inline Bnd_B3::Bnd_B3(const std::array& theCenter, const std::array& theHSize) noexcept : myCenter(theCenter), myHSize(theHSize) { } //================================================================================================= template inline void Bnd_B3::Clear() noexcept { myCenter[0] = THE_RealLast; myCenter[1] = THE_RealLast; myCenter[2] = THE_RealLast; myHSize[0] = -THE_RealLast; myHSize[1] = -THE_RealLast; myHSize[2] = -THE_RealLast; } //================================================================================================= template constexpr inline bool Bnd_B3::IsVoid() const noexcept { return (myHSize[0] < -1e-5); } //================================================================================================= template inline void Bnd_B3::Add(const gp_Pnt& thePnt) { Add(thePnt.XYZ()); } //================================================================================================= template inline void Bnd_B3::Add(const Bnd_B3& theBox) { if (!theBox.IsVoid()) { Add(theBox.CornerMin()); Add(theBox.CornerMax()); } } //================================================================================================= template inline gp_XYZ Bnd_B3::CornerMin() const noexcept { return gp_XYZ(myCenter[0] - myHSize[0], myCenter[1] - myHSize[1], myCenter[2] - myHSize[2]); } //================================================================================================= template inline gp_XYZ Bnd_B3::CornerMax() const noexcept { return gp_XYZ(myCenter[0] + myHSize[0], myCenter[1] + myHSize[1], myCenter[2] + myHSize[2]); } //================================================================================================= template constexpr inline double Bnd_B3::SquareExtent() const noexcept { return 4 * (myHSize[0] * myHSize[0] + myHSize[1] * myHSize[1] + myHSize[2] * myHSize[2]); } //================================================================================================= template inline void Bnd_B3::SetCenter(const gp_XYZ& theCenter) noexcept { myCenter[0] = RealType(theCenter.X()); myCenter[1] = RealType(theCenter.Y()); myCenter[2] = RealType(theCenter.Z()); } //================================================================================================= template inline void Bnd_B3::SetHSize(const gp_XYZ& theHSize) noexcept { myHSize[0] = RealType(theHSize.X()); myHSize[1] = RealType(theHSize.Y()); myHSize[2] = RealType(theHSize.Z()); } //================================================================================================= template inline void Bnd_B3::SetCenter(const std::array& theCenter) noexcept { myCenter = theCenter; } //================================================================================================= template inline void Bnd_B3::SetHSize(const std::array& theHSize) noexcept { myHSize = theHSize; } //================================================================================================= template constexpr inline const std::array& Bnd_B3::Center() const noexcept { return myCenter; } //================================================================================================= template constexpr inline const std::array& Bnd_B3::HSize() const noexcept { return myHSize; } //================================================================================================= template inline void Bnd_B3::Enlarge(const double aDiff) noexcept { const double aD = std::abs(aDiff); myHSize[0] += RealType(aD); myHSize[1] += RealType(aD); myHSize[2] += RealType(aD); } //================================================================================================= template constexpr inline bool Bnd_B3::IsOut(const gp_XYZ& thePnt) const noexcept { return (std::abs(RealType(thePnt.X()) - myCenter[0]) > myHSize[0] || std::abs(RealType(thePnt.Y()) - myCenter[1]) > myHSize[1] || std::abs(RealType(thePnt.Z()) - myCenter[2]) > myHSize[2]); } //================================================================================================= template constexpr inline bool Bnd_B3::IsOut(const Bnd_B3& theBox) const noexcept { return (std::abs(theBox.myCenter[0] - myCenter[0]) > theBox.myHSize[0] + myHSize[0] || std::abs(theBox.myCenter[1] - myCenter[1]) > theBox.myHSize[1] + myHSize[1] || std::abs(theBox.myCenter[2] - myCenter[2]) > theBox.myHSize[2] + myHSize[2]); } //================================================================================================= template constexpr inline bool Bnd_B3::IsIn(const Bnd_B3& theBox) const noexcept { return (std::abs(theBox.myCenter[0] - myCenter[0]) < theBox.myHSize[0] - myHSize[0] && std::abs(theBox.myCenter[1] - myCenter[1]) < theBox.myHSize[1] - myHSize[1] && std::abs(theBox.myCenter[2] - myCenter[2]) < theBox.myHSize[2] - myHSize[2]); } //================================================================================================= template void Bnd_B3::Add(const gp_XYZ& thePnt) { if (IsVoid()) { myCenter[0] = RealType(thePnt.X()); myCenter[1] = RealType(thePnt.Y()); myCenter[2] = RealType(thePnt.Z()); myHSize[0] = 0.; myHSize[1] = 0.; myHSize[2] = 0.; } else { const RealType aDiff[3] = {RealType(thePnt.X()) - myCenter[0], RealType(thePnt.Y()) - myCenter[1], RealType(thePnt.Z()) - myCenter[2]}; if (aDiff[0] > myHSize[0]) { const RealType aShift = (aDiff[0] - myHSize[0]) / 2; myCenter[0] += aShift; myHSize[0] += aShift; } else if (aDiff[0] < -myHSize[0]) { const RealType aShift = (aDiff[0] + myHSize[0]) / 2; myCenter[0] += aShift; myHSize[0] -= aShift; } if (aDiff[1] > myHSize[1]) { const RealType aShift = (aDiff[1] - myHSize[1]) / 2; myCenter[1] += aShift; myHSize[1] += aShift; } else if (aDiff[1] < -myHSize[1]) { const RealType aShift = (aDiff[1] + myHSize[1]) / 2; myCenter[1] += aShift; myHSize[1] -= aShift; } if (aDiff[2] > myHSize[2]) { const RealType aShift = (aDiff[2] - myHSize[2]) / 2; myCenter[2] += aShift; myHSize[2] += aShift; } else if (aDiff[2] < -myHSize[2]) { const RealType aShift = (aDiff[2] + myHSize[2]) / 2; myCenter[2] += aShift; myHSize[2] -= aShift; } } } //================================================================================================= template bool Bnd_B3::Limit(const Bnd_B3& theBox) { bool aResult(false); const RealType diffC[3] = {theBox.myCenter[0] - myCenter[0], theBox.myCenter[1] - myCenter[1], theBox.myCenter[2] - myCenter[2]}; const RealType sumH[3] = {theBox.myHSize[0] + myHSize[0], theBox.myHSize[1] + myHSize[1], theBox.myHSize[2] + myHSize[2]}; // check the condition IsOut if (!compareDist(sumH, diffC)) { const RealType diffH[3] = {theBox.myHSize[0] - myHSize[0], theBox.myHSize[1] - myHSize[1], theBox.myHSize[2] - myHSize[2]}; if (diffC[0] - diffH[0] > 0.) { const RealType aShift = (diffC[0] - diffH[0]) / 2; // positive myCenter[0] += aShift; myHSize[0] -= aShift; } else if (diffC[0] + diffH[0] < 0.) { const RealType aShift = (diffC[0] + diffH[0]) / 2; // negative myCenter[0] += aShift; myHSize[0] += aShift; } if (diffC[1] - diffH[1] > 0.) { const RealType aShift = (diffC[1] - diffH[1]) / 2; // positive myCenter[1] += aShift; myHSize[1] -= aShift; } else if (diffC[1] + diffH[1] < 0.) { const RealType aShift = (diffC[1] + diffH[1]) / 2; // negative myCenter[1] += aShift; myHSize[1] += aShift; } if (diffC[2] - diffH[2] > 0.) { const RealType aShift = (diffC[2] - diffH[2]) / 2; // positive myCenter[2] += aShift; myHSize[2] -= aShift; } else if (diffC[2] + diffH[2] < 0.) { const RealType aShift = (diffC[2] + diffH[2]) / 2; // negative myCenter[2] += aShift; myHSize[2] += aShift; } aResult = true; } return aResult; } //================================================================================================= template Bnd_B3 Bnd_B3::Transformed(const gp_Trsf& theTrsf) const { Bnd_B3 aResult; const gp_TrsfForm aForm = theTrsf.Form(); const double aScale = theTrsf.ScaleFactor(); const double aScaleAbs = std::abs(aScale); if (aForm == gp_Identity) aResult = *this; else if (aForm == gp_Translation || aForm == gp_PntMirror || aForm == gp_Scale) { aResult.myCenter[0] = (RealType)(myCenter[0] * aScale + theTrsf.TranslationPart().X()); aResult.myCenter[1] = (RealType)(myCenter[1] * aScale + theTrsf.TranslationPart().Y()); aResult.myCenter[2] = (RealType)(myCenter[2] * aScale + theTrsf.TranslationPart().Z()); aResult.myHSize[0] = (RealType)(myHSize[0] * aScaleAbs); aResult.myHSize[1] = (RealType)(myHSize[1] * aScaleAbs); aResult.myHSize[2] = (RealType)(myHSize[2] * aScaleAbs); } else { gp_XYZ aCenter((double)myCenter[0], (double)myCenter[1], (double)myCenter[2]); theTrsf.Transforms(aCenter); aResult.myCenter[0] = (RealType)aCenter.X(); aResult.myCenter[1] = (RealType)aCenter.Y(); aResult.myCenter[2] = (RealType)aCenter.Z(); const double* aMat = &theTrsf.HVectorialPart().Value(1, 1); aResult.myHSize[0] = (RealType)(aScaleAbs * (std::abs(aMat[0]) * myHSize[0] + std::abs(aMat[1]) * myHSize[1] + std::abs(aMat[2]) * myHSize[2])); aResult.myHSize[1] = (RealType)(aScaleAbs * (std::abs(aMat[3]) * myHSize[0] + std::abs(aMat[4]) * myHSize[1] + std::abs(aMat[5]) * myHSize[2])); aResult.myHSize[2] = (RealType)(aScaleAbs * (std::abs(aMat[6]) * myHSize[0] + std::abs(aMat[7]) * myHSize[1] + std::abs(aMat[8]) * myHSize[2])); } return aResult; } //================================================================================================= template bool Bnd_B3::IsOut(const gp_XYZ& theCenter, const double theRadius, const bool isSphereHollow) const { bool aResult(true); if (!isSphereHollow) { // vector from the center of the sphere to the nearest box face const double aDist[3] = {std::abs(theCenter.X() - double(myCenter[0])) - double(myHSize[0]), std::abs(theCenter.Y() - double(myCenter[1])) - double(myHSize[1]), std::abs(theCenter.Z() - double(myCenter[2])) - double(myHSize[2])}; double aD(0.); if (aDist[0] > 0.) aD = aDist[0] * aDist[0]; if (aDist[1] > 0.) aD += aDist[1] * aDist[1]; if (aDist[2] > 0.) aD += aDist[2] * aDist[2]; aResult = (aD > theRadius * theRadius); } else { const double aDistC[3] = {std::abs(theCenter.X() - double(myCenter[0])), std::abs(theCenter.Y() - double(myCenter[1])), std::abs(theCenter.Z() - double(myCenter[2]))}; // vector from the center of the sphere to the nearest box face double aDist[3] = {aDistC[0] - double(myHSize[0]), aDistC[1] - double(myHSize[1]), aDistC[2] - double(myHSize[2])}; double aD(0.); if (aDist[0] > 0.) aD = aDist[0] * aDist[0]; if (aDist[1] > 0.) aD += aDist[1] * aDist[1]; if (aDist[2] > 0.) aD += aDist[2] * aDist[2]; if (aD < theRadius * theRadius) { // the box intersects the solid sphere; check if it is completely // inside the circle (in such case return isOut==True) aDist[0] = aDistC[0] + double(myHSize[0]); aDist[1] = aDistC[1] + double(myHSize[1]); aDist[2] = aDistC[2] + double(myHSize[2]); if (aDist[0] * aDist[0] + aDist[1] * aDist[1] + aDist[2] * aDist[2] > theRadius * theRadius) aResult = false; } } return aResult; } //================================================================================================= template bool Bnd_B3::IsOut(const Bnd_B3& theBox, const gp_Trsf& theTrsf) const { bool aResult(false); const gp_TrsfForm aForm = theTrsf.Form(); const double aScale = theTrsf.ScaleFactor(); const double aScaleAbs = std::abs(aScale); if (aForm == gp_Translation || aForm == gp_Identity || aForm == gp_PntMirror || aForm == gp_Scale) { aResult = (std::abs(RealType(theBox.myCenter[0] * aScale + theTrsf.TranslationPart().X()) - myCenter[0]) > RealType(theBox.myHSize[0] * aScaleAbs) + myHSize[0] || std::abs(RealType(theBox.myCenter[1] * aScale + theTrsf.TranslationPart().Y()) - myCenter[1]) > RealType(theBox.myHSize[1] * aScaleAbs) + myHSize[1] || std::abs(RealType(theBox.myCenter[2] * aScale + theTrsf.TranslationPart().Z()) - myCenter[2]) > RealType(theBox.myHSize[2] * aScaleAbs) + myHSize[2]); } else { // theBox is transformed and we check the resulting (enlarged) box against // 'this' box. const double* aMat = &theTrsf.HVectorialPart().Value(1, 1); gp_XYZ aCenter((double)theBox.myCenter[0], (double)theBox.myCenter[1], (double)theBox.myCenter[2]); theTrsf.Transforms(aCenter); const double aDist[3] = {aCenter.X() - (double)myCenter[0], aCenter.Y() - (double)myCenter[1], aCenter.Z() - (double)myCenter[2]}; const double aMatAbs[9] = {std::abs(aMat[0]), std::abs(aMat[1]), std::abs(aMat[2]), std::abs(aMat[3]), std::abs(aMat[4]), std::abs(aMat[5]), std::abs(aMat[6]), std::abs(aMat[7]), std::abs(aMat[8])}; if (std::abs(aDist[0]) > (aScaleAbs * (aMatAbs[0] * theBox.myHSize[0] + aMatAbs[1] * theBox.myHSize[1] + aMatAbs[2] * theBox.myHSize[2]) + (double)myHSize[0]) || std::abs(aDist[1]) > (aScaleAbs * (aMatAbs[3] * theBox.myHSize[0] + aMatAbs[4] * theBox.myHSize[1] + aMatAbs[5] * theBox.myHSize[2]) + (double)myHSize[1]) || std::abs(aDist[2]) > (aScaleAbs * (aMatAbs[6] * theBox.myHSize[0] + aMatAbs[7] * theBox.myHSize[1] + aMatAbs[8] * theBox.myHSize[2]) + (double)myHSize[2])) aResult = true; else { // theBox is rotated, scaled and translated. We apply the reverse // translation and scaling then check against the rotated box 'this' if ((std::abs(aMat[0] * aDist[0] + aMat[3] * aDist[1] + aMat[6] * aDist[2]) > theBox.myHSize[0] * aScaleAbs + (aMatAbs[0] * myHSize[0] + aMatAbs[3] * myHSize[1] + aMatAbs[6] * myHSize[2])) || (std::abs(aMat[1] * aDist[0] + aMat[4] * aDist[1] + aMat[7] * aDist[2]) > theBox.myHSize[1] * aScaleAbs + (aMatAbs[1] * myHSize[0] + aMatAbs[4] * myHSize[1] + aMatAbs[7] * myHSize[2])) || (std::abs(aMat[2] * aDist[0] + aMat[5] * aDist[1] + aMat[8] * aDist[2]) > theBox.myHSize[2] * aScaleAbs + (aMatAbs[2] * myHSize[0] + aMatAbs[5] * myHSize[1] + aMatAbs[8] * myHSize[2]))) aResult = true; } } return aResult; } //================================================================================================= template bool Bnd_B3::IsOut(const gp_Ax3& thePlane) const { if (IsVoid()) return true; const gp_XYZ& anOrigin = thePlane.Location().XYZ(); const gp_XYZ& aDir = thePlane.Direction().XYZ(); const gp_XYZ aBoxCenter((double)myCenter[0], (double)myCenter[1], (double)myCenter[2]); const double aDist0 = (aBoxCenter - anOrigin) * aDir; // Find the signed distances from two opposite corners of the box to the plane // If the distances are not the same sign, then the plane crosses the box const double aDist1 = // proj of HSize on aDir double(myHSize[0]) * std::abs(aDir.X()) + double(myHSize[1]) * std::abs(aDir.Y()) + double(myHSize[2]) * std::abs(aDir.Z()); return ((aDist0 + aDist1) * (aDist0 - aDist1) > 0.); } //================================================================================================= template bool Bnd_B3::IsOut(const gp_Ax1& theLine, const bool isRay, const double theOverthickness) const { const double aRes = gp::Resolution() * 100.; if (IsVoid()) return true; double anInter0[2] = {-RealLast(), RealLast()}, anInter1[2] = {-RealLast(), RealLast()}; const gp_XYZ& aDir = theLine.Direction().XYZ(); const gp_XYZ aDiff((double)myCenter[0] - theLine.Location().X(), (double)myCenter[1] - theLine.Location().Y(), (double)myCenter[2] - theLine.Location().Z()); // Find the parameter interval in X dimension double aHSize = (double)myHSize[0] + theOverthickness; if (aDir.X() > aRes) { anInter0[0] = (aDiff.X() - aHSize) / aDir.X(); anInter0[1] = (aDiff.X() + aHSize) / aDir.X(); } else if (aDir.X() < -aRes) { anInter0[0] = (aDiff.X() + aHSize) / aDir.X(); anInter0[1] = (aDiff.X() - aHSize) / aDir.X(); } else // the line is orthogonal to OX axis. Test for inclusion in box limits if (std::abs(aDiff.X()) > aHSize) return true; // Find the parameter interval in Y dimension aHSize = (double)myHSize[1] + theOverthickness; if (aDir.Y() > aRes) { anInter1[0] = (aDiff.Y() - aHSize) / aDir.Y(); anInter1[1] = (aDiff.Y() + aHSize) / aDir.Y(); } else if (aDir.Y() < -aRes) { anInter1[0] = (aDiff.Y() + aHSize) / aDir.Y(); anInter1[1] = (aDiff.Y() - aHSize) / aDir.Y(); } else // the line is orthogonal to OY axis. Test for inclusion in box limits if (std::abs(aDiff.Y()) > aHSize) return true; // Intersect Y-interval with X-interval if (anInter0[0] > (anInter1[1] + aRes) || anInter0[1] < (anInter1[0] - aRes)) return true; if (anInter1[0] > anInter0[0]) anInter0[0] = anInter1[0]; if (anInter1[1] < anInter0[1]) anInter0[1] = anInter1[1]; if (isRay && anInter0[1] < -aRes) return true; // Find the parameter interval in Z dimension aHSize = (double)myHSize[2] + theOverthickness; if (aDir.Z() > aRes) { anInter1[0] = (aDiff.Z() - aHSize) / aDir.Z(); anInter1[1] = (aDiff.Z() + aHSize) / aDir.Z(); } else if (aDir.Z() < -aRes) { anInter1[0] = (aDiff.Z() + aHSize) / aDir.Z(); anInter1[1] = (aDiff.Z() - aHSize) / aDir.Z(); } else // the line is orthogonal to OZ axis. Test for inclusion in box limits return (std::abs(aDiff.Z()) > aHSize); if (isRay && anInter1[1] < -aRes) return true; return (anInter0[0] > (anInter1[1] + aRes) || anInter0[1] < (anInter1[0] - aRes)); } //================================================================================================= template bool Bnd_B3::IsIn(const Bnd_B3& theBox, const gp_Trsf& theTrsf) const { bool aResult(false); const gp_TrsfForm aForm = theTrsf.Form(); const double aScale = theTrsf.ScaleFactor(); const double aScaleAbs = std::abs(aScale); if (aForm == gp_Translation || aForm == gp_Identity || aForm == gp_PntMirror || aForm == gp_Scale) { aResult = (std::abs(RealType(theBox.myCenter[0] * aScale + theTrsf.TranslationPart().X()) - myCenter[0]) < RealType(theBox.myHSize[0] * aScaleAbs) - myHSize[0] && std::abs(RealType(theBox.myCenter[1] * aScale + theTrsf.TranslationPart().Y()) - myCenter[1]) < RealType(theBox.myHSize[1] * aScaleAbs) - myHSize[1] && std::abs(RealType(theBox.myCenter[2] * aScale + theTrsf.TranslationPart().Z()) - myCenter[2]) < RealType(theBox.myHSize[2] * aScaleAbs) - myHSize[2]); } else { // theBox is rotated, scaled and translated. We apply the reverse // translation and scaling then check against the rotated box 'this' const double* aMat = &theTrsf.HVectorialPart().Value(1, 1); gp_XYZ aCenter((double)theBox.myCenter[0], (double)theBox.myCenter[1], (double)theBox.myCenter[2]); theTrsf.Transforms(aCenter); const double aDist[3] = {aCenter.X() - (double)myCenter[0], aCenter.Y() - (double)myCenter[1], aCenter.Z() - (double)myCenter[2]}; if ((std::abs(aMat[0] * aDist[0] + aMat[3] * aDist[1] + aMat[6] * aDist[2]) < theBox.myHSize[0] * aScaleAbs - (std::abs(aMat[0]) * myHSize[0] + std::abs(aMat[3]) * myHSize[1] + std::abs(aMat[6]) * myHSize[2])) && (std::abs(aMat[1] * aDist[0] + aMat[4] * aDist[1] + aMat[7] * aDist[2]) < theBox.myHSize[1] * aScaleAbs - (std::abs(aMat[1]) * myHSize[0] + std::abs(aMat[4]) * myHSize[1] + std::abs(aMat[7]) * myHSize[2])) && (std::abs(aMat[2] * aDist[0] + aMat[5] * aDist[1] + aMat[8] * aDist[2]) < theBox.myHSize[2] * aScaleAbs - (std::abs(aMat[2]) * myHSize[0] + std::abs(aMat[5]) * myHSize[1] + std::abs(aMat[8]) * myHSize[2]))) aResult = true; } return aResult; } //================================================================================================= //! 3D bounding box with double precision using Bnd_B3d = Bnd_B3; //! 3D bounding box with single precision using Bnd_B3f = Bnd_B3; #endif // _Bnd_B3_HeaderFile