Line data Source code
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 : #include <limits>
37 :
38 : namespace vmml
39 : {
40 : /**
41 : * An axis-aligned bounding box.
42 : *
43 : * An empty bounding box has undefined, implementation-specific values. Read
44 : * operations (getMin(), getMax(), getDimension(), isIn(), etc.) have undefined
45 : * semantics on an empty bounding box. set() and merge() operations will define
46 : * the bounding box correctly.
47 : */
48 : template< typename T > class AABB
49 : {
50 : public:
51 : /** Create an empty bounding box. */
52 : AABB();
53 : AABB( const vector< 3, T >& pMin,
54 : const vector< 3, T >& pMax );
55 : AABB( const vector< 4, T >& sphere );
56 : AABB( T cx, T cy, T cz, T size );
57 :
58 : bool isIn( const vector< 3, T >& pos );
59 : bool isIn2d( const vector< 3, T >& pos ); // only x and y components are checked
60 : bool isIn( const vector< 4, T >& sphere );
61 :
62 : void set( const vector< 3, T >& pMin, const vector< 3, T >& pMax );
63 : void set( T cx, T cy, T cz, T size );
64 : void setMin( const vector< 3, T >& pMin );
65 : void setMax( const vector< 3, T >& pMax );
66 :
67 : const vector< 3, T >& getMin() const;
68 : const vector< 3, T >& getMax() const;
69 : vector< 3, T >& getMin();
70 : vector< 3, T >& getMax();
71 :
72 : void merge( const AABB< T >& aabb );
73 : void merge( const vector< 3, T >& point );
74 :
75 : void setEmpty();
76 : bool isEmpty() const;
77 :
78 : AABB operator*( const T value ) const;
79 : AABB operator/( const T value ) const;
80 : AABB operator+( const T value ) const;
81 : AABB operator-( const T value ) const;
82 :
83 : void operator*=( const T value );
84 : void operator/=( const T value );
85 : void operator+=( const T value );
86 : void operator-=( const T value );
87 :
88 : template< class U >
89 : bool operator==( const AABB< U >& other ) const;
90 : template< class U >
91 : bool operator!=( const AABB< U >& other ) const;
92 :
93 : vector< 3, T > getCenter() const;
94 : vector< 3, T > getDimension() const;
95 :
96 : static AABB< T > makeUnitBox();
97 :
98 : protected:
99 : vector< 3, T > _min;
100 : vector< 3, T > _max;
101 : };
102 :
103 : #ifndef VMMLIB_NO_TYPEDEFS
104 : typedef AABB< float > AABBf;
105 : typedef AABB< double > AABBd;
106 : #endif
107 :
108 : template< typename T >
109 0 : inline std::ostream& operator << ( std::ostream& os,
110 : const AABB< T >& aabb )
111 : {
112 0 : return os << aabb.getMin() << " - " << aabb.getMax();
113 : }
114 :
115 : template< typename T > AABB< T >::AABB()
116 : : _min( std::numeric_limits< T >::max( ))
117 : , _max( std::numeric_limits< T >::min( ))
118 : {}
119 :
120 1 : template<> inline AABB< float >::AABB()
121 1 : : _min( std::numeric_limits< float >::max( ))
122 1 : , _max( -std::numeric_limits< float >::max( ))
123 1 : {}
124 :
125 : template<> inline AABB< double >::AABB()
126 : : _min( std::numeric_limits< double >::max( ))
127 : , _max( -std::numeric_limits< double >::max( ))
128 : {}
129 :
130 : template< typename T >
131 1 : AABB< T >::AABB( const vector< 3, T >& pMin,
132 : const vector< 3, T >& pMax)
133 : : _min( pMin )
134 1 : , _max( pMax )
135 1 : {}
136 :
137 : template< typename T >
138 : AABB< T >::AABB( const vector< 4, T >& sphere )
139 : {
140 : _max = _min = sphere.getCenter();
141 : _max += sphere.getRadius();
142 : _min -= sphere.getRadius();
143 : }
144 :
145 : template< typename T >
146 : AABB< T >::AABB( T cx, T cy, T cz, T size )
147 : {
148 : _max = _min = vector< 3, T >( cx, cy, cz );
149 : _max += size;
150 : _min -= size;
151 : }
152 :
153 : template< typename T >
154 : inline bool AABB< T >::isIn( const vector< 4, T >& sphere )
155 : {
156 : vector< 3, T > sv ( sphere.getCenter() );
157 : sv += sphere.getRadius();
158 : if ( sv.x() > _max.x() || sv.y() > _max.y() || sv.z() > _max.z() )
159 : return false;
160 : sv -= sphere.getRadius() * 2.0f;
161 : if ( sv.x() < _min.x() || sv.y() < _min.y() || sv.z() < _min.z() )
162 : return false;
163 : return true;
164 : }
165 :
166 : template< typename T >
167 : inline bool AABB< T >::isIn( const vector< 3, T >& pos )
168 : {
169 : if ( pos.x() > _max.x() || pos.y() > _max.y() || pos.z() > _max.z() ||
170 : pos.x() < _min.x() || pos.y() < _min.y() || pos.z() < _min.z( ))
171 : {
172 : return false;
173 : }
174 : return true;
175 : }
176 :
177 : template< typename T >
178 : inline bool AABB< T >::isIn2d( const vector< 3, T >& pos )
179 : {
180 : if ( pos.x() > _max.x() || pos.y() > _max.y() || pos.x() < _min.x() ||
181 : pos.y() < _min.y( ))
182 : {
183 : return false;
184 : }
185 : return true;
186 : }
187 :
188 : template< typename T >
189 : inline void AABB< T >::set( const vector< 3, T >& pMin,
190 : const vector< 3, T >& pMax )
191 : {
192 : _min = pMin;
193 : _max = pMax;
194 : }
195 :
196 : template< typename T >
197 : inline void AABB< T >::set( T cx, T cy, T cz, T size )
198 : {
199 : vector< 3, T > center( cx, cy, cz );
200 : _min = center - size;
201 : _max = center + size;
202 : }
203 :
204 : template< typename T >
205 : inline void AABB< T >::setMin( const vector< 3, T >& pMin )
206 : {
207 : _min = pMin;
208 : }
209 :
210 : template< typename T >
211 : inline void AABB< T >::setMax( const vector< 3, T >& pMax )
212 : {
213 : _max = pMax;
214 : }
215 :
216 : template< typename T >
217 2 : inline const vector< 3, T >& AABB< T >::getMin() const
218 : {
219 2 : return _min;
220 : }
221 :
222 : template< typename T >
223 2 : inline const vector< 3, T >& AABB< T >::getMax() const
224 : {
225 2 : return _max;
226 : }
227 :
228 2 : template< typename T > inline vector< 3, T >& AABB< T >::getMin()
229 : {
230 2 : return _min;
231 : }
232 :
233 2 : template< typename T > inline vector< 3, T >& AABB< T >::getMax()
234 : {
235 2 : return _max;
236 : }
237 :
238 : template< typename T > AABB< T >
239 : AABB< T >::operator*( const T value ) const
240 : {
241 : AABB result = *this;
242 : result *= value;
243 : return result;
244 : }
245 :
246 : template< typename T > AABB< T >
247 : AABB< T >::operator/( const T value ) const
248 : {
249 : AABB result = *this;
250 : result /= value;
251 : return result;
252 : }
253 :
254 : template< typename T > AABB< T >
255 : AABB< T >::operator+( const T value ) const
256 : {
257 : AABB result = *this;
258 : result += value;
259 : return result;
260 : }
261 :
262 : template< typename T > AABB< T >
263 : AABB< T >::operator-( const T value ) const
264 : {
265 : AABB result = *this;
266 : result -= value;
267 : return result;
268 : }
269 :
270 : template< typename T >
271 : void AABB< T >::operator*=( const T value )
272 : {
273 : _min *= value;
274 : _max *= value;
275 : }
276 :
277 : template< typename T >
278 : void AABB< T >::operator/=( const T value )
279 : {
280 : _min /= value;
281 : _max /= value;
282 : }
283 :
284 : template< typename T >
285 : void AABB< T >::operator+=( const T value )
286 : {
287 : _min += value;
288 : _max += value;
289 : }
290 :
291 : template< typename T >
292 : void AABB< T >::operator-=( const T value )
293 : {
294 : _min -= value;
295 : _max -= value;
296 : }
297 :
298 : template< typename T > template< class U > bool
299 1 : AABB< T >::operator==( const AABB< U >& other )
300 : const
301 : {
302 1 : return _min == other._min && _max == other._max;
303 : }
304 :
305 : template< typename T > template< class U > bool
306 : AABB< T >::operator!=( const AABB< U >& other )
307 : const
308 : {
309 : return _min != other._min || _max != other._max;
310 : }
311 :
312 : template< typename T >
313 : vector< 3, T > AABB< T >::getCenter() const
314 : {
315 : return _min + ( ( _max - _min ) * 0.5f );
316 : }
317 :
318 : template< typename T >
319 2 : vector< 3, T > AABB< T >::getDimension() const
320 : {
321 2 : return _max - _min;
322 : }
323 :
324 : template< typename T >
325 1 : void AABB< T >::merge( const AABB<T>& aabb )
326 : {
327 1 : const vector< 3, T >& min = aabb.getMin();
328 1 : const vector< 3, T >& max = aabb.getMax();
329 :
330 1 : if ( min.x() < _min.x() )
331 1 : _min.x() = min.x();
332 1 : if ( min.y() < _min.y() )
333 1 : _min.y() = min.y();
334 1 : if ( min.z() < _min.z() )
335 1 : _min.z() = min.z();
336 :
337 1 : if ( max.x() > _max.x() )
338 0 : _max.x() = max.x();
339 1 : if ( max.y() > _max.y() )
340 0 : _max.y() = max.y();
341 1 : if ( max.z() > _max.z() )
342 0 : _max.z() = max.z();
343 1 : }
344 :
345 : template< typename T >
346 2 : void AABB< T >::merge( const vector< 3, T >& point )
347 : {
348 2 : if ( point.x() < _min.x() )
349 1 : _min.x() = point.x();
350 2 : if ( point.y() < _min.y() )
351 1 : _min.y() = point.y();
352 2 : if ( point.z() < _min.z() )
353 1 : _min.z() = point.z();
354 :
355 2 : if ( point.x() > _max.x() )
356 2 : _max.x() = point.x();
357 2 : if ( point.y() > _max.y() )
358 2 : _max.y() = point.y();
359 2 : if ( point.z() > _max.z() )
360 2 : _max.z() = point.z();
361 2 : }
362 :
363 : template< typename T >inline
364 : void AABB< T >::setEmpty()
365 : {
366 : _min = std::numeric_limits< T >::max();
367 : _max = -std::numeric_limits< T >::max();
368 : }
369 :
370 :
371 4 : template< typename T > inline bool AABB< T >::isEmpty() const
372 : {
373 12 : return ( _min.x() >= _max.x() || _min.y() >= _max.y() ||
374 12 : _min.z() >= _max.x( ));
375 : }
376 :
377 : template< typename T >
378 : AABB< T > AABB< T >::makeUnitBox()
379 : {
380 : return AABB( vector< 3, T >::ZERO, vector< 3, T >::ONE );
381 : }
382 :
383 : }; //namespace vmml
384 :
385 : #endif
|