1 /* This file is part of the Pangolin Project.
2  * http://github.com/stevenlovegrove/Pangolin
3  *
4  * Copyright (c) 2014 Steven Lovegrove
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #pragma once
29 
30 #include <pangolin/platform.h>
31 
32 #include <limits>
33 #include <algorithm>
34 #include <cmath>
35 
36 //prevent including Eigen in cuda files
37 #if defined(HAVE_EIGEN) && !defined(__CUDACC__)
38 #  define USE_EIGEN
39 #endif
40 
41 #ifdef USE_EIGEN
42 #  include <Eigen/Core>
43 #  include <Eigen/src/Geometry/AlignedBox.h>
44 #endif // USE_EIGEN
45 
46 namespace pangolin
47 {
48 
49 
50 template<typename T>
51 struct Range
52 {
OpenRange53     static Range<T> Open()
54     {
55         return Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
56     }
57 
EmptyRange58     static Range<T> Empty()
59     {
60         return Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest());
61     }
62 
ContainingRange63     static Range<T> Containing(T val)
64     {
65         return Range<T>(val, val);
66     }
67 
RangeRange68     Range()
69         : min(+std::numeric_limits<T>::max()),
70           max(-std::numeric_limits<T>::max())
71     {
72     }
73 
RangeRange74     Range(T rmin, T rmax)
75         : min(rmin), max(rmax)
76     {
77     }
78 
79     Range operator+(T v)
80     {
81         return Range(min+v, max+v);
82     }
83 
84     Range operator-(T v)
85     {
86         return Range(min-v, max-v);
87     }
88 
89     Range& operator+=(T v)
90     {
91         min += v;
92         max += v;
93         return *this;
94     }
95 
96     Range& operator-=(T v)
97     {
98         min -= v;
99         max -= v;
100         return *this;
101     }
102 
103     Range& operator*=(T v)
104     {
105         min *= v;
106         max *= v;
107         return *this;
108     }
109 
110     Range& operator/=(T v)
111     {
112         min /= v;
113         max /= v;
114         return *this;
115     }
116 
117     Range& operator+=(const Range& o)
118     {
119         min += o.min;
120         max += o.max;
121         return *this;
122     }
123 
124     Range& operator-=(const Range& o)
125     {
126         min -= o.min;
127         max -= o.max;
128         return *this;
129     }
130 
131     Range operator+(const Range& o) const
132     {
133         return Range(min + o.min, max + o.max);
134     }
135 
136     Range operator-(const Range& o) const
137     {
138         return Range(min - o.min, max - o.max);
139     }
140 
141     Range operator*(float s) const
142     {
143         return Range(T(s*min), T(s*max));
144     }
145 
SizeRange146     T Size() const
147     {
148         return max - min;
149     }
150 
AbsSizeRange151     T AbsSize() const
152     {
153         return std::abs(Size());
154     }
155 
MidRange156     T Mid() const
157     {
158         return (min + max) / (T)2.0f;
159     }
160 
161     void Scale(float s, float center = 0.0f)
162     {
163         min = T(s*(min-center) + center);
164         max = T(s*(max-center) + center);
165     }
166 
InsertRange167     void Insert(T v)
168     {
169         min = std::min(min,v);
170         max = std::max(max,v);
171     }
172 
InsertRange173     void Insert(const Range<T>& r)
174     {
175         Insert(r.min);
176         Insert(r.max);
177     }
178 
ClampRange179     void Clamp(T vmin, T vmax)
180     {
181         min = std::min(std::max(vmin, min), vmax);
182         max = std::min(std::max(vmin, max), vmax);
183     }
184 
ClampRange185     void Clamp(const Range& o)
186     {
187         Clamp(o.min, o.max);
188     }
189 
ClearRange190     void Clear()
191     {
192         min = std::numeric_limits<T>::max();
193         max = std::numeric_limits<T>::lowest();
194     }
195 
ContainsRange196     bool Contains(T v) const
197     {
198         return min <= v && v <= max;
199     }
200 
ContainsWeakRange201     bool ContainsWeak(T v) const
202     {
203         return (min <= v && v <= max)
204             || (max <= v && v <= min);
205     }
206 
207     template<typename To>
CastRange208     Range<To> Cast() const
209     {
210         return Range<To>(To(min), To(max));
211     }
212 
213     T min;
214     T max;
215 };
216 
217 template<typename T>
218 struct XYRange
219 {
OpenXYRange220     static XYRange<T> Open()
221     {
222         return XYRange<T>(
223             Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max()),
224             Range<T>(std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max())
225         );
226     }
227 
EmptyXYRange228     static XYRange<T> Empty()
229     {
230         return XYRange<T>(
231             Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()),
232             Range<T>(std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest())
233         );
234     }
235 
ContainingXYRange236     static XYRange<T> Containing(T x, T y)
237     {
238         return XYRange<T>(
239             Range<T>(x, x),
240             Range<T>(y, y)
241         );
242     }
243 
XYRangeXYRange244     XYRange()
245     {
246     }
247 
XYRangeXYRange248     XYRange(const Range<T>& xrange, const Range<T>& yrange)
249         : x(xrange), y(yrange)
250     {
251     }
252 
XYRangeXYRange253     XYRange(T xmin, T xmax, T ymin, T ymax)
254         : x(xmin,xmax), y(ymin,ymax)
255     {
256     }
257 
258     XYRange operator-(const XYRange& o) const
259     {
260         return XYRange(x - o.x, y - o.y);
261     }
262 
263     XYRange operator*(float s) const
264     {
265         return XYRange(x*s, y*s);
266     }
267 
268     XYRange& operator+=(const XYRange& o)
269     {
270         x += o.x;
271         y += o.y;
272         return *this;
273     }
274 
ScaleXYRange275     void Scale(float sx, float sy, float centerx, float centery)
276     {
277         x.Scale(sx, centerx);
278         y.Scale(sy, centery);
279     }
280 
ClearXYRange281     void Clear()
282     {
283         x.Clear();
284         y.Clear();
285     }
286 
ClampXYRange287     void Clamp(T xmin, T xmax, T ymin, T ymax)
288     {
289         x.Clamp(xmin,xmax);
290         y.Clamp(ymin,ymax);
291     }
292 
ClampXYRange293     void Clamp(const XYRange& o)
294     {
295         x.Clamp(o.x);
296         y.Clamp(o.y);
297     }
298 
InsertXYRange299     void Insert(T xval, T yval)
300     {
301         x.Insert(xval);
302         y.Insert(yval);
303     }
304 
InsertXYRange305     void Insert(XYRange<T> r)
306     {
307         x.Insert(r.x);
308         y.Insert(r.y);
309     }
310 
AreaXYRange311     float Area() const
312     {
313         return x.Size() * y.Size();
314     }
315 
ContainsXYRange316     bool Contains(float px, float py) const
317     {
318         return x.Contains(px) && y.Contains(py);
319     }
320 
ContainsWeakXYRange321     bool ContainsWeak(float px, float py) const
322     {
323         return x.ContainsWeak(px) && y.ContainsWeak(py);
324     }
325 
326     template<typename To>
CastXYRange327     XYRange<To> Cast() const
328     {
329         return XYRange<To>(
330             x.template Cast<To>(),
331             y.template Cast<To>()
332         );
333     }
334 
335 #ifdef USE_EIGEN
336     operator Eigen::AlignedBox<T,2>() const {
337         return Eigen::AlignedBox<T,2>(
338             Eigen::Matrix<T,2,1>(x.min, y.min),
339             Eigen::Matrix<T,2,1>(x.max, y.max)
340         );
341     }
342 
CenterXYRange343     Eigen::Matrix<T,2,1> Center() const {
344         return Eigen::Matrix<T,2,1>(x.Mid(), y.Mid());
345     }
346 #endif
347 
348     Range<T> x;
349     Range<T> y;
350 };
351 
352 typedef Range<int> Rangei;
353 typedef Range<float> Rangef;
354 typedef Range<double> Ranged;
355 
356 typedef XYRange<int> XYRangei;
357 typedef XYRange<float> XYRangef;
358 typedef XYRange<double> XYRanged;
359 
360 template<typename T> inline
Round(const Range<T> & r)361 Rangei Round(const Range<T>& r)
362 {
363     return Rangei( int(r.min+0.5), int(r.max+0.5) );
364 }
365 
366 template<typename T> inline
Round(const XYRange<T> & r)367 XYRangei Round(const XYRange<T>& r)
368 {
369     return XYRangei( Round(r.x), Round(r.y) );
370 }
371 
372 }
373