]> git.mxchange.org Git - simgear.git/blob - simgear/math/SGBox.hxx
Boolean uniforms are now updatable by properties
[simgear.git] / simgear / math / SGBox.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 SGBox_H
19 #define SGBox_H
20
21 template<typename T>
22 class SGBox {
23 public:
24   SGBox() :
25     _min(SGLimits<T>::max(), SGLimits<T>::max(), SGLimits<T>::max()),
26     _max(-SGLimits<T>::max(), -SGLimits<T>::max(), -SGLimits<T>::max())
27   { }
28   SGBox(const SGVec3<T>& pt) :
29     _min(pt),
30     _max(pt)
31   { }
32   SGBox(const SGVec3<T>& min, const SGVec3<T>& max) :
33     _min(min),
34     _max(max)
35   { }
36   template<typename S>
37   explicit SGBox(const SGBox<S>& box) :
38     _min(box.getMin()),
39     _max(box.getMax())
40   { }
41
42   void setMin(const SGVec3<T>& min)
43   { _min = min; }
44   const SGVec3<T>& getMin() const
45   { return _min; }
46
47   void setMax(const SGVec3<T>& max)
48   { _max = max; }
49   const SGVec3<T>& getMax() const
50   { return _max; }
51
52   SGVec3<T> getCorner(unsigned i) const
53   { return SGVec3<T>((i&1) ? _min[0] : _max[0],
54                      (i&2) ? _min[1] : _max[1],
55                      (i&4) ? _min[2] : _max[2]); }
56
57   template<typename S>
58   SGVec3<T> getNearestCorner(const SGVec3<S>& pt) const
59   {
60     SGVec3<T> center = getCenter();
61     return SGVec3<T>((pt[0] <= center[0]) ? _min[0] : _max[0],
62                      (pt[1] <= center[1]) ? _min[1] : _max[1],
63                      (pt[2] <= center[2]) ? _min[2] : _max[2]);
64   }
65   template<typename S>
66   SGVec3<T> getFarestCorner(const SGVec3<S>& pt) const
67   {
68     SGVec3<T> center = getCenter();
69     return SGVec3<T>((pt[0] > center[0]) ? _min[0] : _max[0],
70                      (pt[1] > center[1]) ? _min[1] : _max[1],
71                      (pt[2] > center[2]) ? _min[2] : _max[2]);
72   }
73
74   // return the closest point to pt still in the box
75   template<typename S>
76   SGVec3<T> getClosestPoint(const SGVec3<S>& pt) const
77   {
78     return SGVec3<T>((pt[0] < _min[0]) ? _min[0] : ((_max[0] < pt[0]) ? _max[0] : T(pt[0])),
79                      (pt[1] < _min[1]) ? _min[1] : ((_max[1] < pt[1]) ? _max[1] : T(pt[1])),
80                      (pt[2] < _min[2]) ? _min[2] : ((_max[2] < pt[2]) ? _max[2] : T(pt[2])));
81   }
82
83   // Only works for floating point types
84   SGVec3<T> getCenter() const
85   { return T(0.5)*(_min + _max); }
86
87   // Only valid for nonempty boxes
88   SGVec3<T> getSize() const
89   { return _max - _min; }
90   SGVec3<T> getHalfSize() const
91   { return T(0.5)*getSize(); }
92
93   T getVolume() const
94   {
95     if (empty())
96       return 0;
97     return (_max[0] - _min[0])*(_max[1] - _min[1])*(_max[2] - _min[2]);
98   }
99
100   bool empty() const
101   { return !valid(); }
102
103   bool valid() const
104   {
105     if (_max[0] < _min[0])
106       return false;
107     if (_max[1] < _min[1])
108       return false;
109     if (_max[2] < _min[2])
110       return false;
111     return true;
112   }
113
114   void clear()
115   {
116     _min[0] = SGLimits<T>::max();
117     _min[1] = SGLimits<T>::max();
118     _min[2] = SGLimits<T>::max();
119     _max[0] = -SGLimits<T>::max();
120     _max[1] = -SGLimits<T>::max();
121     _max[2] = -SGLimits<T>::max();
122   }
123
124   void expandBy(const SGVec3<T>& v)
125   { _min = min(_min, v); _max = max(_max, v); }
126
127   void expandBy(const SGBox<T>& b)
128   { _min = min(_min, b._min); _max = max(_max, b._max); }
129
130   // Note that this only works if the box is nonmepty
131   unsigned getBroadestAxis() const
132   {
133     SGVec3<T> size = getSize();
134     if (size[1] <= size[0] && size[2] <= size[0])
135       return 0;
136     else if (size[2] <= size[1])
137       return 1;
138     else
139       return 2;
140   }
141
142   // Note that this only works if the box is nonmepty
143   unsigned getSmallestAxis() const
144   {
145     SGVec3<T> size = getSize();
146     if (size[1] >= size[0] && size[2] >= size[0])
147       return 0;
148     else if (size[2] >= size[1])
149       return 1;
150     else
151       return 2;
152   }
153
154 private:
155   SGVec3<T> _min;
156   SGVec3<T> _max;
157 };
158
159 /// Output to an ostream
160 template<typename char_type, typename traits_type, typename T>
161 inline
162 std::basic_ostream<char_type, traits_type>&
163 operator<<(std::basic_ostream<char_type, traits_type>& s, const SGBox<T>& box)
164 { return s << "min = " << box.getMin() << ", max = " << box.getMax(); }
165
166 #endif