二次ベジェ曲線の点線

Top »

任意の長さからt値を得る関数を作る必要がある。曲線の長さの関数の逆関数を作るのは不可能なので、ニュートン法などのアルゴリズムを使う。設定する許容誤差にもよるが4回くらいで収束できる。

長さ関数は直線で近似できると考え、ニュートン法の初期値は目標長÷全長とする。

制御点が一直線に並ぶとき微分値に0が含まれ、万が一その点にあたったとき0除算が起きる可能性がある。しかしこうなるときは解析解が出せる。解の式は4通りあったのだが、2個は必ず虚数解のため破棄。残りのどちらか1個は実数解だが正しくない。出るであろう t が -b/(2*a) より小さいかどうかで解を分岐する。

l = 50; //目標長さ
var xa = 2*(x1-2*x2+x3);
var xb = -2*x1+2*x2;
var ya = 2*(y1-2*y2+y3);
var yb = -2*y1+2*y2;
var a = xa*xa+ya*ya;
var b = 2*(xa*xb+ya*yb);
var c = xb*xb+yb*yb;
var len = getLengthQ1(1, x1, y1, x2, y2, x3, y3);
with (Math) {
	if (b*b != 4*a*c || a == 0) {
		var t = l/length;
		var u = getLengthQ1(t, x1, y1, x2, y2, x3, y3);
		while (abs(l-u)>0.1) { //長さ許容誤差
			t += (l-u)/sqrt(a*t*t+b*t+c);
			u = getLengthQ1(t, x1, y1, x2, y2, x3, y3);
		}
	} else {
		var judge = getLengthQ1(-b/(2*a), x1, y1, x2, y2, x3, y3);
		var t = ((l<judge ? -1 : 1)*pow(32*a*a*l*(2*a*l+b*sqrt(c))+pow(b, 4),0.25)-b)/(2*a);
	}
}
return t;

getLengthQ1はベジェ曲線の長さ関数

実装

inserted by FC2 system