7#include "../numeric/numeric.hpp"
8#include "../geometry/geometry.hpp"
9#include "../container/container.hpp"
10#include "../macros.hpp"
11#include <hikocpu/hikocpu.hpp>
16hi_export_module(hikogui.graphic_path.bezier);
18hi_export
namespace hi {
inline namespace v1 {
23[[nodiscard]]
constexpr T bezier_broadcast(
float x)
noexcept
25 return T::broadcast(x);
29[[nodiscard]]
constexpr float bezier_broadcast(
float x)
noexcept
47 constexpr auto _2 = detail::bezier_broadcast<T>(2);
48 return {P1 - C * _2 + P2, (C - P1) * _2, P1};
53constexpr std::array<T, 4> bezierToPolynomial(T P1, T C1, T C2, T P2)
noexcept
55 constexpr auto _3 = detail::bezier_broadcast<T>(3);
56 constexpr auto _6 = detail::bezier_broadcast<T>(6);
57 constexpr auto min_3 = detail::bezier_broadcast<T>(-3);
58 return {-P1 + C1 * _3 - C2 * _3 + P2, P1 * _3 - C1 * _6 + C2 * _3, P1 * min_3 + C1 * _3, P1};
61constexpr point2 bezierPointAt(point2 P1, point2 P2,
float t)
noexcept
63 auto const t_ = f32x4::broadcast(t);
64 auto const[a, b] = bezierToPolynomial(
static_cast<f32x4
>(P1),
static_cast<f32x4
>(P2));
65 return point2{a * t_ + b};
68constexpr point2 bezierPointAt(point2 P1, point2 C, point2 P2,
float t)
noexcept
70 auto const t_ = f32x4::broadcast(t);
71 auto const[a, b, c] = bezierToPolynomial(
static_cast<f32x4
>(P1),
static_cast<f32x4
>(C),
static_cast<f32x4
>(P2));
72 return point2{a * t_ * t_ + b * t_ + c};
75constexpr point2 bezierPointAt(point2 P1, point2 C1, point2 C2, point2 P2,
float t)
noexcept
77 auto const t_ = f32x4::broadcast(t);
78 auto const tt_ = t_ * t_;
79 auto const ttt_ = tt_ * t_;
81 auto const[a, b, c, d] =
82 bezierToPolynomial(
static_cast<f32x4
>(P1),
static_cast<f32x4
>(C1),
static_cast<f32x4
>(C2),
static_cast<f32x4
>(P2));
83 return point2{a * ttt_ + b * tt_ + c * t_ + d};
86constexpr vector2 bezierTangentAt(point2 P1, point2 P2,
float t)
noexcept
91constexpr vector2 bezierTangentAt(point2 P1, point2 C, point2 P2,
float t)
noexcept
93 constexpr auto _2 = f32x4::broadcast(2);
94 auto const t_ = f32x4::broadcast(t);
95 auto const P1_ =
static_cast<f32x4
>(P1);
96 auto const C_ =
static_cast<f32x4
>(C);
97 auto const P2_ =
static_cast<f32x4
>(P2);
99 return vector2{_2 * t_ * (P2_ - _2 * C_ + P1_) + _2 * (C_ - P1_)};
102constexpr vector2 bezierTangentAt(point2 P1, point2 C1, point2 C2, point2 P2,
float t)
noexcept
104 constexpr auto _2 = f32x4::broadcast(2);
105 constexpr auto _3 = f32x4::broadcast(3);
106 constexpr auto _6 = f32x4::broadcast(6);
107 auto const t_ = f32x4::broadcast(t);
108 auto const tt_ = t_ * t_;
109 auto const P1_ =
static_cast<f32x4
>(P1);
110 auto const C1_ =
static_cast<f32x4
>(C1);
111 auto const C2_ =
static_cast<f32x4
>(C2);
112 auto const P2_ =
static_cast<f32x4
>(P2);
114 return vector2{_3 * tt_ * (P2_ - _3 * C2_ + _3 * C1_ - P1_) + _6 * t_ * (C2_ - _2 * C1_ + P1_) + _3 * (C1_ - P1_)};
117inline lean_vector<float> bezierFindT(
float P1,
float P2,
float x)
noexcept
119 auto const[a, b] = bezierToPolynomial(P1, P2);
123inline lean_vector<float> bezierFindT(
float P1,
float C,
float P2,
float x)
noexcept
125 auto const[a, b, c] = bezierToPolynomial(P1, C, P2);
129inline lean_vector<float> bezierFindT(
float P1,
float C1,
float C2,
float P2,
float x)
noexcept
131 auto const[a, b, c, d] = bezierToPolynomial(P1, C1, C2, P2);
141 auto const t_above = dot(P - P1, P2 - P1);
142 auto const t_below = dot(P2 - P1, P2 - P1);
143 if (t_below == 0.0) {
144 [[unlikely]]
return {};
146 return {t_above / t_below};
156 constexpr auto _2 = f32x4::broadcast(2);
157 auto const P1_ =
static_cast<f32x4>(P1);
158 auto const P2_ =
static_cast<f32x4>(P2);
159 auto const C_ =
static_cast<f32x4>(C);
161 auto const p = P - P1;
162 auto const p1 = C - P1;
163 auto const p2 =
vector2{P2_ - (_2 * C_) + P1_};
165 auto const a = dot(p2, p2);
166 auto const b = 3 * dot(p1, p2);
167 auto const c = dot(2 * p1, p1) - dot(p2, p);
168 auto const d = -dot(p1, p);
169 return solvePolynomial(a, b, c, d);
186 for (
auto const t : bezierFindT(P1.y(), P2.y(), y)) {
187 if (t >= 0.0f && t < 1.0f) {
188 r.
push_back(bezierPointAt(P1, P2, t).x());
206 if (y <
std::min({P1.y(), C.y(), P2.y()}) || y >
std::max({P1.y(), C.y(), P2.y()})) {
210 for (
auto const t : bezierFindT(P1.y(), C.y(), P2.y(), y)) {
211 if (t >= 0.0f && t <= 1.0f) {
212 r.
push_back(bezierPointAt(P1, C, P2, t).x());
230 if (y <
std::min({P1.y(), C1.y(), C2.y(), P2.y()}) || y >
std::max({P1.y(), C1.y(), C2.y(), P2.y()})) {
234 for (
auto const t : bezierFindT(P1.y(), C1.y(), C2.y(), P2.y(), y)) {
235 if (t >= 0.0f && t <= 1.0f) {
236 r.
push_back(bezierPointAt(P1, C1, C2, P2, t).x());
256 auto const P1P2 = hypot(P2 - P1);
261 auto const P1C1 = hypot(C - P1);
262 auto const C1P2 = hypot(P2 - C);
263 return P1P2 / (P1C1 + C1P2);
271 auto const P1P2 = hypot(P2 - P1);
276 auto const P1C1 = hypot(C1 - P1);
277 auto const C1C2 = hypot(C2 - C1);
278 auto const C2P2 = hypot(P2 - C2);
279 return P1P2 / (P1C1 + C1C2 + C2P2);
284 auto const v = P2 - P1;
285 auto const n = normal(v);
286 return {P1 + n * distance, P2 + n * distance};
295 auto const r = A2 - A1;
297 auto const s = B2 - B1;
301 auto const crossRS = cross(r, s);
302 if (crossRS == 0.0f) {
307 auto const q_min_p = q - p;
308 auto const t = cross(q_min_p, s) / crossRS;
309 auto const u = cross(q_min_p, r) / crossRS;
311 if (t >= 0.0f && t <= 1.0f && u >= 0.0f && u <= 1.0f) {
312 return bezierPointAt(A1, A2, t);
326 auto const r = A2 - A1;
328 auto const s = B2 - B1;
332 auto const crossRS = cross(r, s);
333 if (crossRS == 0.0f) {
338 auto const q_min_p = q - p;
339 auto const t = cross(q_min_p, s) / crossRS;
341 return bezierPointAt(A1, A2, t);
The HikoGUI namespace.
Definition array_generic.hpp:20
lean_vector< float > bezierFindX(point2 P1, point2 P2, float y) noexcept
Definition bezier.hpp:179
std::optional< point2 > getIntersectionPoint(point2 A1, point2 A2, point2 B1, point2 B2) noexcept
Definition bezier.hpp:291
lean_vector< float > bezierFindTForNormalsIntersectingPoint(point2 P1, point2 P2, point2 P) noexcept
Find t on the line P1->P2 which is closest to P.
Definition bezier.hpp:139
std::optional< point2 > getExtrapolatedIntersectionPoint(point2 A1, point2 A2, point2 B1, point2 B2) noexcept
Definition bezier.hpp:322
float bezierFlatness(point2 P1, point2 P2) noexcept
Definition bezier.hpp:246
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
hi_force_inline constexpr lean_vector< T > solvePolynomial(T const &a, T const &b) noexcept
Definition polynomial.hpp:30
Definition simd_intf.hpp:18
Lean-vector with (SVO) short-vector-optimization.
Definition lean_vector.hpp:36
void push_back(value_type const &value)
Copy an item to the end of the vector.
Definition lean_vector.hpp:774
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:27