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