3次ベジェ曲線の分割

Top »

曲線上に一つのアンカーポイントを追加する

曲線上 t に一つのアンカーを置くことでベジェ曲線を2分割し、新たな制御点を得たい。

元となる2次ベジェ曲線の制御点はABCDとする。

線分AB上にt:1-tで分割した点をE、同じくBC上にF、CD上にG、EF上にH、FG上にI、HI上にJを置く。これをベクトルの数式で表すと:

E = (1-t)*A + t*B
F = (1-t)*B + t*C
G = (1-t)*C + t*D
H = (1-t)*E + t*F = (1-t)^2*A + 2*(1-t)*t*B + t^2*C
I = (1-t)*F + t*G = (1-t)^2*B + 2*(1-t)*t*C + t^2*D
J = (1-t)*H + t*I = (1-t)^3*A + 3*(1-t)^2*t*B + 3*(1-t)*t^2*C + t^3*D

Jの軌道がベジェ曲線である。

新たな4つのベジェ曲線の制御点は、A側ががAEHJ、C側がJIGDとなる。

曲線の任意の範囲を切り出す

曲線上の t1, t2 にアンカーを置き、新たな制御点を得たい。つまり t = [t1, t2] の範囲のベジェ曲線を成す4つの制御点を新たに得たい。

元となる2次ベジェ曲線の制御点はABCDとする。

線分AB上にt1:1-t1で分割した点をE1、BC上にF1、CD上にG1、E1F1上にH1、F1G1上にI1、H1I1上にJ1
線分AB上にt2:2-t2で分割した点をE2、BC上にF2、CD上にG2、E2F2上にH2、F2G2上にI2、H2I2上にJ2、 これをベクトルの数式で表すと:

E1 = (1-t1)*A + t1*B
F1 = (1-t1)*B + t1*C
G1 = (1-t1)*C + t1*D
H1 = (1-t1)*E1 + t1*F1 = (1-t1)^2*A + 2*(1-t1)*t1*B + t1^2*C
I1 = (1-t1)*F1 + t1*G1 = (1-t1)^2*B + 2*(1-t1)*t1*C + t1^2*D
J1 = (1-t1)*H1 + t1*I1 = (1-t1)^3*A + 3*(1-t1)^2*t1*B + 3*(1-t1)*t1^2*C + t1^3*D
E2 = (1-t2)*A + t2*B
F2 = (1-t2)*B + t2*C
G2 = (1-t2)*C + t2*D
H2 = (1-t2)*E2 + t2*F2 = (1-t2)^2*A + 2*(1-t2)*t2*B + t2^2*C
I2 = (1-t2)*F2 + t2*G2 = (1-t2)^2*B + 2*(1-t2)*t2*C + t2^2*D
J2 = (1-t2)*H2 + t2*I2 = (1-t2)^3*A + 3*(1-t2)^2*t2*B + 3*(1-t2)*t2^2*C + t2^3*D

t1 側制御点 K1は H1I1 上を t2:1-t2 で分割した点、 t2 側制御点 K2は H2I2上を t1:1-t1 で分割した点であると考えられる。

K1 = (1-t2)*H1 + t2*I1
= (1-t2)*((1-t1)*E1 + t1*F1) + t2*((1-t1)*F1 + t1*G1)
= (1-t2)*((1-t1)^2*A + 2*(1-t1)*t1*B + t1^2*C) + t2 *((1-t1)^2*B + 2*(1-t1)*t1*C + t1^2*D)
= (1-t2)*(1-t1)^2*A + 2*(1-t2)*(1-t1)*t1*B + (1-t2)*t1^2*C + t2*(1-t1)^2*B + 2*t2*(1-t1)*t1*C + t2*t1^2*D
= (1-t1)^2*((1-t2)*A + t2*B) + 2*(1-t1)*t1*((1-t2)*B + t2*C) + t1^2*((1-t2)*C + t2*D)
= (1-t1)^2*E2 + 2*(1-t1)*t1*F2 + t1^2*G2
K2 = (1-t1)*H2 + t1*I2

切り出された新たなベジェ曲線の制御点は H1, K1, K2, H2 である。

様々な変形が考えられたが、実装上はこうするのが軽そう。

var t1p = 1-t1;
var t2p = 1-t2;
var nx1 = t1p*t1p*t1p*x1 + 3*t1*t1p*t1p*x2 + 3*t1*t1*t1p*x3 + t1*t1*t1*x4;
var ny1 = t1p*t1p*t1p*y1 + 3*t1*t1p*t1p*y2 + 3*t1*t1*t1p*y3 + t1*t1*t1*y4;
var nx2 = t1p*t1p*(t2p*x1+t2*x2) + 2*t1p*t1*(t2p*x2+t2*x3) + t1*t1*(t2p*x3+t2*x4);
var ny2 = t1p*t1p*(t2p*y1+t2*y2) + 2*t1p*t1*(t2p*y2+t2*y3) + t1*t1*(t2p*y3+t2*y4);
var nx3 = t2p*t2p*(t1p*x1+t1*x2) + 2*t2p*t2*(t1p*x2+t1*x3) + t2*t2*(t1p*x3+t1*x4);
var ny3 = t2p*t2p*(t1p*y1+t1*y2) + 2*t2p*t2*(t1p*y2+t1*y3) + t2*t2*(t1p*y3+t1*y4);
var nx4 = t2p*t2p*t2p*x1 + 3*t2*t2p*t2p*x2 + 3*t2*t2*t2p*x3 + t2*t2*t2*x4;
var ny4 = t2p*t2p*t2p*y1 + 3*t2*t2p*t2p*y2 + 3*t2*t2*t2p*y3 + t2*t2*t2*y4;
inserted by FC2 system