Drawing a curve through the 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 bezierCurveTo () in a canvas html5 object. I spent a lot of time finding the best way to accomplish this, and although the Catmull-Rom Splines sounds promising, I don’t know how to draw them like lines. So I stay with the Poly-line BΓ©zier curves and have to find all the intermediate control points.

I needed to retrain a lot of mathematics, but I have a partially working example here . The line is not particularly smooth from time to time, and there is a problem with turning off my control points for certain vectors. Here is my original math.stackexchange question , which I asked to get the bulk of math for breakpoints.

I would also be open to Catmull-Rom splines, but I needed some help on how I could convert them to strings on the canvas. I found this resource, but again get lost in applying it to my needs.

Here is an image taken from my example above illustrating how to replicate bad breakpoints:

enter image description here

Thanks for any help in advance!

+6
source share
1 answer

Source:

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 to do "Get ma and mc" here. You need a vector orthogonal to the angle of the bisector ( m ) and its negative result.

Sorry for the horrible drawing

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 that you remove resolution() for your control points.

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

+4
source

Source: https://habr.com/ru/post/893386/


All Articles