Autoware.Auto
common_2d.hpp
Go to the documentation of this file.
1 // Copyright 2017-2021 the Autoware Foundation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Co-developed by Tier IV, Inc. and Apex.AI, Inc.
18 
19 #ifndef GEOMETRY__COMMON_2D_HPP_
20 #define GEOMETRY__COMMON_2D_HPP_
21 
22 #include <common/types.hpp>
23 #include <cmath>
24 #include <limits>
25 #include <stdexcept>
26 
27 #include "geometry/interval.hpp"
28 
31 
32 namespace autoware
33 {
34 namespace common
35 {
36 namespace geometry
37 {
38 
40 namespace point_adapter
41 {
46 template<typename PointT>
47 inline auto x_(const PointT & pt)
48 {
49  return pt.x;
50 }
55 template<typename PointT>
56 inline auto y_(const PointT & pt)
57 {
58  return pt.y;
59 }
64 template<typename PointT>
65 inline auto z_(const PointT & pt)
66 {
67  return pt.z;
68 }
73 template<typename PointT>
74 inline auto & xr_(PointT & pt)
75 {
76  return pt.x;
77 }
82 template<typename PointT>
83 inline auto & yr_(PointT & pt)
84 {
85  return pt.y;
86 }
91 template<typename PointT>
92 inline auto & zr_(PointT & pt)
93 {
94  return pt.z;
95 }
96 } // namespace point_adapter
97 
98 namespace details
99 {
100 // Return the next iterator, cycling back to the beginning of the list if you hit the end
101 template<typename IT>
102 IT circular_next(const IT begin, const IT end, const IT current) noexcept
103 {
104  auto next = std::next(current);
105  if (end == next) {
106  next = begin;
107  }
108  return next;
109 }
110 
111 } // namespace details
112 
113 
120 template<typename T1, typename T2, typename T3>
121 inline auto ccw(const T1 & pt, const T2 & q, const T3 & r)
122 {
123  using point_adapter::x_;
124  using point_adapter::y_;
125  return (((x_(q) - x_(pt)) * (y_(r) - y_(pt))) - ((y_(q) - y_(pt)) * (x_(r) - x_(pt)))) <= 0.0F;
126 }
127 
133 template<typename T1, typename T2>
134 inline auto cross_2d(const T1 & pt, const T2 & q)
135 {
136  using point_adapter::x_;
137  using point_adapter::y_;
138  return (x_(pt) * y_(q)) - (y_(pt) * x_(q));
139 }
140 
146 template<typename T1, typename T2>
147 inline auto dot_2d(const T1 & pt, const T2 & q)
148 {
149  using point_adapter::x_;
150  using point_adapter::y_;
151  return (x_(pt) * x_(q)) + (y_(pt) * y_(q));
152 }
153 
160 template<typename T>
161 T minus_2d(const T & p, const T & q)
162 {
163  T r;
164  using point_adapter::x_;
165  using point_adapter::y_;
166  point_adapter::xr_(r) = x_(p) - x_(q);
167  point_adapter::yr_(r) = y_(p) - y_(q);
168  return r;
169 }
170 
176 template<typename T>
177 T minus_2d(const T & p)
178 {
179  T r;
182  return r;
183 }
190 template<typename T>
191 T plus_2d(const T & p, const T & q)
192 {
193  T r;
194  using point_adapter::x_;
195  using point_adapter::y_;
196  point_adapter::xr_(r) = x_(p) + x_(q);
197  point_adapter::yr_(r) = y_(p) + y_(q);
198  return r;
199 }
200 
207 template<typename T>
208 T times_2d(const T & p, const float32_t a)
209 {
210  T r;
213  return r;
214 }
215 
226 template<typename T>
227 inline T intersection_2d(const T & pt, const T & u, const T & q, const T & v)
228 {
229  const float32_t num = cross_2d(minus_2d(pt, q), u);
230  float32_t den = cross_2d(v, u);
231  constexpr auto FEPS = std::numeric_limits<float32_t>::epsilon();
232  if (fabsf(den) < FEPS) {
233  if (fabsf(num) < FEPS) {
234  // collinear case, anything is ok
235  den = 1.0F;
236  } else {
237  // parallel case, no valid output
238  throw std::runtime_error(
239  "intersection_2d: no unique solution (either collinear or parallel)");
240  }
241  }
242  return plus_2d(q, times_2d(v, num / den));
243 }
244 
245 
251 template<typename T>
252 inline void rotate_2d(T & pt, const float32_t cos_th, const float32_t sin_th)
253 {
254  const float32_t x = point_adapter::x_(pt);
255  const float32_t y = point_adapter::y_(pt);
256  point_adapter::xr_(pt) = (cos_th * x) - (sin_th * y);
257  point_adapter::yr_(pt) = (sin_th * x) + (cos_th * y);
258 }
259 
265 template<typename T>
266 inline T rotate_2d(const T & pt, const float32_t th_rad)
267 {
268  T q(pt); // It's reasonable to expect a copy constructor
269  const float32_t s = sinf(th_rad);
270  const float32_t c = cosf(th_rad);
271  rotate_2d(q, c, s);
272  return q;
273 }
274 
280 template<typename T>
281 inline T get_normal(const T & pt)
282 {
283  T q(pt);
286  return q;
287 }
288 
293 template<typename T>
294 inline auto norm_2d(const T & pt)
295 {
296  return sqrtf(dot_2d(pt, pt));
297 }
298 
307 template<typename T>
308 inline T closest_segment_point_2d(const T & p, const T & q, const T & r)
309 {
310  const T qp = minus_2d(q, p);
311  const float32_t len2 = dot_2d(qp, qp);
312  T ret = p;
313  if (len2 > std::numeric_limits<float32_t>::epsilon()) {
314  const Interval_f unit_interval(0.0f, 1.0f);
315  const float32_t val = dot_2d(minus_2d(r, p), qp) / len2;
316  const float32_t t = Interval_f::clamp_to(unit_interval, val);
317  ret = plus_2d(p, times_2d(qp, t));
318  }
319  return ret;
320 }
321 //
324 // Obtained by simplifying closest_segment_point_2d.
330 // define a line
331 template<typename T>
332 inline T closest_line_point_2d(const T & p, const T & q, const T & r)
333 {
334  const T qp = minus_2d(q, p);
335  const float32_t len2 = dot_2d(qp, qp);
336  T ret = p;
337  if (len2 > std::numeric_limits<float32_t>::epsilon()) {
338  const float32_t t = dot_2d(minus_2d(r, p), qp) / len2;
339  ret = plus_2d(p, times_2d(qp, t));
340  } else {
341  throw std::runtime_error(
342  "closet_line_point_2d: line ill-defined because given points coincide");
343  }
344  return ret;
345 }
346 
353 template<typename T>
354 inline auto point_line_segment_distance_2d(const T & p, const T & q, const T & r)
355 {
356  const T pq_r = minus_2d(closest_segment_point_2d(p, q, r), r);
357  return norm_2d(pq_r);
358 }
359 
364 template<typename T>
365 inline T make_unit_vector2d(float th)
366 {
367  T r;
368  point_adapter::xr_(r) = std::cos(th);
369  point_adapter::yr_(r) = std::sin(th);
370  return r;
371 }
372 
380 template<typename T>
381 inline bool is_left_of_line_2d(const T & p1, const T & p2, const T & q)
382 {
383  return cross_2d(minus_2d(p2, p1), minus_2d(q, p1)) > 0.0F;
384 }
385 
391 template<typename IT>
392 bool all_ccw(const IT begin, const IT end) noexcept
393 {
394  // Short circuit: a line or point is always CCW or otherwise ill-defined
395  if (std::distance(begin, end) <= 2U) {
396  return true;
397  }
398  // Can't use std::all_of because that works directly on the values
399  for (auto line_start = begin; line_start != end; ++line_start) {
400  const auto line_end = details::circular_next(begin, end, line_start);
401  const auto query_point = details::circular_next(begin, end, line_end);
402  if (!is_left_of_line_2d(*line_start, *line_end, *query_point)) {
403  return false;
404  }
405  }
406  return true;
407 }
408 
414 template<typename IT>
415 auto area_2d(const IT begin, const IT end) noexcept
416 {
417  using point_adapter::x_;
418  using point_adapter::y_;
419  using T = decltype(x_(*begin));
420  auto area = T{}; // zero initialization
421  // use the approach of https://www.mathwords.com/a/area_convex_polygon.htm
422  for (auto it = begin; it != end; ++it) {
423  const auto next = details::circular_next(begin, end, it);
424  area += x_(*it) * y_(*next);
425  area -= x_(*next) * y_(*it);
426  }
427  return T{0.5} *area;
428 }
429 
437 template<typename IT>
438 auto area_checked_2d(const IT begin, const IT end)
439 {
440  if (!all_ccw(begin, end)) {
441  throw std::domain_error{"Cannot compute area: points are not CCW"};
442  }
443  return area_2d(begin, end);
444 }
445 
446 } // namespace geometry
447 } // namespace common
448 } // namespace autoware
449 
450 #endif // GEOMETRY__COMMON_2D_HPP_
autoware::common::geometry::times_2d
T times_2d(const T &p, const float32_t a)
The scalar multiplication operation, p * a.
Definition: common_2d.hpp:208
autoware::common::geometry::get_normal
T get_normal(const T &pt)
compute q s.t. p T q, or p * q = 0 This is the equivalent of a 90 degree ccw rotation
Definition: common_2d.hpp:281
autoware::common::geometry::cross_2d
auto cross_2d(const T1 &pt, const T2 &q)
compute p x q = p1 * q2 - p2 * q1
Definition: common_2d.hpp:134
catr_diff.T
T
Definition: catr_diff.py:22
autoware::common::geometry::point_adapter::x_
auto x_(const PointT &pt)
Gets the x value for a point.
Definition: common_2d.hpp:47
types.hpp
This file includes common type definition.
y
DifferentialState y
Definition: kinematic_bicycle.snippet.hpp:28
catr_diff.t
t
Definition: catr_diff.py:22
u
DifferentialState u
Definition: kinematic_bicycle.snippet.hpp:29
autoware::common::geometry::closest_line_point_2d
T closest_line_point_2d(const T &p, const T &q, const T &r)
Compute the closest point on the line going through p-q to point r.
Definition: common_2d.hpp:332
autoware::common::geometry::Interval::clamp_to
static T clamp_to(const Interval &i, T val)
Clamp a scalar 'val' onto 'interval'.
Definition: interval.hpp:345
autoware::common::geometry::area_2d
auto area_2d(const IT begin, const IT end) noexcept
Definition: common_2d.hpp:415
autoware::common::geometry::dot_2d
auto dot_2d(const T1 &pt, const T2 &q)
compute p * q = p1 * q1 + p2 * q2
Definition: common_2d.hpp:147
autoware::common::geometry::plus_2d
T plus_2d(const T &p, const T &q)
The 2d addition operation, p + q.
Definition: common_2d.hpp:191
f
DifferentialEquation f
Definition: kinematic_bicycle.snippet.hpp:44
autoware::common::geometry::details::circular_next
IT circular_next(const IT begin, const IT end, const IT current) noexcept
Definition: common_2d.hpp:102
autoware::common::types::bool8_t
bool bool8_t
Definition: types.hpp:39
autoware::common::geometry::area_checked_2d
auto area_checked_2d(const IT begin, const IT end)
Definition: common_2d.hpp:438
autoware
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24
autoware::localization::ndt::next
SerializedNDTMapPoint next(std::array< T, 9U > &pc_its)
Get the next voxel representation from the iterators of a serialized ndt map.
Definition: ndt_map.hpp:263
autoware::common::geometry::point_line_segment_distance_2d
auto point_line_segment_distance_2d(const T &p, const T &q, const T &r)
Compute the distance from line segment p-q to point r.
Definition: common_2d.hpp:354
autoware::common::geometry::point_adapter::yr_
auto & yr_(PointT &pt)
Gets a reference to the y value for a point.
Definition: common_2d.hpp:83
autoware::common::geometry::is_left_of_line_2d
bool is_left_of_line_2d(const T &p1, const T &p2, const T &q)
Check if the given point is strictly to the left of the infinite line passing from p1 to p2....
Definition: common_2d.hpp:381
autoware::common::geometry::norm_2d
auto norm_2d(const T &pt)
get magnitude of x and y components:
Definition: common_2d.hpp:294
x
DifferentialState x
Definition: kinematic_bicycle.snippet.hpp:28
autoware::common::geometry::closest_segment_point_2d
T closest_segment_point_2d(const T &p, const T &q, const T &r)
Compute the closest point on line segment p-q to point r Based on equations from https://stackoverflo...
Definition: common_2d.hpp:308
catr_diff.a
a
Definition: catr_diff.py:22
autoware::common::types::float32_t
float float32_t
Definition: types.hpp:45
autoware::common::geometry::point_adapter::xr_
auto & xr_(PointT &pt)
Gets a reference to the x value for a point.
Definition: common_2d.hpp:74
interval.hpp
autoware::common::geometry::minus_2d
T minus_2d(const T &p, const T &q)
Compute the 2d difference between two points, p - q.
Definition: common_2d.hpp:161
autoware::common::geometry::rotate_2d
void rotate_2d(T &pt, const float32_t cos_th, const float32_t sin_th)
rotate point given precomputed sin and cos
Definition: common_2d.hpp:252
autoware::common::geometry::intersection_2d
T intersection_2d(const T &pt, const T &u, const T &q, const T &v)
solve p + t * u = q + s * v Ref: https://stackoverflow.com/questions/563198/ whats-the-most-efficent-...
Definition: common_2d.hpp:227
autoware::common::geometry::make_unit_vector2d
T make_unit_vector2d(float th)
Make a 2D unit vector given an angle.
Definition: common_2d.hpp:365
autoware::common::geometry::point_adapter::y_
auto y_(const PointT &pt)
Gets the y value for a point.
Definition: common_2d.hpp:56
autoware::common::geometry::point_adapter::z_
auto z_(const PointT &pt)
Gets the z value for a point.
Definition: common_2d.hpp:65
autoware::common::geometry::ccw
auto ccw(const T1 &pt, const T2 &q, const T3 &r)
compute whether line segment rp is counter clockwise relative to line segment qp
Definition: common_2d.hpp:121
autoware::common::geometry::point_adapter::zr_
auto & zr_(PointT &pt)
Gets a reference to the z value for a point.
Definition: common_2d.hpp:92
autoware::common::geometry::Interval
Data structure to contain scalar interval bounds.
Definition: interval.hpp:52
v
DifferentialState v
Definition: linear_tire.snippet.hpp:28
get_open_port.end
end
Definition: scripts/get_open_port.py:23
autoware::common::geometry::all_ccw
bool all_ccw(const IT begin, const IT end) noexcept
Definition: common_2d.hpp:392
catr_diff.th
th
Definition: catr_diff.py:22