blob: 684cf4637f094b6fb0f6f24ec44560ff09db5b30 [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)
{
Vec2D::lerp(hull[0], from, fromOut, t);
Vec2D::lerp(hull[1], fromOut, toIn, t);
Vec2D::lerp(hull[2], toIn, to, t);
Vec2D::lerp(hull[3], hull[0], hull[1], t);
Vec2D::lerp(hull[4], hull[1], hull[2], t);
Vec2D::lerp(hull[5], hull[3], hull[4], t);
}
static bool tooFar(const Vec2D& a, const Vec2D& b, float threshold)
{
return std::max(std::abs(a[0] - b[0]), std::abs(a[1] - b[1])) >
threshold;
}
static bool shouldSplitCubic(const Vec2D& from,
const Vec2D& fromOut,
const Vec2D& toIn,
const Vec2D& to,
float threshold)
{
Vec2D oneThird, twoThird;
Vec2D::lerp(oneThird, from, to, 1.0f / 3.0f);
Vec2D::lerp(twoThird, 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