0031313: Foundation Classes - Dump improvement for classes
[occt.git] / src / Bnd / Bnd_OBB.hxx
1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2017 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _Bnd_OBB_HeaderFile
16 #define _Bnd_OBB_HeaderFile
17
18 #include <Standard.hxx>
19 #include <Standard_DefineAlloc.hxx>
20 #include <Standard_Handle.hxx>
21 #include <Standard_Real.hxx>
22 #include <Standard_Boolean.hxx>
23 #include <Standard_OStream.hxx>
24
25 #include <Bnd_Box.hxx>
26 #include <gp_Ax3.hxx>
27 #include <gp_Dir.hxx>
28 #include <gp_Pnt.hxx>
29 #include <gp_XYZ.hxx>
30 #include <TColgp_Array1OfPnt.hxx>
31 #include <TColStd_Array1OfReal.hxx>
32
33 //! The class describes the Oriented Bounding Box (OBB),
34 //! much tighter enclosing volume for the shape than the
35 //! Axis Aligned Bounding Box (AABB).
36 //! The OBB is defined by a center of the box, the axes and the halves
37 //! of its three dimensions.
38 //! The OBB can be used more effectively than AABB as a rejection mechanism
39 //! for non-interfering objects.
40 class Bnd_OBB
41 {
42 public:
43
44   DEFINE_STANDARD_ALLOC
45
46   //! Empty constructor
47   Bnd_OBB() :myIsAABox(Standard_False)
48   {
49     myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
50   }
51
52   //! Constructor taking all defining parameters
53   Bnd_OBB(const gp_Pnt& theCenter,
54           const gp_Dir& theXDirection,
55           const gp_Dir& theYDirection,
56           const gp_Dir& theZDirection,
57           const Standard_Real theHXSize,
58           const Standard_Real theHYSize,
59           const Standard_Real theHZSize) :myCenter (theCenter.XYZ()),
60                                           myIsAABox(Standard_False)
61   {
62     myAxes[0] = theXDirection.XYZ();
63     myAxes[1] = theYDirection.XYZ();
64     myAxes[2] = theZDirection.XYZ();
65
66     Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
67     Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
68     Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
69     
70     myHDims[0] = theHXSize;
71     myHDims[1] = theHYSize;
72     myHDims[2] = theHZSize;
73   }
74
75   //! Constructor to create OBB from AABB.
76   Bnd_OBB(const Bnd_Box& theBox) : myIsAABox(Standard_True)
77   {
78     if (theBox.IsVoid())
79     {
80       myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
81       myIsAABox = Standard_False;
82       return;
83     }
84
85     Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2;
86     theBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);
87
88     myAxes[0].SetCoord(1.0, 0.0, 0.0);
89     myAxes[1].SetCoord(0.0, 1.0, 0.0);
90     myAxes[2].SetCoord(0.0, 0.0, 1.0);
91
92     myHDims[0] = 0.5*(aX2 - aX1);
93     myHDims[1] = 0.5*(aY2 - aY1);
94     myHDims[2] = 0.5*(aZ2 - aZ1);
95
96     myCenter.SetCoord(0.5*(aX2 + aX1), 0.5*(aY2 + aY1), 0.5*(aZ2 + aZ1));
97   }
98
99   //! Creates new OBB covering every point in theListOfPoints.
100   //! Tolerance of every such point is set by *theListOfTolerances array.
101   //! If this array is not void (not null-pointer) then the resulted Bnd_OBB
102   //! will be enlarged using tolerances of points lying on the box surface.
103   //! <theIsOptimal> flag defines the mode in which the OBB will be built.
104   //! Constructing Optimal box takes more time, but the resulting box is usually
105   //! more tight. In case of construction of Optimal OBB more possible
106   //! axes are checked.
107   Standard_EXPORT void ReBuild(const TColgp_Array1OfPnt& theListOfPoints,
108                                const TColStd_Array1OfReal *theListOfTolerances = 0,
109                                const Standard_Boolean theIsOptimal = Standard_False);
110
111   //! Sets the center of OBB
112   void SetCenter(const gp_Pnt& theCenter)
113   {
114     myCenter = theCenter.XYZ();
115   }
116
117     //! Sets the X component of OBB - direction and size
118   void SetXComponent(const gp_Dir& theXDirection,
119                      const Standard_Real theHXSize)
120   {
121     Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
122
123     myAxes[0] = theXDirection.XYZ();
124     myHDims[0] = theHXSize;
125   }
126
127   //! Sets the Y component of OBB - direction and size
128   void SetYComponent(const gp_Dir& theYDirection,
129                      const Standard_Real theHYSize)
130   {
131     Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
132
133     myAxes[1] = theYDirection.XYZ();
134     myHDims[1] = theHYSize;
135   }
136
137   //! Sets the Z component of OBB - direction and size
138   void SetZComponent(const gp_Dir& theZDirection,
139                      const Standard_Real theHZSize)
140   {
141     Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
142
143     myAxes[2] = theZDirection.XYZ();
144     myHDims[2] = theHZSize;
145   }
146
147   //! Returns the local coordinates system of this oriented box.
148   //! So that applying it to axis-aligned box ((-XHSize, -YHSize, -ZHSize), (XHSize, YHSize, ZHSize)) will produce this oriented box.
149   //! @code
150   //!   gp_Trsf aLoc;
151   //!   aLoc.SetTransformation (theOBB.Position(), gp::XOY());
152   //! @endcode
153   gp_Ax3 Position() const { return gp_Ax3 (myCenter, ZDirection(), XDirection()); }
154
155   //! Returns the center of OBB
156   const gp_XYZ& Center() const
157   {
158     return myCenter;
159   }
160
161   //! Returns the X Direction of OBB
162   const gp_XYZ& XDirection() const
163   {
164     return myAxes[0];
165   }
166
167   //! Returns the Y Direction of OBB
168   const gp_XYZ& YDirection() const
169   {
170     return myAxes[1];
171   }
172
173   //! Returns the Z Direction of OBB
174   const gp_XYZ& ZDirection() const
175   {
176     return myAxes[2];
177   }
178
179   //! Returns the X Dimension of OBB
180   Standard_Real XHSize() const
181   {
182     return myHDims[0];
183   }
184
185   //! Returns the Y Dimension of OBB
186   Standard_Real YHSize() const
187   {
188     return myHDims[1];
189   }
190
191   //! Returns the Z Dimension of OBB
192   Standard_Real ZHSize() const
193   {
194     return myHDims[2];
195   }
196
197   //! Checks if the box is empty.
198   Standard_Boolean IsVoid() const
199   {
200     return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0));
201   }
202
203   //! Clears this box
204   void SetVoid()
205   {
206     myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
207     myCenter = myAxes[0] = myAxes[1] = myAxes[2] = gp_XYZ();
208     myIsAABox = Standard_False;
209   }
210
211   //! Sets the flag for axes aligned box
212   void SetAABox(const Standard_Boolean& theFlag)
213   {
214     myIsAABox = theFlag;
215   }
216
217   //! Returns TRUE if the box is axes aligned
218   Standard_Boolean IsAABox() const
219   {
220     return myIsAABox;
221   }
222
223   //! Enlarges the box with the given value
224   void Enlarge(const Standard_Real theGapAdd)
225   {
226     const Standard_Real aGap = Abs(theGapAdd);
227     myHDims[0] += aGap;
228     myHDims[1] += aGap;
229     myHDims[2] += aGap;
230   }
231
232   //! Returns the array of vertices in <this>.
233   //! The local coordinate of the vertex depending on the
234   //! index of the array are follow:
235   //! Index == 0: (-XHSize(), -YHSize(), -ZHSize())
236   //! Index == 1: ( XHSize(), -YHSize(), -ZHSize())
237   //! Index == 2: (-XHSize(),  YHSize(), -ZHSize())
238   //! Index == 3: ( XHSize(),  YHSize(), -ZHSize())
239   //! Index == 4: (-XHSize(), -YHSize(),  ZHSize())
240   //! Index == 5: ( XHSize(), -YHSize(),  ZHSize())
241   //! Index == 6: (-XHSize(),  YHSize(),  ZHSize())
242   //! Index == 7: ( XHSize(),  YHSize(),  ZHSize()).
243   Standard_Boolean GetVertex(gp_Pnt theP[8]) const
244   {
245     if(IsVoid())
246       return Standard_False;
247
248     theP[0].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
249     theP[1].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
250     theP[2].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
251     theP[3].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
252     theP[4].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
253     theP[5].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
254     theP[6].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
255     theP[7].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
256
257     return Standard_True;
258   }
259
260   //! Returns square diagonal of this box
261   Standard_Real SquareExtent() const
262   {
263     return 4.0 * (myHDims[0] * myHDims[0] + 
264                   myHDims[1] * myHDims[1] +
265                   myHDims[2] * myHDims[2]);
266   }
267
268   //! Check if the box do not interfere the other box.
269   Standard_EXPORT Standard_Boolean IsOut(const Bnd_OBB& theOther) const;
270
271   //! Check if the point is inside of <this>.
272   Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& theP) const;
273
274   //! Check if the theOther is completely inside *this.
275   Standard_EXPORT Standard_Boolean IsCompletelyInside(const Bnd_OBB& theOther) const;
276
277   //! Rebuilds this in order to include all previous objects
278   //! (which it was created from) and theOther.
279   Standard_EXPORT void Add(const Bnd_OBB& theOther);
280
281   //! Rebuilds this in order to include all previous objects
282   //! (which it was created from) and theP.
283   Standard_EXPORT void Add(const gp_Pnt& theP);
284
285   //! Dumps the content of me into the stream
286   Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
287
288 protected:
289
290     void ProcessOnePoint(const gp_Pnt& theP)
291     {
292       myIsAABox = Standard_True;
293       myHDims[0] = myHDims[1] = myHDims[2] = 0.0;
294       myAxes[0].SetCoord(1.0, 0.0, 0.0);
295       myAxes[1].SetCoord(0.0, 1.0, 0.0);
296       myAxes[2].SetCoord(0.0, 0.0, 1.0);
297       myCenter = theP.XYZ();
298     }
299
300 private:
301
302   //! Center of the OBB
303   gp_XYZ myCenter;
304
305   //! Directions of the box's axes
306   //! (all vectors are already normalized)
307   gp_XYZ myAxes[3];
308
309   //! Half-size dimensions of the OBB
310   Standard_Real myHDims[3];
311
312   //! To be set if the OBB is axis aligned box;
313   Standard_Boolean myIsAABox;
314 };
315
316 #endif