23
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HoudiniAdvent Calendar 2020

Day 6

ジオメトリからポリライン抽出あれこれ -Various Methods to Extract Polyline from Geometry-

Last updated at Posted at 2020-12-06

Houdini Advent Calendar 2020 6日目 の記事です

はじめに

背景TAになって1年目、TAらしい良い記事を書こうとひねり出したテーマは__"ポリラインの抽出"__です
Houdini歴0-2年ぐらいの方に向けて書いたつもりです

ポリラインはポリゴンに比べて単純な構造で、プロシージャルに制御するのにハードルが低いと思います
ジオメトリから欲しいポリラインを適切に抽出できれば、様々なシーンで活躍します
この記事を読んで生成されたポリライン達が、皆さんのHoudiniライフの一助となれば幸いです

また、抽出したポリラインの変換については、↓↓こちらのページにわかりやすくまとまっています
https://issekinichou.wordpress.com/2020/03/01/houdini-curve-editing/

動作環境

Houdini Apprentice 18.5.351
Labs 18.5.417

Primitive毎にエッジからポリラインを抽出

Ends,Primitive,Carve、これら3つのSOPは大体同じことができますが微妙に違います
image.png

Ends

エッジを一周する一つのポリラインを、プリミティブ毎に生成します
PrimitiveSOPでも同じことができますが、新しそうな__こちらが推奨__です

CloseU>Unroll with New Pointsを選べば端点が繋がっていないポリライン
image.png
CloseU>Unroll with Shared Pointsを選べば端点が繋がっていないポリライン
image.png
を得ることができます

Primitive

EndsSOPの親玉的SOPで、特別な事情が無い限り基本使わないことを推奨 恐らくWrangle登場以前の古いノードで、最近のシーンファイルではあまり見かけません(Wrangleでやっちゃうから) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239573/6ea72bfb-3e06-9e32-5cee-b0ed372798ac.png) Face/Hull>CloseU のプルダウンから Unroll with New Pointsを選べば端点が繋がっていないポリライン Unroll with Shared Pointsを選べば端点が繋がっていないポリライン をそれぞれ作成することができます(EndsSOPと同じ)

端点について

なお、EndsSOPもPrimitiveSOPも__ポリラインの端点は必ず元のプリミティブの頂点番号0が参照するポイント__になります
任意で指定することはできないので、端点を変更したい場合はReverseSOPのVertex>Shiftで対処してください
image.png
※PrimitiveSOP内にも同じパラメータがありますがうまく行かないので注意!
image.png

Carve

端点をパラメトリック座標から__始点終点を指定して__ポリラインを生成できます
前述の2つのSOPと違い、__必ず端点は繋がってない__状態でポリラインが出力されます
ポリゴンエッジをポリラインにする目的でCarveSOPを使う場合、FirstU,SecondUのみを使用します
image.png
FirstUのみ設定すると、EndsSOPのUnroll with New Pointsと同じ挙動をしますが…
image.png
FirstUを設定することで、端点を任意に指定できます(ポイント及びVtxは増えるので注意)
image.png
FirstU,SecondUを設定すると、始点終点をそれぞれ指定できます
image.png
※パラメトリック座標についてよく理解していない場合は、以下を参照
プリミティブのパラメトリック空間(暗黙的なUV): https://www.sidefx.com/ja/docs/houdini/model/primitive_spaces.html
何度読んでも難しい…

Facet

上記3つのSOPに共通する事項として
入力ポリゴンのエッジを構成するポイントがPrimitive間で共有されていれば、出力されるポリラインもポイントが共有されます
つまりポリラインがダブっている箇所があるのに、ジオメトリとしては切り離せないということになります
基本回避したい状況だと思いますので、FacetSOPを繋いでUniquePointsをチェックしてプリミティブ同士を切り離してから接続するようにしましょう
image.png
見かけでは分かりづらいので注意!

※ポイントと頂点についてよく理解していない場合は、以下を参照
ポイントと頂点: https://www.sidefx.com/ja/docs/houdini/model/points.html

各エッジでダブらないポリラインを抽出

ConvertLine,PolyPathは、上記3つと違ってダブらないポリラインを生成します
image.png

ConvertLine

各エッジに一つのポリラインを生成します
入力ジオメトリでポイントが共有されている場合は、ジオメトリとして繋がって出力されます
バラバラのポリラインにしたい場合は、FacetSOPを使用しましょう
image.png
FacetSOPの位置で挙動が変わります
右の結果はEndsSOPなどの出力結果と似ていますが、すべてのエッジが独立したポリラインになっている点で異なります
image.png
ちなみにダブルクリックで中を覗けます
image.png
結構シンプルな作りでわかりやすいです(こちらのVEX関数については後で説明します)
ポイント番号で駆動しているので、ポリラインの向きの制御が難しいです
image.png
向きのそろったポリラインが欲しい時は仕方なくVEXを書きます(VEX関数を参照)

