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