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_Macro.hxx>
22 #include <Standard_Dump.hxx>
23 #include <Standard_ShortReal.hxx>
27 //! Base class for BVH_Box (CRTP idiom is used).
28 //! @tparam T Numeric data type
29 //! @tparam N Vector dimension
30 //! @tparam TheDerivedBox Template of derived class that defined axis aligned bounding box.
31 template <class T, int N, template <class /*T*/, int /*N*/> class TheDerivedBox>
34 // forward declaration
35 template <class T, int N> class BVH_Box;
37 //! Partial template specialization for BVH_Box when N = 3.
39 class BVH_BaseBox<T, 3, BVH_Box>
43 //! Transforms this box with given transformation.
44 void Transform (const NCollection_Mat4<T>& theTransform)
46 if (theTransform.IsIdentity())
51 BVH_Box<T, 3> *aThis = static_cast<BVH_Box<T, 3>*>(this);
52 if (!aThis->IsValid())
57 BVH_Box<T, 3> aBox = Transformed (theTransform);
59 aThis->CornerMin() = aBox.CornerMin();
60 aThis->CornerMax() = aBox.CornerMax();
63 //! Returns a box which is the result of applying the
64 //! given transformation to this box.
65 BVH_Box<T, 3> Transformed (const NCollection_Mat4<T>& theTransform) const
67 BVH_Box<T, 3> aResultBox;
69 if (theTransform.IsIdentity())
74 const BVH_Box<T, 3> *aThis = static_cast<const BVH_Box<T, 3>*>(this);
75 if (!aThis->IsValid())
80 for (size_t aX = 0; aX <= 1; ++aX)
82 for (size_t aY = 0; aY <= 1; ++aY)
84 for (size_t aZ = 0; aZ <= 1; ++aZ)
86 typename BVH::VectorType<T, 4>::Type aPnt =
87 theTransform * typename BVH::VectorType<T, 4>::Type (aX ? aThis->CornerMax().x() : aThis->CornerMin().x(),
88 aY ? aThis->CornerMax().y() : aThis->CornerMin().y(),
89 aZ ? aThis->CornerMax().z() : aThis->CornerMin().z(),
90 static_cast<T> (1.0));
92 aResultBox.Add (aPnt.xyz());
100 //! Defines axis aligned bounding box (AABB) based on BVH vectors.
101 //! \tparam T Numeric data type
102 //! \tparam N Vector dimension
103 template<class T, int N>
104 class BVH_Box : public BVH_BaseBox<T, N, BVH_Box>
108 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
112 //! Creates uninitialized bounding box.
113 BVH_Box() : myIsInited (Standard_False) {}
115 //! Creates bounding box of given point.
116 BVH_Box (const BVH_VecNt& thePoint)
117 : myMinPoint (thePoint),
118 myMaxPoint (thePoint),
119 myIsInited (Standard_True) {}
121 //! Creates bounding box from corner points.
122 BVH_Box (const BVH_VecNt& theMinPoint,
123 const BVH_VecNt& theMaxPoint)
124 : myMinPoint (theMinPoint),
125 myMaxPoint (theMaxPoint),
126 myIsInited (Standard_True) {}
130 //! Clears bounding box.
131 void Clear() { myIsInited = Standard_False; }
133 //! Is bounding box valid?
134 Standard_Boolean IsValid() const { return myIsInited; }
136 //! Appends new point to the bounding box.
137 void Add (const BVH_VecNt& thePoint)
141 myMinPoint = thePoint;
142 myMaxPoint = thePoint;
143 myIsInited = Standard_True;
147 myMinPoint = myMinPoint.cwiseMin (thePoint);
148 myMaxPoint = myMaxPoint.cwiseMax (thePoint);
152 //! Combines bounding box with another one.
153 void Combine (const BVH_Box& theBox);
155 //! Returns minimum point of bounding box.
156 const BVH_VecNt& CornerMin() const { return myMinPoint; }
158 //! Returns maximum point of bounding box.
159 const BVH_VecNt& CornerMax() const { return myMaxPoint; }
161 //! Returns minimum point of bounding box.
162 BVH_VecNt& CornerMin() { return myMinPoint; }
164 //! Returns maximum point of bounding box.
165 BVH_VecNt& CornerMax() { return myMaxPoint; }
167 //! Returns surface area of bounding box.
168 //! If the box is degenerated into line, returns the perimeter instead.
171 //! Returns diagonal of bounding box.
172 BVH_VecNt Size() const { return myMaxPoint - myMinPoint; }
174 //! Returns center of bounding box.
175 BVH_VecNt Center() const { return (myMinPoint + myMaxPoint) * static_cast<T> (0.5); }
177 //! Returns center of bounding box along the given axis.
178 T Center (const Standard_Integer theAxis) const;
180 //! Dumps the content of me into the stream
181 void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const
184 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsInited)
189 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinPoint[0])
190 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myMinPoint[0])
194 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MinPoint", n, myMinPoint[0], myMinPoint[1])
195 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MaxPoint", n, myMaxPoint[0], myMaxPoint[1])
199 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MinPoint", n, myMinPoint[0], myMinPoint[1], myMinPoint[2])
200 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "MaxPoint", n, myMaxPoint[0], myMaxPoint[1], myMaxPoint[2])
206 //! Checks if the Box is out of the other box.
207 Standard_Boolean IsOut (const BVH_Box<T, N>& theOther) const
209 if (!theOther.IsValid())
210 return Standard_True;
212 return IsOut (theOther.myMinPoint, theOther.myMaxPoint);
215 //! Checks if the Box is out of the other box defined by two points.
216 Standard_Boolean IsOut (const BVH_VecNt& theMinPoint,
217 const BVH_VecNt& theMaxPoint) const
220 return Standard_True;
223 for (int i = 0; i < n; ++i)
225 if (myMinPoint[i] > theMaxPoint[i] ||
226 myMaxPoint[i] < theMinPoint[i])
227 return Standard_True;
229 return Standard_False;
232 //! Checks if the Box fully contains the other box.
233 Standard_Boolean Contains (const BVH_Box<T, N>& theOther,
234 Standard_Boolean& hasOverlap) const
236 hasOverlap = Standard_False;
237 if (!theOther.IsValid())
238 return Standard_False;
240 return Contains (theOther.myMinPoint, theOther.myMaxPoint, hasOverlap);
243 //! Checks if the Box is fully contains the other box.
244 Standard_Boolean Contains (const BVH_VecNt& theMinPoint,
245 const BVH_VecNt& theMaxPoint,
246 Standard_Boolean& hasOverlap) const
248 hasOverlap = Standard_False;
250 return Standard_False;
252 Standard_Boolean isInside = Standard_True;
255 for (int i = 0; i < n; ++i)
257 hasOverlap = (myMinPoint[i] <= theMaxPoint[i] &&
258 myMaxPoint[i] >= theMinPoint[i]);
260 return Standard_False;
262 isInside = isInside && (myMinPoint[i] <= theMinPoint[i] &&
263 myMaxPoint[i] >= theMaxPoint[i]);
268 //! Checks if the Point is out of the box.
269 Standard_Boolean IsOut (const BVH_VecNt& thePoint) const
272 return Standard_True;
275 for (int i = 0; i < n; ++i)
277 if (thePoint[i] < myMinPoint[i] ||
278 thePoint[i] > myMaxPoint[i])
279 return Standard_True;
281 return Standard_False;
287 BVH_VecNt myMinPoint; //!< Minimum point of bounding box
288 BVH_VecNt myMaxPoint; //!< Maximum point of bounding box
289 Standard_Boolean myIsInited; //!< Is bounding box initialized?
295 //! Tool class for calculating box center along the given axis.
296 //! \tparam T Numeric data type
297 //! \tparam N Vector dimension
298 template<class T, int N>
305 struct CenterAxis<T, 2>
307 static T Center (const BVH_Box<T, 2>& theBox, const Standard_Integer theAxis)
311 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
313 else if (theAxis == 1)
315 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
317 return static_cast<T> (0.0);
322 struct CenterAxis<T, 3>
324 static T Center (const BVH_Box<T, 3>& theBox, const Standard_Integer theAxis)
328 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
330 else if (theAxis == 1)
332 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
334 else if (theAxis == 2)
336 return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
338 return static_cast<T> (0.0);
343 struct CenterAxis<T, 4>
345 static T Center (const BVH_Box<T, 4>& theBox, const Standard_Integer theAxis)
349 return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
351 else if (theAxis == 1)
353 return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
355 else if (theAxis == 2)
357 return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
359 return static_cast<T> (0.0);
363 //! Tool class for calculating surface area of the box.
364 //! \tparam T Numeric data type
365 //! \tparam N Vector dimension
366 template<class T, int N>
367 struct SurfaceCalculator
373 struct SurfaceCalculator<T, 2>
375 static T Area (const typename BVH_Box<T, 2>::BVH_VecNt& theSize)
377 const T anArea = theSize.x() * theSize.y();
379 if (anArea < std::numeric_limits<T>::epsilon())
381 return theSize.x() + theSize.y();
389 struct SurfaceCalculator<T, 3>
391 static T Area (const typename BVH_Box<T, 3>::BVH_VecNt& theSize)
393 const T anArea = ( theSize.x() * theSize.y() +
394 theSize.x() * theSize.z() +
395 theSize.z() * theSize.y() ) * static_cast<T> (2.0);
397 if (anArea < std::numeric_limits<T>::epsilon())
409 struct SurfaceCalculator<T, 4>
411 static T Area (const typename BVH_Box<T, 4>::BVH_VecNt& theSize)
413 const T anArea = ( theSize.x() * theSize.y() +
414 theSize.x() * theSize.z() +
415 theSize.z() * theSize.y() ) * static_cast<T> (2.0);
417 if (anArea < std::numeric_limits<T>::epsilon())
428 //! Tool class for calculate component-wise vector minimum
429 //! and maximum (optimized version).
430 //! \tparam T Numeric data type
431 //! \tparam N Vector dimension
432 template<class T, int N>
435 typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
437 static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
439 theVec1.x() = Min (theVec1.x(), theVec2.x());
440 theVec1.y() = Min (theVec1.y(), theVec2.y());
441 theVec1.z() = Min (theVec1.z(), theVec2.z());
444 static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
446 theVec1.x() = Max (theVec1.x(), theVec2.x());
447 theVec1.y() = Max (theVec1.y(), theVec2.y());
448 theVec1.z() = Max (theVec1.z(), theVec2.z());
453 struct BoxMinMax<T, 2>
455 typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt;
457 static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
459 theVec1.x() = Min (theVec1.x(), theVec2.x());
460 theVec1.y() = Min (theVec1.y(), theVec2.y());
463 static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
465 theVec1.x() = Max (theVec1.x(), theVec2.x());
466 theVec1.y() = Max (theVec1.y(), theVec2.y());
471 // =======================================================================
472 // function : Combine
474 // =======================================================================
475 template<class T, int N>
476 void BVH_Box<T, N>::Combine (const BVH_Box& theBox)
478 if (theBox.myIsInited)
482 myMinPoint = theBox.myMinPoint;
483 myMaxPoint = theBox.myMaxPoint;
484 myIsInited = Standard_True;
488 BVH::BoxMinMax<T, N>::CwiseMin (myMinPoint, theBox.myMinPoint);
489 BVH::BoxMinMax<T, N>::CwiseMax (myMaxPoint, theBox.myMaxPoint);
494 // =======================================================================
497 // =======================================================================
498 template<class T, int N>
499 T BVH_Box<T, N>::Area() const
501 return !myIsInited ? static_cast<T> (0.0) : BVH::SurfaceCalculator<T, N>::Area (myMaxPoint - myMinPoint);
504 // =======================================================================
507 // =======================================================================
508 template<class T, int N>
509 T BVH_Box<T, N>::Center (const Standard_Integer theAxis) const
511 return BVH::CenterAxis<T, N>::Center (*this, theAxis);
514 #endif // _BVH_Box_Header