7#include "polynomial.hpp"
8#include "rapid/numeric_array.hpp"
9#include "geometry/point.hpp"
13namespace hi::inline
v1 {
26 return {P1 - C * 2 + P2, (C - P1) * 2, P1};
31constexpr std::array<T, 4> bezierToPolynomial(T P1, T C1, T C2, T P2)
noexcept
33 return {-P1 + C1 * 3 - C2 * 3 + P2, P1 * 3 - C1 * 6 + C2 * 3, P1 * -3 + C1 * 3, P1};
37constexpr geo::point<float, D> bezierPointAt(geo::point<float, D> P1, geo::point<float, D> P2,
float t)
noexcept
39 hilet[a, b] = bezierToPolynomial(
static_cast<f32x4
>(P1),
static_cast<f32x4
>(P2));
40 return geo::point<float, D>{a * t + b};
44constexpr geo::point<float, D>
45bezierPointAt(geo::point<float, D> P1, geo::point<float, D> C, geo::point<float, D> P2,
float t)
noexcept
47 hilet[a, b,
c] = bezierToPolynomial(
static_cast<f32x4
>(P1),
static_cast<f32x4
>(C),
static_cast<f32x4
>(P2));
48 return geo::point<float, D>{a * t * t + b * t +
c};
52constexpr geo::point<float, D> bezierPointAt(
53 geo::point<float, D> P1,
54 geo::point<float, D> C1,
55 geo::point<float, D> C2,
56 geo::point<float, D> P2,
60 bezierToPolynomial(
static_cast<f32x4
>(P1),
static_cast<f32x4
>(C1),
static_cast<f32x4
>(C2),
static_cast<f32x4
>(P2));
61 return geo::point<float, D>{a * t * t * t + b * t * t +
c * t + d};
65constexpr geo::vector<float, D> bezierTangentAt(geo::point<float, D> P1, geo::point<float, D> P2,
float t)
noexcept
71constexpr geo::vector<float, D>
72bezierTangentAt(geo::point<float, D> P1, geo::point<float, D> C, geo::point<float, D> P2,
float t)
noexcept
74 hilet P1_ =
static_cast<f32x4
>(P1);
75 hilet C_ =
static_cast<f32x4
>(C);
76 hilet P2_ =
static_cast<f32x4
>(P2);
78 return geo::vector<float, D>{2 * t * (P2_ - 2 * C_ + P1_) + 2 * (C_ - P1_)};
82constexpr geo::vector<float, D> bezierTangentAt(
83 geo::point<float, D> P1,
84 geo::point<float, D> C1,
85 geo::point<float, D> C2,
86 geo::point<float, D> P2,
89 hilet P1_ =
static_cast<f32x4
>(P1);
90 hilet C1_ =
static_cast<f32x4
>(C1);
91 hilet C2_ =
static_cast<f32x4
>(C2);
92 hilet P2_ =
static_cast<f32x4
>(P2);
94 return geo::vector<float, D>{3 * t * t * (P2_ - 3 * C2_ + 3 * C1_ - P1_) + 6 * t * (C2_ - 2 * C1_ + P1_) + 3 * (C1_ - P1_)};
97constexpr results<float, 1> bezierFindT(
float P1,
float P2,
float x)
noexcept
99 hilet[a, b] = bezierToPolynomial(P1, P2);
103constexpr results<float, 2> bezierFindT(
float P1,
float C,
float P2,
float x)
noexcept
105 hilet[a, b,
c] = bezierToPolynomial(P1, C, P2);
109hi_force_inline
constexpr results<float, 3> bezierFindT(
float P1,
float C1,
float C2,
float P2,
float x)
noexcept
111 hilet[a, b,
c, d] = bezierToPolynomial(P1, C1, C2, P2);
121 hilet t_above = dot(P - P1, P2 - P1);
122 hilet t_below = dot(P2 - P1, P2 - P1);
123 if (t_below == 0.0) {
124 [[unlikely]]
return {};
126 return {t_above / t_below};
134hi_force_inline
constexpr results<float, 3>
145 hilet a = dot(p2, p2);
146 hilet b = 3 * dot(p1, p2);
147 hilet c = dot(2 * p1, p1) - dot(p2, p);
148 hilet d = -dot(p1, p);
166 for (
hilet t : bezierFindT(P1.y(), P2.y(), y)) {
167 if (t >= 0.0f && t < 1.0f) {
168 r.add(bezierPointAt(P1, P2, t).x());
186 if (y <
std::min({P1.y(), C.y(), P2.y()}) || y >
std::max({P1.y(), C.y(), P2.y()})) {
190 for (
hilet t : bezierFindT(P1.y(), C.y(), P2.y(), y)) {
191 if (t >= 0.0f && t <= 1.0f) {
192 r.add(bezierPointAt(P1, C, P2, t).x());
210 if (y <
std::min({P1.y(), C1.y(), C2.y(), P2.y()}) || y >
std::max({P1.y(), C1.y(), C2.y(), P2.y()})) {
214 for (
hilet t : bezierFindT(P1.y(), C1.y(), C2.y(), P2.y(), y)) {
215 if (t >= 0.0f && t <= 1.0f) {
216 r.add(bezierPointAt(P1, C1, C2, P2, t).x());
237 hilet P1P2 = hypot(P2 - P1);
242 hilet P1C1 = hypot(C - P1);
243 hilet C1P2 = hypot(P2 - C);
244 return P1P2 / (P1C1 + C1P2);
253 hilet P1P2 = hypot(P2 - P1);
258 hilet P1C1 = hypot(C1 - P1);
259 hilet C1C2 = hypot(C2 - C1);
260 hilet C2P2 = hypot(P2 - C2);
261 return P1P2 / (P1C1 + C1C2 + C2P2);
268 return {P1 + n * distance, P2 + n * distance};
283 hilet crossRS = cross(r, s);
284 if (crossRS == 0.0f) {
289 hilet q_min_p = q - p;
290 hilet t = cross(q_min_p, s) / crossRS;
291 hilet u = cross(q_min_p, r) / crossRS;
293 if (t >= 0.0f && t <= 1.0f && u >= 0.0f && u <= 1.0f) {
294 return bezierPointAt(A1, A2, t);
314 hilet crossRS = cross(r, s);
315 if (crossRS == 0.0f) {
320 hilet q_min_p = q - p;
321 hilet t = cross(q_min_p, s) / crossRS;
323 return bezierPointAt(A1, A2, t);
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
constexpr results< float, 1 > bezierFindX(point2 P1, point2 P2, float y) noexcept
Definition bezier.hpp:159
std::optional< point2 > getExtrapolatedIntersectionPoint(point2 A1, point2 A2, point2 B1, point2 B2) noexcept
Definition bezier.hpp:304
float bezierFlatness(point2 P1, point2 P2) noexcept
Definition bezier.hpp:226
hi_force_inline constexpr results< float, 1 > bezierFindTForNormalsIntersectingPoint(point2 P1, point2 P2, point2 P) noexcept
Find t on the line P1->P2 which is closest to P.
Definition bezier.hpp:119
std::optional< point2 > getIntersectionPoint(point2 A1, point2 A2, point2 B1, point2 B2) noexcept
Definition bezier.hpp:273
hi_force_inline constexpr results< T, 1 > solvePolynomial(T const &a, T const &b) noexcept
Definition polynomial.hpp:141
Definition polynomial.hpp:14