環境:Houdini 20.0.751
平面上のポリラインを曲がる方向ごとにグループで分割する。
2つの連続したベクトルを比較して方向の違いを判定している。1つめのベクトルのレフトベクトル(進行ベクトルと平面の法線の外積で求める)と、2つめのベクトルの進行ベクトルの内積から曲がる方向をプラスとマイナスの符号で判定できる。これをポイントごとに行い、一つ前のポイントと符号の値が変わったらそこから曲がる方向が変わったとみなすことが出来る。
//
// ポリラインを曲がる方向でグループ分割する
// Run Over: Primitives
//
int pts[] = primpoints(0, @primnum);
vector up = set(0, 0, 1);
int prim = addprim(0, "polyline");
addvertex(0, prim, pts[0]);
addvertex(0, prim, pts[1]);
vector p0 = point(0, "P", pts[0]);
vector p1 = point(0, "P", pts[1]);
vector p2 = point(0, "P", pts[2]);
vector v0 = normalize(p1 - p0);
vector v1 = normalize(p2 - p1);
vector left = cross(up, v0);
float d = dot(left, v1);
// sign 0:直線、1:右回り、-1:左回り
int sign = 0;
if(d > 0) sign = 1;
else if(d < 0) sign = -1;
setprimattrib(0, "sign", prim, sign);
// 2番目のポイントからループ処理
for(int i = 2; i < len(pts)-1; i++)
{
p0 = point(0, "P", pts[i-1]);
p1 = point(0, "P", pts[i]);
p2 = point(0, "P", pts[i+1]);
v0 = normalize(p1 - p0);
v1 = normalize(p2 - p1);
left = cross(up, v0);
d = dot(left, v1);
// 前回と符号が逆転している場合
if((d > 0 && sign < 0) || (d < 0 && sign > 0))
{
addvertex(0, prim, pts[i]);
// 新しいポリラインを生成する
prim = addprim(0, "polyline");
addvertex(0, prim, pts[i]);
if(d > 0) sign = 1;
else if(d < 0) sign = -1;
setprimattrib(0, "sign", prim, sign);
}
else
{
addvertex(0, prim, pts[i]);
}
}
// 最後のポイントを加える
addvertex(0, prim, pts[-1]);
// 元のポリラインを削除
removeprim(0, @primnum, 1);