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. |
39 | class Bnd_OBB |
40 | { |
41 | public: |
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 |
279 | protected: |
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 | |
291 | private: |
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 |