ポリラインの両端をカットする

環境:Houdini 20.5.487

ポリラインの両端を任意の長さでカットし、カットした位置にポイントが置かれるようにします。

処理の流れ

始点と終点からどれくらいの距離をカットするか決めたら、それぞれの点がポリラインのどのポイント区間にあるかを調べる。位置の直前のポイントのインデックスを記録しておく。同時に座標も計算しておく。

プリミティブから頂点をすべて外した状態にしてから、再度ポイントを追加して構成しなおす。始点の位置までポイントを削除していき、始点の位置にはポリラインの最初のポイントpts[0]を移動させる。同じ要領で終点もポリラインの最後のポイントpts[-1]を移動させ、以後のポイントを削除する。

コード

f[]@cut_length = {2.0, 3.2};

事前にアトリビュートを持たせておく。値は始点と終点からのカットする距離。始点から2m、終点から3.2mをカットする、といった感じ。

//
// ポリラインの両端をカットする
// Run Over: Primitives
//

// ポリラインを切る位置(始点側、終点側)
float cut_length[] = f[]@cut_length;

float start_length = cut_length[0];
float end_length = cut_length[1];

// カットするポリラインの座標やインデックスを探す
int start_idx = -1;
int end_idx = -1;

vector start_pos;
vector end_pos;

float curLength = 0;
int pts[] = primpoints(0, @primnum);
//
// 始点を調べる
//
if(start_length <= 0)
{
    start_idx = 0;
    start_pos = point(0, "P", pts[0]);
}
else
{
    for(int i = 0; i < len(pts)-1; i++)
    {
        vector p0 = point(0, "P", pts[i]);
        vector p1 = point(0, "P", pts[i+1]);
        float dist = length(p1-p0);
        
        // 始点と終点がどの範囲にあるか探す
        if(curLength <= start_length && start_length <= curLength + dist)
        {
            start_idx = i;
            float remainingDist = start_length - curLength;
            start_pos = p0 + normalize(p1 - p0) * remainingDist;
            break;
        }
    
        curLength += dist;
    }
}

//
// 終点を調べる
//
curLength = 0;
if(end_length <= 0)
{
    end_idx = pts[-1]-1;
    end_pos = point(0, "P", pts[-1]);
}
else
{
    float total_length = primintrinsic(0, "measuredperimeter", @primnum);
    end_length = total_length - end_length;
    
    for(int i = 0; i < len(pts)-1; i++)
    {
        vector p0 = point(0, "P", pts[i]);
        vector p1 = point(0, "P", pts[i+1]);
        float dist = length(p1-p0);
        
        // 始点と終点がどの範囲にあるか探す
        if(curLength <= end_length && end_length <= curLength + dist)
        {
            end_idx = i;
            float remainingDist = end_length - curLength;
            end_pos = p0 + normalize(p1 - p0) * remainingDist;
            break;
        }
    
        curLength += dist;
    }
}

// 頂点をポリラインからすべて除外する
int vertices[] = primvertices(0, @primnum);
for(int i = 0; i < len(vertices); i++)
    removevertex(0, vertices[i]);

// 再構成
// 始点
setpointattrib(0, "P", pts[0], start_pos);
addvertex(0, @primnum, pts[0]);

// 中間点
for(int i = 1; i < len(pts)-1; i++)
{
    if(i <= start_idx || end_idx < i)
        removepoint(0, pts[i]);
    else
        addvertex(0, @primnum, pts[i]);
}

// 終点
setpointattrib(0, "P", pts[-1], end_pos);
addvertex(0, @primnum, pts[-1]);

タイトルとURLをコピーしました