7#include "../numeric/numeric.hpp"
8#include "../SIMD/SIMD.hpp"
9#include "../geometry/geometry.hpp"
10#include "../container/container.hpp"
11#include "../macros.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);
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);
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);
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);
119 auto const[a, b] = bezierToPolynomial(P1, P2);
123hi_inline
lean_vector<float> bezierFindT(
float P1,
float C,
float P2,
float x)
noexcept
125 auto const[a, b, c] = bezierToPolynomial(P1, C, P2);
129hi_inline
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);
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;
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);
269hi_inline
float bezierFlatness(point2 P1, point2 C1, point2 C2, point2 P2)
noexcept
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);
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);
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);
341 return bezierPointAt(
A1,
A2, t);
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
The HikoGUI namespace.
Definition recursive_iterator.hpp:15
hi_inline std::optional< point2 > getIntersectionPoint(point2 A1, point2 A2, point2 B1, point2 B2) noexcept
Definition bezier.hpp:291
hi_inline lean_vector< float > bezierFindX(point2 P1, point2 P2, float y) noexcept
Definition bezier.hpp:179
hi_inline float bezierFlatness(point2 P1, point2 P2) noexcept
Definition bezier.hpp:246
hi_inline 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
hi_inline std::optional< point2 > getExtrapolatedIntersectionPoint(point2 A1, point2 A2, point2 B1, point2 B2) noexcept
Definition bezier.hpp:322
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:378
Lean-vector with (SVO) short-vector-optimization.
Definition lean_vector.hpp:35
void push_back(value_type const &value)
Copy an item to the end of the vector.
Definition lean_vector.hpp:773
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector2.hpp:26