TKYM's profile※ 画面は開発中のものですPhotosBlogListsMore Tools Help

Blog


    December 07

    ベジエ曲線の分割

    曲線を t : 1-t に分割したければ、 制御点 1-2,  2-3,  3-4 を  t : 1-t に分割し、
    それを結んで出来た2本の直線を、再び t : 1-t に分割し、
    残りの1本を t : 1-t に分割する。

    分割した点は、新たな曲線の制御点になっている。


    image

            static public PointF[,] BezierCut(PointF[] points, float t){
                PointF[,] result = new PointF[2, points.Length];
                
                //stでくぎられる点を見つける
                //分割前の P0, Pn が分割後の L0, Rn になる
                result[0,0] = points[0];
                result[1,points.Length-1] = points[points.Length - 1];
    
                PointF[] prev = points;
                for (int i = 1; i < points.Length; i++)
                {
                    PointF[] tmp = new PointF[points.Length - i];
                    for (int j = 0; j < points.Length - i; j++)
                    {
                        //tmp[j] - tmp[j+1] の間を st で区切る
                        tmp[j].X = prev[j].X + (prev[j + 1].X - prev[j].X) * t;
                        tmp[j].Y = prev[j].Y + (prev[j + 1].Y - prev[j].Y) * t;
                    }
                    result[0,i].X = tmp[0].X;
                    result[0,i].Y = tmp[0].Y;
                    result[1,points.Length - i - 1].X = tmp[tmp.Length - 1].X;
                    result[1,points.Length - i - 1].Y = tmp[tmp.Length - 1].Y;
    
                    prev = tmp; //算出したものを保持
                }
    
                return result;
            }

    image

    このシリーズの他記事 http://prog-city.spaces.live.com/lists/cns!E5379F11D9E8BB3F!1047/

     

    December 01

    C#でベジエ曲線(5) ベジエ曲線同士の交点

    どのようにして曲線同士の交点を求めるか、全くわからずに悩んでいたが、直線との交点を求める方法を応用すれば可能であることに気づいた。

    曲線同士が接しているということは、その凸包も接していることになる。
    凸包の共有部分を調べ、絞り込むことで交点を得ることが出来るだろう。

    なんとなく思いついた流れ

    交点を求める( 曲線A, 曲線B){

        if( 2つの凸包が接していない ) return null;

        do{
            clipA[] = 曲線A が、曲線Bの凸包内部である部分
            clipB[] = 曲線B が、曲線Aの凸包内部である部分
        }while( ClipA.length == 1 && ClipB.length == 1 && 収束していない );

        if( ClipA.length ==  0 || ClipB.length == 0 ) return null;
        if( ClipA.length == 1 && ClipB.length == 1 && 収束した ) return 座標;

        result[] = {};

        for( ClipA.length 回 ){
            for( ClipB.length 回 ){
                result +=  交点を求める( ClipA[cnt1], ClipB[cnt2] );
            }
        }
        return result;
    }


    このシリーズの他記事: http://prog-city.spaces.live.com/lists/cns!E5379F11D9E8BB3F!1047/