0029311: Implementation of the Oriented Bounding Boxes (OBB) functionality
[occt.git] / src / Bnd / Bnd_OBB.hxx
CommitLineData
1a0339b4 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
24#include <Bnd_Box.hxx>
25#include <gp_Dir.hxx>
26#include <gp_Pnt.hxx>
27#include <gp_XYZ.hxx>
28#include <TColgp_Array1OfPnt.hxx>
29#include <TColStd_Array1OfReal.hxx>
30
31//! The class describes the Oriented Bounding Box (OBB),
32//! much tighter enclosing volume for the shape than the
33//! Axis Aligned Bounding Box (AABB).
34//! The OBB is defined by a center of the box, the axes and the halves
35//! of its three dimensions.
36//! The OBB can be used more effectively than AABB as a rejection mechanism
37//! for non-interfering objects.
38class Bnd_OBB
39{
40public:
41
42 DEFINE_STANDARD_ALLOC
43
44 //! Empty constructor
45 Bnd_OBB() :myIsAABox(Standard_False)
46 {
47 myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
48 }
49
50 //! Constructor taking all defining parameters
51 Bnd_OBB(const gp_Pnt& theCenter,
52 const gp_Dir& theXDirection,
53 const gp_Dir& theYDirection,
54 const gp_Dir& theZDirection,
55 const Standard_Real theHXSize,
56 const Standard_Real theHYSize,
57 const Standard_Real theHZSize) :myCenter (theCenter.XYZ()),
58 myIsAABox(Standard_False)
59 {
60 myAxes[0] = theXDirection.XYZ();
61 myAxes[1] = theYDirection.XYZ();
62 myAxes[2] = theZDirection.XYZ();
63
64 Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
65 Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
66 Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
67
68 myHDims[0] = theHXSize;
69 myHDims[1] = theHYSize;
70 myHDims[2] = theHZSize;
71 }
72
73 //! Constructor to create OBB from AABB.
74 Bnd_OBB(const Bnd_Box& theBox) : myIsAABox(Standard_True)
75 {
76 Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2;
77 theBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);
78
79 myAxes[0].SetCoord(1.0, 0.0, 0.0);
80 myAxes[1].SetCoord(0.0, 1.0, 0.0);
81 myAxes[2].SetCoord(0.0, 0.0, 1.0);
82
83 myHDims[0] = 0.5*(aX2 - aX1);
84 myHDims[1] = 0.5*(aY2 - aY1);
85 myHDims[2] = 0.5*(aZ2 - aZ1);
86
87 myCenter.SetCoord(0.5*(aX2 + aX1), 0.5*(aY2 + aY1), 0.5*(aZ2 + aZ1));
88 }
89
90 //! Created new OBB covering every point in theListOfPoints.
91 //! Tolerance of every such point is set by *theListOfTolerances array.
92 //! If this array is not void (not null-pointer) then the resulted Bnd_OBB
93 //! will be enlarged using tolerances of points lying on the box surface.
94 Standard_EXPORT void ReBuild(const TColgp_Array1OfPnt& theListOfPoints,
95 const TColStd_Array1OfReal *theListOfTolerances = 0);
96
97 //! Sets the center of OBB
98 void SetCenter(const gp_Pnt& theCenter)
99 {
100 myCenter = theCenter.XYZ();
101 }
102
103 //! Sets the X component of OBB - direction and size
104 void SetXComponent(const gp_Dir& theXDirection,
105 const Standard_Real theHXSize)
106 {
107 Standard_ASSERT_VOID(theHXSize >= 0.0, "Negative value of X-size");
108
109 myAxes[0] = theXDirection.XYZ();
110 myHDims[0] = theHXSize;
111 }
112
113 //! Sets the Y component of OBB - direction and size
114 void SetYComponent(const gp_Dir& theYDirection,
115 const Standard_Real theHYSize)
116 {
117 Standard_ASSERT_VOID(theHYSize >= 0.0, "Negative value of Y-size");
118
119 myAxes[1] = theYDirection.XYZ();
120 myHDims[1] = theHYSize;
121 }
122
123 //! Sets the Z component of OBB - direction and size
124 void SetZComponent(const gp_Dir& theZDirection,
125 const Standard_Real theHZSize)
126 {
127 Standard_ASSERT_VOID(theHZSize >= 0.0, "Negative value of Z-size");
128
129 myAxes[2] = theZDirection.XYZ();
130 myHDims[2] = theHZSize;
131 }
132
133 //! Returns the center of OBB
134 const gp_XYZ& Center() const
135 {
136 return myCenter;
137 }
138
139 //! Returns the X Direction of OBB
140 const gp_XYZ& XDirection() const
141 {
142 return myAxes[0];
143 }
144
145 //! Returns the Y Direction of OBB
146 const gp_XYZ& YDirection() const
147 {
148 return myAxes[1];
149 }
150
151 //! Returns the Z Direction of OBB
152 const gp_XYZ& ZDirection() const
153 {
154 return myAxes[2];
155 }
156
157 //! Returns the X Dimension of OBB
158 Standard_Real XHSize() const
159 {
160 return myHDims[0];
161 }
162
163 //! Returns the Y Dimension of OBB
164 Standard_Real YHSize() const
165 {
166 return myHDims[1];
167 }
168
169 //! Returns the Z Dimension of OBB
170 Standard_Real ZHSize() const
171 {
172 return myHDims[2];
173 }
174
175 //! Checks if the box is empty.
176 Standard_Boolean IsVoid() const
177 {
178 return ((myHDims[0] < 0.0) || (myHDims[1] < 0.0) || (myHDims[2] < 0.0));
179 }
180
181 //! Clears this box
182 void SetVoid()
183 {
184 myHDims[0] = myHDims[1] = myHDims[2] = -1.0;
185 myCenter = myAxes[0] = myAxes[1] = myAxes[2] = gp_XYZ();
186 myIsAABox = Standard_False;
187 }
188
189 //! Sets the flag for axes aligned box
190 void SetAABox(const Standard_Boolean& theFlag)
191 {
192 myIsAABox = theFlag;
193 }
194
195 //! Returns TRUE if the box is axes aligned
196 Standard_Boolean IsAABox() const
197 {
198 return myIsAABox;
199 }
200
201 //! Enlarges the box with the given value
202 void Enlarge(const Standard_Real theGapAdd)
203 {
204 const Standard_Real aGap = Abs(theGapAdd);
205 myHDims[0] += aGap;
206 myHDims[1] += aGap;
207 myHDims[2] += aGap;
208 }
209
210 //! Returns the array of vertices in <this>.
211 //! The local coordinate of the vertex depending on the
212 //! index of the array are follow:
213 //! Index == 0: (-XHSize(), -YHSize(), -ZHSize())
214 //! Index == 1: ( XHSize(), -YHSize(), -ZHSize())
215 //! Index == 2: (-XHSize(), YHSize(), -ZHSize())
216 //! Index == 3: ( XHSize(), YHSize(), -ZHSize())
217 //! Index == 4: (-XHSize(), -YHSize(), ZHSize())
218 //! Index == 5: ( XHSize(), -YHSize(), ZHSize())
219 //! Index == 6: (-XHSize(), YHSize(), ZHSize())
220 //! Index == 7: ( XHSize(), YHSize(), ZHSize()).
221 Standard_Boolean GetVertex(gp_Pnt theP[8]) const
222 {
223 if(IsVoid())
224 return Standard_False;
225
226 theP[0].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
227 theP[1].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
228 theP[2].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
229 theP[3].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] - myHDims[2]*myAxes[2]);
230 theP[4].SetXYZ(myCenter - myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
231 theP[5].SetXYZ(myCenter + myHDims[0]*myAxes[0] - myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
232 theP[6].SetXYZ(myCenter - myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
233 theP[7].SetXYZ(myCenter + myHDims[0]*myAxes[0] + myHDims[1]*myAxes[1] + myHDims[2]*myAxes[2]);
234
235 return Standard_True;
236 }
237
238 //! Returns square diagonal of this box
239 Standard_Real SquareExtent() const
240 {
241 return (4.0*myHDims[0] * myHDims[0] +
242 myHDims[1] * myHDims[1] +
243 myHDims[1] * myHDims[1]);
244 }
245
246 //! Check if the box do not interfere the other box.
247 Standard_EXPORT Standard_Boolean IsOut(const Bnd_OBB& theOther) const;
248
249 //! Check if the point is inside of <this>.
250 Standard_EXPORT Standard_Boolean IsOut(const gp_Pnt& theP) const;
251
252 //! Check if the theOther is completely inside *this.
253 Standard_EXPORT Standard_Boolean IsCompletelyInside(const Bnd_OBB& theOther) const;
254
255 //! Rebuilds this in order to include all previous objects
256 //! (which it was created from) and theOther.
257 Standard_EXPORT void Add(const Bnd_OBB& theOther);
258
259 //! Rebuilds this in order to include all previous objects
260 //! (which it was created from) and theP.
261 Standard_EXPORT void Add(const gp_Pnt& theP);
262
263 protected:
264 void ProcessOnePoint(const gp_Pnt& theP)
265 {
266 myIsAABox = Standard_True;
267 myHDims[0] = myHDims[1] = myHDims[2] = 0.0;
268 myAxes[0].SetCoord(1.0, 0.0, 0.0);
269 myAxes[1].SetCoord(0.0, 1.0, 0.0);
270 myAxes[2].SetCoord(0.0, 0.0, 1.0);
271 myCenter = theP.XYZ();
272 }
273
274private:
275
276 //! Center of the OBB
277 gp_XYZ myCenter;
278
279 //! Directions of the box's axes
280 //! (all vectors are already normalized)
281 gp_XYZ myAxes[3];
282
283 //! Half-size dimensions of the OBB
284 Standard_Real myHDims[3];
285
286 //! To be set if the OBB is axis aligned box;
287 Standard_Boolean myIsAABox;
288};
289
290#endif