エッジの凹凸

ハーフエッジを使った凹凸判定

山折りのエッジのみをグループする

// Run Over: Points
// 事前にプリミティブに法線を設定している必要あり
//
int neighbours[] = neighbours(0, @ptnum);

foreach(int distPoint; neighbours)
{
    // 重複を避ける
    if(@ptnum > distPoint)
    {
        vector binormal = normalize(point(0, "P", distPoint)-@P);
        
        int hedge = pointhedge(0, @ptnum, distPoint);
        
        if(hedge != -1)
        {
            // 共有するハーフエッジを求める
            int hcount = hedge_equivcount(0, hedge);
            
            // 通常は2本
            if(hcount == 2)
            {
                int nextHedge = hedge_nextequiv(0,hedge);
                
                // エッジが属すプリミティブを求める
                int prim0 = hedge_prim(0, hedge);
                int prim1 = hedge_prim(0, nextHedge);
                
                // プリミティブの法線
                vector n0 = prim(0, "N", prim0);
                vector n1 = prim(0, "N", prim1);
                
                // 法線とエッジの外積から従法線を求める
                vector cross = cross(n1, binormal);
                
                // 内積
                float dot = dot(n0, cross);
                f@dot = degrees(acos(dot))+90;
                
                if(dot < 0)
                {
                    setedgegroup(0, "reflexAngle", @ptnum, distPoint, 1);
                    //printf(':' + sprintf('%g', @ptnum) + '\n');
                }
            }
        }
    }
}

角度で閾値を設けてグループする

下のコードは角度(30°)以下の山折りのエッジを選択している。

// Run Over: Points
// 事前にプリミティブに法線を設定している必要あり
//
float thresholdAngle = radians(30); // 制限角度

int neighbours[] = neighbours(0, @ptnum);

foreach(int distPoint; neighbours)
{
    // 重複を避ける
    if(@ptnum > distPoint)
    {
        vector binormal = normalize(point(0, "P", distPoint)-@P);
        
        int hedge = pointhedge(0, @ptnum, distPoint);
        
        if(hedge != -1)
        {
            // 共有するハーフエッジを求める
            int hcount = hedge_equivcount(0, hedge);
            
            // 通常は2本
            if(hcount == 2)
            {
                int nextHedge = hedge_nextequiv(0,hedge);
                
                // エッジが属すプリミティブを求める
                int prim0 = hedge_prim(0, hedge);
                int prim1 = hedge_prim(0, nextHedge);
                
                // プリミティブの法線
                vector n0 = prim(0, "N", prim0);
                vector n1 = prim(0, "N", prim1);
                
                // 法線とエッジの外積から従法線を求める
                vector cross = cross(n1, binormal);
                
                // 内積
                float dot = dot(n0, cross);
                float angle = acos(dot(n0, -n1));
                
                // 角度の条件で選ぶ
                if(dot < 0 && angle < thresholdAngle)
                {
                    setedgegroup(0, "reflexAngle", @ptnum, distPoint, 1);
                }
            }
        }
    }
}

エッジの関数

neighbours()
指定したポイントとエッジを通じて隣り合うポイント(複数)を返す

pointhedge()
2つのポイントを指定してハーフエッジを取得する

hedge_equivcount()
共有するハーフエッジの数を取得する
隣接するプリミティブがなければ1が返る

hedge_nextequiv()
エッジからもう片方のハーフエッジを取得する

hedge_prim()
ハーフエッジが含まれるプリミティブを取得する

setedgegroup()
ハーフエッジのグループを設定する

参考
https://www.sidefx.com/ja/docs/houdini/vex/halfedges.html

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