8210aa39ba3693d1a2c3581aa63ad08fc86621ba
[occt.git] / src / BVH / BVH_Box.hxx
1 // Created on: 2013-12-20
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _BVH_Box_Header
17 #define _BVH_Box_Header
18
19 #include <BVH_Constants.hxx>
20 #include <BVH_Types.hxx>
21 #include <Standard_ShortReal.hxx>
22
23 #include <limits>
24
25 //! Defines axis aligned bounding box (AABB) based on BVH vectors.
26 //! \tparam T Numeric data type
27 //! \tparam N Vector dimension
28 template<class T, int N>
29 class BVH_Box
30 {
31 public:
32
33   typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
34
35 public:
36
37   //! Creates uninitialized bounding box.
38   BVH_Box() : myIsInited (Standard_False) {}
39
40   //! Creates bounding box of given point.
41   BVH_Box (const BVH_VecNt& thePoint)
42   : myMinPoint (thePoint),
43     myMaxPoint (thePoint),
44     myIsInited (Standard_True) {}
45
46   //! Creates copy of another bounding box.
47   BVH_Box (const BVH_Box& theBox)
48   : myMinPoint (theBox.myMinPoint),
49     myMaxPoint (theBox.myMaxPoint),
50     myIsInited (theBox.myIsInited) {}
51
52   //! Creates bounding box from corner points.
53   BVH_Box (const BVH_VecNt& theMinPoint,
54            const BVH_VecNt& theMaxPoint)
55   : myMinPoint (theMinPoint),
56     myMaxPoint (theMaxPoint),
57     myIsInited (Standard_True) {}
58
59 public:
60
61   //! Clears bounding box.
62   void Clear() { myIsInited = Standard_False; }
63
64   //! Is bounding box valid?
65   Standard_Boolean IsValid() const { return myIsInited; }
66
67   //! Appends new point to the bounding box.
68   void Add (const BVH_VecNt& thePoint)
69   {
70     if (!myIsInited)
71     {
72       myMinPoint = thePoint;
73       myMaxPoint = thePoint;
74       myIsInited = Standard_True;
75     }
76     else
77     {
78       myMinPoint = myMinPoint.cwiseMin (thePoint);
79       myMaxPoint = myMaxPoint.cwiseMax (thePoint);
80     }
81   }
82
83   //! Combines bounding box with another one.
84   void Combine (const BVH_Box& theBox);
85
86   //! Returns minimum point of bounding box.
87   const BVH_VecNt& CornerMin() const { return myMinPoint; }
88
89   //! Returns maximum point of bounding box.
90   const BVH_VecNt& CornerMax() const { return myMaxPoint; }
91
92   //! Returns minimum point of bounding box.
93   BVH_VecNt& CornerMin() { return myMinPoint; }
94
95   //! Returns maximum point of bounding box.
96   BVH_VecNt& CornerMax() { return myMaxPoint; }
97
98   //! Returns surface area of bounding box.
99   //! If the box is degenerated into line, returns the perimeter instead.
100   T Area() const;
101
102   //! Returns diagonal of bounding box.
103   BVH_VecNt Size() const { return myMaxPoint - myMinPoint; }
104
105   //! Returns center of bounding box.
106   BVH_VecNt Center() const { return (myMinPoint + myMaxPoint) * static_cast<T> (0.5); }
107
108   //! Returns center of bounding box along the given axis.
109   T Center (const Standard_Integer theAxis) const;
110
111 protected:
112
113   BVH_VecNt        myMinPoint; //!< Minimum point of bounding box
114   BVH_VecNt        myMaxPoint; //!< Maximum point of bounding box
115   Standard_Boolean myIsInited; //!< Is bounding box initialized?
116
117 };
118
119 namespace BVH
120 {
121   //! Tool class for calculating box center along the given axis.
122   //! \tparam T Numeric data type
123   //! \tparam N Vector dimension
124   template<class T, int N>
125   struct CenterAxis
126   {
127     // Not implemented
128   };
129
130   template<class T>
131   struct CenterAxis<T, 2>
132   {
133     static T Center (const BVH_Box<T, 2>& theBox, const Standard_Integer theAxis)
134     {
135       if (theAxis == 0)
136       {
137         return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
138       }
139       else if (theAxis == 1)
140       {
141         return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
142       }
143       return static_cast<T> (0.0);
144     }
145   };
146
147   template<class T>
148   struct CenterAxis<T, 3>
149   {
150     static T Center (const BVH_Box<T, 3>& theBox, const Standard_Integer theAxis)
151     {
152       if (theAxis == 0)
153       {
154         return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
155       }
156       else if (theAxis == 1)
157       {
158         return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
159       }
160       else if (theAxis == 2)
161       {
162         return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
163       }
164       return static_cast<T> (0.0);
165     }
166   };
167
168   template<class T>
169   struct CenterAxis<T, 4>
170   {
171     static T Center (const BVH_Box<T, 4>& theBox, const Standard_Integer theAxis)
172     {
173       if (theAxis == 0)
174       {
175         return (theBox.CornerMin().x() + theBox.CornerMax().x()) * static_cast<T> (0.5);
176       }
177       else if (theAxis == 1)
178       {
179         return (theBox.CornerMin().y() + theBox.CornerMax().y()) * static_cast<T> (0.5);
180       }
181       else if (theAxis == 2)
182       {
183         return (theBox.CornerMin().z() + theBox.CornerMax().z()) * static_cast<T> (0.5);
184       }
185       return static_cast<T> (0.0);
186     }
187   };
188
189   //! Tool class for calculating surface area of the box.
190   //! \tparam T Numeric data type
191   //! \tparam N Vector dimension
192   template<class T, int N>
193   struct SurfaceCalculator
194   {
195     // Not implemented
196   };
197
198   template<class T>
199   struct SurfaceCalculator<T, 2>
200   {
201     static T Area (const typename BVH_Box<T, 2>::BVH_VecNt& theSize)
202     {
203       const T anArea = theSize.x() * theSize.y();
204
205       if (anArea < std::numeric_limits<T>::epsilon())
206       {
207         return theSize.x() + theSize.y();
208       }
209
210       return anArea;
211     }
212   };
213
214   template<class T>
215   struct SurfaceCalculator<T, 3>
216   {
217     static T Area (const typename BVH_Box<T, 3>::BVH_VecNt& theSize)
218     {
219       const T anArea = ( theSize.x() * theSize.y() +
220                          theSize.x() * theSize.z() +
221                          theSize.z() * theSize.y() ) * static_cast<T> (2.0);
222
223       if (anArea < std::numeric_limits<T>::epsilon())
224       {
225         return theSize.x() +
226                theSize.y() +
227                theSize.z();
228       }
229
230       return anArea;
231     }
232   };
233
234   template<class T>
235   struct SurfaceCalculator<T, 4>
236   {
237     static T Area (const typename BVH_Box<T, 4>::BVH_VecNt& theSize)
238     {
239       const T anArea = ( theSize.x() * theSize.y() +
240                          theSize.x() * theSize.z() +
241                          theSize.z() * theSize.y() ) * static_cast<T> (2.0);
242
243       if (anArea < std::numeric_limits<T>::epsilon())
244       {
245         return theSize.x() +
246                theSize.y() +
247                theSize.z();
248       }
249
250       return anArea;
251     }
252   };
253
254   //! Tool class for calculate component-wise vector minimum
255   //! and maximum (optimized version).
256   //! \tparam T Numeric data type
257   //! \tparam N Vector dimension
258   template<class T, int N>
259   struct BoxMinMax
260   {
261     typedef typename BVH::VectorType<T, N>::Type BVH_VecNt;
262
263     static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
264     {
265       theVec1.x() = Min (theVec1.x(), theVec2.x());
266       theVec1.y() = Min (theVec1.y(), theVec2.y());
267       theVec1.z() = Min (theVec1.z(), theVec2.z());
268     }
269
270     static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
271     {
272       theVec1.x() = Max (theVec1.x(), theVec2.x());
273       theVec1.y() = Max (theVec1.y(), theVec2.y());
274       theVec1.z() = Max (theVec1.z(), theVec2.z());
275     }
276   };
277
278   template<class T>
279   struct BoxMinMax<T, 2>
280   {
281     typedef typename BVH::VectorType<T, 2>::Type BVH_VecNt;
282
283     static void CwiseMin (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
284     {
285       theVec1.x() = Min (theVec1.x(), theVec2.x());
286       theVec1.y() = Min (theVec1.y(), theVec2.y());
287     }
288
289     static void CwiseMax (BVH_VecNt& theVec1, const BVH_VecNt& theVec2)
290     {
291       theVec1.x() = Max (theVec1.x(), theVec2.x());
292       theVec1.y() = Max (theVec1.y(), theVec2.y());
293     }
294   };
295 }
296
297 // =======================================================================
298 // function : Combine
299 // purpose  :
300 // =======================================================================
301 template<class T, int N>
302 void BVH_Box<T, N>::Combine (const BVH_Box& theBox)
303 {
304   if (theBox.myIsInited)
305   {
306     if (!myIsInited)
307     {
308       myMinPoint = theBox.myMinPoint;
309       myMaxPoint = theBox.myMaxPoint;
310       myIsInited = Standard_True;
311     }
312     else
313     {
314       BVH::BoxMinMax<T, N>::CwiseMin (myMinPoint, theBox.myMinPoint);
315       BVH::BoxMinMax<T, N>::CwiseMax (myMaxPoint, theBox.myMaxPoint);
316     }
317   }
318 }
319
320 // =======================================================================
321 // function : Area
322 // purpose  :
323 // =======================================================================
324 template<class T, int N>
325 T BVH_Box<T, N>::Area() const
326 {
327   return !myIsInited ? static_cast<T> (0.0) : BVH::SurfaceCalculator<T, N>::Area (myMaxPoint - myMinPoint);
328 }
329
330 // =======================================================================
331 // function : Center
332 // purpose  :
333 // =======================================================================
334 template<class T, int N>
335 T BVH_Box<T, N>::Center (const Standard_Integer theAxis) const
336 {
337   return BVH::CenterAxis<T, N>::Center (*this, theAxis);
338 }
339
340 #endif // _BVH_Box_Header