Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:03:03

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 #include <Standard_Real.hxx>
0022 
0023 #include <Bnd_Box.hxx>
0024 #include <gp_Ax3.hxx>
0025 #include <gp_Dir.hxx>
0026 #include <gp_Pnt.hxx>
0027 #include <gp_XYZ.hxx>
0028 #include <TColgp_Array1OfPnt.hxx>
0029 #include <TColStd_Array1OfReal.hxx>
0030 
0031 //! The class describes the Oriented Bounding Box (OBB),
0032 //! much tighter enclosing volume for the shape than the
0033 //! Axis Aligned Bounding Box (AABB).
0034 //! The OBB is defined by a center of the box, the axes and the halves
0035 //! of its three dimensions.
0036 //! The OBB can be used more effectively than AABB as a rejection mechanism
0037 //! for non-interfering objects.
0038 class Bnd_OBB
0039 {
0040 public:
0041 
0042   DEFINE_STANDARD_ALLOC
0043 
0044   //! Empty constructor
0045   Bnd_OBB() :myIsAABox(Standard_False)
0046   {
0047     myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
0048   }
0049 
0050   //! Constructor taking all defining parameters
0051   Bnd_OBB(const gp_Pnt& theCenter,
0052           const gp_Dir& theXDirection,
0053           const gp_Dir& theYDirection,
0054           const gp_Dir& theZDirection,
0055           const Standard_Real theHXSize,
0056           const Standard_Real theHYSize,
0057           const Standard_Real theHZSize) :myCenter (theCenter.XYZ()),
0058                                           myIsAABox(Standard_False)
0059   {
0060     myAxes[0] = theXDirection.XYZ();
0061     myAxes[1] = theYDirection.XYZ();
0062     myAxes[2] = theZDirection.XYZ();
0063 
0064     Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
0065     Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
0066     Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
0067     
0068     myHDims[0] = theHXSize;
0069     myHDims[1] = theHYSize;
0070     myHDims[2] = theHZSize;
0071   }
0072 
0073   //! Constructor to create OBB from AABB.
0074   Bnd_OBB(const Bnd_Box& theBox) : myIsAABox(Standard_True)
0075   {
0076     if (theBox.IsVoid())
0077     {
0078       myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
0079       myIsAABox = Standard_False;
0080       return;
0081     }
0082 
0083     Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2;
0084     theBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);
0085 
0086     myAxes[0].SetCoord(1.0, 0.0, 0.0);
0087     myAxes[1].SetCoord(0.0, 1.0, 0.0);
0088     myAxes[2].SetCoord(0.0, 0.0, 1.0);
0089 
0090     myHDims[0] = 0.5*(aX2 - aX1);
0091     myHDims[1] = 0.5*(aY2 - aY1);
0092     myHDims[2] = 0.5*(aZ2 - aZ1);
0093 
0094     myCenter.SetCoord(0.5*(aX2 + aX1), 0.5*(aY2 + aY1), 0.5*(aZ2 + aZ1));
0095   }
0096 
0097   //! Creates new OBB covering every point in theListOfPoints.
0098   //! Tolerance of every such point is set by *theListOfTolerances array.
0099   //! If this array is not void (not null-pointer) then the resulted Bnd_OBB
0100   //! will be enlarged using tolerances of points lying on the box surface.
0101   //! <theIsOptimal> flag defines the mode in which the OBB will be built.
0102   //! Constructing Optimal box takes more time, but the resulting box is usually
0103   //! more tight. In case of construction of Optimal OBB more possible
0104   //! axes are checked.
0105   Standard_EXPORT void ReBuild(const TColgp_Array1OfPnt& theListOfPoints,
0106                                const TColStd_Array1OfReal *theListOfTolerances = 0,
0107                                const Standard_Boolean theIsOptimal = Standard_False);
0108 
0109   //! Sets the center of OBB
0110   void SetCenter(const gp_Pnt& theCenter)
0111   {
0112     myCenter = theCenter.XYZ();
0113   }
0114 
0115     //! Sets the X component of OBB - direction and size
0116   void SetXComponent(const gp_Dir& theXDirection,
0117                      const Standard_Real theHXSize)
0118   {
0119     Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
0120 
0121     myAxes[0] = theXDirection.XYZ();
0122     myHDims[0] = theHXSize;
0123   }
0124 
0125   //! Sets the Y component of OBB - direction and size
0126   void SetYComponent(const gp_Dir& theYDirection,
0127                      const Standard_Real theHYSize)
0128   {
0129     Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
0130 
0131     myAxes[1] = theYDirection.XYZ();
0132     myHDims[1] = theHYSize;
0133   }
0134 
0135   //! Sets the Z component of OBB - direction and size
0136   void SetZComponent(const gp_Dir& theZDirection,
0137                      const Standard_Real theHZSize)
0138   {
0139     Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
0140 
0141     myAxes[2] = theZDirection.XYZ();
0142     myHDims[2] = theHZSize;
0143   }
0144 
0145   //! Returns the local coordinates system of this oriented box.
0146   //! So that applying it to axis-aligned box ((-XHSize, -YHSize, -ZHSize), (XHSize, YHSize, ZHSize)) will produce this oriented box.
0147   //! @code
0148   //!   gp_Trsf aLoc;
0149   //!   aLoc.SetTransformation (theOBB.Position(), gp::XOY());
0150   //! @endcode
0151   gp_Ax3 Position() const { return gp_Ax3 (myCenter, ZDirection(), XDirection()); }
0152 
0153   //! Returns the center of OBB
0154   const gp_XYZ& Center() const
0155   {
0156     return myCenter;
0157   }
0158 
0159   //! Returns the X Direction of OBB
0160   const gp_XYZ& XDirection() const
0161   {
0162     return myAxes[0];
0163   }
0164 
0165   //! Returns the Y Direction of OBB
0166   const gp_XYZ& YDirection() const
0167   {
0168     return myAxes[1];
0169   }
0170 
0171   //! Returns the Z Direction of OBB
0172   const gp_XYZ& ZDirection() const
0173   {
0174     return myAxes[2];
0175   }
0176 
0177   //! Returns the X Dimension of OBB
0178   Standard_Real XHSize() const
0179   {
0180     return myHDims[0];
0181   }
0182 
0183   //! Returns the Y Dimension of OBB
0184   Standard_Real YHSize() const
0185   {
0186     return myHDims[1];
0187   }
0188 
0189   //! Returns the Z Dimension of OBB
0190   Standard_Real ZHSize() const
0191   {
0192     return myHDims[2];
0193   }
0194 
0195   //! Checks if the box is empty.
0196   Standard_Boolean IsVoid() const
0197   {
0198     return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0));
0199   }
0200 
0201   //! Clears this box
0202   void SetVoid()
0203   {
0204     myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
0205     myCenter = myAxes[0] = myAxes[1] = myAxes[2] = gp_XYZ();
0206     myIsAABox = Standard_False;
0207   }
0208 
0209   //! Sets the flag for axes aligned box
0210   void SetAABox(const Standard_Boolean& theFlag)
0211   {
0212     myIsAABox = theFlag;
0213   }
0214 
0215   //! Returns TRUE if the box is axes aligned
0216   Standard_Boolean IsAABox() const
0217   {
0218     return myIsAABox;
0219   }
0220 
0221   //! Enlarges the box with the given value
0222   void Enlarge(const Standard_Real theGapAdd)
0223   {
0224     const Standard_Real aGap = Abs(theGapAdd);
0225     myHDims[0] += aGap;
0226     myHDims[1] += aGap;
0227     myHDims[2] += aGap;
0228   }
0229 
0230   //! Returns the array of vertices in <this>.
0231   //! The local coordinate of the vertex depending on the
0232   //! index of the array are follow:
0233   //! Index == 0: (-XHSize(), -YHSize(), -ZHSize())
0234   //! Index == 1: ( XHSize(), -YHSize(), -ZHSize())
0235   //! Index == 2: (-XHSize(),  YHSize(), -ZHSize())
0236   //! Index == 3: ( XHSize(),  YHSize(), -ZHSize())
0237   //! Index == 4: (-XHSize(), -YHSize(),  ZHSize())
0238   //! Index == 5: ( XHSize(), -YHSize(),  ZHSize())
0239   //! Index == 6: (-XHSize(),  YHSize(),  ZHSize())
0240   //! Index == 7: ( XHSize(),  YHSize(),  ZHSize()).
0241   Standard_Boolean GetVertex(gp_Pnt theP[8]) const
0242   {
0243     if(IsVoid())
0244       return Standard_False;
0245 
0246     theP[0].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
0247     theP[1].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
0248     theP[2].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
0249     theP[3].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
0250     theP[4].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
0251     theP[5].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
0252     theP[6].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
0253     theP[7].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
0254 
0255     return Standard_True;
0256   }
0257 
0258   //! Returns square diagonal of this box
0259   Standard_Real SquareExtent() const
0260   {
0261     return 4.0 * (myHDims[0] * myHDims[0] + 
0262                   myHDims[1] * myHDims[1] +
0263                   myHDims[2] * myHDims[2]);
0264   }
0265 
0266   //! Check if the box do not interfere the other box.
0267   Standard_EXPORT Standard_Boolean IsOut(const Bnd_OBB& theOther) const;
0268 
0269   //! Check if the point is inside of <this>.
0270   Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& theP) const;
0271 
0272   //! Check if the theOther is completely inside *this.
0273   Standard_EXPORT Standard_Boolean IsCompletelyInside(const Bnd_OBB& theOther) const;
0274 
0275   //! Rebuilds this in order to include all previous objects
0276   //! (which it was created from) and theOther.
0277   Standard_EXPORT void Add(const Bnd_OBB& theOther);
0278 
0279   //! Rebuilds this in order to include all previous objects
0280   //! (which it was created from) and theP.
0281   Standard_EXPORT void Add(const gp_Pnt& theP);
0282 
0283   //! Dumps the content of me into the stream
0284   Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
0285 
0286 protected:
0287 
0288     void ProcessOnePoint(const gp_Pnt& theP)
0289     {
0290       myIsAABox = Standard_True;
0291       myHDims[0] = myHDims[1] = myHDims[2] = 0.0;
0292       myAxes[0].SetCoord(1.0, 0.0, 0.0);
0293       myAxes[1].SetCoord(0.0, 1.0, 0.0);
0294       myAxes[2].SetCoord(0.0, 0.0, 1.0);
0295       myCenter = theP.XYZ();
0296     }
0297 
0298 private:
0299 
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   Standard_Real myHDims[3];
0309 
0310   //! To be set if the OBB is axis aligned box;
0311   Standard_Boolean myIsAABox;
0312 };
0313 
0314 #endif