X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2FSGSphere.hxx;h=e4fcb096a7e576a53ca1cfe69d867cf6b695a542;hb=914d3e6a2b323cf9f186cbef2aef7865ea07b309;hp=792d939b89bd14da6da5c9addff08a5e222247cc;hpb=de020ee69524393daf11200aa0a46bfd5aa2409a;p=simgear.git diff --git a/simgear/math/SGSphere.hxx b/simgear/math/SGSphere.hxx index 792d939b..e4fcb096 100644 --- a/simgear/math/SGSphere.hxx +++ b/simgear/math/SGSphere.hxx @@ -18,16 +18,38 @@ #ifndef SGSphere_H #define SGSphere_H + template 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& center, const T& radius) : _center(center), _radius(radius) { } + template + explicit SGSphere(const SGSphere& sphere) : + _center(sphere.getCenter()), + _radius(sphere.getRadius()) + { } + +#ifdef __GNUC__ + // Restore warning settings. +# pragma GCC diagnostic warning "-Wuninitialized" +#endif const SGVec3& 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& 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& v) { if (empty()) { @@ -68,6 +102,65 @@ public: _radius = newRadius; } + void expandBy(const SGSphere& s) + { + if (s.empty()) + return; + + if (empty()) { + _center = s.getCenter(); + _radius = s.getRadius(); + return; + } + + T dist = length(_center - s.getCenter()); + if (dist <= SGLimits::min()) { + _radius = SGMisc::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& box) + { + if (box.empty()) + return; + + if (empty()) { + _center = box.getCenter(); + _radius = T(0.5)*length(box.getSize()); + return; + } + + SGVec3 boxCenter = box.getCenter(); + SGVec3 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 _center; T _radius;