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();
43 for (
float& val : u) {
53Point generateQuadBezier(
const std::vector<Point>& points,
const std::vector<float>& u) {
54 Point Q0 = points.front();
55 Point Q2 = points.back();
57 float numX = 0.0, numY = 0.0;
60 for (
int i = 0; i < u.size(); ++i) {
62 float invT = 1.0f - t;
65 float A = 2.0f * t * invT;
69 float B0 = invT * invT;
71 Point V = points[i] - (Q0 * B0 + Q2 * B2);
81 return Q0 + (Q2 - Q0) * 0.5;
84 return {numX / den, numY / den};
89 const std::vector<Point>& points,
float errorLimit, std::vector<QuadBezier>& outCurves
92 if (points.size() <= 2) {
94 Point mid = points.front() + (points.back() - points.front()) * 0.5;
95 outCurves.push_back({points.front(), mid, points.back()});
100 std::vector<float> u = chordLengthParameterize(points);
103 Point Q1 = generateQuadBezier(points, u);
104 QuadBezier curve = {points.front(), Q1, points.back()};
107 float maxDistSq = 0.0f;
113 for (
int i = 0; i < u.size(); ++i) {
115 Point CurveP = evalBezier(curve, u[i]);
116 float d2 = Point::distSq(P, CurveP);
118 if (d2 > maxDistSq) {
125 if (maxDistSq < (errorLimit * errorLimit)) {
126 outCurves.push_back(curve);
130 if (splitPoint == 0 || splitPoint == points.size() - 1) {
132 splitPoint = points.size() / 2;
135 std::vector<Point> p1(points.begin(), points.begin() + splitPoint + 1);
136 std::vector<Point> p2(points.begin() + splitPoint, points.end());
138 fitRecursive(p1, errorLimit, outCurves);
139 fitRecursive(p2, errorLimit, outCurves);
144void fit_curve_reduction(
145 const std::vector<std::vector<Point>>& chains, std::vector<std::vector<QuadBezier>>& results,
150 for (
int i = 0; i < chains.size(); ++i) {
152 std::vector<QuadBezier> result;
153 fitRecursive(chains[i], tolerance, result);
154 results.push_back(result);
162void fit_curve_reduction(
163 const std::vector<std::vector<Point>>& chains,
const std::vector<std::vector<uint8_t>>& fixed,
164 std::vector<std::vector<QuadBezier>>& results,
float tolerance
166 for (
size_t i = 0; i < chains.size(); ++i) {
167 const std::vector<Point>& chain = chains[i];
168 const int n =
static_cast<int>(chain.size());
169 std::vector<QuadBezier> result;
171 results.push_back(result);
176 std::vector<int> bounds;
178 for (
int k = 1; k < n - 1; ++k)
179 if (k <
static_cast<int>(fixed[i].size()) && fixed[i][k])
181 bounds.push_back(n - 1);
185 for (
size_t s = 0; s + 1 < bounds.size(); ++s) {
186 const int a = bounds[s], b = bounds[s + 1];
187 std::vector<Point> seg(chain.begin() + a, chain.begin() + b + 1);
188 fitRecursive(seg, tolerance, result);
190 results.push_back(result);