mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-26 08:09:14 +00:00
common bezier: enhancement to the common Bezier function
Add a method that returns the angle at position 't'. also revise bezAt() method to allow optimal usages.
This commit is contained in:
parent
20cf8c6725
commit
d53d8d726f
2 changed files with 30 additions and 8 deletions
|
@ -108,26 +108,25 @@ void bezSplitLeft(Bezier& cur, float at, Bezier& left)
|
|||
}
|
||||
|
||||
|
||||
float bezAt(const Bezier& bz, float at)
|
||||
float bezAt(const Bezier& bz, float at, float length)
|
||||
{
|
||||
auto len = bezLength(bz);
|
||||
auto biggest = 1.0f;
|
||||
auto smallest = 0.0f;
|
||||
auto t = 0.5f;
|
||||
|
||||
//just in case to prevent an infinite loop
|
||||
if (at <= 0) return 0.0f;
|
||||
if (at >= len) return len;
|
||||
if (at >= length) return length;
|
||||
|
||||
while (true) {
|
||||
auto right = bz;
|
||||
Bezier left;
|
||||
bezSplitLeft(right, t, left);
|
||||
len = bezLength(left);
|
||||
if (fabsf(len - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) {
|
||||
length = bezLength(left);
|
||||
if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) {
|
||||
break;
|
||||
}
|
||||
if (len < at) {
|
||||
if (length < at) {
|
||||
smallest = t;
|
||||
t = (t + biggest) * 0.5f;
|
||||
} else {
|
||||
|
@ -142,7 +141,7 @@ float bezAt(const Bezier& bz, float at)
|
|||
void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right)
|
||||
{
|
||||
right = cur;
|
||||
auto t = bezAt(right, at);
|
||||
auto t = bezAt(right, at, bezLength(right));
|
||||
bezSplitLeft(right, t, left);
|
||||
}
|
||||
|
||||
|
@ -169,4 +168,26 @@ Point bezPointAt(const Bezier& bz, float t)
|
|||
return cur;
|
||||
}
|
||||
|
||||
|
||||
float bezAngleAt(const Bezier& bz, float t)
|
||||
{
|
||||
if (t < 0 || t > 1) return 0;
|
||||
|
||||
//derivate
|
||||
// p'(t) = 3 * (-(1-2t+t^2) * p0 + (1 - 4 * t + 3 * t^2) * p1 + (2 * t - 3 *
|
||||
// t^2) * p2 + t^2 * p3)
|
||||
float mt = 1.0f - t;
|
||||
float d = t * t;
|
||||
float a = -mt * mt;
|
||||
float b = 1 - 4 * t + 3 * d;
|
||||
float c = 2 * t - 3 * d;
|
||||
|
||||
Point pt ={a * bz.start.x + b * bz.ctrl1.x + c * bz.ctrl2.x + d * bz.end.x, a * bz.start.y + b * bz.ctrl1.y + c * bz.ctrl2.y + d * bz.end.y};
|
||||
pt.x *= 3;
|
||||
pt.y *= 3;
|
||||
|
||||
return atan2(pt.x, pt.y) * 180.0f / 3.141592f;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -39,9 +39,10 @@ struct Bezier
|
|||
void bezSplit(const Bezier&cur, Bezier& left, Bezier& right);
|
||||
float bezLength(const Bezier& cur);
|
||||
void bezSplitLeft(Bezier& cur, float at, Bezier& left);
|
||||
float bezAt(const Bezier& bz, float at);
|
||||
float bezAt(const Bezier& bz, float at, float length);
|
||||
void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right);
|
||||
Point bezPointAt(const Bezier& bz, float t);
|
||||
float bezAngleAt(const Bezier& bz, float t);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue