1#include "internal/bezier.h"
9 return a.x * b.x + a.y * b.y;
13 return std::sqrt(c.x * c.x + c.y * c.y);
20 float c0 = invT * invT;
21 float c1 = 2.0f * t * invT;
24 return c0 * b.p0 + c1 * b.p1 + c2 * b.p2;
29std::vector<float> chordLengthParameterize(
const std::vector<Point> &points) {
31 u.reserve(points.size());
34 for (
int i = 1; i < points.size(); ++i) {
35 float dist = len(points[i], points[i - 1]);
36 u.push_back(u.back() + dist);
39 float totalLen = u.back();
40 if (totalLen == 0)
return u;
42 for (
float &val : u) {
52Point generateQuadBezier(
const std::vector<Point> &points,
const std::vector<float> &u) {
53 Point Q0 = points.front();
54 Point Q2 = points.back();
56 float numX = 0.0, numY = 0.0;
59 for (
int i = 0; i < u.size(); ++i) {
61 float invT = 1.0f - t;
64 float A = 2.0f * t * invT;
68 float B0 = invT * invT;
70 Point V = points[i] - (Q0 * B0 + Q2 * B2);
80 return Q0 + (Q2 - Q0) * 0.5;
83 return {numX / den, numY / den};
87void fitRecursive(
const std::vector<Point> &points,
float errorLimit,
88 std::vector<QuadBezier> &outCurves) {
90 if (points.size() <= 2) {
92 Point mid = points.front() + (points.back() - points.front()) * 0.5;
93 outCurves.push_back({points.front(), mid, points.back()});
98 std::vector<float> u = chordLengthParameterize(points);
101 Point Q1 = generateQuadBezier(points, u);
102 QuadBezier curve = {points.front(), Q1, points.back()};
105 float maxDistSq = 0.0f;
111 for (
int i = 0; i < u.size(); ++i) {
113 Point CurveP = evalBezier(curve, u[i]);
114 float d2 = Point::distSq(P, CurveP);
116 if (d2 > maxDistSq) {
123 if (maxDistSq < (errorLimit * errorLimit)) {
124 outCurves.push_back(curve);
128 if (splitPoint == 0 || splitPoint == points.size() - 1) {
130 splitPoint = points.size() / 2;
133 std::vector<Point> p1(points.begin(), points.begin() + splitPoint + 1);
134 std::vector<Point> p2(points.begin() + splitPoint, points.end());
136 fitRecursive(p1, errorLimit, outCurves);
137 fitRecursive(p2, errorLimit, outCurves);
142void fit_curve_reduction(
const std::vector<std::vector<Point>> &chains,
143 std::vector<std::vector<QuadBezier>> &results,
float tolerance) {
146 for (
int i = 0; i < chains.size(); ++i) {
148 std::vector<QuadBezier> result;
149 fitRecursive(chains[i], tolerance, result);
150 results.push_back(result);