Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
_js-snippet-CubicBezierSplit2 - This split method is from iScriptDesign.com under "Tutorial > Split Bezier" I'm posting here in case that site goes down.
Split bezier
Shows the possibility to split a bezier curve, two separate techniques are used:
Bernstein's Polynomials
Casteljau's Algorithm
Bernstein's Polynomials
The Bernstein Polynomial implemented in javascript reads as:
getBezier = function getBez(percent,p1,cp1,cp2,p2) {
function b1(t) { return t*t*t }
function b2(t) { return 3*t*t*(1-t) }
function b3(t) { return 3*t*(1-t)*(1-t) }
function b4(t) { return (1-t)*(1-t)*(1-t) }
return {x: p1.x*b1(percent) + cp1.x*b2(percent) + cp2.x*b3(percent) + p2.x*b4(percent)
, y: p1.y*b1(percent) + cp1.y*b2(percent) + cp2.y*b3(percent) + p2.y*b4(percent) }
};
Returning xy coordinates of the point laying on the given percentage of the curve. Bernsteins polynomial at Wikipedia physics forum Bezier at Wikipedia
de Casteljau's algorithm
is an recursive or iterative algorithm for finding the fixed point and the control point of a given point (percent) on the bezier curve. It does this by calculation tangents and interpolating the controlpoints on the tangent lines. It is way more suitable for splitting a bezier curve as the Bernstein's polynomial only gives a point on the curve, with Casteljau it is relatively easy to return the control points of the split point.
below an iterative javascript implementation for splitting a bezier using the de-Casteljau's algorithm
// returns an object containing properties b1 & b2 each holding an array representing the either side of the split argument.
// be aware that the argument is destructively modified. Call splitBezier(array.slice(0)) if you need to keep the original array.
// The argument array is a representation of a quadratic bezier like [controlpoint1, controlpoint2, endpoint] (with points being objects holding x&y properties.
//
Bezier2Poly.prototype.splitBezier = function(array, perc) {
array.unshift({x:0, y:0});
var coll = [];
while (array.length > 0) {
for (var i = 0;i < array.length-1; i++) {
coll.unshift(array[i]);
array[i] = this.interpolate(array[i], array[i+1], perc);
}
coll.unshift(array.pop());
}
return {b1: [{x:coll[5].x, y:coll[5].y}, {x:coll[2].x, y:coll[2].y},{x:coll[0].x, y:coll[0].y}]
, b2: [{x:coll[1].x - coll[0].x,y:coll[1].y-coll[0].y}, {x:coll[3].x - coll[0].x,y:coll[3].y-coll[0].y}, {x:coll[6].x - coll[0].x,y:coll[6].y-coll[0].y}]};
}
Bezier2Poly.prototype.interpolate = function (p0, p1, percent) {
if (typeof percent === 'undefined') percent = 0.5;
return {x: p0.x + (p1.x - p0.x) * percent
, y: p0.y + (p1.y - p0.y) * percent};
}
stores all the points of the tangentlines in an array which is returned. Note that the 1-percentage equals the percentage for the parametric bezier version.
You can use it like:
pts_red = getPoints(perc, [{x:0, y:0}, {x:x1, y:y1}, {x:x2, y:y2}, {x:x3, y:y3}]);
pts_blue = getPoints(1-perc, [{x:x3, y:y3}, {x:x2-x3, y:y2-y3}, {x:x1-x3, y:y1-y3}, {x:-1*x3, y:-1*y3}]);
@Noitidart

This comment has been minimized.

Copy link
Owner Author

commented May 5, 2014

README

Rev1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.