Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:19:24

0001 // Created on: 2005-09-08
0002 // Created by: Alexander GRIGORIEV
0003 // Copyright (c) 2005-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _Bnd_B3_HeaderFile
0017 #define _Bnd_B3_HeaderFile
0018 
0019 #include <Standard.hxx>
0020 #include <Standard_DefineAlloc.hxx>
0021 #include <Standard_Real.hxx>
0022 #include <Standard_ShortReal.hxx>
0023 #include <gp.hxx>
0024 #include <gp_XYZ.hxx>
0025 #include <gp_Pnt.hxx>
0026 #include <gp_Trsf.hxx>
0027 #include <gp_Ax1.hxx>
0028 #include <gp_Ax3.hxx>
0029 
0030 #include <array>
0031 
0032 //! Template class for 3D bounding box.
0033 //! This is a base template that is instantiated for double and float.
0034 template <typename RealType>
0035 class Bnd_B3
0036 {
0037 public:
0038   DEFINE_STANDARD_ALLOC
0039 
0040   //! Empty constructor.
0041   constexpr Bnd_B3() noexcept;
0042 
0043   //! Constructor.
0044   constexpr Bnd_B3(const gp_XYZ& theCenter, const gp_XYZ& theHSize) noexcept;
0045 
0046   //! Constructor.
0047   constexpr Bnd_B3(const std::array<RealType, 3>& theCenter,
0048                    const std::array<RealType, 3>& theHSize) noexcept;
0049 
0050   //! Returns True if the box is void (non-initialized).
0051   constexpr bool IsVoid() const noexcept;
0052 
0053   //! Reset the box data.
0054   void Clear() noexcept;
0055 
0056   //! Update the box by a point.
0057   void Add(const gp_XYZ& thePnt);
0058 
0059   //! Update the box by a point.
0060   void Add(const gp_Pnt& thePnt);
0061 
0062   //! Update the box by another box.
0063   void Add(const Bnd_B3<RealType>& theBox);
0064 
0065   //! Query the lower corner: (Center - HSize). You must make sure that
0066   //! the box is NOT VOID (see IsVoid()), otherwise the method returns
0067   //! irrelevant result.
0068   gp_XYZ CornerMin() const noexcept;
0069 
0070   //! Query the upper corner: (Center + HSize). You must make sure that
0071   //! the box is NOT VOID (see IsVoid()), otherwise the method returns
0072   //! irrelevant result.
0073   gp_XYZ CornerMax() const noexcept;
0074 
0075   //! Query the square diagonal. If the box is VOID (see method IsVoid())
0076   //! then a very big real value is returned.
0077   constexpr double SquareExtent() const noexcept;
0078 
0079   //! Extend the Box by the absolute value of theDiff.
0080   void Enlarge(const double theDiff) noexcept;
0081 
0082   //! Limit the Box by the internals of theOtherBox.
0083   //! Returns True if the limitation takes place, otherwise False
0084   //! indicating that the boxes do not intersect.
0085   bool Limit(const Bnd_B3<RealType>& theOtherBox);
0086 
0087   //! Transform the bounding box with the given transformation.
0088   //! The resulting box will be larger if theTrsf contains rotation.
0089   [[nodiscard]] Bnd_B3<RealType> Transformed(const gp_Trsf& theTrsf) const;
0090 
0091   //! Check the given point for the inclusion in the Box.
0092   //! Returns True if the point is outside.
0093   constexpr bool IsOut(const gp_XYZ& thePnt) const noexcept;
0094 
0095   //! Check a sphere for the intersection with the current box.
0096   //! Returns True if there is no intersection between boxes. If the
0097   //! parameter 'IsSphereHollow' is True, then the intersection is not
0098   //! reported for a box that is completely inside the sphere (otherwise
0099   //! this method would report an intersection).
0100   bool IsOut(const gp_XYZ& theCenter,
0101              const double  theRadius,
0102              const bool    isSphereHollow = false) const;
0103 
0104   //! Check the given box for the intersection with the current box.
0105   //! Returns True if there is no intersection between boxes.
0106   constexpr bool IsOut(const Bnd_B3<RealType>& theOtherBox) const noexcept;
0107 
0108   //! Check the given box oriented by the given transformation
0109   //! for the intersection with the current box.
0110   //! Returns True if there is no intersection between boxes.
0111   bool IsOut(const Bnd_B3<RealType>& theOtherBox, const gp_Trsf& theTrsf) const;
0112 
0113   //! Check the given Line for the intersection with the current box.
0114   //! Returns True if there is no intersection.
0115   //! isRay==True means intersection check with the positive half-line
0116   //! theOverthickness is the addition to the size of the current box
0117   //! (may be negative). If positive, it can be treated as the thickness
0118   //! of the line 'theLine' or the radius of the cylinder along 'theLine'
0119   bool IsOut(const gp_Ax1& theLine,
0120              const bool    isRay            = false,
0121              const double  theOverthickness = 0.0) const;
0122 
0123   //! Check the given Plane for the intersection with the current box.
0124   //! Returns True if there is no intersection.
0125   bool IsOut(const gp_Ax3& thePlane) const;
0126 
0127   //! Check that the box 'this' is inside the given box 'theBox'. Returns
0128   //! True if 'this' box is fully inside 'theBox'.
0129   constexpr bool IsIn(const Bnd_B3<RealType>& theBox) const noexcept;
0130 
0131   //! Check that the box 'this' is inside the given box 'theBox'
0132   //! transformed by 'theTrsf'. Returns True if 'this' box is fully
0133   //! inside the transformed 'theBox'.
0134   bool IsIn(const Bnd_B3<RealType>& theBox, const gp_Trsf& theTrsf) const;
0135 
0136   //! Set the Center coordinates
0137   void SetCenter(const gp_XYZ& theCenter) noexcept;
0138 
0139   //! Set the Center coordinates
0140   void SetCenter(const std::array<RealType, 3>& theCenter) noexcept;
0141 
0142   //! Set the HSize (half-diagonal) coordinates.
0143   //! All components of theHSize must be non-negative.
0144   void SetHSize(const gp_XYZ& theHSize) noexcept;
0145 
0146   //! Set the HSize (half-diagonal) coordinates.
0147   //! All components of theHSize must be non-negative.
0148   void SetHSize(const std::array<RealType, 3>& theHSize) noexcept;
0149 
0150   //! Get the Center coordinates
0151   constexpr const std::array<RealType, 3>& Center() const noexcept;
0152 
0153   //! Get the HSize (half-diagonal) coordinates
0154   constexpr const std::array<RealType, 3>& HSize() const noexcept;
0155 
0156 protected:
0157   static constexpr bool compareDist(const RealType aHSize[3], const RealType aDist[3]) noexcept
0158   {
0159     return (std::abs(aDist[0]) > aHSize[0] || std::abs(aDist[1]) > aHSize[1]
0160             || std::abs(aDist[2]) > aHSize[2]);
0161   }
0162 
0163   static bool compareDistD(const gp_XYZ& aHSize, const gp_XYZ& aDist) noexcept
0164   {
0165     return (std::abs(aDist.X()) > aHSize.X() || std::abs(aDist.Y()) > aHSize.Y()
0166             || std::abs(aDist.Z()) > aHSize.Z());
0167   }
0168 
0169   //! Constant representing a very large value for void box initialization
0170   static constexpr RealType THE_RealLast = RealType(1e30);
0171 
0172 private:
0173   std::array<RealType, 3> myCenter;
0174   std::array<RealType, 3> myHSize;
0175 };
0176 
0177 //=================================================================================================
0178 
0179 template <typename RealType>
0180 constexpr inline Bnd_B3<RealType>::Bnd_B3() noexcept
0181     : myCenter{THE_RealLast, THE_RealLast, THE_RealLast},
0182       myHSize{-THE_RealLast, -THE_RealLast, -THE_RealLast}
0183 {
0184 }
0185 
0186 //=================================================================================================
0187 
0188 template <typename RealType>
0189 constexpr inline Bnd_B3<RealType>::Bnd_B3(const gp_XYZ& theCenter, const gp_XYZ& theHSize) noexcept
0190     : myCenter{RealType(theCenter.X()), RealType(theCenter.Y()), RealType(theCenter.Z())},
0191       myHSize{RealType(theHSize.X()), RealType(theHSize.Y()), RealType(theHSize.Z())}
0192 {
0193 }
0194 
0195 //=================================================================================================
0196 
0197 template <typename RealType>
0198 constexpr inline Bnd_B3<RealType>::Bnd_B3(const std::array<RealType, 3>& theCenter,
0199                                           const std::array<RealType, 3>& theHSize) noexcept
0200     : myCenter(theCenter),
0201       myHSize(theHSize)
0202 {
0203 }
0204 
0205 //=================================================================================================
0206 
0207 template <typename RealType>
0208 inline void Bnd_B3<RealType>::Clear() noexcept
0209 {
0210   myCenter[0] = THE_RealLast;
0211   myCenter[1] = THE_RealLast;
0212   myCenter[2] = THE_RealLast;
0213   myHSize[0]  = -THE_RealLast;
0214   myHSize[1]  = -THE_RealLast;
0215   myHSize[2]  = -THE_RealLast;
0216 }
0217 
0218 //=================================================================================================
0219 
0220 template <typename RealType>
0221 constexpr inline bool Bnd_B3<RealType>::IsVoid() const noexcept
0222 {
0223   return (myHSize[0] < -1e-5);
0224 }
0225 
0226 //=================================================================================================
0227 
0228 template <typename RealType>
0229 inline void Bnd_B3<RealType>::Add(const gp_Pnt& thePnt)
0230 {
0231   Add(thePnt.XYZ());
0232 }
0233 
0234 //=================================================================================================
0235 
0236 template <typename RealType>
0237 inline void Bnd_B3<RealType>::Add(const Bnd_B3<RealType>& theBox)
0238 {
0239   if (!theBox.IsVoid())
0240   {
0241     Add(theBox.CornerMin());
0242     Add(theBox.CornerMax());
0243   }
0244 }
0245 
0246 //=================================================================================================
0247 
0248 template <typename RealType>
0249 inline gp_XYZ Bnd_B3<RealType>::CornerMin() const noexcept
0250 {
0251   return gp_XYZ(myCenter[0] - myHSize[0], myCenter[1] - myHSize[1], myCenter[2] - myHSize[2]);
0252 }
0253 
0254 //=================================================================================================
0255 
0256 template <typename RealType>
0257 inline gp_XYZ Bnd_B3<RealType>::CornerMax() const noexcept
0258 {
0259   return gp_XYZ(myCenter[0] + myHSize[0], myCenter[1] + myHSize[1], myCenter[2] + myHSize[2]);
0260 }
0261 
0262 //=================================================================================================
0263 
0264 template <typename RealType>
0265 constexpr inline double Bnd_B3<RealType>::SquareExtent() const noexcept
0266 {
0267   return 4 * (myHSize[0] * myHSize[0] + myHSize[1] * myHSize[1] + myHSize[2] * myHSize[2]);
0268 }
0269 
0270 //=================================================================================================
0271 
0272 template <typename RealType>
0273 inline void Bnd_B3<RealType>::SetCenter(const gp_XYZ& theCenter) noexcept
0274 {
0275   myCenter[0] = RealType(theCenter.X());
0276   myCenter[1] = RealType(theCenter.Y());
0277   myCenter[2] = RealType(theCenter.Z());
0278 }
0279 
0280 //=================================================================================================
0281 
0282 template <typename RealType>
0283 inline void Bnd_B3<RealType>::SetHSize(const gp_XYZ& theHSize) noexcept
0284 {
0285   myHSize[0] = RealType(theHSize.X());
0286   myHSize[1] = RealType(theHSize.Y());
0287   myHSize[2] = RealType(theHSize.Z());
0288 }
0289 
0290 //=================================================================================================
0291 
0292 template <typename RealType>
0293 inline void Bnd_B3<RealType>::SetCenter(const std::array<RealType, 3>& theCenter) noexcept
0294 {
0295   myCenter = theCenter;
0296 }
0297 
0298 //=================================================================================================
0299 
0300 template <typename RealType>
0301 inline void Bnd_B3<RealType>::SetHSize(const std::array<RealType, 3>& theHSize) noexcept
0302 {
0303   myHSize = theHSize;
0304 }
0305 
0306 //=================================================================================================
0307 
0308 template <typename RealType>
0309 constexpr inline const std::array<RealType, 3>& Bnd_B3<RealType>::Center() const noexcept
0310 {
0311   return myCenter;
0312 }
0313 
0314 //=================================================================================================
0315 
0316 template <typename RealType>
0317 constexpr inline const std::array<RealType, 3>& Bnd_B3<RealType>::HSize() const noexcept
0318 {
0319   return myHSize;
0320 }
0321 
0322 //=================================================================================================
0323 
0324 template <typename RealType>
0325 inline void Bnd_B3<RealType>::Enlarge(const double aDiff) noexcept
0326 {
0327   const double aD = std::abs(aDiff);
0328   myHSize[0] += RealType(aD);
0329   myHSize[1] += RealType(aD);
0330   myHSize[2] += RealType(aD);
0331 }
0332 
0333 //=================================================================================================
0334 
0335 template <typename RealType>
0336 constexpr inline bool Bnd_B3<RealType>::IsOut(const gp_XYZ& thePnt) const noexcept
0337 {
0338   return (std::abs(RealType(thePnt.X()) - myCenter[0]) > myHSize[0]
0339           || std::abs(RealType(thePnt.Y()) - myCenter[1]) > myHSize[1]
0340           || std::abs(RealType(thePnt.Z()) - myCenter[2]) > myHSize[2]);
0341 }
0342 
0343 //=================================================================================================
0344 
0345 template <typename RealType>
0346 constexpr inline bool Bnd_B3<RealType>::IsOut(const Bnd_B3<RealType>& theBox) const noexcept
0347 {
0348   return (std::abs(theBox.myCenter[0] - myCenter[0]) > theBox.myHSize[0] + myHSize[0]
0349           || std::abs(theBox.myCenter[1] - myCenter[1]) > theBox.myHSize[1] + myHSize[1]
0350           || std::abs(theBox.myCenter[2] - myCenter[2]) > theBox.myHSize[2] + myHSize[2]);
0351 }
0352 
0353 //=================================================================================================
0354 
0355 template <typename RealType>
0356 constexpr inline bool Bnd_B3<RealType>::IsIn(const Bnd_B3<RealType>& theBox) const noexcept
0357 {
0358   return (std::abs(theBox.myCenter[0] - myCenter[0]) < theBox.myHSize[0] - myHSize[0]
0359           && std::abs(theBox.myCenter[1] - myCenter[1]) < theBox.myHSize[1] - myHSize[1]
0360           && std::abs(theBox.myCenter[2] - myCenter[2]) < theBox.myHSize[2] - myHSize[2]);
0361 }
0362 
0363 //=================================================================================================
0364 
0365 template <typename RealType>
0366 void Bnd_B3<RealType>::Add(const gp_XYZ& thePnt)
0367 {
0368   if (IsVoid())
0369   {
0370     myCenter[0] = RealType(thePnt.X());
0371     myCenter[1] = RealType(thePnt.Y());
0372     myCenter[2] = RealType(thePnt.Z());
0373     myHSize[0]  = 0.;
0374     myHSize[1]  = 0.;
0375     myHSize[2]  = 0.;
0376   }
0377   else
0378   {
0379     const RealType aDiff[3] = {RealType(thePnt.X()) - myCenter[0],
0380                                RealType(thePnt.Y()) - myCenter[1],
0381                                RealType(thePnt.Z()) - myCenter[2]};
0382     if (aDiff[0] > myHSize[0])
0383     {
0384       const RealType aShift = (aDiff[0] - myHSize[0]) / 2;
0385       myCenter[0] += aShift;
0386       myHSize[0] += aShift;
0387     }
0388     else if (aDiff[0] < -myHSize[0])
0389     {
0390       const RealType aShift = (aDiff[0] + myHSize[0]) / 2;
0391       myCenter[0] += aShift;
0392       myHSize[0] -= aShift;
0393     }
0394     if (aDiff[1] > myHSize[1])
0395     {
0396       const RealType aShift = (aDiff[1] - myHSize[1]) / 2;
0397       myCenter[1] += aShift;
0398       myHSize[1] += aShift;
0399     }
0400     else if (aDiff[1] < -myHSize[1])
0401     {
0402       const RealType aShift = (aDiff[1] + myHSize[1]) / 2;
0403       myCenter[1] += aShift;
0404       myHSize[1] -= aShift;
0405     }
0406     if (aDiff[2] > myHSize[2])
0407     {
0408       const RealType aShift = (aDiff[2] - myHSize[2]) / 2;
0409       myCenter[2] += aShift;
0410       myHSize[2] += aShift;
0411     }
0412     else if (aDiff[2] < -myHSize[2])
0413     {
0414       const RealType aShift = (aDiff[2] + myHSize[2]) / 2;
0415       myCenter[2] += aShift;
0416       myHSize[2] -= aShift;
0417     }
0418   }
0419 }
0420 
0421 //=================================================================================================
0422 
0423 template <typename RealType>
0424 bool Bnd_B3<RealType>::Limit(const Bnd_B3<RealType>& theBox)
0425 {
0426   bool           aResult(false);
0427   const RealType diffC[3] = {theBox.myCenter[0] - myCenter[0],
0428                              theBox.myCenter[1] - myCenter[1],
0429                              theBox.myCenter[2] - myCenter[2]};
0430   const RealType sumH[3]  = {theBox.myHSize[0] + myHSize[0],
0431                              theBox.myHSize[1] + myHSize[1],
0432                              theBox.myHSize[2] + myHSize[2]};
0433   // check the condition IsOut
0434   if (!compareDist(sumH, diffC))
0435   {
0436     const RealType diffH[3] = {theBox.myHSize[0] - myHSize[0],
0437                                theBox.myHSize[1] - myHSize[1],
0438                                theBox.myHSize[2] - myHSize[2]};
0439     if (diffC[0] - diffH[0] > 0.)
0440     {
0441       const RealType aShift = (diffC[0] - diffH[0]) / 2; // positive
0442       myCenter[0] += aShift;
0443       myHSize[0] -= aShift;
0444     }
0445     else if (diffC[0] + diffH[0] < 0.)
0446     {
0447       const RealType aShift = (diffC[0] + diffH[0]) / 2; // negative
0448       myCenter[0] += aShift;
0449       myHSize[0] += aShift;
0450     }
0451     if (diffC[1] - diffH[1] > 0.)
0452     {
0453       const RealType aShift = (diffC[1] - diffH[1]) / 2; // positive
0454       myCenter[1] += aShift;
0455       myHSize[1] -= aShift;
0456     }
0457     else if (diffC[1] + diffH[1] < 0.)
0458     {
0459       const RealType aShift = (diffC[1] + diffH[1]) / 2; // negative
0460       myCenter[1] += aShift;
0461       myHSize[1] += aShift;
0462     }
0463     if (diffC[2] - diffH[2] > 0.)
0464     {
0465       const RealType aShift = (diffC[2] - diffH[2]) / 2; // positive
0466       myCenter[2] += aShift;
0467       myHSize[2] -= aShift;
0468     }
0469     else if (diffC[2] + diffH[2] < 0.)
0470     {
0471       const RealType aShift = (diffC[2] + diffH[2]) / 2; // negative
0472       myCenter[2] += aShift;
0473       myHSize[2] += aShift;
0474     }
0475     aResult = true;
0476   }
0477   return aResult;
0478 }
0479 
0480 //=================================================================================================
0481 
0482 template <typename RealType>
0483 Bnd_B3<RealType> Bnd_B3<RealType>::Transformed(const gp_Trsf& theTrsf) const
0484 {
0485   Bnd_B3<RealType>  aResult;
0486   const gp_TrsfForm aForm     = theTrsf.Form();
0487   const double      aScale    = theTrsf.ScaleFactor();
0488   const double      aScaleAbs = std::abs(aScale);
0489   if (aForm == gp_Identity)
0490     aResult = *this;
0491   else if (aForm == gp_Translation || aForm == gp_PntMirror || aForm == gp_Scale)
0492   {
0493     aResult.myCenter[0] = (RealType)(myCenter[0] * aScale + theTrsf.TranslationPart().X());
0494     aResult.myCenter[1] = (RealType)(myCenter[1] * aScale + theTrsf.TranslationPart().Y());
0495     aResult.myCenter[2] = (RealType)(myCenter[2] * aScale + theTrsf.TranslationPart().Z());
0496     aResult.myHSize[0]  = (RealType)(myHSize[0] * aScaleAbs);
0497     aResult.myHSize[1]  = (RealType)(myHSize[1] * aScaleAbs);
0498     aResult.myHSize[2]  = (RealType)(myHSize[2] * aScaleAbs);
0499   }
0500   else
0501   {
0502     gp_XYZ aCenter((double)myCenter[0], (double)myCenter[1], (double)myCenter[2]);
0503     theTrsf.Transforms(aCenter);
0504     aResult.myCenter[0] = (RealType)aCenter.X();
0505     aResult.myCenter[1] = (RealType)aCenter.Y();
0506     aResult.myCenter[2] = (RealType)aCenter.Z();
0507 
0508     const double* aMat = &theTrsf.HVectorialPart().Value(1, 1);
0509     aResult.myHSize[0] =
0510       (RealType)(aScaleAbs
0511                  * (std::abs(aMat[0]) * myHSize[0] + std::abs(aMat[1]) * myHSize[1]
0512                     + std::abs(aMat[2]) * myHSize[2]));
0513     aResult.myHSize[1] =
0514       (RealType)(aScaleAbs
0515                  * (std::abs(aMat[3]) * myHSize[0] + std::abs(aMat[4]) * myHSize[1]
0516                     + std::abs(aMat[5]) * myHSize[2]));
0517     aResult.myHSize[2] =
0518       (RealType)(aScaleAbs
0519                  * (std::abs(aMat[6]) * myHSize[0] + std::abs(aMat[7]) * myHSize[1]
0520                     + std::abs(aMat[8]) * myHSize[2]));
0521   }
0522   return aResult;
0523 }
0524 
0525 //=================================================================================================
0526 
0527 template <typename RealType>
0528 bool Bnd_B3<RealType>::IsOut(const gp_XYZ& theCenter,
0529                              const double  theRadius,
0530                              const bool    isSphereHollow) const
0531 {
0532   bool aResult(true);
0533   if (!isSphereHollow)
0534   {
0535     // vector from the center of the sphere to the nearest box face
0536     const double aDist[3] = {std::abs(theCenter.X() - double(myCenter[0])) - double(myHSize[0]),
0537                              std::abs(theCenter.Y() - double(myCenter[1])) - double(myHSize[1]),
0538                              std::abs(theCenter.Z() - double(myCenter[2])) - double(myHSize[2])};
0539     double       aD(0.);
0540     if (aDist[0] > 0.)
0541       aD = aDist[0] * aDist[0];
0542     if (aDist[1] > 0.)
0543       aD += aDist[1] * aDist[1];
0544     if (aDist[2] > 0.)
0545       aD += aDist[2] * aDist[2];
0546     aResult = (aD > theRadius * theRadius);
0547   }
0548   else
0549   {
0550     const double aDistC[3] = {std::abs(theCenter.X() - double(myCenter[0])),
0551                               std::abs(theCenter.Y() - double(myCenter[1])),
0552                               std::abs(theCenter.Z() - double(myCenter[2]))};
0553     // vector from the center of the sphere to the nearest box face
0554     double aDist[3] = {aDistC[0] - double(myHSize[0]),
0555                        aDistC[1] - double(myHSize[1]),
0556                        aDistC[2] - double(myHSize[2])};
0557     double aD(0.);
0558     if (aDist[0] > 0.)
0559       aD = aDist[0] * aDist[0];
0560     if (aDist[1] > 0.)
0561       aD += aDist[1] * aDist[1];
0562     if (aDist[2] > 0.)
0563       aD += aDist[2] * aDist[2];
0564     if (aD < theRadius * theRadius)
0565     {
0566       // the box intersects the solid sphere; check if it is completely
0567       // inside the circle (in such case return isOut==True)
0568       aDist[0] = aDistC[0] + double(myHSize[0]);
0569       aDist[1] = aDistC[1] + double(myHSize[1]);
0570       aDist[2] = aDistC[2] + double(myHSize[2]);
0571       if (aDist[0] * aDist[0] + aDist[1] * aDist[1] + aDist[2] * aDist[2] > theRadius * theRadius)
0572         aResult = false;
0573     }
0574   }
0575   return aResult;
0576 }
0577 
0578 //=================================================================================================
0579 
0580 template <typename RealType>
0581 bool Bnd_B3<RealType>::IsOut(const Bnd_B3<RealType>& theBox, const gp_Trsf& theTrsf) const
0582 {
0583   bool              aResult(false);
0584   const gp_TrsfForm aForm     = theTrsf.Form();
0585   const double      aScale    = theTrsf.ScaleFactor();
0586   const double      aScaleAbs = std::abs(aScale);
0587   if (aForm == gp_Translation || aForm == gp_Identity || aForm == gp_PntMirror || aForm == gp_Scale)
0588   {
0589     aResult =
0590       (std::abs(RealType(theBox.myCenter[0] * aScale + theTrsf.TranslationPart().X()) - myCenter[0])
0591          > RealType(theBox.myHSize[0] * aScaleAbs) + myHSize[0]
0592        || std::abs(RealType(theBox.myCenter[1] * aScale + theTrsf.TranslationPart().Y())
0593                    - myCenter[1])
0594             > RealType(theBox.myHSize[1] * aScaleAbs) + myHSize[1]
0595        || std::abs(RealType(theBox.myCenter[2] * aScale + theTrsf.TranslationPart().Z())
0596                    - myCenter[2])
0597             > RealType(theBox.myHSize[2] * aScaleAbs) + myHSize[2]);
0598   }
0599   else
0600   {
0601     // theBox is transformed and we check the resulting (enlarged) box against
0602     // 'this' box.
0603     const double* aMat = &theTrsf.HVectorialPart().Value(1, 1);
0604 
0605     gp_XYZ aCenter((double)theBox.myCenter[0],
0606                    (double)theBox.myCenter[1],
0607                    (double)theBox.myCenter[2]);
0608     theTrsf.Transforms(aCenter);
0609     const double aDist[3]   = {aCenter.X() - (double)myCenter[0],
0610                                aCenter.Y() - (double)myCenter[1],
0611                                aCenter.Z() - (double)myCenter[2]};
0612     const double aMatAbs[9] = {std::abs(aMat[0]),
0613                                std::abs(aMat[1]),
0614                                std::abs(aMat[2]),
0615                                std::abs(aMat[3]),
0616                                std::abs(aMat[4]),
0617                                std::abs(aMat[5]),
0618                                std::abs(aMat[6]),
0619                                std::abs(aMat[7]),
0620                                std::abs(aMat[8])};
0621     if (std::abs(aDist[0]) > (aScaleAbs
0622                                 * (aMatAbs[0] * theBox.myHSize[0] + aMatAbs[1] * theBox.myHSize[1]
0623                                    + aMatAbs[2] * theBox.myHSize[2])
0624                               + (double)myHSize[0])
0625         || std::abs(aDist[1])
0626              > (aScaleAbs
0627                   * (aMatAbs[3] * theBox.myHSize[0] + aMatAbs[4] * theBox.myHSize[1]
0628                      + aMatAbs[5] * theBox.myHSize[2])
0629                 + (double)myHSize[1])
0630         || std::abs(aDist[2])
0631              > (aScaleAbs
0632                   * (aMatAbs[6] * theBox.myHSize[0] + aMatAbs[7] * theBox.myHSize[1]
0633                      + aMatAbs[8] * theBox.myHSize[2])
0634                 + (double)myHSize[2]))
0635       aResult = true;
0636 
0637     else
0638     {
0639       // theBox is rotated, scaled and translated. We apply the reverse
0640       // translation and scaling then check against the rotated box 'this'
0641       if ((std::abs(aMat[0] * aDist[0] + aMat[3] * aDist[1] + aMat[6] * aDist[2])
0642            > theBox.myHSize[0] * aScaleAbs
0643                + (aMatAbs[0] * myHSize[0] + aMatAbs[3] * myHSize[1] + aMatAbs[6] * myHSize[2]))
0644           || (std::abs(aMat[1] * aDist[0] + aMat[4] * aDist[1] + aMat[7] * aDist[2])
0645               > theBox.myHSize[1] * aScaleAbs
0646                   + (aMatAbs[1] * myHSize[0] + aMatAbs[4] * myHSize[1] + aMatAbs[7] * myHSize[2]))
0647           || (std::abs(aMat[2] * aDist[0] + aMat[5] * aDist[1] + aMat[8] * aDist[2])
0648               > theBox.myHSize[2] * aScaleAbs
0649                   + (aMatAbs[2] * myHSize[0] + aMatAbs[5] * myHSize[1] + aMatAbs[8] * myHSize[2])))
0650         aResult = true;
0651     }
0652   }
0653   return aResult;
0654 }
0655 
0656 //=================================================================================================
0657 
0658 template <typename RealType>
0659 bool Bnd_B3<RealType>::IsOut(const gp_Ax3& thePlane) const
0660 {
0661   if (IsVoid())
0662     return true;
0663   const gp_XYZ& anOrigin = thePlane.Location().XYZ();
0664   const gp_XYZ& aDir     = thePlane.Direction().XYZ();
0665   const gp_XYZ  aBoxCenter((double)myCenter[0], (double)myCenter[1], (double)myCenter[2]);
0666   const double  aDist0 = (aBoxCenter - anOrigin) * aDir;
0667   // Find the signed distances from two opposite corners of the box to the plane
0668   // If the distances are not the same sign, then the plane crosses the box
0669   const double aDist1 = // proj of HSize on aDir
0670     double(myHSize[0]) * std::abs(aDir.X()) + double(myHSize[1]) * std::abs(aDir.Y())
0671     + double(myHSize[2]) * std::abs(aDir.Z());
0672   return ((aDist0 + aDist1) * (aDist0 - aDist1) > 0.);
0673 }
0674 
0675 //=================================================================================================
0676 
0677 template <typename RealType>
0678 bool Bnd_B3<RealType>::IsOut(const gp_Ax1& theLine,
0679                              const bool    isRay,
0680                              const double  theOverthickness) const
0681 {
0682   const double aRes = gp::Resolution() * 100.;
0683   if (IsVoid())
0684     return true;
0685   double        anInter0[2] = {-RealLast(), RealLast()}, anInter1[2] = {-RealLast(), RealLast()};
0686   const gp_XYZ& aDir = theLine.Direction().XYZ();
0687   const gp_XYZ  aDiff((double)myCenter[0] - theLine.Location().X(),
0688                      (double)myCenter[1] - theLine.Location().Y(),
0689                      (double)myCenter[2] - theLine.Location().Z());
0690 
0691   // Find the parameter interval in X dimension
0692   double aHSize = (double)myHSize[0] + theOverthickness;
0693   if (aDir.X() > aRes)
0694   {
0695     anInter0[0] = (aDiff.X() - aHSize) / aDir.X();
0696     anInter0[1] = (aDiff.X() + aHSize) / aDir.X();
0697   }
0698   else if (aDir.X() < -aRes)
0699   {
0700     anInter0[0] = (aDiff.X() + aHSize) / aDir.X();
0701     anInter0[1] = (aDiff.X() - aHSize) / aDir.X();
0702   }
0703   else
0704     // the line is orthogonal to OX axis. Test for inclusion in box limits
0705     if (std::abs(aDiff.X()) > aHSize)
0706       return true;
0707 
0708   // Find the parameter interval in Y dimension
0709   aHSize = (double)myHSize[1] + theOverthickness;
0710   if (aDir.Y() > aRes)
0711   {
0712     anInter1[0] = (aDiff.Y() - aHSize) / aDir.Y();
0713     anInter1[1] = (aDiff.Y() + aHSize) / aDir.Y();
0714   }
0715   else if (aDir.Y() < -aRes)
0716   {
0717     anInter1[0] = (aDiff.Y() + aHSize) / aDir.Y();
0718     anInter1[1] = (aDiff.Y() - aHSize) / aDir.Y();
0719   }
0720   else
0721     // the line is orthogonal to OY axis. Test for inclusion in box limits
0722     if (std::abs(aDiff.Y()) > aHSize)
0723       return true;
0724 
0725   // Intersect Y-interval with X-interval
0726   if (anInter0[0] > (anInter1[1] + aRes) || anInter0[1] < (anInter1[0] - aRes))
0727     return true;
0728   if (anInter1[0] > anInter0[0])
0729     anInter0[0] = anInter1[0];
0730   if (anInter1[1] < anInter0[1])
0731     anInter0[1] = anInter1[1];
0732   if (isRay && anInter0[1] < -aRes)
0733     return true;
0734 
0735   // Find the parameter interval in Z dimension
0736   aHSize = (double)myHSize[2] + theOverthickness;
0737   if (aDir.Z() > aRes)
0738   {
0739     anInter1[0] = (aDiff.Z() - aHSize) / aDir.Z();
0740     anInter1[1] = (aDiff.Z() + aHSize) / aDir.Z();
0741   }
0742   else if (aDir.Z() < -aRes)
0743   {
0744     anInter1[0] = (aDiff.Z() + aHSize) / aDir.Z();
0745     anInter1[1] = (aDiff.Z() - aHSize) / aDir.Z();
0746   }
0747   else
0748     // the line is orthogonal to OZ axis. Test for inclusion in box limits
0749     return (std::abs(aDiff.Z()) > aHSize);
0750   if (isRay && anInter1[1] < -aRes)
0751     return true;
0752 
0753   return (anInter0[0] > (anInter1[1] + aRes) || anInter0[1] < (anInter1[0] - aRes));
0754 }
0755 
0756 //=================================================================================================
0757 
0758 template <typename RealType>
0759 bool Bnd_B3<RealType>::IsIn(const Bnd_B3<RealType>& theBox, const gp_Trsf& theTrsf) const
0760 {
0761   bool              aResult(false);
0762   const gp_TrsfForm aForm     = theTrsf.Form();
0763   const double      aScale    = theTrsf.ScaleFactor();
0764   const double      aScaleAbs = std::abs(aScale);
0765   if (aForm == gp_Translation || aForm == gp_Identity || aForm == gp_PntMirror || aForm == gp_Scale)
0766   {
0767     aResult =
0768       (std::abs(RealType(theBox.myCenter[0] * aScale + theTrsf.TranslationPart().X()) - myCenter[0])
0769          < RealType(theBox.myHSize[0] * aScaleAbs) - myHSize[0]
0770        && std::abs(RealType(theBox.myCenter[1] * aScale + theTrsf.TranslationPart().Y())
0771                    - myCenter[1])
0772             < RealType(theBox.myHSize[1] * aScaleAbs) - myHSize[1]
0773        && std::abs(RealType(theBox.myCenter[2] * aScale + theTrsf.TranslationPart().Z())
0774                    - myCenter[2])
0775             < RealType(theBox.myHSize[2] * aScaleAbs) - myHSize[2]);
0776   }
0777   else
0778   {
0779     // theBox is rotated, scaled and translated. We apply the reverse
0780     // translation and scaling then check against the rotated box 'this'
0781     const double* aMat = &theTrsf.HVectorialPart().Value(1, 1);
0782     gp_XYZ        aCenter((double)theBox.myCenter[0],
0783                    (double)theBox.myCenter[1],
0784                    (double)theBox.myCenter[2]);
0785     theTrsf.Transforms(aCenter);
0786     const double aDist[3] = {aCenter.X() - (double)myCenter[0],
0787                              aCenter.Y() - (double)myCenter[1],
0788                              aCenter.Z() - (double)myCenter[2]};
0789     if ((std::abs(aMat[0] * aDist[0] + aMat[3] * aDist[1] + aMat[6] * aDist[2])
0790          < theBox.myHSize[0] * aScaleAbs
0791              - (std::abs(aMat[0]) * myHSize[0] + std::abs(aMat[3]) * myHSize[1]
0792                 + std::abs(aMat[6]) * myHSize[2]))
0793         && (std::abs(aMat[1] * aDist[0] + aMat[4] * aDist[1] + aMat[7] * aDist[2])
0794             < theBox.myHSize[1] * aScaleAbs
0795                 - (std::abs(aMat[1]) * myHSize[0] + std::abs(aMat[4]) * myHSize[1]
0796                    + std::abs(aMat[7]) * myHSize[2]))
0797         && (std::abs(aMat[2] * aDist[0] + aMat[5] * aDist[1] + aMat[8] * aDist[2])
0798             < theBox.myHSize[2] * aScaleAbs
0799                 - (std::abs(aMat[2]) * myHSize[0] + std::abs(aMat[5]) * myHSize[1]
0800                    + std::abs(aMat[8]) * myHSize[2])))
0801       aResult = true;
0802   }
0803   return aResult;
0804 }
0805 
0806 //=================================================================================================
0807 
0808 //! 3D bounding box with double precision
0809 using Bnd_B3d = Bnd_B3<double>;
0810 
0811 //! 3D bounding box with single precision
0812 using Bnd_B3f = Bnd_B3<float>;
0813 
0814 #endif // _Bnd_B3_HeaderFile