| INDEX |

久しぶりのエントリーです。仕事が忙しくなると物欲がたくましくなる今日この頃です。年末はゲームもプラモもいろいろ発売でゆるゆるです。バーチャとシュトルヒが欲しい…。で、懲りずにベジェです。3次ベジェの切り分けです。

上の図は、3次ベジェを調べたことのある方なら見慣れた図かと思います。図のtpの座標をスクリプトで書くと、

/**
* Bezier Function
* @param	t
* @return	Point
*/
/*
_point0:Point 始点
_point1:Point 終点
_control0:Point 制御点
_control1:Point 制御点
*/
function f(t:Number):Point
{
  var tp:Number = 1.0 - t;
  return new Point( _point0.x*tp*tp*tp + 3*_control0.x*t*tp*tp + 3*_control1.x*t*t*tp + _point1.x*t*t*t,
                    _point0.y*tp*tp*tp + 3*_control0.y*t*tp*tp + 3*_control1.y*t*t*tp + _point1.y*t*t*t );
}

な感じのtに関する関数になります。
で、任意のt値、例えばポイントtpで3次ベジェを2つに分けようというものです。

2つに分けるには、2つの3次ベジェの新しい制御点を求めることになりますが、図を眺めているとすでに見えているのですね。2分割した後の曲線は、以下の図のようになります。勢いでやってみると、案外すんなりいくものです。

図でいうところの、■□、△▲が新しい制御点になります。
ベタにスクリプトで書くと、

/**
* Split Bezier at t.
* @param	t( 0 to 1 )
*/
function split(t:Number):Array
{
  var tp:Point   = f(t); //上に書いた関数
  var m:Point   = Point.interpolate( _control1, _control0, t);

  //制御点■□
  var ac0:Point = Point.interpolate( _control0, _point0, t);
  var ac1:Point = Point.interpolate( m, ac0, t);

  //制御点△▲
  var bc1:Point = Point.interpolate( _point1, _control1, t);
  var bc0:Point = Point.interpolate( bc1, m, t);

  return [ {p0:_point0.clone(),p1:tp,cp0:ac0,cp1:ac1},
           {p0:tp.clone(),p1:_point1.clone(),cp0:bc0,cp1:bc1}];
}

のような感じです。

青、オレンジの曲線が切り取った線で、中の黒い線がもともとの曲線です。

SVGの読み込みをしようと思って、その過程で3次ベジェを2次ベジェに変換したくて、その前処理に使ったりしてます。

| INDEX |