开发者

Drawing a curve through a set of N points, where N>2

I开发者_开发知识库 need to draw a curve smoothly through N points with N>2 with Javascript. I am currently using the bezierCurveTo() within an html5 canvas object. I've invested a good deal of time into trying to find the best method of accomplishing this, and while Catmull-Rom Splines sound promising, I am unaware of a way to draw them as lines. I therefore am left with Poly-line Bézier curves and need to find all intermediate control points.

It took me relearning a good deal of math but I have a partially working example here. The line is not particularly smooth at times, and there is an issue with my control points being off for certain vectors. Here is my initial math.stackexchange question that I asked to get the bulk of the math for the control points.

I would also be open to the Catmull-Rom Splines but would need some help as to how I can convert them to lines on the canvas. I have found this resource, but again am lost in applying it to my needs.

Heres an image created from my example link above illustrating how to replicate the bad control points:

Drawing a curve through a set of N points, where N>2

Thank you very much for any help in advance!


Original code:

var a = new Array(points[p-1].x,points[p-1].y);
var b = new Array(points[p].x,points[p].y);
var c = new Array(points[p+1].x,points[p+1].y);

var delta_a = subtract_v(a, b);
var delta_c = subtract_v(c, b);

// Get vector (m) perpendicular bisector
var m = normalize_v( add_v( normalize_v(delta_a),normalize_v(delta_c) ) );

// Get ma and mc
var ma = normalize_v( subtract_v(delta_a,multiply_v(multiply_v(delta_a,m),m) ) );
var mc = normalize_v( subtract_v(delta_c,multiply_v(multiply_v(delta_c,m),m) ) );

// Get the coordinates
points[p].c2x = resolution( b[0] + ( (Math.sqrt( sqr(delta_a[0]) + sqr(delta_a[1]) ) / tightness) * ma[0] ) );
points[p].c2y = resolution( b[1] + ( (Math.sqrt( sqr(delta_a[0]) + sqr(delta_a[1]) ) / tightness) * ma[1] ) );
points[p+1].c1x = resolution( b[0] + ( (Math.sqrt( sqr(delta_c[0]) + sqr(delta_c[1]) ) / tightness) * mc[0] ) );
points[p+1].c1y = resolution( b[1] + ( (Math.sqrt( sqr(delta_c[0]) + sqr(delta_c[1]) ) / tightness) * mc[1] ) );

I have no idea what "Get ma and mc" is supposed to do here. What you need is a vector orthogonal to the angle bisector (m), and its negative.

Drawing a curve through a set of N points, where N>2

So this should be fine:

var delta_a = subtract_v(b, a); // note that we're calculating AB instead of BA
var delta_c = subtract_v(c, b);

// Get an orthogonal to the angle bisector
var m = normalize_v( add_v( normalize_v(delta_a),normalize_v(delta_c) ) );

var ma = [-m[0],-m[1]];
var mc = m;

Also make sure to remove the resolution() for your control points.

Edit:
You should also add a fallback for edge cases (for example, A==B or A==C, in which case your script will throw an exception, trying to normalize the 0 vector)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