8#include "../constexpr_math.h"
9#include "../enum_flags.h"
13#include <glm/geometric.hpp>
14#include <glm/trigonometric.hpp>
15#include <glm/ext/vector_float2.hpp>
16#include <glm/ext/vector_float4.hpp>
17#include <glm/gtx/norm.hpp>
21 template <
typename STRINGIFIER>
22 auto stringify(STRINGIFIER& str, glm::vec4& b) {
return str(
'[', b.x,
',', b.y,
',', b.z,
',', b.w,
']'); }
23 template <
typename STRINGIFIER>
24 auto stringify(STRINGIFIER& str, glm::vec4
const& b) {
return str(
'[', b.x,
',', b.y,
',', b.z,
',', b.w,
']'); }
26 template <
typename STRINGIFIER>
27 auto stringify(STRINGIFIER& str, glm::vec2& b) {
return str(
'[', b.x,
',', b.y,
']'); }
28 template <
typename STRINGIFIER>
29 auto stringify(STRINGIFIER& str, glm::vec2
const& b) {
return str(
'[', b.x,
',', b.y,
']'); }
35 struct precision_limits;
38 struct precision_limits<
double>
40 static constexpr double equivalent_point_max_distance = 0.00002;
41 static constexpr double equivalent_texel_max_distance = 1.0 / 1024.0;
42 static constexpr double near_point_distance = 0.015;
43 static constexpr double point_on_plane_max_distance = 0.1;
44 static constexpr double point_on_line_max_distance = 0.1;
46 static constexpr double foldable_vertex_max_distance = 0.0004;
48 static constexpr double cos_1_deg = 0.99984769515;
49 static constexpr double cos_89_deg = 0.01745240643;
51 static constexpr double min_dot_product_of_parallel_normals = cos_1_deg;
52 static constexpr double max_dot_product_of_perpendicular_normals = cos_1_deg;
58 enum class winding_order
65 constexpr T dot(glm::tvec2<T>
const& a, glm::tvec2<T>
const& b)
noexcept
67 if (std::is_constant_evaluated())
68 return a.x * b.x + a.y * b.y;
70 return glm::dot(a, b);
74 constexpr glm::tvec2<T> length(glm::tvec2<T>
const& a)
noexcept
76 return cem::sqrt(ghassanpl::dot(a, a));
80 constexpr std::pair<glm::tvec2<T>, T> dir_and_length(glm::tvec2<T>
const& a)
noexcept
82 const auto len = length(a);
83 if (len >= std::numeric_limits<T>::epsilon())
84 return { a /
invlen, len };
89 constexpr glm::tvec2<T> with_length(glm::tvec2<T>
const& a, T length)
noexcept
91 const auto dl = dir_and_length(a);
92 return dl.first * length;
96 constexpr glm::tvec2<T> clamp_length(glm::tvec2<T>
const& a, T min, T max)
noexcept
98 const auto lsq = ghassanpl::dot(a, a);
99 const auto sqmin = min * min;
100 const auto sqmax = max * max;
103 const auto clamped = glm::clamp(
lsq, min * min, max * max);
104 return with_length(a, cem::sqrt(
lsq));
109 template <
typename T>
110 constexpr glm::tvec2<T> max_length(glm::tvec2<T>
const& a, T max)
noexcept
112 const auto lsq = ghassanpl::dot(a, a);
113 const auto sqmax = max * max;
116 const auto clamped = glm::min(
lsq, max * max);
117 return with_length(a, cem::sqrt(
lsq));
123namespace ghassanpl::geometry::normals
126 template <
typename T,
size_t N>
127 static constexpr bool are_similar(glm::vec<N, T>
const& a, glm::vec<N, T>
const& b) {
128 constexpr auto min = precision_limits<T>::min_dot_product_of_parallel_normals;
129 return glm::dot(a, b) >= min;
132 template <
typename T,
size_t N>
133 static constexpr bool are_parallel(glm::vec<N, T>
const& a, glm::vec<N, T>
const& b) {
134 constexpr auto min = precision_limits<T>::min_dot_product_of_parallel_normals;
135 return glm::abs(glm::dot(a, b)) >= min;
138 template <
typename T,
size_t N>
139 static constexpr bool are_perpendicular(glm::vec<N, T>
const& a, glm::vec<N, T>
const& b) {
140 constexpr auto max = precision_limits<T>::max_dot_product_of_perpendicular_normals;
141 return glm::abs(glm::dot(a, b)) <= max;
148 template <std::
floating_po
int T>
using basic_radians_t = named<T,
"radians", traits::displacement>;
149 template <std::
floating_po
int T>
using basic_degrees_t = named<T,
"degrees", traits::displacement>;
151 template <std::
floating_po
int T>
using basic_heading_t = named<T,
"heading", traits::location, traits::is_location_of<basic_degrees_t<T>>>;
157 template <
typename TARGET, std::
floating_po
int T>
158 requires std::same_as<TARGET, basic_degrees_t<T>>
164 template <
typename TARGET, std::
floating_po
int T>
165 requires std::same_as<TARGET, basic_radians_t<T>>
173 template <std::
floating_po
int T>
175 template <std::
floating_po
int T>
178 inline constexpr auto full_circle = degrees{ 360.0f };
179 inline constexpr auto half_circle = degrees{ 360.0f / 2.0f };
180 inline constexpr auto quarter_circle = degrees{ 360.0f / 4.0f };
183 inline constexpr std::pair<degrees, degrees> circle_slice = {
198#include <glm/gtx/polar_coordinates.hpp>
202 template <
typename T>
207 template <
typename T>
inline auto rho(
basic_polar2d_t<T> const& polar) {
return polar.value.x; }
208 template <
typename T>
inline auto phi(
basic_polar2d_t<T> const& polar) {
return polar.value.y; }
209 template <
typename T>
inline auto theta(
basic_polar2d_t<T> const& polar) {
return polar.value.y; }
211 template <
typename T>
214 const auto r = std::hypot(euclidean.x, euclidean.y);
215 const auto t = glm::atan(euclidean.y, euclidean.x);
219 template <
typename T>
222 const auto r = rho(polar);
223 const auto t = theta(polar);
224 return glm::tvec2<T>{
r * glm::cos(
t),
r * glm::sin(
t) };
233 template <
typename T>
240 template <
typename U>
241 U distance(glm::tvec2<U>
const& point)
243 return (a * point.x + b * point.y + c) / std::hypot(a, b);
246 template <
typename U>
247 glm::tvec2<U> projected(glm::tvec2<U>
const& point)
249 const auto d = glm::distance(point);
250 return point - glm::tvec2<T>{ a, b } *
d;
254 template <
typename T>
255 basic_line_t<T> line_crossing_points(glm::tvec2<T>
const& p1, glm::tvec2<T>
const& p2)
257 return basic_line_t<T>{ p1.y - p2.y, p2.x - p1.x, p1.x * p2.y - p2.x * p1.y };
260 template <
typename T>
constexpr auto bit_count
Equal to the number of bits in the type.
TODO: This all needs to be tested.