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

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:

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!

-
Answered at stackoverflow first... whew, I'll post the answer after the 3 day minimum. Answer: var ma = [-m[0],-m[1]]; var mc = m; – RANGER Jul 23 '11 at 5:24
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: stackoverflow.com/questions/6797614/… – joriki Jul 25 '11 at 21:58

@Peter Taylor: I have to confess to not having heard of $G^1$ continuity before, but after googling it, I must admit that it seems like a natural way to formulate the appropriate condition. Wikipedia does say that "[i]n general, $G^n$ continuity exists if the curves can be reparameterized to have $C^n$ (parametric) continuity", so I don't think I was too far off in using "once differentiable" in a loose sense. – Ilmari Karonen Sep 22 '11 at 15:53
Precisely, so "if and only if" is wrong. The curve could be non-differentiable at the knot with $\lim_{P\to P_0+}$ and $\lim_{P\to P_0-}$ parallel but non-equal. – Peter Taylor Sep 22 '11 at 16:13
@Peter Taylor: If the derivatives are parallel but non-equal, you should be able to reparametrize the curve so that they're equal. And since I didn't really fix a parametrization anyway... (Although a spline does come with a natural parametrization, whose derivative can be discontinuous even if the curve also admits a $C^1$ parametrization, so I can see where we might be talking past each other.) Anyway, I'll be happy to change "once differentiable" to something else that better captures the notion of $G^1$ continuity in a way a layperson can understand: maybe "has no corners" might do? – Ilmari Karonen Sep 22 '11 at 16:40