mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-27 00:26:51 +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 biggest = 1.0f;
|
||||||
auto smallest = 0.0f;
|
auto smallest = 0.0f;
|
||||||
auto t = 0.5f;
|
auto t = 0.5f;
|
||||||
|
|
||||||
//just in case to prevent an infinite loop
|
//just in case to prevent an infinite loop
|
||||||
if (at <= 0) return 0.0f;
|
if (at <= 0) return 0.0f;
|
||||||
if (at >= len) return len;
|
if (at >= length) return length;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto right = bz;
|
auto right = bz;
|
||||||
Bezier left;
|
Bezier left;
|
||||||
bezSplitLeft(right, t, left);
|
bezSplitLeft(right, t, left);
|
||||||
len = bezLength(left);
|
length = bezLength(left);
|
||||||
if (fabsf(len - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) {
|
if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (len < at) {
|
if (length < at) {
|
||||||
smallest = t;
|
smallest = t;
|
||||||
t = (t + biggest) * 0.5f;
|
t = (t + biggest) * 0.5f;
|
||||||
} else {
|
} else {
|
||||||
|
@ -142,7 +141,7 @@ float bezAt(const Bezier& bz, float at)
|
||||||
void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right)
|
void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right)
|
||||||
{
|
{
|
||||||
right = cur;
|
right = cur;
|
||||||
auto t = bezAt(right, at);
|
auto t = bezAt(right, at, bezLength(right));
|
||||||
bezSplitLeft(right, t, left);
|
bezSplitLeft(right, t, left);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,4 +168,26 @@ Point bezPointAt(const Bezier& bz, float t)
|
||||||
return cur;
|
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);
|
void bezSplit(const Bezier&cur, Bezier& left, Bezier& right);
|
||||||
float bezLength(const Bezier& cur);
|
float bezLength(const Bezier& cur);
|
||||||
void bezSplitLeft(Bezier& cur, float at, Bezier& left);
|
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);
|
void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right);
|
||||||
Point bezPointAt(const Bezier& bz, float t);
|
Point bezPointAt(const Bezier& bz, float t);
|
||||||
|
float bezAngleAt(const Bezier& bz, float t);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue