Autoware.Auto
interval.hpp
Go to the documentation of this file.
1 // Copyright 2020 Mapless AI, Inc.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 // IN THE SOFTWARE.
20 
21 #ifndef GEOMETRY__INTERVAL_HPP_
22 #define GEOMETRY__INTERVAL_HPP_
23 
24 #include <algorithm>
25 #include <cmath>
26 #include <iostream>
27 #include <limits>
28 #include <sstream>
29 #include <stdexcept>
30 #include <string>
31 #include <type_traits>
32 #include <utility>
33 
34 #include "common/types.hpp"
36 
37 namespace autoware
38 {
39 namespace common
40 {
41 namespace geometry
42 {
43 
51 template<typename T>
52 class Interval
53 {
54  static_assert(
55  std::is_floating_point<T>::value,
56  "Intervals only support floating point types.");
57 
58 public:
69  friend bool operator==(const Interval & i1, const Interval & i2)
70  {
71  const auto min_eq = (Interval::min(i1) == Interval::min(i2));
72  const auto max_eq = (Interval::max(i1) == Interval::max(i2));
73  const auto bounds_equal = (min_eq && max_eq);
74  const auto both_empty = (Interval::empty(i1) && Interval::empty(i2));
75  return both_empty || bounds_equal;
76  }
77 
82  friend bool operator!=(const Interval & i1, const Interval & i2)
83  {
84  return !(i1 == i2);
85  }
86 
96  friend std::ostream & operator<<(std::ostream & os, const Interval & i)
97  {
98  constexpr auto PRECISION = 5;
99 
100  // Internal helper to format the output.
101  const auto readable_extremum = [](const T & val) {
102  if (val == std::numeric_limits<T>::lowest()) {
103  return std::string("REAL_MIN");
104  }
105  if (val == std::numeric_limits<T>::max()) {
106  return std::string("REAL_MAX");
107  }
108 
109  std::stringstream ss;
110  ss.setf(std::ios::fixed, std::ios::floatfield);
111  ss.precision(PRECISION);
112  ss << val;
113  return ss.str();
114  };
115 
116  // Do stream output.
117  if (Interval::empty(i)) {
118  return os << "{}";
119  }
120  return os << "{\"min\": " << readable_extremum(Interval::min(i)) <<
121  ", \"max\": " << readable_extremum(Interval::max(i)) << "}";
122  }
123 
131  static bool abs_eq(const Interval & i1, const Interval & i2, const T & eps);
132 
134  static T min(const Interval & i) {return i.min_;}
135 
137  static T max(const Interval & i) {return i.max_;}
138 
145  static T measure(const Interval & i);
146 
156  static bool zero_measure(const Interval & i);
157 
167  static bool empty(const Interval & i);
168 
173  static bool contains(const Interval & i, const T & value);
174 
179  static bool is_subset_eq(const Interval & i1, const Interval & i2);
180 
184  static Interval intersect(const Interval & i1, const Interval & i2);
185 
191  static T clamp_to(const Interval & i, T val);
192 
196  Interval();
197 
206  Interval(const T & min, const T & max);
207 
208 private:
209  static constexpr T NaN = std::numeric_limits<T>::quiet_NaN();
210 
211  T min_;
212  T max_;
213 
220  static bool bounds_valid(const Interval & i);
221 }; // class Interval
222 
223 //------------------------------------------------------------------------------
224 
227 
228 //------------------------------------------------------------------------------
229 
230 template<typename T>
231 constexpr T Interval<T>::NaN;
232 
233 //------------------------------------------------------------------------------
234 
235 template<typename T>
237 : min_(Interval::NaN), max_(Interval::NaN) {}
238 
239 //------------------------------------------------------------------------------
240 
241 template<typename T>
242 Interval<T>::Interval(const T & min, const T & max)
243 : min_(min), max_(max)
244 {
245  if (!Interval::bounds_valid(*this)) {
246  std::stringstream ss;
247  ss << "Attempted to construct an invalid interval: " << *this;
248  throw std::runtime_error(ss.str());
249  }
250 }
251 
252 //------------------------------------------------------------------------------
253 
254 template<typename T>
256  const Interval & i1, const Interval & i2, const T & eps)
257 {
258  namespace comp = helper_functions::comparisons;
259 
260  const auto both_empty = Interval::empty(i1) && Interval::empty(i2);
261  const auto both_non_empty = !Interval::empty(i1) && !Interval::empty(i2);
262 
263  const auto mins_equal = comp::abs_eq(Interval::min(i1), Interval::min(i2), eps);
264  const auto maxs_equal = comp::abs_eq(Interval::max(i1), Interval::max(i2), eps);
265  const auto both_non_empty_equal = both_non_empty && mins_equal && maxs_equal;
266 
267  return both_empty || both_non_empty_equal;
268 }
269 
270 //------------------------------------------------------------------------------
271 
272 template<typename T>
274 {
275  // An empty interval will return false because (NaN == NaN) is false.
276  return Interval::min(i) == Interval::max(i);
277 }
278 
279 //------------------------------------------------------------------------------
280 
281 template<typename T>
283 {
284  return std::isnan(Interval::min(i)) && std::isnan(Interval::max(i));
285 }
286 
287 //------------------------------------------------------------------------------
288 
289 template<typename T>
290 bool Interval<T>::bounds_valid(const Interval & i)
291 {
292  const auto is_ordered = (Interval::min(i) <= Interval::max(i));
293 
294  // Check for emptiness expicitly because it requires both bounds to be NaN
295  return Interval::empty(i) || is_ordered;
296 }
297 
298 //------------------------------------------------------------------------------
299 
300 template<typename T>
301 bool Interval<T>::is_subset_eq(const Interval & i1, const Interval & i2)
302 {
303  const auto lower_contained = (Interval::min(i1) >= Interval::min(i2));
304  const auto upper_contained = (Interval::max(i1) <= Interval::max(i2));
305  return lower_contained && upper_contained;
306 }
307 
308 //------------------------------------------------------------------------------
309 
310 template<typename T>
311 bool Interval<T>::contains(const Interval & i, const T & value)
312 {
313  return (value >= Interval::min(i)) && (value <= Interval::max(i));
314 }
315 
316 //------------------------------------------------------------------------------
317 
318 template<typename T>
320 {
321  return Interval::max(i) - Interval::min(i);
322 }
323 
324 //------------------------------------------------------------------------------
325 
326 template<typename T>
328 {
329  // Construct intersection assuming an intersection exists.
330  try {
331  const auto either_empty = Interval::empty(i1) || Interval::empty(i2);
332  const auto min = std::max(Interval::min(i1), Interval::min(i2));
333  const auto max = std::min(Interval::max(i1), Interval::max(i2));
334  return either_empty ? Interval() : Interval(min, max);
335  } catch (...) {
336  }
337 
338  // Otherwise, the intersection is empty.
339  return Interval();
340 }
341 
342 //------------------------------------------------------------------------------
343 
344 template<typename T>
346 {
347  // clamp val to min
348  val = std::max(val, Interval::min(i));
349 
350  // clamp val to max
351  val = std::min(val, Interval::max(i));
352 
353  return Interval::empty(i) ? Interval::NaN : val;
354 }
355 
356 //------------------------------------------------------------------------------
357 
358 } // namespace geometry
359 } // namespace common
360 } // namespace autoware
361 
362 #endif // GEOMETRY__INTERVAL_HPP_
Interval< autoware::common::types::float32_t > Interval_f
Definition: interval.hpp:226
bool abs_eq(const T &a, const T &b, const T &eps)
Check for approximate equality in absolute terms.
Definition: float_comparisons.hpp:43
T
Definition: catr_diff.py:22
static bool zero_measure(const Interval &i)
Utility for checking whether an interval has zero measure.
Definition: interval.hpp:273
static T max(const Interval &i)
The maximum bound of the interval.
Definition: interval.hpp:137
friend std::ostream & operator<<(std::ostream &os, const Interval &i)
Stream overload for Interval types.
Definition: interval.hpp:96
friend bool operator==(const Interval &i1, const Interval &i2)
Compute equality.
Definition: interval.hpp:69
This file includes common type definition.
static bool is_subset_eq(const Interval &i1, const Interval &i2)
Test for whether &#39;i1&#39; subseteq &#39;i2&#39;.
Definition: interval.hpp:301
static T measure(const Interval &i)
Return the measure (length) of the interval.
Definition: interval.hpp:319
Data structure to contain scalar interval bounds.
Definition: interval.hpp:52
Definition: bool_comparisons.hpp:32
static bool abs_eq(const Interval &i1, const Interval &i2, const T &eps)
Test whether the two intervals have bounds within epsilon of each other.
Definition: interval.hpp:255
friend bool operator!=(const Interval &i1, const Interval &i2)
Compute inequality and the logical negation of equality.
Definition: interval.hpp:82
static Interval intersect(const Interval &i1, const Interval &i2)
Compute the intersection of two intervals as a new interval.
Definition: interval.hpp:327
static T min(const Interval &i)
The minimum bound of the interval.
Definition: interval.hpp:134
static bool empty(const Interval &i)
Whether the interval is empty or not.
Definition: interval.hpp:282
static T clamp_to(const Interval &i, T val)
Clamp a scalar &#39;val&#39; onto &#39;interval&#39;.
Definition: interval.hpp:345
Interval()
Constructor: initialize an empty interval with members set to NaN.
Definition: interval.hpp:236
static bool contains(const Interval &i, const T &value)
Test for whether a given interval contains a given value.
Definition: interval.hpp:311
Interval< autoware::common::types::float64_t > Interval_d
Definition: interval.hpp:225
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24