連続性のあるベジェ曲線の描画

公開 更新

連続したベジェ曲線

ベジェ曲線は始点と終点を必ず通り、他の制御点は通らない特徴がある。ポリラインの辺の中点で分割したガイドカーブを使い、その中点を各区間の始点・終点にする。つなぎ目の点は前後の制御点の中点なので、3点が一直線上に並び、両側の接線の向きが揃う。 これで各区間が滑らかにつながった連続したカーブを描くことができる。

2次(Quadratic)のベジェ曲線

3点のガイドカーブを利用して、2次のベジェ曲線を描いていく。ガイドカーブの生成は以下のページに書きました。

ポリラインをベジェ制御点に分割する
//
// 2次(Quadratic)のベジェ曲線
//
// input1にガイドカーブをつなげる
// RunOver:Detail
//
int num = 100;
int prim = addprim(0, "polyline");
for(int i = 0; i < nprimitives(1); i++)
{
    
    int pts[] = primpoints(1, i);

    vector p0 = point(1, "P", pts[0]);
    vector p1 = point(1, "P", pts[1]);
    vector p2 = point(1, "P", pts[2]);
    
    //
    // ベジェ曲線を描く
    //
    for(int n = 0; n < num; n++)
    {
        // 区間の終点は次の区間の始点と重なるので、最後の区間以外は飛ばす
        if(n == num - 1 && i < nprimitives(1)-1)
            continue;

        float t = n / float(num-1);
        
        vector pos = (1-t)*(1-t)*p0 + 2*(1-t)*t*p1 + t*t*p2;
        
        int pt = addpoint(0, pos);
        addvertex(0, prim, pt);
    }
}

3次(Cubic)のベジェ曲線

4点のガイドカーブを利用して3次のベジェ曲線を描いていく。最後が3点なら2次のベジェ曲線を描いて終わらせる。3点でも4点でもないプリミティブは飛ばす。

//
// 3次(Cubic)のベジェ曲線
//
// input1にガイドカーブをつなげる
// RunOver:Detail
//
int num = 100;
int prim = addprim(0, "polyline");

for(int i = 0; i < nprimitives(1); i++)
{
    int pts[] = primpoints(1, i);

    if(len(pts) == 3)
    {
        vector p0 = point(1, "P", pts[0]);
        vector p1 = point(1, "P", pts[1]);
        vector p2 = point(1, "P", pts[2]);
        
        // 2次ベジェ曲線を描く
        for(int n = 0; n < num; n++)
        {
            // 区間の終点は次の区間の始点と重なるので、最後の区間以外は飛ばす
            if(n == num - 1 && i < nprimitives(1)-1)
                continue;

            float t = n / float(num-1);
            
            vector pos = (1-t)*(1-t)*p0 + 2*(1-t)*t*p1 + t*t*p2;
            
            int pt = addpoint(0, pos);
            addvertex(0, prim, pt);
        }
    }
    else if(len(pts) == 4)
    {
        // ベジェ曲線のための4点を選ぶ
        vector p0 = point(1, "P", pts[0]);
        vector p1 = point(1, "P", pts[1]);
        vector p2 = point(1, "P", pts[2]);
        vector p3 = point(1, "P", pts[3]);
        
        // 3次ベジェ曲線を描く
        for(int n = 0; n < num; n++)
        {
            // 区間の終点は次の区間の始点と重なるので、最後の区間以外は飛ばす
            if(n == num - 1 && i < nprimitives(1)-1)
                continue;

            float t = n / float(num-1);
            
            vector pos = (1-t)*(1-t)*(1-t)*p0 + 3*(1-t)*(1-t)*t*p1 + 3*(1-t)*t*t*p2 + t*t*t*p3;
            
            int pt = addpoint(0, pos);
            addvertex(0, prim, pt);
        }
    }
}

← 記事一覧へ