PolyPath

できるだけ繋がったポリラインを生成します
左がConvertLineSOP,右がPolyPathSOPで、プリミティブごとに色分けしています
image.png
Sweepしたいときに良いです
image.png
こちらもダブルクリックで中を覗けます
image.png
trace_edgesというAttributeWrangleがキモです…が難しくてよくわかりません
いつか追記するかもしれません

VEX関数

addprim: https://www.sidefx.com/ja/docs/houdini/vex/functions/addprim.html
addvertex: https://www.sidefx.com/ja/docs/houdini/vex/functions/addvertex.html
の2つでとりあえずポリラインが作れます

↓↓に簡単なサンプルを用意しました
image.png
Wrangleの中身はこんな感じ

addprim_sample(RunOverはPrimitiveで)
//プリミティブの構成ポイント番号を配列で取得
int primpts[] = primpoints(0,@primnum);

//プリミティブの重心にポイントを作成
int newpt = addpoint(0,@P);

//構成ポイント毎に重心までのポリラインを作成
foreach(int ptnum;primpts){
int polyline = addprim(0,"polyline",newpt);
addvertex(0,polyline,ptnum);
}

//元のポリゴンを消去
removeprim(0,@primnum,1);

もっとこの辺りのVEXを詳しく知りたい方はこちらこちらなどを参照してください

おまけで、Vtxの並び方が綺麗にパラメトリック座標に反映されたポリライン
image.png

addprim_eachedge(RunOverはPrimitiveで)
//プリミティブの構成ポイント番号を配列で取得
int primpts[] = primpoints(0,@primnum);


//構成ポイント毎にエッジを生成する
foreach(int ptnum;primpts){
int hedge = pointhedge(0, ptnum);
int ptnum_next = hedge_dstpoint(0,hedge);
addprim(0,"polyline",ptnum,ptnum_next);
}

//元のポリゴンを消去
removeprim(0,@primnum,1);

image.png

addprim_eachPrim(RunOverはPrimitiveで)
//プリミティブの構成ポイント番号を配列で取得
int primpts[] = primpoints(0,@primnum);
//終点用に配列に始点を追加
push(primpts,primpts[0]);

//空のポリラインを作成
int polyline = addprim(0,"polyline");

//ポリラインに頂点を追加
foreach(int ptnum;primpts){
addvertex(0,polyline,ptnum);
}

//元のポリゴンを消去
removeprim(0,@primnum,1);

EdgeGroupから抽出

"エッジは水物"、と先輩が言っているように
エッジグループはとても壊れやすく扱いにくい存在で、スプレッドシートでも通常確認することができない困ったちゃんです
しかしながら、エッジからカーブを抽出できるととても重用します

EdgeGrouptoCurves,Dissolve

端点の結線を任意で指定できる
処理は遅め
Thredsholdがついていない

PolyExtrude

処理は速い
端点は必ず繋がってしまう
ノード増える

VEXで

expandedgegroupという関数を使うことで、VEXでエッジグループを扱う事ができました
image.png

ozkEdgeGroupToCurve
//set_detailattrib_exp(RunOver:Detail)
//EdgeGroupを配列にしてDetailアトリビュートに
i[]@exp = expandedgegroup(0,"edgeToCurve");

//create_ptattrib_target(RunOver:Points)
//空の配列アトリビュートを用意
i[]@__target;

//append_ptattrib_target(RunOver:Detail)
//エッジの始点の配列アトリビュートにエッジの終点番号を追加
int exp[] = detail(0,"exp");
int exp_length = len(exp);
for(int i=0; i<exp_length; i+=2){
	setpointattrib(0,"__target",exp[i],exp[i+1],"append");
}

//create_polyline(RunOver:Points)
//配列アトリビュートを元にポリラインを作成
int num_target = len(i[]@__target);

if(num_target!=0){
    foreach(int target;i@__target){
      	int addedprim = addprim(0,"polyline",@ptnum);
        addvertex(0,addedprim,target);
    }
}

以下随時追記予定…

ジオメトリを切断して抽出

Boolean,Surfsect,Profile

Clip,VoronoiFracture

PolyCut

グリッド構造からアイソカーブを抽出

Convert

VEX

Sim用のSOPを使って抽出

ConnectAdjecentPieces

TetConform(旧SolidConform)

TetEmbed(旧SolidEmbed)

Labsのツール

StraightSkelton2D

StraightSkelton3D

ExtractBorders

ExtractSilhouette

最短距離,測地線

FindShortestPath

DistanceAlongGeometry

おまけ

Trail

DrawCurve

23
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?