Recti 1.2.4
Loading...
Searching...
No Matches
polygon.hpp
Go to the documentation of this file.
1
5#pragma once
6
7#include <span>
8#include <vector>
9
10#include "point.hpp"
11
12namespace recti {
13
23 template <typename T> class Polygon {
24 private:
25 Point<T> _origin{};
26 std::vector<Vector2<T>> _vecs{};
27
28 public:
32 constexpr Polygon() = default;
33
40 constexpr Polygon(Point<T> origin, std::vector<Vector2<T>> vecs)
41 : _origin{std::move(origin)}, _vecs{std::move(vecs)} {}
42
53 explicit constexpr Polygon(std::span<const Point<T>> pointset) : _origin{pointset.front()} {
54 if (pointset.size() <= 1) return;
55 _vecs.reserve(pointset.size() - 1);
56 for (auto it = pointset.begin() + 1; it != pointset.end(); ++it) {
57 _vecs.emplace_back(*it - _origin);
58 }
59 }
60
64 constexpr bool operator==(const Polygon& rhs) const {
65 return _origin == rhs._origin && _vecs == rhs._vecs;
66 }
67
71 constexpr bool operator!=(const Polygon& rhs) const { return !(*this == rhs); }
72
80 constexpr auto operator+=(const Vector2<T>& rhs) -> Polygon& {
81 this->_origin += rhs;
82 return *this;
83 }
84
92 constexpr auto operator-=(const Vector2<T>& rhs) -> Polygon& {
93 this->_origin -= rhs;
94 return *this;
95 }
96
106 constexpr auto signed_area_x2() const -> T {
107 if (_vecs.size() < 2) return T{0};
108
109 T res = _vecs[0].x() * _vecs[1].y() - _vecs.back().x() * _vecs[_vecs.size() - 2].y();
110 for (size_t i = 1; i < _vecs.size() - 1; ++i) {
111 res += _vecs[i].x() * (_vecs[i + 1].y() - _vecs[i - 1].y());
112 }
113 return res;
114 }
115
119 constexpr const Point<T>& origin() const { return _origin; }
120
124 constexpr const std::vector<Vector2<T>>& vectors() const { return _vecs; }
125
129 constexpr auto vertices() const -> std::vector<Point<T>> {
130 std::vector<Point<T>> result;
131 result.reserve(_vecs.size() + 1);
132 result.emplace_back(_origin);
133 for (const auto& vec : _vecs) {
134 result.emplace_back(_origin + vec);
135 }
136 return result;
137 }
138
147 constexpr auto is_rectilinear() const -> bool {
148 if (_vecs.empty()) return true;
149
150 // Check from origin (0,0) to first vec
151 if (_vecs[0].x() != 0 && _vecs[0].y() != 0) return false;
152
153 // Check consecutive vecs directly (no vector allocation)
154 for (size_t i = 0; i < _vecs.size() - 1; ++i) {
155 if (_vecs[i].x() != _vecs[i + 1].x() && _vecs[i].y() != _vecs[i + 1].y()) {
156 return false;
157 }
158 }
159
160 // Check closing: last vec back to origin (0,0)
161 if (_vecs.back().x() != 0 && _vecs.back().y() != 0) return false;
162
163 return true;
164 }
165
173 constexpr auto is_convex() const -> bool {
174 if (_vecs.size() < 2) return false;
175 if (_vecs.size() == 2) return true;
176
177 // pointset[i] maps to: _vecs[i-1] for i>0, or (0,0) for i=0
178 // cross_product_sign uses _vecs[N-2] and _vecs[0]
179 T cross_product_sign = -_vecs[_vecs.size() - 2].x() * _vecs[0].y()
180 + _vecs[_vecs.size() - 2].y() * _vecs[0].x();
181
182 for (size_t i = 0; i < _vecs.size() - 1; ++i) {
183 auto v0 = (i == 0) ? Vector2<T>(0, 0) : _vecs[i - 1];
184 const auto& v1 = _vecs[i];
185 const auto& v2 = _vecs[i + 1];
186
187 T current_cross
188 = (v1.x() - v0.x()) * (v2.y() - v1.y()) - (v1.y() - v0.y()) * (v2.x() - v1.x());
189
190 if ((cross_product_sign > 0) != (current_cross > 0)) {
191 return false;
192 }
193 }
194
195 return true;
196 }
197 };
198
210 template <typename FwIter> auto create_xmono_polygon(FwIter first, FwIter last) -> void;
211
223 template <typename FwIter> auto create_ymono_polygon(FwIter first, FwIter last) -> void;
224
237 template <typename T, typename DirFunc>
238 auto polygon_is_monotone(std::span<const Point<T>> pointset, const DirFunc& dir) -> bool;
239
250 template <typename T> auto polygon_is_xmonotone(std::span<const Point<T>> pointset) -> bool;
251
262 template <typename T> auto polygon_is_ymonotone(std::span<const Point<T>> pointset) -> bool;
263
287 template <typename T>
288 auto point_in_polygon(std::span<const Point<T>> pointset, const Point<T>& ptq) -> bool;
289
297 template <typename T> auto polygon_is_anticlockwise(std::span<const Point<T>> pointset) -> bool;
298} // namespace recti
Point.
Definition point.hpp:30
Polygon.
Definition polygon.hpp:23
constexpr auto is_rectilinear() const -> bool
Checks if the polygon is rectilinear.
Definition polygon.hpp:147
constexpr auto operator+=(const Vector2< T > &rhs) -> Polygon &
Adds a vector to the origin of the polygon, effectively translating the polygon.
Definition polygon.hpp:80
constexpr Polygon(std::span< const Point< T > > pointset)
Constructs a new Polygon object from a set of points.
Definition polygon.hpp:53
constexpr auto is_convex() const -> bool
Checks if the polygon is convex.
Definition polygon.hpp:173
constexpr auto vertices() const -> std::vector< Point< T > >
Gets all vertices of the polygon as points.
Definition polygon.hpp:129
constexpr Polygon(Point< T > origin, std::vector< Vector2< T > > vecs)
Constructs a new Polygon object from origin and vectors.
Definition polygon.hpp:40
constexpr bool operator==(const Polygon &rhs) const
Equality comparison operator.
Definition polygon.hpp:64
constexpr bool operator!=(const Polygon &rhs) const
Inequality comparison operator.
Definition polygon.hpp:71
constexpr const std::vector< Vector2< T > > & vectors() const
Gets the displacement vectors of the polygon.
Definition polygon.hpp:124
constexpr auto operator-=(const Vector2< T > &rhs) -> Polygon &
Subtracts a vector from the origin of the polygon, effectively translating the polygon.
Definition polygon.hpp:92
constexpr const Point< T > & origin() const
Gets the origin point of the polygon.
Definition polygon.hpp:119
constexpr auto signed_area_x2() const -> T
Calculates the signed area of the polygon multiplied by 2.
Definition polygon.hpp:106
constexpr Polygon()=default
Default constructor.
2D vector template class.
Definition vector2.hpp:28
Definition svg_utils.hpp:12
auto polygon_is_xmonotone(std::span< const Point< T > > pointset) -> bool
Check if a polygon is x-monotone.
auto point_in_polygon(std::span< const Point< T > > pointset, const Point< T > &ptq) -> bool
Determine if a point is within a polygon.
auto create_xmono_polygon(FwIter first, FwIter last) -> void
Create a xmono Polygon object.
auto polygon_is_ymonotone(std::span< const Point< T > > pointset) -> bool
Check if a polygon is y-monotone.
auto polygon_is_monotone(std::span< const Point< T > > pointset, const DirFunc &dir) -> bool
Check if a polygon is monotone with respect to a given direction function.
auto create_ymono_polygon(FwIter first, FwIter last) -> void
Create a ymono Polygon object.
auto polygon_is_anticlockwise(std::span< const Point< T > > pointset) -> bool
Determines if a polygon represented by a range of points is oriented anticlockwise.
2D Point template class supporting intervals, arithmetic, and geometric queries.