mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 14:41:50 +00:00
common/math: introduced custom atan2()
the custom atan2 algorithm by Remez. see: https://en.wikipedia.org/wiki/Remez_algorithm This improved the Lottie example by ~2ms. Total atan2 performance time was reduced by 43%
This commit is contained in:
parent
8c4102362f
commit
79cf7ca5af
9 changed files with 29 additions and 12 deletions
|
@ -238,7 +238,7 @@ float bezAngleAt(const Bezier& bz, float t)
|
|||
pt.x *= 3;
|
||||
pt.y *= 3;
|
||||
|
||||
return mathRad2Deg(atan2(pt.y, pt.x));
|
||||
return mathRad2Deg(mathAtan2(pt.y, pt.x));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,20 @@
|
|||
|
||||
#include "tvgMath.h"
|
||||
|
||||
//see: https://en.wikipedia.org/wiki/Remez_algorithm
|
||||
float mathAtan2(float y, float x)
|
||||
{
|
||||
if (y == 0.0f) return 0.0f;
|
||||
|
||||
auto a = std::min(fabsf(x), fabsf(y)) / std::max(fabsf(x), fabsf(y));
|
||||
auto s = a * a;
|
||||
auto r = ((-0.0464964749f * s + 0.15931422f) * s - 0.327622764f) * s * a + a;
|
||||
if (fabsf(y) > fabsf(x)) r = 1.57079637f - r;
|
||||
if (x < 0) r = 3.14159274f - r;
|
||||
if (y < 0) return -r;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
bool mathInverse(const Matrix* m, Matrix* out)
|
||||
{
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
/* General functions */
|
||||
/************************************************************************/
|
||||
|
||||
float mathAtan2(float y, float x);
|
||||
|
||||
static inline float mathDeg2Rad(float degree)
|
||||
{
|
||||
|
@ -76,7 +77,7 @@ bool operator==(const Matrix& lhs, const Matrix& rhs);
|
|||
|
||||
static inline bool mathRightAngle(const Matrix* m)
|
||||
{
|
||||
auto radian = fabsf(atan2f(m->e21, m->e11));
|
||||
auto radian = fabsf(mathAtan2(m->e21, m->e11));
|
||||
if (radian < FLOAT_EPSILON || mathEqual(radian, MATH_PI2) || mathEqual(radian, MATH_PI)) return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -724,10 +724,10 @@ static void _updateStar(LottieGroup* parent, LottiePolyStar* star, Matrix* trans
|
|||
y = radius * sinf(angle);
|
||||
|
||||
if (hasRoundness) {
|
||||
auto cp1Theta = (atan2f(previousY, previousX) - MATH_PI2 * direction);
|
||||
auto cp1Theta = (mathAtan2(previousY, previousX) - MATH_PI2 * direction);
|
||||
auto cp1Dx = cosf(cp1Theta);
|
||||
auto cp1Dy = sinf(cp1Theta);
|
||||
auto cp2Theta = (atan2f(y, x) - MATH_PI2 * direction);
|
||||
auto cp2Theta = (mathAtan2(y, x) - MATH_PI2 * direction);
|
||||
auto cp2Dx = cosf(cp2Theta);
|
||||
auto cp2Dy = sinf(cp2Theta);
|
||||
|
||||
|
@ -810,10 +810,10 @@ static void _updatePolygon(LottieGroup* parent, LottiePolyStar* star, Matrix* tr
|
|||
y = (radius * sinf(angle));
|
||||
|
||||
if (hasRoundness) {
|
||||
auto cp1Theta = atan2f(previousY, previousX) - MATH_PI2 * direction;
|
||||
auto cp1Theta = mathAtan2(previousY, previousX) - MATH_PI2 * direction;
|
||||
auto cp1Dx = cosf(cp1Theta);
|
||||
auto cp1Dy = sinf(cp1Theta);
|
||||
auto cp2Theta = atan2f(y, x) - MATH_PI2 * direction;
|
||||
auto cp2Theta = mathAtan2(y, x) - MATH_PI2 * direction;
|
||||
auto cp2Dx = cosf(cp2Theta);
|
||||
auto cp2Dy = sinf(cp2Theta);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tvgMath.h"
|
||||
#include "tvgPaint.h"
|
||||
#include "tvgFill.h"
|
||||
#include "tvgLottieModel.h"
|
||||
|
@ -249,7 +250,7 @@ Fill* LottieGradient::fill(float frameNo, LottieExpressions* exps)
|
|||
P(static_cast<RadialGradient*>(fill))->radial(s.x, s.y, r, s.x, s.y, 0.0f);
|
||||
} else {
|
||||
if (mathEqual(progress, 1.0f)) progress = 0.99f;
|
||||
auto startAngle = mathRad2Deg(atan2(e.y - s.y, e.x - s.x));
|
||||
auto startAngle = mathRad2Deg(mathAtan2(e.y - s.y, e.x - s.x));
|
||||
auto angle = mathDeg2Rad((startAngle + this->angle(frameNo, exps)));
|
||||
auto fx = s.x + cos(angle) * progress * r;
|
||||
auto fy = s.y + sin(angle) * progress * r;
|
||||
|
|
|
@ -156,7 +156,7 @@ struct LottieVectorFrame
|
|||
{
|
||||
if (!hasTangent) {
|
||||
Point dp = next->value - value;
|
||||
return mathRad2Deg(atan2(dp.y, dp.x));
|
||||
return mathRad2Deg(mathAtan2(dp.y, dp.x));
|
||||
}
|
||||
|
||||
auto t = (frameNo - no) / (next->no - no);
|
||||
|
|
|
@ -194,10 +194,10 @@ void _pathAppendArcTo(Array<PathCommand>* cmds, Array<Point>* pts, Point* cur, P
|
|||
//We dont' use arccos (as per w3c doc), see
|
||||
//http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
|
||||
//Note: atan2 (0.0, 1.0) == 0.0
|
||||
at = atan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
|
||||
at = mathAtan2(((y1p - cyp) / ry), ((x1p - cxp) / rx));
|
||||
theta1 = (at < 0.0f) ? 2.0f * MATH_PI + at : at;
|
||||
|
||||
nat = atan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
|
||||
nat = mathAtan2(((-y1p - cyp) / ry), ((-x1p - cxp) / rx));
|
||||
deltaTheta = (nat < at) ? 2.0f * MATH_PI - at + nat : nat - at;
|
||||
|
||||
if (sweep) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tvgMath.h"
|
||||
#include "tvgGlTessellator.h"
|
||||
#include "tvgRender.h"
|
||||
#include "tvgGlList.h"
|
||||
|
@ -780,7 +781,7 @@ static int32_t _bezierCurveCount(const Bezier &curve)
|
|||
|
||||
static Bezier _bezFromArc(const GlPoint& start, const GlPoint& end, float radius) {
|
||||
// Calculate the angle between the start and end points
|
||||
float angle = atan2(end.y - start.y, end.x - start.x);
|
||||
float angle = mathAtan2(end.y - start.y, end.x - start.x);
|
||||
|
||||
// Calculate the control points of the cubic bezier curve
|
||||
float c = radius * 0.552284749831; // c = radius * (4/3) * tan(pi/8)
|
||||
|
|
|
@ -179,7 +179,7 @@ SwFixed mathTan(SwFixed angle)
|
|||
SwFixed mathAtan(const SwPoint& pt)
|
||||
{
|
||||
if (pt.zero()) return 0;
|
||||
return SwFixed(atan2f(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
|
||||
return SwFixed(mathAtan2(TO_FLOAT(pt.y), TO_FLOAT(pt.x)) * (180.0f / MATH_PI) * 65536.0f);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue