Skip to content

Commit

Permalink
Updated /lib scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
Sphinxxxx authored Jul 20, 2016
1 parent aebdba7 commit 1475986
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 33 deletions.
106 changes: 81 additions & 25 deletions lib/fit-curve.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,52 +100,73 @@
};
return bezier;
}();
function fitCurve(points, maxError) {
function fitCurve(points, maxError, progressCallback) {
var len = points.length, leftTangent = createTangent(points[1], points[0]), rightTangent = createTangent(points[len - 2], points[len - 1]);
return fitCubic(points, leftTangent, rightTangent, maxError);
return fitCubic(points, leftTangent, rightTangent, maxError, progressCallback);
}
function fitCubic(points, leftTangent, rightTangent, error) {
function fitCubic(points, leftTangent, rightTangent, error, progressCallback) {
var MaxIterations = 20;
var bezCurve, u, uPrime, maxError, splitPoint, centerVector, toCenterTangent, fromCenterTangent, beziers, dist, i;
var bezCurve, u, uPrime, maxError, prevErr, splitPoint, prevSplit, centerVector, toCenterTangent, fromCenterTangent, beziers, dist, i;
if (points.length === 2) {
dist = maths.vectorLen(maths.subtract(points[0], points[1])) / 3;
bezCurve = [points[0], maths.addArrays(points[0], maths.mulItems(leftTangent, dist)), maths.addArrays(points[1], maths.mulItems(rightTangent, dist)), points[1]];
return [bezCurve];
}
u = chordLengthParameterize(points);
bezCurve = generateBezier(points, u, leftTangent, rightTangent);
var _computeMaxError = computeMaxError(points, bezCurve, u);
maxError = _computeMaxError[0];
splitPoint = _computeMaxError[1];
var _generateAndReport = generateAndReport(points, u, u, leftTangent, rightTangent, progressCallback);
bezCurve = _generateAndReport[0];
maxError = _generateAndReport[1];
splitPoint = _generateAndReport[2];
if (maxError < error) {
return [bezCurve];
}
if (maxError < error * error) {
uPrime = u;
prevErr = maxError;
prevSplit = splitPoint;
for (i = 0;i < MaxIterations;i++) {
uPrime = reparameterize(bezCurve, points, u);
bezCurve = generateBezier(points, uPrime, leftTangent, rightTangent);
var _computeMaxError2 = computeMaxError(points, bezCurve, uPrime);
maxError = _computeMaxError2[0];
splitPoint = _computeMaxError2[1];
uPrime = reparameterize(bezCurve, points, uPrime);
var _generateAndReport2 = generateAndReport(points, u, uPrime, leftTangent, rightTangent, progressCallback);
bezCurve = _generateAndReport2[0];
maxError = _generateAndReport2[1];
splitPoint = _generateAndReport2[2];
if (maxError < error) {
return [bezCurve];
} else {
if (splitPoint === prevSplit) {
var errChange = maxError / prevErr;
if (errChange > .9999 && errChange < 1.0001) {
break;
}
}
}
u = uPrime;
prevErr = maxError;
prevSplit = splitPoint;
}
}
beziers = [];
centerVector = maths.subtract(points[splitPoint - 1], points[splitPoint + 1]);
if (centerVector[0] || centerVector[1]) {
toCenterTangent = maths.normalize(centerVector);
fromCenterTangent = maths.mulItems(toCenterTangent, -1);
} else {
toCenterTangent = createTangent(points[splitPoint - 1], points[splitPoint]);
fromCenterTangent = createTangent(points[splitPoint + 1], points[splitPoint]);
if (centerVector[0] === 0 && centerVector[1] === 0) {
centerVector = maths.subtract(points[splitPoint - 1], points[splitPoint]).reverse();
centerVector[0] = -centerVector[0];
}
beziers = beziers.concat(fitCubic(points.slice(0, splitPoint + 1), leftTangent, toCenterTangent, error));
beziers = beziers.concat(fitCubic(points.slice(splitPoint), fromCenterTangent, rightTangent, error));
toCenterTangent = maths.normalize(centerVector);
fromCenterTangent = maths.mulItems(toCenterTangent, -1);
beziers = beziers.concat(fitCubic(points.slice(0, splitPoint + 1), leftTangent, toCenterTangent, error, progressCallback));
beziers = beziers.concat(fitCubic(points.slice(splitPoint), fromCenterTangent, rightTangent, error, progressCallback));
return beziers;
}
function generateAndReport(points, paramsOrig, paramsPrime, leftTangent, rightTangent, progressCallback) {
var bezCurve, maxError, splitPoint;
bezCurve = generateBezier(points, paramsPrime, leftTangent, rightTangent, progressCallback);
var _computeMaxError = computeMaxError(points, bezCurve, paramsOrig);
maxError = _computeMaxError[0];
splitPoint = _computeMaxError[1];
if (progressCallback) {
progressCallback({bez:bezCurve, points:points, params:paramsOrig, maxErr:maxError, maxPoint:splitPoint});
}
return [bezCurve, maxError, splitPoint];
}
function generateBezier(points, parameters, leftTangent, rightTangent) {
var bezCurve, A, a, C, X, det_C0_C1, det_C0_X, det_X_C1, alpha_l, alpha_r, epsilon, segLength, i, len, tmp, u, ux, firstPoint = points[0], lastPoint = points[points.length - 1];
bezCurve = [firstPoint, null, null, lastPoint];
Expand Down Expand Up @@ -213,13 +234,13 @@
return u;
}
function computeMaxError(points, bez, parameters) {
var dist, maxDist, splitPoint, v, i, count, point, u;
var dist, maxDist, splitPoint, v, i, count, point, t;
maxDist = 0;
splitPoint = points.length / 2;
for (i = 0, count = points.length;i < count;i++) {
point = points[i];
u = parameters[i];
v = maths.subtract(bezier.q(bez, u), point);
t = find_t(bez, parameters[i]);
v = maths.subtract(bezier.q(bez, t), point);
dist = v[0] * v[0] + v[1] * v[1];
if (dist > maxDist) {
maxDist = dist;
Expand All @@ -228,6 +249,41 @@
}
return [maxDist, splitPoint];
}
function find_t(bez, param) {
if (param <= 0) {
return 0;
}
if (param >= 1) {
return 1;
}
var B_parts = 10;
var lenMax, lenMin, tMax, tMin, t;
bez.__map_t_p = bez.__map_t_p || function() {
var B_t_dist = [0], B_t_prev = bez[0], B_t_curr, sumLen = 0;
for (var i = 1;i <= B_parts;i++) {
B_t_curr = bezier.q(bez, i / B_parts);
sumLen += maths.vectorLen(maths.subtract(B_t_curr, B_t_prev));
B_t_dist.push(sumLen);
B_t_prev = B_t_curr;
}
B_t_dist = B_t_dist.map(function(x) {
return x / sumLen;
});
return B_t_dist;
}();
var t_distMap = bez.__map_t_p;
for (var i = 1;i <= B_parts;i++) {
if (param <= t_distMap[i]) {
tMin = (i - 1) / B_parts;
tMax = i / B_parts;
lenMin = t_distMap[i - 1];
lenMax = t_distMap[i];
t = (param - lenMin) / (lenMax - lenMin) * (tMax - tMin) + tMin;
break;
}
}
return t;
}
function createTangent(pointA, pointB) {
return maths.normalize(maths.subtract(pointA, pointB));
}
Expand Down
17 changes: 9 additions & 8 deletions lib/fit-curve.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1475986

Please sign in to comment.