00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef SGSphere_H
00019 #define SGSphere_H
00020
00021 template<typename T>
00022 class SGSphere {
00023 public:
00024 SGSphere() :
00025 _radius(-1)
00026 { }
00027 SGSphere(const SGVec3<T>& center, const T& radius) :
00028 _center(center),
00029 _radius(radius)
00030 { }
00031 template<typename S>
00032 explicit SGSphere(const SGSphere<S>& sphere) :
00033 _center(sphere.getCenter()),
00034 _radius(sphere.getRadius())
00035 { }
00036
00037 const SGVec3<T>& getCenter() const
00038 { return _center; }
00039 void setCenter(const SGVec3<T>& center)
00040 { _center = center; }
00041
00042 const T& getRadius() const
00043 { return _radius; }
00044 void setRadius(const T& radius)
00045 { _radius = radius; }
00046 T getRadius2() const
00047 { return _radius*_radius; }
00048
00049 bool empty() const
00050 { return !valid(); }
00051
00052 bool valid() const
00053 { return 0 <= _radius; }
00054
00055 void clear()
00056 { _radius = -1; }
00057
00058 void expandBy(const SGVec3<T>& v)
00059 {
00060 if (empty()) {
00061 _center = v;
00062 _radius = 0;
00063 return;
00064 }
00065
00066 T dist2 = distSqr(_center, v);
00067 if (dist2 <= getRadius2())
00068 return;
00069
00070 T dist = sqrt(dist2);
00071 T newRadius = T(0.5)*(_radius + dist);
00072 _center += ((newRadius - _radius)/dist)*(v - _center);
00073 _radius = newRadius;
00074 }
00075
00076 void expandBy(const SGSphere<T>& s)
00077 {
00078 if (s.empty())
00079 return;
00080
00081 if (empty()) {
00082 _center = s.getCenter();
00083 _radius = s.getRadius();
00084 return;
00085 }
00086
00087 T dist = length(_center - s.getCenter());
00088 if (dist <= SGLimits<T>::min()) {
00089 _radius = SGMisc<T>::max(_radius, s._radius);
00090 return;
00091 }
00092
00093
00094 if (dist + s.getRadius() <= _radius)
00095 return;
00096
00097
00098 if (dist + _radius <= s.getRadius()) {
00099 _center = s.getCenter();
00100 _radius = s.getRadius();
00101 return;
00102 }
00103
00104 T newRadius = T(0.5)*(_radius + dist + s.getRadius());
00105 T ratio = (newRadius - _radius) / dist;
00106 _radius = newRadius;
00107
00108 _center[0] += ratio*(s._center[0] - _center[0]);
00109 _center[1] += ratio*(s._center[1] - _center[1]);
00110 _center[2] += ratio*(s._center[2] - _center[2]);
00111 }
00112
00113 void expandBy(const SGBox<T>& box)
00114 {
00115 if (box.empty())
00116 return;
00117
00118 if (empty()) {
00119 _center = box.getCenter();
00120 _radius = T(0.5)*length(box.getSize());
00121 return;
00122 }
00123
00124 SGVec3<T> boxCenter = box.getCenter();
00125 SGVec3<T> corner;
00126 for (unsigned i = 0; i < 3; ++i) {
00127 if (_center[i] < boxCenter[i])
00128 corner[i] = box.getMax()[i];
00129 else
00130 corner[i] = box.getMin()[i];
00131 }
00132 expandBy(corner);
00133 }
00134
00135 private:
00136 SGVec3<T> _center;
00137 T _radius;
00138 };
00139
00141 template<typename char_type, typename traits_type, typename T>
00142 inline
00143 std::basic_ostream<char_type, traits_type>&
00144 operator<<(std::basic_ostream<char_type, traits_type>& s,
00145 const SGSphere<T>& sphere)
00146 {
00147 return s << "center = " << sphere.getCenter()
00148 << ", radius = " << sphere.getRadius();
00149 }
00150
00151 #endif