RhinoPython の Tips #2 – オブジェクトを適切に選択するための関数
スクリプトから Rhino のコマンドを実行した前回の記事に引き続き、RhinoPython について書いていきます。
今回は、連番処理や重い作業の自動化の中で必要なオブジェクトを適切に選択するための関数についてまとめてみようと思います。
(筆者が使ったことのある関数を中心に書いていくので抜けはありますがご容赦ください & ほかにも便利な関数があるよとコメント等で教えて下さい)
RhinoScriptSyntax の選択に関する関数について
まずは、RhinoScriptSyntax のドキュメントより選択に関する関数はこちら
https://developer.rhino3d.com/api/RhinoScriptSyntax/#selection
いくつか関数を挙げてみます。細かな引数やオプションについてはドキュメントを参照してください。
すべてのオブジェクトを選択し guid(注1)を取得する
rs.AllObjects()
デフォルト引数として select=False というものが設定されています。これはライノ上でオブジェクトを選択状態にするかどうかという設定で、RhinoPython で処理する上では基本的に False で良いです。
前回の記事のように rs.Command() を用いて Rhino の関数をスクリプト内で実行するときには Select=Ture にして Rhino のコマンドにオブジェクトを渡す必要があります。
オブジェクトをマウス操作で選ばせ、それらのオブジェクトの guid を返す
rs.GetObject()
rs.GetObjectEx()
rs.GetObjects()
### Curve をユーザに指定させる場合
### message により、Select Curve というメッセージが出ます。
### filter により、選択できるオブジェクトはカーブだけになります。
curve_ids = rs.GetObject(message="Select Curve", filter=4)
rs.GetObjectEx() に関しては使ったことがないので使い勝手はわかりませんが、返り値として情報がまとまって返ってくるようです。デフォルト引数‘の select=False については前述のとおり。
message という引数(デフォルトは None)があり、これは実行時に表示するメッセージを設定できます。選ぶべきオブジェクトについて説明しておくと親切だと思います。例えば断面の曲線をユーザに選んでほしい場合には message=”Select Profile-Curve” などが設定できると思います。
filter という引数(デフォルトは 0)もあり、これは選択できるオブジェクトの種別を指定できます。これにより間違ったオブジェクトを選ぶことを防ぐことができます。例えば断面の曲線をユーザに選んでほしい場合には filter=4 とすると選択可能なオブジェクトがカーブだけになります。filter に渡すべきはジオメトリの種別を数値で渡しますが、それは後述します。
現在 Rhino で選択状態のオブジェクトの guid を取得する
rs.SelectedObjects()
ライノ上のオブジェクトの選択状態を解放する
rs.SelectedObjects() で guid を取得したあとにこの関数で選択状態を開放することが多いです。
rs.UnselectAllObjects()
指定したレイヤーに含まれるオブジェクトの guid を返す
rs.ObjectsByLayer(layer_name)
Elefront でも似たような機能がありますがこれが便利。デフォルト引数の select=False については前述のとおり。
指定した型のオブジェクトの guid を返す
rs.ObjectsByType(geometry_type)
"""
geometry_type
Value Description
0 All objects
1 Point
2 Point cloud
4 Curve
8 Surface or single-face brep
16 Polysurface or multiple-face
32 Mesh
256 Light
512 Annotation
4096 Instance or block reference
8192 Text dot object
16384 Grip object
32768 Detail
65536 Hatch
131072 Morph control
134217728 Cage
268435456 Phantom
536870912 Clipping plane
1073741824 Extrusion
"""
### Point を取得する場合
point_ids = rs.ObjectsByType(1)
### Curve を取得する場合
curve_ids = rs.ObjectsByType(4)
Elefront でも似たような機能がありますがこれが便利。オブジェクトの種類の指定は数値で指定します。デフォルト引数の select=False については前述のとおり。
オブジェクトを guid で指定して、ライノ上で選択状態にする
rs.SelectObject(id)
rs.SelectObjects(ids)
スクリプト内では guid で受け渡ししているので選択状態にする必要はないですが、処理の最後にこの関数でオブジェクトを選択状態にして終わることがあります。
手元にあったスクリプトを確認してみると以上のものが頻繁に使われてました。現在進行形のプロジェクトでは rs.ObjectByHoge() のような既存の関数によるフィルタリングと合わせて、オブジェクトに書き込まれた UserText を用いてフィルタリングも併せて行っています。近いうちにこれについても書ければと思います。
まとめ
面倒な作業をスクリプトで処理できれば便利ですが、選ぶべきものを適切に選ぶことができなければ、手作業でミスなくオブジェクトを選択する必要になったり、そもそもうまく機能しなかったりと面倒な作業を手放すことができません。
「手作業で」という部分を残すと、処理するファイルや選ぶべきオブジェクトの数が多ければ煩雑になり単純な作業ミスをしてしまう可能性は残ります。そのためには適切な関数を用いて自動で選ぶべきものを選ぶことやフィルターとして機能させることで、ミスなく処理していくための方法を考えることが大事と考えています。ミスをなく作業をしていくことの難しさを日々感じてるので似たような話が次回へ続きます。
(余談になりますが、毎回記事を書くにあたり公式のドキュメントを読み返すと、自分の誤認識や探していたあの機能が見つかります…。フォーラムに貼ってあるコードをガチャガチャ試すだけでなく、公式のドキュメントの読み込むことが手早く適切な実装をするための近道だと感じています。)
(注1) Rhino ではオブジェクトごとに guid (globally unique identifier) が振られて管理されています。詳しくは以下を参照。 https://developer.rhino3d.com/api/RhinoCommon/html/P_Rhino_DocObjects_RhinoObject_Id.htm