#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; }
T getRadius2() const
{ return _radius*_radius; }
- const bool empty() const
+ bool empty() const
{ return !valid(); }
bool valid() const
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()) {
_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;