vmmlib  1.7.0
 All Classes Namespaces Functions Pages
aabb.hpp
1 /*
2  * Copyright (c) 2006-2014, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 #ifndef __VMML__AXIS_ALIGNED_BOUNDING_BOX__HPP__
33 #define __VMML__AXIS_ALIGNED_BOUNDING_BOX__HPP__
34 
35 #include <vmmlib/vector.hpp>
36 
37 namespace vmml
38 {
39 
40 template< typename T >
42 {
43 public:
45  AxisAlignedBoundingBox( const vector< 3, T >& pMin, const vector< 3, T >& pMax );
46  AxisAlignedBoundingBox( const vector< 4, T >& sphere );
47  AxisAlignedBoundingBox( T cx, T cy, T cz, T size );
48 
49  inline bool isIn( const vector< 3, T >& pos );
50  inline bool isIn2d( const vector< 3, T >& pos ); // only x and y components are checked
51  inline bool isIn( const vector< 4, T >& sphere );
52 
53  inline void set( const vector< 3, T >& pMin, const vector< 3, T >& pMax );
54  inline void set( T cx, T cy, T cz, T size );
55  inline void setMin( const vector< 3, T >& pMin );
56  inline void setMax( const vector< 3, T >& pMax );
57  inline const vector< 3, T >& getMin() const;
58  inline const vector< 3, T >& getMax() const;
59 
60  inline void merge( const AxisAlignedBoundingBox< T >& aabb );
61  inline void merge( const vector< 3, T >& point );
62 
63  inline void setEmpty( bool empty = true );
64  inline bool isEmpty() const;
65  inline void setDirty( bool dirty = true );
66  inline bool isDirty() const;
67 
68  vector< 3, T > getCenter() const;
69  vector< 3, T > getDimension() const;
70 
71 protected:
72  vector< 3, T > _min;
73  vector< 3, T > _max;
74  bool _dirty;
75  bool _empty;
76 
77 };
78 
79 template< typename T >
80 inline std::ostream& operator << ( std::ostream& os,
81  const AxisAlignedBoundingBox< T >& aabb )
82 {
83  return os << aabb.getMin() << " - " << aabb.getMax();
84 }
85 
86 template< typename T >
87 AxisAlignedBoundingBox< T >::AxisAlignedBoundingBox()
88  : _dirty( false )
89  , _empty( true )
90 {}
91 
92 
93 
94 template< typename T >
95 AxisAlignedBoundingBox< T >::AxisAlignedBoundingBox( const vector< 3, T >& pMin,
96  const vector< 3, T >& pMax)
97  : _min( pMin )
98  , _max( pMax )
99  , _dirty( false )
100  , _empty( false )
101 {}
102 
103 
104 
105 template< typename T >
106 AxisAlignedBoundingBox< T >::AxisAlignedBoundingBox( const vector< 4, T >& sphere )
107  : _dirty( false )
108  , _empty( false )
109 {
110  _max = _min = sphere.getCenter();
111  _max += sphere.getRadius();
112  _min -= sphere.getRadius();
113 }
114 
115 
116 
117 template< typename T >
118 AxisAlignedBoundingBox< T >::AxisAlignedBoundingBox( T cx, T cy, T cz, T size )
119  : _dirty( false )
120  , _empty( false )
121 {
122  _max = _min = vector< 3, T >( cx, cy, cz );
123  _max += size;
124  _min -= size;
125 }
126 
127 
128 
129 template< typename T >
130 inline bool AxisAlignedBoundingBox< T >::isIn( const vector< 4, T >& sphere )
131 {
132  if ( _empty )
133  return false;
134  vector< 3, T > sv ( sphere.getCenter() );
135  sv += sphere.getRadius();
136  if ( sv.x() > _max.x() || sv.y() > _max.y() || sv.z() > _max.z() )
137  return false;
138  sv -= sphere.getRadius() * 2.0f;
139  if ( sv.x() < _min.x() || sv.y() < _min.y() || sv.z() < _min.z() )
140  return false;
141  return true;
142 }
143 
144 
145 
146 template< typename T >
147 inline bool AxisAlignedBoundingBox< T >::isIn( const vector< 3, T >& pos )
148 {
149  if ( _empty )
150  return false;
151  if ( pos.x() > _max.x() || pos.y() > _max.y() || pos.z() > _max.z()
152  || pos.x() < _min.x() || pos.y() < _min.y() || pos.z() < _min.z() )
153  {
154  return false;
155  }
156  return true;
157 }
158 
159 
160 
161 template< typename T >
162 inline bool AxisAlignedBoundingBox< T >::isIn2d( const vector< 3, T >& pos )
163 {
164  if ( _empty )
165  return false;
166  if ( pos.x() > _max.x() || pos.y() > _max.y() || pos.x() < _min.x()
167  || pos.y() < _min.y() )
168  {
169  return false;
170  }
171  return true;
172 }
173 
174 
175 
176 template< typename T >
177 inline void AxisAlignedBoundingBox< T >::set( const vector< 3, T >& pMin,
178  const vector< 3, T >& pMax )
179 {
180  _min = pMin;
181  _max = pMax;
182  _empty = false;
183 }
184 
185 
186 
187 template< typename T >
188 inline void AxisAlignedBoundingBox< T >::set( T cx, T cy, T cz, T size )
189 {
190  vector< 3, T > center( cx, cy, cz );
191  _min = center - size;
192  _max = center + size;
193  _empty = false;
194 }
195 
196 
197 
198 template< typename T >
199 inline void AxisAlignedBoundingBox< T >::setMin( const vector< 3, T >& pMin )
200 {
201  _min = pMin;
202 }
203 
204 
205 
206 template< typename T >
207 inline void AxisAlignedBoundingBox< T >::setMax( const vector< 3, T >& pMax )
208 {
209  _max = pMax;
210 }
211 
212 
213 
214 template< typename T >
215 inline const vector< 3, T >& AxisAlignedBoundingBox< T >::getMin() const
216 {
217  return _min;
218 }
219 
220 
221 
222 template< typename T >
223 inline const vector< 3, T >& AxisAlignedBoundingBox< T >::getMax() const
224 {
225  return _max;
226 }
227 
228 
229 
230 template< typename T >
232 AxisAlignedBoundingBox< T >::getCenter() const
233 {
234  return _min + ( ( _max - _min ) * 0.5f );
235 }
236 
237 
238 
239 template< typename T >
241 AxisAlignedBoundingBox< T >::getDimension() const
242 {
243  return _max - _min;
244 }
245 
246 
247 
248 template< typename T >
249 void AxisAlignedBoundingBox< T >::merge( const AxisAlignedBoundingBox<T>& aabb )
250 {
251  if ( aabb._empty )
252  return; // nothing to do
253 
254  if ( _empty )
255  {
256  // copy non-empty aabb
257  _min = aabb._min;
258  _max = aabb._max;
259  _empty = _dirty = false;
260  return;
261  }
262 
263  // else merge the two aabbs
264  const vector< 3, T >& min = aabb.getMin();
265  const vector< 3, T >& max = aabb.getMax();
266 
267  if ( min.x() < _min.x() )
268  _min.x() = min.x();
269  if ( min.y() < _min.y() )
270  _min.y() = min.y();
271  if ( min.z() < _min.z() )
272  _min.z() = min.z();
273 
274  if ( max.x() > _max.x() )
275  _max.x() = max.x();
276  if ( max.y() > _max.y() )
277  _max.y() = max.y();
278  if ( max.z() > _max.z() )
279  _max.z() = max.z();
280 }
281 
282 template< typename T >
283 void AxisAlignedBoundingBox< T >::merge( const vector< 3, T >& point )
284 {
285  if( _empty )
286  {
287  _min = point;
288  _max = point;
289  _empty = _dirty = false;
290  return;
291  }
292 
293  if ( point.x() < _min.x() )
294  _min.x() = point.x();
295  if ( point.y() < _min.y() )
296  _min.y() = point.y();
297  if ( point.z() < _min.z() )
298  _min.z() = point.z();
299 
300  if ( point.x() > _max.x() )
301  _max.x() = point.x();
302  if ( point.y() > _max.y() )
303  _max.y() = point.y();
304  if ( point.z() > _max.z() )
305  _max.z() = point.z();
306 }
307 
308 template< typename T >
309 inline void AxisAlignedBoundingBox< T >::setEmpty( bool empty )
310 {
311  _empty = empty;
312 }
313 
314 
315 
316 template< typename T >
317 inline bool
318 AxisAlignedBoundingBox< T >::isEmpty() const
319 {
320  return _empty;
321 }
322 
323 
324 
325 template< typename T >
326 inline void
327 AxisAlignedBoundingBox< T >::setDirty( bool dirty )
328 {
329  _dirty = dirty;
330 }
331 
332 
333 
334 template< typename T >
335 inline bool
336 AxisAlignedBoundingBox< T >::isDirty() const
337 {
338  return _dirty;
339 }
340 
341 
342 
343 typedef AxisAlignedBoundingBox< float > Aabbf;
344 
345 }; //namespace vmml
346 
347 #endif