]> git.mxchange.org Git - simgear.git/blobdiff - simgear/math/SGSphere.hxx
Lots of (mostly) doxygen fixes/cleanup.
[simgear.git] / simgear / math / SGSphere.hxx
index 792d939b89bd14da6da5c9addff08a5e222247cc..e4fcb096a7e576a53ca1cfe69d867cf6b695a542 100644 (file)
 #ifndef SGSphere_H
 #define SGSphere_H
 
+
 template<typename T>
 class SGSphere {
 public:
+
+#ifdef __GNUC__
+// Avoid "_center not initialized" warnings.
+#   pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+
   SGSphere() :
+     /*
+      * Do not initialize _center to save unneeded initialization time.
+      * Fix 'may be used uninitialized' warnings locally instead
+      */
+//  _center(0.0, 0.0, 0.0),
     _radius(-1)
   { }
   SGSphere(const SGVec3<T>& center, const T& radius) :
     _center(center),
     _radius(radius)
   { }
+  template<typename S>
+  explicit SGSphere(const SGSphere<S>& sphere) :
+    _center(sphere.getCenter()),
+    _radius(sphere.getRadius())
+  { }
+
+#ifdef __GNUC__
+  // Restore warning settings.
+#   pragma GCC diagnostic warning "-Wuninitialized"
+#endif
 
   const SGVec3<T>& getCenter() const
   { return _center; }
@@ -41,7 +63,7 @@ public:
   T getRadius2() const
   { return _radius*_radius; }
 
-  const bool empty() const
+  bool empty() const
   { return !valid(); }
 
   bool valid() const
@@ -50,6 +72,18 @@ public:
   void clear()
   { _radius = -1; }
 
+  /// Return true if this is inside sphere
+  bool inside(const SGSphere<T>& sphere) const
+  {
+    if (empty())
+      return false;
+    if (sphere.empty())
+      return false;
+
+    T dist = sphere.getRadius() - getRadius();
+    return distSqr(getCenter(), sphere.getCenter()) <= dist*dist;
+  }
+
   void expandBy(const SGVec3<T>& v)
   {
     if (empty()) {
@@ -68,6 +102,65 @@ public:
     _radius = newRadius;
   }
 
+  void expandBy(const SGSphere<T>& s)
+  {
+    if (s.empty())
+      return;
+
+    if (empty()) {
+      _center = s.getCenter();
+      _radius = s.getRadius();
+      return;
+    }
+
+    T dist = length(_center - s.getCenter());
+    if (dist <= SGLimits<T>::min()) {
+      _radius = SGMisc<T>::max(_radius, s._radius);
+      return;
+    }
+
+    // already included
+    if (dist + s.getRadius() <= _radius)
+      return;
+
+    // new one includes all
+    if (dist + _radius <= s.getRadius()) {
+      _center = s.getCenter();
+      _radius = s.getRadius();
+      return;
+    }
+
+    T newRadius = T(0.5)*(_radius + dist + s.getRadius());
+    T ratio = (newRadius - _radius) / dist;
+    _radius = newRadius;
+
+    _center[0] += ratio*(s._center[0] - _center[0]);
+    _center[1] += ratio*(s._center[1] - _center[1]);
+    _center[2] += ratio*(s._center[2] - _center[2]);
+  }
+
+  void expandBy(const SGBox<T>& box)
+  {
+    if (box.empty())
+      return;
+
+    if (empty()) {
+      _center = box.getCenter();
+      _radius = T(0.5)*length(box.getSize());
+      return;
+    }
+
+    SGVec3<T> boxCenter = box.getCenter();
+    SGVec3<T> corner;
+    for (unsigned i = 0; i < 3; ++i) {
+      if (_center[i] < boxCenter[i])
+        corner[i] = box.getMax()[i];
+      else
+        corner[i] = box.getMin()[i];
+    }
+    expandBy(corner);
+  }
+
 private:
   SGVec3<T> _center;
   T _radius;