1 // Created on: 2013-12-20
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef _BVH_Box_Header
17 #define _BVH_Box_Header
19 #include <BVH_Constants.hxx>
20 #include <BVH_Types.hxx>
21 #include <Standard_ShortReal.hxx>
22 #include <Standard_Dump.hxx>
26 //! Defines axis aligned bounding box (AABB) based on BVH vectors.
27 //! \tparam T Numeric data type
28 //! \tparam N Vector dimension
29 template<class T, int N>
34 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
38 //! Creates uninitialized bounding box.
39 BVH_Box() : myIsInited (Standard_False) {}
41 //! Creates bounding box of given point.
42 BVH_Box (const BVH_VecNt& thePoint)
43 : myMinPoint (thePoint),
44 myMaxPoint (thePoint),
45 myIsInited (Standard_True) {}
47 //! Creates copy of another bounding box.
48 BVH_Box (const BVH_Box& theBox)
49 : myMinPoint (theBox.myMinPoint),
50 myMaxPoint (theBox.myMaxPoint),
51 myIsInited (theBox.myIsInited) {}
53 //! Creates bounding box from corner points.
54 BVH_Box (const BVH_VecNt& theMinPoint,
55 const BVH_VecNt& theMaxPoint)
56 : myMinPoint (theMinPoint),
57 myMaxPoint (theMaxPoint),
58 myIsInited (Standard_True) {}
62 //! Clears bounding box.
63 void Clear() { myIsInited = Standard_False; }
65 //! Is bounding box valid?
66 Standard_Boolean IsValid() const { return myIsInited; }
68 //! Appends new point to the bounding box.
69 void Add (const BVH_VecNt& thePoint)
73 myMinPoint = thePoint;
74 myMaxPoint = thePoint;
75 myIsInited = Standard_True;
79 myMinPoint = myMinPoint.cwiseMin (thePoint);
80 myMaxPoint = myMaxPoint.cwiseMax (thePoint);
84 //! Combines bounding box with another one.
85 void Combine (const BVH_Box& theBox);
87 //! Returns minimum point of bounding box.
88 const BVH_VecNt& CornerMin() const { return myMinPoint; }
90 //! Returns maximum point of bounding box.
91 const BVH_VecNt& CornerMax() const { return myMaxPoint; }
93 //! Returns minimum point of bounding box.
94 BVH_VecNt& CornerMin() { return myMinPoint; }
96 //! Returns maximum point of bounding box.
97 BVH_VecNt& CornerMax() { return myMaxPoint; }
99 //! Returns surface area of bounding box.
100 //! If the box is degenerated into line, returns the perimeter instead.
103 //! Returns diagonal of bounding box.
104 BVH_VecNt Size() const { return myMaxPoint - myMinPoint; }
106 //! Returns center of bounding box.
107 BVH_VecNt Center() const { return (myMinPoint + myMaxPoint) * static_cast<T> (0.5); }
109 //! Returns center of bounding box along the given axis.
110 T Center (const Standard_Integer theAxis) const;
112 //! Dumps the content of me into the stream
113 void DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth = -1) const
116 DUMP_CLASS_BEGIN (theOStream, BVH_Box);
117 DUMP_FIELD_VALUE_NUMERICAL (theOStream, IsValid());
122 //! Checks if the Box is out of the other box.
123 Standard_Boolean IsOut (const BVH_Box<T, N>& theOther) const
125 if (!theOther.IsValid())
126 return Standard_True;
128 return IsOut (theOther.myMinPoint, theOther.myMaxPoint);
131 //! Checks if the Box is out of the other box defined by two points.
132 Standard_Boolean IsOut (const BVH_VecNt& theMinPoint,
133 const BVH_VecNt& theMaxPoint) const
136 return Standard_True;
139 for (int i = 0; i < n; ++i)
141 if (myMinPoint[i] > theMaxPoint[i] ||
142 myMaxPoint[i] < theMinPoint[i])
143 return Standard_True;
145 return Standard_False;
148 //! Checks if the Box fully contains the other box.
149 Standard_Boolean Contains (const BVH_Box<T, N>& theOther,
150 Standard_Boolean& hasOverlap) const
152 hasOverlap = Standard_False;
153 if (!theOther.IsValid())
154 return Standard_False;
156 return Contains (theOther.myMinPoint, theOther.myMaxPoint, hasOverlap);
159 //! Checks if the Box is fully contains the other box.
160 Standard_Boolean Contains (const BVH_VecNt& theMinPoint,
161 const BVH_VecNt& theMaxPoint,
162 Standard_Boolean& hasOverlap) const
164 hasOverlap = Standard_False;
166 return Standard_False;
168 Standard_Boolean isInside = Standard_True;
171 for (int i = 0; i < n; ++i)
173 hasOverlap = (myMinPoint[i] <= theMaxPoint[i] &&
174 myMaxPoint[i] >= theMinPoint[i]);
176 return Standard_False;
178 isInside = isInside && (myMinPoint[i] <= theMinPoint[i] &&
179 myMaxPoint[i] >= theMaxPoint[i]);
184 //! Checks if the Point is out of the box.
185 Standard_Boolean IsOut (const BVH_VecNt& thePoint) const
188 return Standard_True;
191 for (int i = 0; i < n; ++i)
193 if (thePoint[i] < myMinPoint[i] ||
194 thePoint[i] > myMaxPoint[i])
195 return Standard_True;
197 return Standard_False;
203 BVH_VecNt myMinPoint; //!< Minimum point of bounding box
204 BVH_VecNt myMaxPoint; //!< Maximum point of bounding box
205 Standard_Boolean myIsInited; //!< Is bounding box initialized?
211 //! Tool class for calculating box center along the given axis.
212 //! \tparam T Numeric data type
213 //! \tparam N Vector dimension
214 template<class T, int N>
221 struct CenterAxis<T, 2>
223 static T Center (const BVH_Box<T, 2>& theBox, const Standard_Integer theAxis)
227 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
229 else if (theAxis == 1)
231 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
233 return static_cast<T> (0.0);
238 struct CenterAxis<T, 3>
240 static T Center (const BVH_Box<T, 3>& theBox, const Standard_Integer theAxis)
244 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
246 else if (theAxis == 1)
248 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
250 else if (theAxis == 2)
252 return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
254 return static_cast<T> (0.0);
259 struct CenterAxis<T, 4>
261 static T Center (const BVH_Box<T, 4>& theBox, const Standard_Integer theAxis)
265 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
267 else if (theAxis == 1)
269 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
271 else if (theAxis == 2)
273 return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
275 return static_cast<T> (0.0);
279 //! Tool class for calculating surface area of the box.
280 //! \tparam T Numeric data type
281 //! \tparam N Vector dimension
282 template<class T, int N>
283 struct SurfaceCalculator
289 struct SurfaceCalculator<T, 2>
291 static T Area (const typename BVH_Box<T, 2>::BVH_VecNt& theSize)
293 const T anArea = theSize.x() * theSize.y();
295 if (anArea < std::numeric_limits<T>::epsilon())
297 return theSize.x() + theSize.y();
305 struct SurfaceCalculator<T, 3>
307 static T Area (const typename BVH_Box<T, 3>::BVH_VecNt& theSize)
309 const T anArea = ( theSize.x() * theSize.y() +
310 theSize.x() * theSize.z() +
311 theSize.z() * theSize.y() ) * static_cast<T> (2.0);
313 if (anArea < std::numeric_limits<T>::epsilon())
325 struct SurfaceCalculator<T, 4>
327 static T Area (const typename BVH_Box<T, 4>::BVH_VecNt& theSize)
329 const T anArea = ( theSize.x() * theSize.y() +
330 theSize.x() * theSize.z() +
331 theSize.z() * theSize.y() ) * static_cast<T> (2.0);
333 if (anArea < std::numeric_limits<T>::epsilon())
344 //! Tool class for calculate component-wise vector minimum
345 //! and maximum (optimized version).
346 //! \tparam T Numeric data type
347 //! \tparam N Vector dimension
348 template<class T, int N>
351 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
353 static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
355 theVec1.x() = Min (theVec1.x(), theVec2.x());
356 theVec1.y() = Min (theVec1.y(), theVec2.y());
357 theVec1.z() = Min (theVec1.z(), theVec2.z());
360 static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
362 theVec1.x() = Max (theVec1.x(), theVec2.x());
363 theVec1.y() = Max (theVec1.y(), theVec2.y());
364 theVec1.z() = Max (theVec1.z(), theVec2.z());
369 struct BoxMinMax<T, 2>
371 typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt;
373 static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
375 theVec1.x() = Min (theVec1.x(), theVec2.x());
376 theVec1.y() = Min (theVec1.y(), theVec2.y());
379 static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
381 theVec1.x() = Max (theVec1.x(), theVec2.x());
382 theVec1.y() = Max (theVec1.y(), theVec2.y());
387 // =======================================================================
388 // function : Combine
390 // =======================================================================
391 template<class T, int N>
392 void BVH_Box<T, N>::Combine (const BVH_Box& theBox)
394 if (theBox.myIsInited)
398 myMinPoint = theBox.myMinPoint;
399 myMaxPoint = theBox.myMaxPoint;
400 myIsInited = Standard_True;
404 BVH::BoxMinMax<T, N>::CwiseMin (myMinPoint, theBox.myMinPoint);
405 BVH::BoxMinMax<T, N>::CwiseMax (myMaxPoint, theBox.myMaxPoint);
410 // =======================================================================
413 // =======================================================================
414 template<class T, int N>
415 T BVH_Box<T, N>::Area() const
417 return !myIsInited ? static_cast<T> (0.0) : BVH::SurfaceCalculator<T, N>::Area (myMaxPoint - myMinPoint);
420 // =======================================================================
423 // =======================================================================
424 template<class T, int N>
425 T BVH_Box<T, N>::Center (const Standard_Integer theAxis) const
427 return BVH::CenterAxis<T, N>::Center (*this, theAxis);
430 #endif // _BVH_Box_Header