blob: 4127fed106b5b84a82fc9bd90180789bb034f6d3 [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