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