| INDEX |

12月第1週でゲーム3本購入。なんとも年末気分になっています。前回の流れで3次ベジェ曲線の切り出しを書いてみます。

前回のエントリーのように、3次ベジェをtの関数としたとき、t=t0、t=t1での座標は、fig1のようにtp0、tp1となるとします。この間の曲線を切り出すわけですが、次のfig2のような手順でいけます。

つまり、一度tp0で切り分けて、切り分けられた曲線の一方をtp1で切り分けるんですね。手順としては前回の切り分けを2度行うわけです。

ただ、2度目の切り分け(fig2b)のとき、tp1を示すt値がt1ではなくなります。基準となる曲線が変わるので、t値も変化するわけです。で、t=t1に対応するような、t1’を導きます。

t値を相対的にみると、t1は、長さ 1-t0 の内の t1′ となり、1-t0 を 1 とすると、t1’=(t1-t0)/(1.0-t0) となります。
これを素直にスクリプトにすると、

/**
* Clip Bezier at t0 and t1.
* @param	t0( 0 to 1 )
* @param	t1( 0 to 1 )
*/
/*
_point0:Point 始点
_point1:Point 終点
_control0:Point 制御点
_control1:Point 制御点
*/
function clip( t0:Number, t1:Number ):Object
{
  if( t0==t1 ){
    //同じ値の場合なし
    return null;
  }else if( t0==0 || t0==1 ){
    //端点の場合は切り分けに同じ
    return (split(t1))[ (t0==1)?1:0 ]; //splitって前エントリーで書いた関数
  }else if( t1==0 || t1==1 ){
    //端点の場合は切り分けに同じ
    return (split(t0))[ (t1==1)?1:0 ];
  }

  var p0:Point   = f(t0); //3次ベジェの関数
  var p1:Point   = f(t1);

  //t0で切り分け
  var m0:Point  = Point.interpolate( _control1, _control0, t0);
  var c01:Point = Point.interpolate( _point1, _control1, t0);
  var c00:Point = Point.interpolate( c01, m0, t0);

  //t1'で切り分け
  var t2:Number = (t1-t0)/(1.0-t0);
  var m1:Point   = Point.interpolate( c01, c00, t2);
  var c0:Point = Point.interpolate( c00, p0, t2);
  var c1:Point = Point.interpolate( m1, c0, t2);

  return {p0:p0,p1:p1,cp0:c0,cp1:c1};
}

のような感じです。

“[as]3次ベジェ切り出し” への2件のフィードバック

  1. vjwada より:

    もうちょっと頑張って計算すると、指定した範囲だけを切り出す数式が出来ますよ。
    P(x,y),Q(x,y),R(x,y),S(x,y),T=u+v,V=t+uとのとき、t:u:vに分割したときのuの部分の制御点
    P’=(T^3P + 3T^2tQ + 3Tt^2R + t^3S)
    Q’=(T^2vP + T(3tv + u)Q + t(3tv + 2u)R + t^2VS)
    R’=(Tv^2P + v(2u + 3tv)Q + V(u + 3tv)R + tV^2S)
    S’=(v^3P + 3v^2VQ + 3vV^2R + V^3S)
    ※^は累乗記号です

  2. nutsu より:

    どうもです。アドバイスありがとうございます。試してみますね。

| INDEX |