Help us understand the problem. What is going on with this article?

【Houdini】ポイント番号ををVEXでソートする

vexを使ってポイントを任意のルールでソートしようと思ったらちょっと手間取ったのでメモしておきます。

まずsort SOPで答え合わせ

サークルにscatterしてsortSOPにY軸の値でソートさせたのがこちらです。

image.png

vexでのソート

このようなコードでソートさせました。ランオーバーはdetailです。高級言語のソート関数に相当するものは存在しないので、argsort関数で別の配列にソート済みの並び順を代入することでソート処理の代わりとします。argsort関数は文字コード及び数値の降順でしかソートできないようです。

float pos_arr[] = {}; // y座標の配列
for(int i=0;i<@numpt;i++) {
    vector p = point(0, "P", i);
    push(pos_arr, p.y);
}
int ordering[] = argsort(pos_arr); // 数値が大きい順にポイント番号(ただしくは配列のインデックス番号)を格納する
ordering = reverse(ordering); // 小さい順にしたいので反転する。

// visualizeさせるために適当なアトリビュートに代入する
//(ordering配列のまま処理を進めるだけならばこの処理は必要ない)
for(int i=0;i<@numpt;i++) {
    setpointattrib(0, "sort_index", ordering[i], i);
}

sort_indexをvisualizeしたのがこちらです。

image.png

visualize のために sort_index アトリビュートを設定しましたが、通常は上記のコードで ordering に相当する配列にソート済みポイント番号が入っているのでそれをそのまま使います。

さらに別要素でソートする

argsort 関数(および sort SOP)は stable sort といって、評価順位が同じものは元の順序を保ったままのソート実装だそうです。つまり、別の要素で2度目のソートをしても同じ優先順位を持つ部分では1度目のソート順をキープするはずです。

円ではわかりずらいので2x2のグリッドを用意します。

image.png

上段左からグリッド作成時そのまま、SortSOPによるY座標昇順ソート、SortSOPによるX座標降順ソートの順に対応したもの、下段はグリッドそのままをSortSOPによるX座標降順ソートのみ対応したものです。一番右上のグリッドではポイント番号が右方向からかつ上方向からで並んでいるのが確認できます。

これを vex で同等の処理をさせてみます。

float pos_arr[] = {};
int ordering[];
vector p;

// y座標を収集
for(int i=0;i<@numpt;i++) {
    p = point(0, "P", i);
    push(pos_arr, p.y);
}

// y軸で降順ソートして昇順に変換
ordering = reverse(argsort(pos_arr));

// x座標を収集
pos_arr = {};
for(int i=0;i<@numpt;i++) {
    p = point(0, "P", ordering[i]);
    push(pos_arr, p.x);
}
// x軸で降順ソートして昇順に変換
ordering = reverse(argsort(pos_arr));

for(int i=0;i<@numpt;i++) {
    setpointattrib(0, "index", ordering[i], i);
}

image.png
求めている状態になりました。

sort SOP のパラメータ設定では対応できない複雑なソートでも、vex であれば対応させられそうです。

実際にポイント番号をソート順に割り振りたい

プログラムでそのまま処理する場合はordering配列をそのまま扱えばいいのですが、実際にポイント番号を入れ替えたい場合は、sort SOPにアトリビュートを元にソートさせてしまった方が簡単です。

image.png

これを vex でやるには、ポイントの位置を入れ替えて、頂点をつなぎなおせば可能な気はします。やってみるか?

考察

今回は0から並んだポイント番号をソートさせたので必要なかった(ordering配列が欲しいものそのものだった)ですが、任意の要素をソートさせた場合、reorder関数でソート済みの任意の配列を得る処理が必要です。
参考 vex : argsort

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away