I'm trying to create a JS function that will return a Y coordinate on a cubic bezier given the X coordinate. Here's what I have:
function pointOnBezier(t, p0, p1, p2, p3) {
var x = Math.pow(1-t,3) * p0[0] + 3 * t * Math.pow(1 - t, 2) * p1[0] + 3 * t * t * (1 - t) * p2[0] + t * t * t * p3[0];
var y = Math.pow(1-t,3) * p0[1] + 3 * t * Math.pow(1 - t, 2) * p1[1] + 3 * t * t * (1 - t) * p2[1] + t * t * t * p3[1];
return [x, y];
}
console.log(0.25, pointOnBezier(0.25, [0,0], [0.5, 0.5], [0.5, 0.5], [1.0, 1.0]));
console.log(0.5, pointOnBezier(0.5, [0,0], [0.5, 0.5], [0.5, 0.5], [1.0, 1.0]));
console.log(0.75, pointOnBezier(0.75, [0,0], [0.5, 0.5], [0.5, 0.5], [1.0, 1.0]));
I included the three test values. If you run the code, the expected results of t=0.25 and t=0.75 is a value of 0.25 and 0.75 but it's returning 0.3 and 0.7.
Can anyone see the problem with the calculations?
Edit: while similar to other questions, I've looked at the answers there and so far I haven't found a working solution plus the discussion has continued about the merits of two common techniques.
There are three values involved in such Bezier curves:
twhich is the input to the function, andxandywhich are the output. Your code returns the value ofxandyfor a given value oft, but there is no reasontwould be related toxin any obvious way.Generally speaking it is easy to get
xandyfromt(your code), but it is more complicated to getyfromx.The onlyOne way to do it is by binary search: try some values oftuntil you get close enough to the desiredx, which also gets you theyyou are looking for.Example code (untested and assuming the bezier curve is increasing):
Edit: As mentioned in the comments, another way to do it without binary search would be to solve the third degree equation mathematically to directly get the correct value of
t, and then calculate the correspondingy. However this would most likely lead to significantly more complicated code, for no clear benefit.