Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-16 09:16:26

0001 // Created by: Eugeny MALTCHIKOV
0002 // Copyright (c) 2017 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014 
0015 #ifndef _Bnd_OBB_HeaderFile
0016 #define _Bnd_OBB_HeaderFile
0017 
0018 #include <Standard.hxx>
0019 #include <Standard_DefineAlloc.hxx>
0020 #include <Standard_Handle.hxx>
0021 
0022 #include <Bnd_Box.hxx>
0023 #include <gp_Ax3.hxx>
0024 #include <gp_Dir.hxx>
0025 #include <gp_Pnt.hxx>
0026 #include <gp_XYZ.hxx>
0027 #include <NCollection_Array1.hxx>
0028 
0029 //! The class describes the Oriented Bounding Box (OBB),
0030 //! much tighter enclosing volume for the shape than the
0031 //! Axis Aligned Bounding Box (AABB).
0032 //! The OBB is defined by a center of the box, the axes and the halves
0033 //! of its three dimensions.
0034 //! The OBB can be used more effectively than AABB as a rejection mechanism
0035 //! for non-interfering objects.
0036 class Bnd_OBB
0037 {
0038 public:
0039   DEFINE_STANDARD_ALLOC
0040 
0041   //! Structure containing the OBB half-size dimensions.
0042   //! Can be used with C++17 structured bindings:
0043   //! @code
0044   //!   auto [aHX, aHY, aHZ] = anOBB.GetHalfSizes();
0045   //! @endcode
0046   struct HalfSizes
0047   {
0048     double X; //!< Half-size along X axis
0049     double Y; //!< Half-size along Y axis
0050     double Z; //!< Half-size along Z axis
0051   };
0052 
0053   //! Empty constructor
0054   Bnd_OBB()
0055       : myIsAABox(false)
0056   {
0057     myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
0058   }
0059 
0060   //! Constructor taking all defining parameters
0061   Bnd_OBB(const gp_Pnt& theCenter,
0062           const gp_Dir& theXDirection,
0063           const gp_Dir& theYDirection,
0064           const gp_Dir& theZDirection,
0065           const double  theHXSize,
0066           const double  theHYSize,
0067           const double  theHZSize)
0068       : myCenter(theCenter.XYZ()),
0069         myIsAABox(false)
0070   {
0071     myAxes[0] = theXDirection.XYZ();
0072     myAxes[1] = theYDirection.XYZ();
0073     myAxes[2] = theZDirection.XYZ();
0074 
0075     Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
0076     Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
0077     Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
0078 
0079     myHDims[0] = theHXSize;
0080     myHDims[1] = theHYSize;
0081     myHDims[2] = theHZSize;
0082   }
0083 
0084   //! Constructor to create OBB from AABB.
0085   Bnd_OBB(const Bnd_Box& theBox)
0086       : myIsAABox(true)
0087   {
0088     if (theBox.IsVoid())
0089     {
0090       myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
0091       myIsAABox                            = false;
0092       return;
0093     }
0094 
0095     double aX1, aY1, aZ1, aX2, aY2, aZ2;
0096     theBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);
0097 
0098     myAxes[0].SetCoord(1.0, 0.0, 0.0);
0099     myAxes[1].SetCoord(0.0, 1.0, 0.0);
0100     myAxes[2].SetCoord(0.0, 0.0, 1.0);
0101 
0102     myHDims[0] = 0.5 * (aX2 - aX1);
0103     myHDims[1] = 0.5 * (aY2 - aY1);
0104     myHDims[2] = 0.5 * (aZ2 - aZ1);
0105 
0106     myCenter.SetCoord(0.5 * (aX2 + aX1), 0.5 * (aY2 + aY1), 0.5 * (aZ2 + aZ1));
0107   }
0108 
0109   //! Creates new OBB covering every point in theListOfPoints.
0110   //! Tolerance of every such point is set by *theListOfTolerances array.
0111   //! If this array is not void (not null-pointer) then the resulted Bnd_OBB
0112   //! will be enlarged using tolerances of points lying on the box surface.
0113   //! <theIsOptimal> flag defines the mode in which the OBB will be built.
0114   //! Constructing Optimal box takes more time, but the resulting box is usually
0115   //! more tight. In case of construction of Optimal OBB more possible
0116   //! axes are checked.
0117   Standard_EXPORT void ReBuild(const NCollection_Array1<gp_Pnt>& theListOfPoints,
0118                                const NCollection_Array1<double>* theListOfTolerances = nullptr,
0119                                const bool                        theIsOptimal        = false);
0120 
0121   //! Sets the center of OBB
0122   void SetCenter(const gp_Pnt& theCenter) { myCenter = theCenter.XYZ(); }
0123 
0124   //! Sets the X component of OBB - direction and size
0125   void SetXComponent(const gp_Dir& theXDirection, const double theHXSize)
0126   {
0127     Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
0128 
0129     myAxes[0]  = theXDirection.XYZ();
0130     myHDims[0] = theHXSize;
0131   }
0132 
0133   //! Sets the Y component of OBB - direction and size
0134   void SetYComponent(const gp_Dir& theYDirection, const double theHYSize)
0135   {
0136     Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
0137 
0138     myAxes[1]  = theYDirection.XYZ();
0139     myHDims[1] = theHYSize;
0140   }
0141 
0142   //! Sets the Z component of OBB - direction and size
0143   void SetZComponent(const gp_Dir& theZDirection, const double theHZSize)
0144   {
0145     Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
0146 
0147     myAxes[2]  = theZDirection.XYZ();
0148     myHDims[2] = theHZSize;
0149   }
0150 
0151   //! Returns the local coordinates system of this oriented box.
0152   //! So that applying it to axis-aligned box ((-XHSize, -YHSize, -ZHSize), (XHSize, YHSize,
0153   //! ZHSize)) will produce this oriented box.
0154   //! @code
0155   //!   gp_Trsf aLoc;
0156   //!   aLoc.SetTransformation (theOBB.Position(), gp::XOY());
0157   //! @endcode
0158   [[nodiscard]] gp_Ax3 Position() const { return gp_Ax3(myCenter, ZDirection(), XDirection()); }
0159 
0160   //! Returns the center of OBB
0161   [[nodiscard]] const gp_XYZ& Center() const noexcept { return myCenter; }
0162 
0163   //! Returns the X Direction of OBB
0164   [[nodiscard]] const gp_XYZ& XDirection() const noexcept { return myAxes[0]; }
0165 
0166   //! Returns the Y Direction of OBB
0167   [[nodiscard]] const gp_XYZ& YDirection() const noexcept { return myAxes[1]; }
0168 
0169   //! Returns the Z Direction of OBB
0170   [[nodiscard]] const gp_XYZ& ZDirection() const noexcept { return myAxes[2]; }
0171 
0172   //! Returns the X Dimension of OBB
0173   [[nodiscard]] double XHSize() const noexcept { return myHDims[0]; }
0174 
0175   //! Returns the Y Dimension of OBB
0176   [[nodiscard]] double YHSize() const noexcept { return myHDims[1]; }
0177 
0178   //! Returns the Z Dimension of OBB
0179   [[nodiscard]] double ZHSize() const noexcept { return myHDims[2]; }
0180 
0181   //! Returns the half-size dimensions of the OBB as a HalfSizes structure.
0182   //! Can be used with C++17 structured bindings:
0183   //! @code
0184   //!   auto [aHX, aHY, aHZ] = anOBB.GetHalfSizes();
0185   //! @endcode
0186   [[nodiscard]] HalfSizes GetHalfSizes() const noexcept
0187   {
0188     return {myHDims[0], myHDims[1], myHDims[2]};
0189   }
0190 
0191   //! Checks if the box is empty.
0192   [[nodiscard]] bool IsVoid() const noexcept
0193   {
0194     return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0));
0195   }
0196 
0197   //! Clears this box
0198   void SetVoid()
0199   {
0200     myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
0201     myCenter = myAxes[0] = myAxes[1] = myAxes[2] = gp_XYZ();
0202     myIsAABox                                    = false;
0203   }
0204 
0205   //! Sets the flag for axes aligned box
0206   void SetAABox(const bool& theFlag) { myIsAABox = theFlag; }
0207 
0208   //! Returns TRUE if the box is axes aligned
0209   [[nodiscard]] bool IsAABox() const noexcept { return myIsAABox; }
0210 
0211   //! Enlarges the box with the given value
0212   void Enlarge(const double theGapAdd)
0213   {
0214     const double aGap = std::abs(theGapAdd);
0215     myHDims[0] += aGap;
0216     myHDims[1] += aGap;
0217     myHDims[2] += aGap;
0218   }
0219 
0220   //! Returns the array of vertices in <this>.
0221   //! The local coordinate of the vertex depending on the
0222   //! index of the array are follow:
0223   //! Index == 0: (-XHSize(), -YHSize(), -ZHSize())
0224   //! Index == 1: ( XHSize(), -YHSize(), -ZHSize())
0225   //! Index == 2: (-XHSize(),  YHSize(), -ZHSize())
0226   //! Index == 3: ( XHSize(),  YHSize(), -ZHSize())
0227   //! Index == 4: (-XHSize(), -YHSize(),  ZHSize())
0228   //! Index == 5: ( XHSize(), -YHSize(),  ZHSize())
0229   //! Index == 6: (-XHSize(),  YHSize(),  ZHSize())
0230   //! Index == 7: ( XHSize(),  YHSize(),  ZHSize()).
0231   bool GetVertex(gp_Pnt theP[8]) const
0232   {
0233     if (IsVoid())
0234       return false;
0235 
0236     theP[0].SetXYZ(myCenter - myHDims[0] * myAxes[0] - myHDims[1] * myAxes[1]
0237                    - myHDims[2] * myAxes[2]);
0238     theP[1].SetXYZ(myCenter + myHDims[0] * myAxes[0] - myHDims[1] * myAxes[1]
0239                    - myHDims[2] * myAxes[2]);
0240     theP[2].SetXYZ(myCenter - myHDims[0] * myAxes[0] + myHDims[1] * myAxes[1]
0241                    - myHDims[2] * myAxes[2]);
0242     theP[3].SetXYZ(myCenter + myHDims[0] * myAxes[0] + myHDims[1] * myAxes[1]
0243                    - myHDims[2] * myAxes[2]);
0244     theP[4].SetXYZ(myCenter - myHDims[0] * myAxes[0] - myHDims[1] * myAxes[1]
0245                    + myHDims[2] * myAxes[2]);
0246     theP[5].SetXYZ(myCenter + myHDims[0] * myAxes[0] - myHDims[1] * myAxes[1]
0247                    + myHDims[2] * myAxes[2]);
0248     theP[6].SetXYZ(myCenter - myHDims[0] * myAxes[0] + myHDims[1] * myAxes[1]
0249                    + myHDims[2] * myAxes[2]);
0250     theP[7].SetXYZ(myCenter + myHDims[0] * myAxes[0] + myHDims[1] * myAxes[1]
0251                    + myHDims[2] * myAxes[2]);
0252 
0253     return true;
0254   }
0255 
0256   //! Returns square diagonal of this box
0257   [[nodiscard]] double SquareExtent() const noexcept
0258   {
0259     return 4.0 * (myHDims[0] * myHDims[0] + myHDims[1] * myHDims[1] + myHDims[2] * myHDims[2]);
0260   }
0261 
0262   //! Check if the box do not interfere the other box.
0263   [[nodiscard]] Standard_EXPORT bool IsOut(const Bnd_OBB& theOther) const;
0264 
0265   //! Check if the point is inside of <this>.
0266   [[nodiscard]] Standard_EXPORT bool IsOut(const gp_Pnt& theP) const;
0267 
0268   //! Returns True if the point is inside or on the boundary of this OBB.
0269   [[nodiscard]] bool Contains(const gp_Pnt& theP) const { return !IsOut(theP); }
0270 
0271   //! Returns True if the other OBB intersects or is inside this OBB.
0272   [[nodiscard]] bool Intersects(const Bnd_OBB& theOther) const { return !IsOut(theOther); }
0273 
0274   //! Check if the theOther is completely inside *this.
0275   [[nodiscard]] Standard_EXPORT bool IsCompletelyInside(const Bnd_OBB& theOther) const;
0276 
0277   //! Rebuilds this in order to include all previous objects
0278   //! (which it was created from) and theOther.
0279   Standard_EXPORT void Add(const Bnd_OBB& theOther);
0280 
0281   //! Rebuilds this in order to include all previous objects
0282   //! (which it was created from) and theP.
0283   Standard_EXPORT void Add(const gp_Pnt& theP);
0284 
0285   //! Dumps the content of me into the stream
0286   Standard_EXPORT void DumpJson(Standard_OStream& theOStream, int theDepth = -1) const;
0287 
0288 protected:
0289   void ProcessOnePoint(const gp_Pnt& theP)
0290   {
0291     myIsAABox  = true;
0292     myHDims[0] = myHDims[1] = myHDims[2] = 0.0;
0293     myAxes[0].SetCoord(1.0, 0.0, 0.0);
0294     myAxes[1].SetCoord(0.0, 1.0, 0.0);
0295     myAxes[2].SetCoord(0.0, 0.0, 1.0);
0296     myCenter = theP.XYZ();
0297   }
0298 
0299 private:
0300   //! Center of the OBB
0301   gp_XYZ myCenter;
0302 
0303   //! Directions of the box's axes
0304   //! (all vectors are already normalized)
0305   gp_XYZ myAxes[3];
0306 
0307   //! Half-size dimensions of the OBB
0308   double myHDims[3];
0309 
0310   //! To be set if the OBB is axis aligned box;
0311   bool myIsAABox;
0312 };
0313 
0314 #endif