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