« Player のバージョンによって Array と Vector を使い分ける | メイン | AS3 についていろいろメモ »

2008年10月21日

[as3] 3 次ベジェ曲線を curveTo() を使って描く

小さいと分かり難いんですが、赤線が curveTo で引いた線。青線が lineTo で20分割して描いてる線。
curveTo の分割数は曲線の形によって変化しています。
少ないときで 1 本。多くて 8 本くらいです。


なんだか、やたら長くなってしまった。
最初は曲線の角度から分割しようと思ってたけど、どうやって割り出せばいいかよくわからず、結局こんなことになってしまった。
一応これだと、どんだけひねっても、ほとんどずれないです。

それにしても、もうちょっとやりようはありそうなもんだけども。
とりあえず僕の低い学力では、今はここまで。

function bezierCurve(
        ax:Number, ay:Number, 
        bx:Number, by:Number, 
        cx:Number, cy:Number, 
        dx:Number, dy:Number, n:Number, t:Number):void
{
    var t1:Number = n + (t - n) * 0.5;
    var t2:Number = n + (t - n) * 0.25;
    var ax2:Number = cubicBezier(ax, bx, cx, dx, n);
    var ay2:Number = cubicBezier(ay, by, cy, dy, n);
    var dx2:Number = cubicBezier(ax, bx, cx, dx, t);
    var dy2:Number = cubicBezier(ay, by, cy, dy, t);
    
    var px:Number = cubicBezier(ax, bx, cx, dx, t1);
    var py:Number = cubicBezier(ay, by, cy, dy, t1);
    var rx:Number = getControl(ax2, px, dx2);
    var ry:Number = getControl(ay2, py, dy2);
    var qx:Number = quadraticBezier(ax2, rx, dx2, 0.25);
    var qy:Number = quadraticBezier(ay2, ry, dy2, 0.25);
    var px2:Number = cubicBezier(ax, bx, cx, dx, t2);
    var py2:Number = cubicBezier(ay, by, cy, dy, t2);
    
    if (checkPosition(qx-px2, qy-py2, 0.5))
    {
        curveTo(rx, ry, dx2, dy2);
    }
    else
    {
        bezierCurve(ax, ay, bx, by, cx, cy, dx, dy, n, t1);
        bezierCurve(ax, ay, bx, by, cx, cy, dx, dy, t1, t);
    }
}

ベジェ曲線のそれぞれの計算は以下。

//曲線が許容範囲内に収まってるかチェック
function checkPosition(x:Number, y:Number, d:Number):Boolean
{
    return (Math.abs(x) < d && Math.abs(y) < d);
}

//2次ベジェ曲線の通過点からコントロールポイントを得る
function getControl(
        a:Number, b:Number, c:Number):Number
{
    return (b * 4 - a - c) * 0.5;
}

//2次ベジェ曲線の任意の点を取得
function quadraticBezier(
        a:Number, b:Number, c:Number, t:Number):Number
{
    var s:Number = 1 - t;
    return s * s * a + 2 * s * t * b + t * t * c;
}

//3次ベジェ曲線の任意の点を取得
function cubicBezier(
        a:Number, b:Number, c:Number, d:Number, t:Number):Number
{
    var s:Number = 1 - t;
    return s * s * s * a 
        + 3 * s * s * t * b 
        + 3 * s * t * t * c 
        + t * t * t * d;
}


やっぱりソースが長い。
無駄に計算してる感が否めないので、
せめてこの半分くらいにはしたい。

トラックバック(0)

このブログ記事を参照しているブログ一覧: 3 次ベジェ曲線を curveTo() を使って描く

このブログ記事に対するトラックバックURL: http://system.seyself.com/mt-tb.cgi/518

コメントする


画像の中に見える文字を入力してください。

しばらく時間が経過すると、システム内部と表示されている文字内容に食い違いが発生するようなので、
投稿する前にページをリロードすることをお勧めします。
リロードしてもフォームの内容は維持されます。