]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGSphere.hxx
26649e1b12c5202f62bdf999e462509c1b0c70d1
[simgear.git] / simgear / math / SGSphere.hxx
1 // Copyright (C) 2006  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
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 GNU
11 // Library General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 //
17
18 #ifndef SGSphere_H
19 #define SGSphere_H
20
21 template<typename T>
22 class SGSphere {
23 public:
24   SGSphere() :
25      /*
26       * Do not initialize _center to save unneeded initialization time.
27       * Fix 'may be used uninitialized' warnings locally instead
28       */
29 //  _center(0.0, 0.0, 0.0),
30     _radius(-1)
31   { }
32   SGSphere(const SGVec3<T>& center, const T& radius) :
33     _center(center),
34     _radius(radius)
35   { }
36   template<typename S>
37   explicit SGSphere(const SGSphere<S>& sphere) :
38     _center(sphere.getCenter()),
39     _radius(sphere.getRadius())
40   { }
41
42   const SGVec3<T>& getCenter() const
43   { return _center; }
44   void setCenter(const SGVec3<T>& center)
45   { _center = center; }
46
47   const T& getRadius() const
48   { return _radius; }
49   void setRadius(const T& radius)
50   { _radius = radius; }
51   T getRadius2() const
52   { return _radius*_radius; }
53
54   bool empty() const
55   { return !valid(); }
56
57   bool valid() const
58   { return 0 <= _radius; }
59
60   void clear()
61   { _radius = -1; }
62
63   void expandBy(const SGVec3<T>& v)
64   {
65     if (empty()) {
66       _center = v;
67       _radius = 0;
68       return;
69     }
70
71     T dist2 = distSqr(_center, v);
72     if (dist2 <= getRadius2())
73       return;
74
75     T dist = sqrt(dist2);
76     T newRadius = T(0.5)*(_radius + dist);
77     _center += ((newRadius - _radius)/dist)*(v - _center);
78     _radius = newRadius;
79   }
80
81   void expandBy(const SGSphere<T>& s)
82   {
83     if (s.empty())
84       return;
85
86     if (empty()) {
87       _center = s.getCenter();
88       _radius = s.getRadius();
89       return;
90     }
91
92     T dist = length(_center - s.getCenter());
93     if (dist <= SGLimits<T>::min()) {
94       _radius = SGMisc<T>::max(_radius, s._radius);
95       return;
96     }
97
98     // already included
99     if (dist + s.getRadius() <= _radius)
100       return;
101
102     // new one includes all
103     if (dist + _radius <= s.getRadius()) {
104       _center = s.getCenter();
105       _radius = s.getRadius();
106       return;
107     }
108
109     T newRadius = T(0.5)*(_radius + dist + s.getRadius());
110     T ratio = (newRadius - _radius) / dist;
111     _radius = newRadius;
112
113     _center[0] += ratio*(s._center[0] - _center[0]);
114     _center[1] += ratio*(s._center[1] - _center[1]);
115     _center[2] += ratio*(s._center[2] - _center[2]);
116   }
117
118   void expandBy(const SGBox<T>& box)
119   {
120     if (box.empty())
121       return;
122
123     if (empty()) {
124       _center = box.getCenter();
125       _radius = T(0.5)*length(box.getSize());
126       return;
127     }
128
129     SGVec3<T> boxCenter = box.getCenter();
130     SGVec3<T> corner;
131     for (unsigned i = 0; i < 3; ++i) {
132       if (_center[i] < boxCenter[i])
133         corner[i] = box.getMax()[i];
134       else
135         corner[i] = box.getMin()[i];
136     }
137     expandBy(corner);
138   }
139
140 private:
141   SGVec3<T> _center;
142   T _radius;
143 };
144
145 /// Output to an ostream
146 template<typename char_type, typename traits_type, typename T>
147 inline
148 std::basic_ostream<char_type, traits_type>&
149 operator<<(std::basic_ostream<char_type, traits_type>& s,
150            const SGSphere<T>& sphere)
151 {
152   return s << "center = " << sphere.getCenter()
153            << ", radius = " << sphere.getRadius();
154 }
155
156 #endif