21 #ifndef PARKING_PLANNER__GEOMETRY_HPP_
22 #define PARKING_PLANNER__GEOMETRY_HPP_
39 namespace parking_planner
51 this->m_coord = std::pair<T, T>(
T{},
T{});
57 this->m_coord = std::pair<T, T>(
x,
y);
63 return this->m_coord == other.m_coord;
70 this->m_coord.first + other.m_coord.first,
71 this->m_coord.second + other.m_coord.second);
78 this->m_coord.first - other.m_coord.first,
79 this->m_coord.second - other.m_coord.second);
85 if (dividend ==
T{}) {
86 throw std::domain_error{
"Divide by zero encountered"};
90 this->m_coord.first / dividend,
91 this->m_coord.second / dividend);
98 this->m_coord.first * multiplier,
99 this->m_coord.second * multiplier);
105 return sqrt(this->
dot(*
this));
111 return this->m_coord.first * other.m_coord.first +
112 this->m_coord.second * other.m_coord.second;
118 T cos_angle = cos(angle);
119 T sin_angle = sin(angle);
120 T x = this->m_coord.first;
121 T y = this->m_coord.second;
122 this->m_coord.first =
x * cos_angle -
y * sin_angle;
123 this->m_coord.second =
x * sin_angle +
y * cos_angle;
129 return this->m_coord;
134 bool operator<=(
const Point2D<T> & other)
const noexcept
136 return this->m_coord <= other.m_coord;
140 bool operator<(
const Point2D<T> & other)
const noexcept
142 return this->m_coord <= other.m_coord;
146 bool operator>=(
const Point2D<T> & other)
const noexcept
148 return this->m_coord <= other.m_coord;
152 bool operator>(
const Point2D<T> & other)
const noexcept
154 return this->m_coord <= other.m_coord;
157 std::pair<T, T> m_coord;
168 this->m_coefficients = coefficients;
169 this->m_right_hand_side = right_hand_side;
174 template<typename S = T, std::enable_if_t<std::is_arithmetic<S>::value,
int> = 0>
177 return this->m_coefficients.dot(point) <= this->m_right_hand_side;
183 return this->m_coefficients;
189 return this->m_right_hand_side;
195 std::vector<T> serialized{};
196 serialized.reserve(internal_scalars_number);
197 const auto & coordinates = m_coefficients.get_coord();
198 serialized.push_back(coordinates.first);
199 serialized.push_back(coordinates.second);
200 serialized.push_back(m_right_hand_side);
207 return internal_scalars_number;
212 static constexpr std::size_t internal_scalars_number = 3;
222 template<typename S = T, std::enable_if_t<std::is_arithmetic<S>::value,
int> = 0>
225 S two_norm = this->m_coefficients.
norm2();
226 if (two_norm < std::numeric_limits<S>::epsilon()) {
227 throw std::domain_error{
"Divide by zero encountered"};
229 this->m_coefficients = this->m_coefficients / two_norm;
230 this->m_right_hand_side = this->m_right_hand_side / two_norm;
234 template<typename S = T, std::enable_if_t<!std::is_arithmetic<S>::value,
int> = 0>
235 void normalize() noexcept
252 this->m_vertices = vertices;
253 this->update_halfplanes_from_vertices();
258 const T rotation_angle,
262 for (
auto &
v : this->m_vertices) {
263 v =
v - rotation_center;
264 v.rotate(rotation_angle);
265 v =
v + rotation_center;
266 v =
v + shift_vector;
268 this->update_halfplanes_from_vertices();
274 for (
const auto & halfplane : this->m_halfplanes) {
275 if (!halfplane.contains_point(point)) {
285 for (
const auto & halfplane : other.m_halfplanes) {
286 bool contains_any_point =
false;
287 for (
const auto & vertex : this->m_vertices) {
288 if (halfplane.contains_point(vertex)) {
289 contains_any_point =
true;
292 if (!contains_any_point) {
297 for (
const auto & halfplane : this->m_halfplanes) {
298 bool contains_any_point =
false;
299 for (
const auto & vertex : other.m_vertices) {
300 if (halfplane.contains_point(vertex)) {
301 contains_any_point =
true;
304 if (!contains_any_point) {
315 return this->m_halfplanes;
321 return this->m_vertices;
325 void update_vertices_from_halfplanes() noexcept
327 this->m_vertices.clear();
328 const auto it_begin = this->m_halfplanes.begin();
329 const auto it_end = this->m_halfplanes.end();
330 auto it_last = it_end;
331 for (
auto it_current = it_begin; it_current != it_end; ++it_current) {
332 const Point2D<T> & coeff_last = it_last->get_coefficients();
333 const T & rhs_last = it_last->get_right_hand_side();
334 const Point2D<T> & coeff_current = it_current->get_coefficients();
335 const T & rhs_current = it_current->get_right_hand_side();
336 T x = coeff_current.
get_coord().second * rhs_last -
337 coeff_last.
get_coord().second * rhs_current;
339 coeff_current.
get_coord().first * rhs_current;
341 it_last = it_current;
345 void update_halfplanes_from_vertices() noexcept
347 this->m_halfplanes.clear();
348 const auto it_begin = this->m_vertices.begin();
349 auto it_last = it_begin;
350 const auto it_end = this->m_vertices.end();
351 if (it_begin != it_end) {
352 for (
auto it = it_begin + 1; it != it_end; ++it) {
353 const Point2D<T> & vertex_last = *it_last;
354 const Point2D<T> & vertex_current = *it;
355 Point2D<T> diff_vector = vertex_current - vertex_last;
356 Point2D<T> norm_vector = Point2D<T>(
357 diff_vector.get_coord().second,
358 -diff_vector.get_coord().first);
359 this->m_halfplanes.push_back(Halfplane2D<T>(norm_vector, norm_vector.dot(vertex_current)));
362 const Point2D<T> & vertex_last = *it_last;
363 const Point2D<T> & vertex_current = *it_begin;
364 Point2D<T> diff_vector = vertex_current - vertex_last;
365 Point2D<T> norm_vector = Point2D<T>(
366 diff_vector.get_coord().second,
367 -diff_vector.get_coord().first);
368 this->m_halfplanes.push_back(Halfplane2D<T>(norm_vector, norm_vector.dot(vertex_current)));
378 std::vector<Point2D<T>> m_vertices;
381 std::vector<Halfplane2D<T>> m_halfplanes;
390 #endif // PARKING_PLANNER__GEOMETRY_HPP_