blob: 34503004a8537ce8b4e151ea2c55d363d25934da [file] [log] [blame]
#ifndef _RIVE_CUBIC_UTILITIES_HPP_
#define _RIVE_CUBIC_UTILITIES_HPP_
#include "rive/math/vec2d.hpp"
#include <algorithm>
namespace rive
{
///
/// Utility functions for recursively subdividing a cubic.
///
class CubicUtilities
{
public:
static void computeHull(const Vec2D& from,
const Vec2D& fromOut,
const Vec2D& toIn,
const Vec2D& to,
float t,
Vec2D* hull)
{
hull[0] = Vec2D::lerp(from, fromOut, t);
hull[1] = Vec2D::lerp(fromOut, toIn, t);
hull[2] = Vec2D::lerp(toIn, to, t);
hull[3] = Vec2D::lerp(hull[0], hull[1], t);
hull[4] = Vec2D::lerp(hull[1], hull[2], t);
hull[5] = Vec2D::lerp(hull[3], hull[4], t);
}
static bool tooFar(const Vec2D& a, const Vec2D& b, float threshold)
{
return std::max(std::abs(a.x - b.x), std::abs(a.y - b.y)) > threshold;
}
static bool shouldSplitCubic(const Vec2D& from,
const Vec2D& fromOut,
const Vec2D& toIn,
const Vec2D& to,
float threshold)
{
Vec2D oneThird = Vec2D::lerp(from, to, 1.0f / 3.0f);
Vec2D twoThird = Vec2D::lerp(from, to, 2.0f / 3.0f);
return tooFar(fromOut, oneThird, threshold) || tooFar(toIn, twoThird, threshold);
}
static float cubicAt(float t, float a, float b, float c, float d)
{
float ti = 1.0f - t;
float value =
ti * ti * ti * a + 3.0f * ti * ti * t * b + 3.0f * ti * t * t * c + t * t * t * d;
return value;
}
};
} // namespace rive
#endif