poly_ops/base.hpp¶
Concepts¶
-
template<typename T>
concept coordinate¶ Defined as:
wheredetail::arithmetic<T> && detail::arithmetic<long_coord_t<T>> && detail::arithmetic<real_coord_t<T>> && detail::arithmetic_promotes<T,long_coord_t<T>> && detail::arithmetic_promotes<T,real_coord_t<T>> && std::totally_ordered<T> && std::totally_ordered<long_coord_t<T>> && std::totally_ordered<real_coord_t<T>> && std::convertible_to<T,long_coord_t<T>> && std::convertible_to<int,long_coord_t<T>> && std::convertible_to<T,real_coord_t<T>> && requires(T c,long_coord_t<T> cl,real_coord_t<T> cr) { static_cast<long>(c); { coord_ops<T>::acos(c) } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::acos(cr) } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::cos(cr) } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::sin(cr) } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::sqrt(c) } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::sqrt(cr) } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::round(cr) } -> std::same_as<T>; { coord_ops<T>::ceil(cr) } -> std::same_as<T>; { coord_ops<T>::floor(cr) } -> std::same_as<T>; { coord_ops<T>::to_coord(cr) } -> std::same_as<T>; { coord_ops<T>::pi() } -> std::same_as<real_coord_t<T>>; { coord_ops<T>::mul(c,c) } -> std::same_as<long_coord_t<T>>; { cr * cr } -> std::convertible_to<real_coord_t<T>>; { cr / cr } -> std::convertible_to<real_coord_t<T>>; { c * cr } -> std::convertible_to<real_coord_t<T>>; { cr * c } -> std::convertible_to<real_coord_t<T>>; }
detail::arithmetic<typename T>
is:andrequires(T x) { { x + x } -> std::convertible_to<T>; { x - x } -> std::convertible_to<T>; { -x } -> std::convertible_to<T>; }
detail::arithmetic_promotes<typename Lesser,typename Greater>
is:requires(Lesser a,Greater b) { { a + b } -> std::convertible_to<Greater>; { b + a } -> std::convertible_to<Greater>; { a - b } -> std::convertible_to<Greater>; { b - a } -> std::convertible_to<Greater>; }
-
template<typename T, typename Coord>
concept point_like¶ Defined as:
requires(const T &v) { { point_ops<T>::get_x(v) } -> std::convertible_to<Coord>; { point_ops<T>::get_y(v) } -> std::convertible_to<Coord>; }
-
template<typename T, typename Coord>
concept point_range¶ Defined as:
std::ranges::range<T> && point_like<std::ranges::range_value_t<T>,Coord>
-
template<typename T, typename Coord>
concept point_range_range¶ Defined as:
std::ranges::range<T> && point_range<std::ranges::range_value_t<T>,Coord>
-
template<typename T, typename Coord>
concept point_range_or_range_range¶ Defined as:
td::ranges::range<T> && (point_range<std::ranges::range_value_t<T>,Coord> || point_like<std::ranges::range_value_t<T>,Coord>)
Types¶
-
template<typename T>
struct point_ops¶ A struct containing getters for point-like objects. Specializations exist for
T[2]
,std::span<T,2>
andpoint_t<T>
. This can be specialized by the user for other types. Static functionsget_x
andget_y
should be defined to get the X and Y coordinates respectively.Example:
template<> struct poly_ops::point_ops<MyPoint> { static int get_x(const MyPoint &p) { return static_cast<int>(MyPoint.X * 100.0f); } static int get_y(const MyPoint &p) { return static_cast<int>(MyPoint.Y * 100.0f); } };
-
template<typename Coord>
struct coord_ops¶ Mathematical operations on coordinate types. This struct can be specialized by users of this library. Arithmetic operators should be defined for every permutation of
Coord
,long_t
andreal_t
. Binary operations withCoord
andlong_t
should returnlong_t
,long_t
andreal_t
should returnreal_t
, andCoord
andreal_t
should returnreal_t
.Public Types
-
using long_t = large_ints::sized_int<sizeof(Coord) * 2>¶
Certain operations require multiplying two coordinate values and thus need double the bits of the maximum coordinate value to avoid overflow.
By default, if
Coord
is a 64 bit type, this islarge_ints::compound_int
.This can be specialized as a user-defined type.
-
using real_t = double¶
The coordinates of generated points are usually not integers. By default, they are represented by
double
before being rounded back to integers. This type can be specialized to use some custom type for more precision.
Public Static Functions
-
static inline long_t mul(Coord a, Coord b)¶
Multiply
a
andb
and return the result.This should be equivalent to
static_cast<long_t>(a) * static_cast<long_t>(b)
, exceptlong_t
is not required to support multiplication.
-
static inline real_t acos(Coord x)¶
Default implementation:
return std::acos(static_cast<real_t>(x));
-
static inline real_t acos(real_t x)¶
Default implementation:
return static_cast<Coord>(std::acos(x));
-
static inline real_t sqrt(Coord x)¶
Default implementation:
return std::sqrt(static_cast<real_t>(x));
-
static inline real_t sqrt(real_t x)¶
Default implementation:
return static_cast<Coord>(std::sqrt(x));
-
static inline Coord round(real_t x)¶
Default implementation:
return static_cast<Coord>(std::lround(x));
-
static inline Coord floor(real_t x)¶
Default implementation:
return static_cast<Coord>(std::floor(x));
-
static inline Coord ceil(real_t x)¶
Default implementation:
return static_cast<Coord>(std::ceil(x));
-
using long_t = large_ints::sized_int<sizeof(Coord) * 2>¶
-
template<typename T>
struct point_t¶ A two-dimensional point or vector
Public Functions
-
point_t() noexcept = default¶
The default constructor leaves the values uninitialized
-
template<point_like<T> U>
inline constexpr point_t( - const U &b,
Construct
point_t
from any point-like object
-
constexpr point_t &operator=(const point_t &b) noexcept(std::is_nothrow_copy_constructible_v<T>) = default¶
-
inline constexpr std::size_t size() const noexcept¶
Always returns 2
-
point_t() noexcept = default¶
-
template<coordinate Coord>
class winding_dir_sink¶
Functions¶
-
template<typename T, typename U>
constexpr point_t<std::common_type_t<T, U>> operator+(
)¶ Element-wise addition.
-
template<typename T, typename U>
constexpr point_t<std::common_type_t<T, U>> operator-(
)¶ Element-wise subtraction.
-
template<typename T, typename U>
constexpr point_t<std::common_type_t<T, U>> operator*(
)¶ Element-wise multiplication.
-
template<typename T, typename U>
constexpr point_t<std::common_type_t<T, U>> operator*(const point_t<T> &a, U b)¶ Multiply both elements of
a
byb
and return the result
-
template<typename T, typename U>
constexpr point_t<std::common_type_t<T, U>> operator*(T a, const point_t<U> &b)¶ Multiply both elements of
b
bya
and return the result
-
template<typename T, typename U>
constexpr point_t<std::common_type_t<T, U>> operator/(
)¶ Element-wise division.
-
template<typename T, typename U>
constexpr auto vdot(const point_t<T> &a, const point_t<U> &b)¶ Return the dot product of
a
andb
-
template<typename T, typename U>
constexpr point_t<T> vcast(const point_t<U> &x)¶ Equivalent to
point_t{static_cast<T>(x[0]),static_cast<T>(x[1])}
-
template<typename Coord, typename T>
constexpr real_coord_t<Coord> vmag(const point_t<T> &x)¶
-
template<typename Coord, typename T>
constexpr real_coord_t<T> vangle(const point_t<T> &a, const point_t<T> &b)¶
-
template<typename Coord>
constexpr long_coord_t<Coord> triangle_winding(
)¶ Returns a positive number if the triangle formed by the given points is clockwise, negative if counter-clockwise and zero if degenerate
-
template<coordinate Coord, point_range<Coord> Points>
long_coord_t<Coord> winding_dir(Points &&points)¶ Returns a positive number if mostly clockwise, negative if mostly counter-clockwise and zero if degenerate or exactly half of the polygon’s area is inverted.
This algorithm works on any polygon. For non-overlapping non-inverting polygons, more efficient methods exist.