Control points are off for "negative" vectors in a poly-line Bézier curve

377 Views Asked by At

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!

1

There are 1 best solutions below

6
On

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).