1
$\begingroup$

I need to calculate the control points of a Bézier curve passing through N points where N > 2. I have been able to use the equations in this post to get close... but when "negative vectors" (the only thing I can think to call them) are used the control points no longer are in the correct location. I have constructed a simple javascript plotter to illustrate my issue. Here is a screen shot of the exact problem created from the above example:

screenshot

The control points should always create a line that passes through it's parent point. I can post some of the math I have used here, or anyone familiar with coding/javascript can look through the math in my code by viewing the above example's page-source.

I believe the problem has to do with how I am normalizing the vectors, but am very out of practice with this level of math. This equation was given in the other article but I do not know how to implement it $\vec x'=\vec x/|\vec x|$.

function normalize_v(a){     var b = new Array();     b[0] = a[0] / Math.sqrt( sqr(a[0]) + sqr(a[1]) );     b[1] = a[1] / Math.sqrt( sqr(a[0]) + sqr(a[1]) );     return b; } 

This is the math run on each point (other than the first):

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 = b[0] + ( (Math.sqrt( sqr(delta_a[0]) + sqr(delta_a[1]) ) / tightness) * ma[0] ); points[p].c2y = b[1] + ( (Math.sqrt( sqr(delta_a[0]) + sqr(delta_a[1]) ) / tightness) * ma[1] ); points[p+1].c1x = b[0] + ( (Math.sqrt( sqr(delta_c[0]) + sqr(delta_c[1]) ) / tightness) * mc[0] ); points[p+1].c1y = b[1] + ( (Math.sqrt( sqr(delta_c[0]) + sqr(delta_c[1]) ) / tightness) * mc[1] ); 

Thank you in advance for any help provided!

  • 0
    For future reference: The change above is part of$a$larger change that also flips the order of $a$ and $b$ in $\Delta_a$; it won't work on its own; the full solution is here: http://stackoverflow.com/questions/6797614/drawing-a-curve-through-a-set-of-n-points-where-n22011-07-25

1 Answers 1

1

The parent point and its control points will be collinear if and only if the curve is smooth* at the parent point. If the curve has a sharp corner there, the control points will not lie on opposite sides of the parent point. Looking at your picture, I'd say both the "good" and the "bad" control points seem to lie more or less where they should.

*) I'm using "smooth" in the colloquial sense (has no corners) here, not in the mathematical one (infinitely differentiable).

  • 0
    Ah, yes, I always think of Bézier curves in terms of the natural parameterisation. "Has no corners" seems like a good way of expressing G-1 for laymen.2011-09-22