]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGSphere.hxx
MSVC: don't try to compile unknown pragma
[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 #ifndef _MSC_VER
22 #   pragma GCC diagnostic ignored "-Wuninitialized" SGSphere();
23 #endif
24
25 template<typename T>
26 class SGSphere {
27 public:
28   SGSphere() :
29      /*
30       * Do not initialize _center to save unneeded initialization time.
31       * Fix 'may be used uninitialized' warnings locally instead
32       */
33 //  _center(0.0, 0.0, 0.0),
34     _radius(-1)
35   { }
36   SGSphere(const SGVec3<T>& center, const T& radius) :
37     _center(center),
38     _radius(radius)
39   { }
40   template<typename S>
41   explicit SGSphere(const SGSphere<S>& sphere) :
42     _center(sphere.getCenter()),
43     _radius(sphere.getRadius())
44   { }
45
46   const SGVec3<T>& getCenter() const
47   { return _center; }
48   void setCenter(const SGVec3<T>& center)
49   { _center = center; }
50
51   const T& getRadius() const
52   { return _radius; }
53   void setRadius(const T& radius)
54   { _radius = radius; }
55   T getRadius2() const
56   { return _radius*_radius; }
57
58   bool empty() const
59   { return !valid(); }
60
61   bool valid() const
62   { return 0 <= _radius; }
63
64   void clear()
65   { _radius = -1; }
66
67   void expandBy(const SGVec3<T>& v)
68   {
69     if (empty()) {
70       _center = v;
71       _radius = 0;
72       return;
73     }
74
75     T dist2 = distSqr(_center, v);
76     if (dist2 <= getRadius2())
77       return;
78
79     T dist = sqrt(dist2);
80     T newRadius = T(0.5)*(_radius + dist);
81     _center += ((newRadius - _radius)/dist)*(v - _center);
82     _radius = newRadius;
83   }
84
85   void expandBy(const SGSphere<T>& s)
86   {
87     if (s.empty())
88       return;
89
90     if (empty()) {
91       _center = s.getCenter();
92       _radius = s.getRadius();
93       return;
94     }
95
96     T dist = length(_center - s.getCenter());
97     if (dist <= SGLimits<T>::min()) {
98       _radius = SGMisc<T>::max(_radius, s._radius);
99       return;
100     }
101
102     // already included
103     if (dist + s.getRadius() <= _radius)
104       return;
105
106     // new one includes all
107     if (dist + _radius <= s.getRadius()) {
108       _center = s.getCenter();
109       _radius = s.getRadius();
110       return;
111     }
112
113     T newRadius = T(0.5)*(_radius + dist + s.getRadius());
114     T ratio = (newRadius - _radius) / dist;
115     _radius = newRadius;
116
117     _center[0] += ratio*(s._center[0] - _center[0]);
118     _center[1] += ratio*(s._center[1] - _center[1]);
119     _center[2] += ratio*(s._center[2] - _center[2]);
120   }
121
122   void expandBy(const SGBox<T>& box)
123   {
124     if (box.empty())
125       return;
126
127     if (empty()) {
128       _center = box.getCenter();
129       _radius = T(0.5)*length(box.getSize());
130       return;
131     }
132
133     SGVec3<T> boxCenter = box.getCenter();
134     SGVec3<T> corner;
135     for (unsigned i = 0; i < 3; ++i) {
136       if (_center[i] < boxCenter[i])
137         corner[i] = box.getMax()[i];
138       else
139         corner[i] = box.getMin()[i];
140     }
141     expandBy(corner);
142   }
143
144 private:
145   SGVec3<T> _center;
146   T _radius;
147 };
148
149 /// Output to an ostream
150 template<typename char_type, typename traits_type, typename T>
151 inline
152 std::basic_ostream<char_type, traits_type>&
153 operator<<(std::basic_ostream<char_type, traits_type>& s,
154            const SGSphere<T>& sphere)
155 {
156   return s << "center = " << sphere.getCenter()
157            << ", radius = " << sphere.getRadius();
158 }
159
160 #endif