最近は子供が昼寝から起きたら作業中断になるので昼間はほぼ何もできない…
■ [Houdini]プリミティブ端のエッジを除去して中のラインだけ残す
convertLineを参考に。
int n[] = neighbours(1, @ptnum);
foreach(int pt; n){
int e0 = inpointgroup(1, "edge", @ptnum);
int e1 = inpointgroup(1, "edge", pt);
if( (e0==0 || e1==0) && pt<@ptnum){
int pr = addprim(geoself(), "polyline");
addvertex(geoself(), pr, @ptnum);
addvertex(geoself(), pr, pt);
}
}
追記:上記だとまずいパターンがあった。単純なvoronoiであれば問題ないが、複数の分割が重なって、エッジの中央に他のポリゴンの点があるなど、共有されない頂点で割られている時にうまく動かない
そういう形状の時は、いったん綺麗な形のポリゴンになるように前処理してやる必要がある
- scatter→voronoifractureだと裏面ポリゴンが生まれるケースが多いので、deleteで裏面を削除してから作業開始
- エッジが共有されていない時には、groupのunshared Edgesがうまく動かないので、fuseで連結した後にcleanで重複したラインやポリゴンを削除してから実行する必要がある
追記2:さらにまずいパターンを発見。エッジが共有されていない分割だと、Group SOPのエッジ検出がポリゴンの内側にエッジがあるとみなしてしまっておかしくなる
対策として、ConvertLineしたラインの向きベクトルを微小にしたものから計算した、左右斜め前両方のポジションでレイキャストしてどちらかが抜けてたら弾く、という処理にしてみた。
float delta = 0.01;
int pn0 = primpoint(0,@primnum,0);
int pn1 = primpoint(0,@primnum,1);
vector p0 = point(0,"P",pn0);
vector p1 = point(0,"P",pn1);
vector dirVec = normalize(p1-p0) * delta;
vector crossVec = dirVec;
crossVec.x = dirVec.z;
crossVec.z = dirVec.x;
vector chkPos = p0;
chkPos.y = delta;
vector chkDir = {0,-1,0};
vector cp0 = chkPos+(dirVec+crossVec);
vector cp1 = chkPos+(dirVec-crossVec);
vector retPos;
float retU, retV;
int ck_l = intersect(1, cp0, chkDir, retPos, retU, retV);
int ck_r = intersect(1, cp1, chkDir, retPos, retU, retV);
if( ck_l == -1 || ck_r == -1){
removeprim(geoself(), @primnum, 0);
}
余りに鋭角なポリゴンだと検出点に引っかからない可能性はあるが、それ以外はたぶんこれでほぼどんな形状になっても大丈夫?
■ [Houdini]polyExpand2Dで失敗するケースへの対策
上記で作ったLineをpolyExpand2Dでポリゴン化しようとすると、重複したラインがある為にそのままでは失敗する。
intersectionStichで交点で分割することで、長いポリゴンの辺になっていて、間に点のある重複したラインを分割できる
実用的な複雑な形状だと、intersectionStichしても失敗するケースがある。
その時は、intersectionStich → fuse → intersectionStich とつなぐことで、polyExpand2Dが成功するようになる
これで、ブロック内を任意のポリゴンで分割したときに、間にできる道をpolyExpand2Dで作ることができるようになる…
2019/07/15追記
fuse->intersectionStich->fuse で中点を消すパターン、cleanで綺麗になるケースもありそう。要検証
外周のエッジのみ消す方法は、traianglete2d(凸型限定)->clean->groupでエッジ抽出
したものを、groupTransfarでプリミティブに転送(このとき、include only Elements Entirely.... をONしないと余分に転送される)してblastすれば消える
2019/10/20追記
外周をGroup SOPのUnshard Edgeでエッジグループにしておいて、Primitive SOPのCloseUをOpenにしてラインに変換したあとに外周グループのみをBlastで消せる
2019/10/21追記
これでいける。
Voronoi結果をFuse→GroupのUnshared Edgeでエッジのグループ生成→ConvertLineでライン化したあとにGroupTransferでエッジグループを転送(このとき、グループが残ってるのでGroup Name Confrict時の処理をOverwriteにする必要がある)→GroupTransferでEdgeグループをPrimitiveに転送して、Balstで外周だけ消す