OSG  3.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BoundingSphere.h
Go to the documentation of this file.
1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2  *
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.
7  *
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.
12 */
13 
14 #ifndef OSG_BOUNDINGSPHERE
15 #define OSG_BOUNDINGSPHERE 1
16 
17 #include <osg/Config>
18 #include <osg/Export>
19 #include <osg/Vec3f>
20 #include <osg/Vec3d>
21 
22 namespace osg {
23 
24 template<typename VT>
25 class BoundingBoxImpl;
26 
33 template<typename VT>
34 class BoundingSphereImpl
35 {
36  public:
37  typedef VT vec_type;
38  typedef typename VT::value_type value_type;
39 
40  vec_type _center;
41  value_type _radius;
42 
44  BoundingSphereImpl() : _center(0.0,0.0,0.0),_radius(-1.0) {}
45 
47  BoundingSphereImpl(const vec_type& center, value_type radius) : _center(center),_radius(radius) {}
48 
50  BoundingSphereImpl(const BoundingSphereImpl& bs) : _center(bs._center),_radius(bs._radius) {}
51 
53  BoundingSphereImpl(const BoundingBoxImpl<VT>& bb) : _center(0.0,0.0,0.0),_radius(-1.0) { expandBy(bb); }
54 
56  inline void init()
57  {
58  _center.set(0.0,0.0,0.0);
59  _radius = -1.0;
60  }
61 
64  inline bool valid() const { return _radius>=0.0; }
65 
66  inline bool operator == (const BoundingSphereImpl& rhs) const { return _center==rhs._center && _radius==rhs._radius; }
67  inline bool operator != (const BoundingSphereImpl& rhs) const { return _center!=rhs._center || _radius==rhs._radius; }
68 
70  inline void set(const vec_type& center,value_type radius)
71  {
72  _center = center;
73  _radius = radius;
74  }
75 
77  inline vec_type& center() { return _center; }
78 
80  inline const vec_type& center() const { return _center; }
81 
83  inline value_type& radius() { return _radius; }
85  inline value_type radius() const { return _radius; }
86 
90  inline value_type radius2() const { return _radius*_radius; }
91 
95  template<typename vector_type>
96  void expandBy(const vector_type& v);
97 
101  template<typename vector_type>
102  void expandRadiusBy(const vector_type& v);
103 
107  void expandBy(const BoundingSphereImpl& sh);
108 
112  void expandRadiusBy(const BoundingSphereImpl& sh);
113 
116  template<typename BBT>
117  void expandBy(const BoundingBoxImpl<BBT>& bb);
118 
121  template<typename BBT>
122  void expandRadiusBy(const BoundingBoxImpl<BBT>& bb);
123 
125  inline bool contains(const vec_type& v) const
126  {
127  return valid() && ((v-_center).length2()<=radius2());
128  }
129 
130 
133  inline bool intersects( const BoundingSphereImpl& bs ) const
134  {
135  return valid() && bs.valid() &&
136  ((_center - bs._center).length2() <= (_radius + bs._radius)*(_radius + bs._radius));
137  }
138 };
139 
140 
141 template<typename VT>
142 template<typename vector_type>
143 void BoundingSphereImpl<VT>::expandBy(const vector_type& v)
144 {
145  if (valid())
146  {
147  vec_type dv = vec_type(v)-_center;
148  value_type r = dv.length();
149  if (r>_radius)
150  {
151  value_type dr = (r-_radius)*0.5;
152  _center += dv*(dr/r);
153  _radius += dr;
154  } // else do nothing as vertex is within sphere.
155  }
156  else
157  {
158  _center = v;
159  _radius = 0.0;
160  }
161 }
162 
163 template<typename VT>
164 template<typename vector_type>
165 void BoundingSphereImpl<VT>::expandRadiusBy(const vector_type& v)
166 {
167  if (valid())
168  {
169  value_type r = (vec_type(v)-_center).length();
170  if (r>_radius) _radius = r;
171  // else do nothing as vertex is within sphere.
172  }
173  else
174  {
175  _center = v;
176  _radius = 0.0;
177  }
178 }
179 
180 template<typename VT>
182 {
183  // ignore operation if incoming BoundingSphere is invalid.
184  if (!sh.valid()) return;
185 
186  // This sphere is not set so use the inbound sphere
187  if (!valid())
188  {
189  _center = sh._center;
190  _radius = sh._radius;
191 
192  return;
193  }
194 
195 
196  // Calculate d == The distance between the sphere centers
197  double d = ( _center - sh.center() ).length();
198 
199  // New sphere is already inside this one
200  if ( d + sh.radius() <= _radius )
201  {
202  return;
203  }
204 
205  // New sphere completely contains this one
206  if ( d + _radius <= sh.radius() )
207  {
208  _center = sh._center;
209  _radius = sh._radius;
210  return;
211  }
212 
213 
214  // Build a new sphere that completely contains the other two:
215  //
216  // The center point lies halfway along the line between the furthest
217  // points on the edges of the two spheres.
218  //
219  // Computing those two points is ugly - so we'll use similar triangles
220  double new_radius = (_radius + d + sh.radius() ) * 0.5;
221  double ratio = ( new_radius - _radius ) / d ;
222 
223  _center[0] += ( sh.center()[0] - _center[0] ) * ratio;
224  _center[1] += ( sh.center()[1] - _center[1] ) * ratio;
225  _center[2] += ( sh.center()[2] - _center[2] ) * ratio;
226 
227  _radius = new_radius;
228 
229 }
230 
231 template<typename VT>
233 {
234  if (sh.valid())
235  {
236  if (valid())
237  {
238  value_type r = (sh._center-_center).length()+sh._radius;
239  if (r>_radius) _radius = r;
240  // else do nothing as vertex is within sphere.
241  }
242  else
243  {
244  _center = sh._center;
245  _radius = sh._radius;
246  }
247  }
248 }
249 
250 template<typename VT>
251 template<typename BBT>
253 {
254  if (bb.valid())
255  {
256  if (valid())
257  {
258  BoundingBoxImpl<vec_type> newbb(bb);
259 
260  for(unsigned int c=0;c<8;++c)
261  {
262  vec_type v = bb.corner(c)-_center; // get the direction vector from corner
263  v.normalize(); // normalise it.
264  v *= -_radius; // move the vector in the opposite direction distance radius.
265  v += _center; // move to absolute position.
266  newbb.expandBy(v); // add it into the new bounding box.
267  }
268 
269  _center = newbb.center();
270  _radius = newbb.radius();
271 
272  }
273  else
274  {
275  _center = bb.center();
276  _radius = bb.radius();
277  }
278  }
279 }
280 
281 template<typename VT>
282 template<typename BBT>
284 {
285  if (bb.valid())
286  {
287  if (valid())
288  {
289  for(unsigned int c=0;c<8;++c)
290  {
291  expandRadiusBy(bb.corner(c));
292  }
293  }
294  else
295  {
296  _center = bb.center();
297  _radius = bb.radius();
298  }
299  }
300 }
301 
304 
305 #ifdef OSG_USE_FLOAT_BOUNDINGSPHERE
306  typedef BoundingSpheref BoundingSphere;
307 #else
308  typedef BoundingSphered BoundingSphere;
309 #endif
310 }
311 
312 #endif
bool valid() const
Definition: BoundingBox.h:86
value_type radius2() const
value_type radius() const
Definition: BoundingBox.h:132
bool contains(const vec_type &v) const
BoundingSphereImpl< Vec3d > BoundingSphered
BoundingSphereImpl< Vec3f > BoundingSpheref
value_type radius() const
void expandRadiusBy(const vector_type &v)
BoundingSphereImpl(const BoundingSphereImpl &bs)
bool operator==(const BoundingSphereImpl &rhs) const
const vec_type & center() const
void expandBy(const vec_type &v)
Definition: BoundingBox.h:156
VT::value_type value_type
void set(const vec_type &center, value_type radius)
const vec_type corner(unsigned int pos) const
Definition: BoundingBox.h:149
Definition: AlphaFunc.h:19
BoundingSphered BoundingSphere
bool intersects(const BoundingSphereImpl &bs) const
bool operator!=(const BoundingSphereImpl &rhs) const
BoundingSphereImpl(const BoundingBoxImpl< VT > &bb)
const vec_type center() const
Definition: BoundingBox.h:126
void expandBy(const vector_type &v)
BoundingSphereImpl(const vec_type &center, value_type radius)