1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSG_BOUNDINGBOX
15#define OSG_BOUNDINGBOX 1
26class BoundingSphereImpl;
28/** General purpose axis-aligned bounding box class for enclosing objects/vertices.
29 * Bounds leaf objects in a scene such as osg::Drawable objects. Used for frustum
37 typedef typename VT::value_type value_type;
39 /** Minimum extent. (Smallest X, Y, and Z values of all coordinates.) */
41 /** Maximum extent. (Greatest X, Y, and Z values of all coordinates.) */
44 /** Creates an uninitialized bounding box. */
45 inline BoundingBoxImpl() :
55 inline BoundingBoxImpl(const BoundingBoxImpl<BT>& bb) :
60 /** Creates a bounding box initialized to the given extents. */
61 inline BoundingBoxImpl(value_type xmin, value_type ymin, value_type zmin,
62 value_type xmax, value_type ymax, value_type zmax) :
64 _max(xmax,ymax,zmax) {}
66 /** Creates a bounding box initialized to the given extents. */
67 inline BoundingBoxImpl(const vec_type& min,const vec_type& max) :
71 /** Clear the bounding box. Erases existing minimum and maximum extents. */
82 inline bool operator == (const BoundingBoxImpl& rhs) const { return _min==rhs._min && _max==rhs._max; }
83 inline bool operator != (const BoundingBoxImpl& rhs) const { return _min!=rhs._min || _max!=rhs._max; }
85 /** Returns true if the bounding box extents are valid, false otherwise. */
86 inline bool valid() const
88 return _max.x()>=_min.x() && _max.y()>=_min.y() && _max.z()>=_min.z();
91 /** Sets the bounding box extents. */
92 inline void set (value_type xmin, value_type ymin, value_type zmin,
93 value_type xmax, value_type ymax, value_type zmax)
95 _min.set(xmin,ymin,zmin);
96 _max.set(xmax,ymax,zmax);
99 /** Sets the bounding box extents. */
100 inline void set(const vec_type& min,const vec_type& max)
107 inline value_type& xMin() { return _min.x(); }
108 inline value_type xMin() const { return _min.x(); }
110 inline value_type& yMin() { return _min.y(); }
111 inline value_type yMin() const { return _min.y(); }
113 inline value_type& zMin() { return _min.z(); }
114 inline value_type zMin() const { return _min.z(); }
116 inline value_type& xMax() { return _max.x(); }
117 inline value_type xMax() const { return _max.x(); }
119 inline value_type& yMax() { return _max.y(); }
120 inline value_type yMax() const { return _max.y(); }
122 inline value_type& zMax() { return _max.z(); }
123 inline value_type zMax() const { return _max.z(); }
125 /** Calculates and returns the bounding box center. */
126 inline const vec_type center() const
128 return (_min+_max)*0.5;
131 /** Calculates and returns the bounding box radius. */
132 inline value_type radius() const
134 return sqrt(radius2());
137 /** Calculates and returns the squared length of the bounding box radius.
138 * Note, radius2() is faster to calculate than radius(). */
139 inline value_type radius2() const
141 return 0.25*((_max-_min).length2());
144 /** Returns a specific corner of the bounding box.
145 * pos specifies the corner as a number between 0 and 7.
146 * Each bit selects an axis, X, Y, or Z from least- to
147 * most-significant. Unset bits select the minimum value
148 * for that axis, and set bits select the maximum. */
149 inline const vec_type corner(unsigned int pos) const
151 return vec_type(pos&1?_max.x():_min.x(),pos&2?_max.y():_min.y(),pos&4?_max.z():_min.z());
154 /** Expands the bounding box to include the given coordinate.
155 * If the box is uninitialized, set its min and max extents to v. */
156 inline void expandBy(const vec_type& v)
158 if(v.x()<_min.x()) _min.x() = v.x();
159 if(v.x()>_max.x()) _max.x() = v.x();
161 if(v.y()<_min.y()) _min.y() = v.y();
162 if(v.y()>_max.y()) _max.y() = v.y();
164 if(v.z()<_min.z()) _min.z() = v.z();
165 if(v.z()>_max.z()) _max.z() = v.z();
168 /** Expands the bounding box to include the given coordinate.
169 * If the box is uninitialized, set its min and max extents to
171 inline void expandBy(value_type x,value_type y,value_type z)
173 if(x<_min.x()) _min.x() = x;
174 if(x>_max.x()) _max.x() = x;
176 if(y<_min.y()) _min.y() = y;
177 if(y>_max.y()) _max.y() = y;
179 if(z<_min.z()) _min.z() = z;
180 if(z>_max.z()) _max.z() = z;
183 /** Expands this bounding box to include the given bounding box.
184 * If this box is uninitialized, set it equal to bb. */
185 void expandBy(const BoundingBoxImpl& bb)
187 if (!bb.valid()) return;
189 if(bb._min.x()<_min.x()) _min.x() = bb._min.x();
190 if(bb._max.x()>_max.x()) _max.x() = bb._max.x();
192 if(bb._min.y()<_min.y()) _min.y() = bb._min.y();
193 if(bb._max.y()>_max.y()) _max.y() = bb._max.y();
195 if(bb._min.z()<_min.z()) _min.z() = bb._min.z();
196 if(bb._max.z()>_max.z()) _max.z() = bb._max.z();
199 /** Expands this bounding box to include the given sphere.
200 * If this box is uninitialized, set it to include sh. */
201 template<typename BST>
202 void expandBy(const BoundingSphereImpl<BST>& sh)
204 if (!sh.valid()) return;
206 if(sh._center.x()-sh._radius<_min.x()) _min.x() = sh._center.x()-sh._radius;
207 if(sh._center.x()+sh._radius>_max.x()) _max.x() = sh._center.x()+sh._radius;
209 if(sh._center.y()-sh._radius<_min.y()) _min.y() = sh._center.y()-sh._radius;
210 if(sh._center.y()+sh._radius>_max.y()) _max.y() = sh._center.y()+sh._radius;
212 if(sh._center.z()-sh._radius<_min.z()) _min.z() = sh._center.z()-sh._radius;
213 if(sh._center.z()+sh._radius>_max.z()) _max.z() = sh._center.z()+sh._radius;
217 /** Returns the intersection of this bounding box and the specified bounding box. */
218 BoundingBoxImpl intersect(const BoundingBoxImpl& bb) const
219 { return BoundingBoxImpl(osg::maximum(xMin(),bb.xMin()),osg::maximum(yMin(),bb.yMin()),osg::maximum(zMin(),bb.zMin()),
220 osg::minimum(xMax(),bb.xMax()),osg::minimum(yMax(),bb.yMax()),osg::minimum(zMax(),bb.zMax()));
224 /** Return true if this bounding box intersects the specified bounding box. */
225 bool intersects(const BoundingBoxImpl& bb) const
226 { return osg::maximum(xMin(),bb.xMin()) <= osg::minimum(xMax(),bb.xMax()) &&
227 osg::maximum(yMin(),bb.yMin()) <= osg::minimum(yMax(),bb.yMax()) &&
228 osg::maximum(zMin(),bb.zMin()) <= osg::minimum(zMax(),bb.zMax());
232 /** Returns true if this bounding box contains the specified coordinate. */
233 inline bool contains(const vec_type& v) const
236 (v.x()>=_min.x() && v.x()<=_max.x()) &&
237 (v.y()>=_min.y() && v.y()<=_max.y()) &&
238 (v.z()>=_min.z() && v.z()<=_max.z());
241 /** Returns true if this bounding box contains the specified coordinate allowing for specific epsilon. */
242 inline bool contains(const vec_type& v, value_type epsilon) const
245 ((v.x()+epsilon)>=_min.x() && (v.x()-epsilon)<=_max.x()) &&
246 ((v.y()+epsilon)>=_min.y() && (v.y()-epsilon)<=_max.y()) &&
247 ((v.z()+epsilon)>=_min.z() && (v.z()-epsilon)<=_max.z());
251typedef BoundingBoxImpl<Vec3f> BoundingBoxf;
252typedef BoundingBoxImpl<Vec3d> BoundingBoxd;
254#ifdef OSG_USE_FLOAT_BOUNDINGBOX
255typedef BoundingBoxf BoundingBox;
257typedef BoundingBoxd BoundingBox;