rhino3d-scripts について
rhino3d-scripts は、Rhinoceros 3D のスクリプトを作成、編集、デバッグする開発者向けのスキルです。RhinoScript、RhinoPython、RhinoCommon、コマンドマクロを扱い、作業手順やトラブルシューティングも説明します。
主な機能
- 013種類の Rhino スクリプト方式に対応
- 02スクリプトとマクロの選び方
- 03ジオメトリ操作のコード例
- 04スクリプトの読み込みと配布方法
- 05一般的な問題と対処法
活用シーン
- 01RhinoPython スクリプトの作成やデバッグ
- 02VBScript または RhinoScript の保守
- 03Rhino オブジェクトの一括変更
- 04起動スクリプトやツールバーボタンの設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ github/ awesome-copilot --skill rhino3d-scriptsインストール後、Claude Code で/rhino3d-scriptsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/macros-and-loading.mdrhinocommon-map.mdrhinoscriptsyntax-cheatsheet.mdvbscript-quirks.md詳細
Rhino 3D スクリプト作成スキル
Rhinoceros 3D 用の本番品質のスクリプトを作成します。3 つのスクリプト環境(RhinoScript/VBScript、RhinoPython、RhinoCommon .NET の直接利用)と、Rhino 8 以降の Script Editor を扱います。
このスキルを使う場面
- Rhino スクリプトの
.rvb、.vbs、.pyファイルの作成、編集、デバッグを依頼された場合 - Rhino のコマンドマクロの作成や、Rhino コマンドの一連の操作の自動化を求められた場合
- コードからジオメトリ、レイヤー、ブロック、マテリアル、ビューポート、注釈を操作したい場合
rhinoscriptsyntax、scriptcontext、RhinoCommon、Rhino.Geometry、RhinoDoc、Script Editor に言及された場合- Rhino 内でオブジェクトを選択したり、入力を求めたり、小規模な UI を構築したい場合
- スクリプトの読み込み、実行、配布方法(起動時スクリプト、エイリアス、ツールバーボタン)を尋ねられた場合
スクリプト環境の選択
好みではなく、タスクに応じて環境を選びます。新規作業では、デフォルトで Python を推奨します。
| 環境 | 選択する場面 | ファイル拡張子 |
|---|---|---|
RhinoPython(rhinoscriptsyntax + RhinoCommon) | 新しいスクリプトのデフォルトです。エコシステムが充実しており、読みやすく、RhinoCommon に完全にアクセスできます。 | .py |
| RhinoScript(VBScript) | 既存の .rvb/.vbs ファイルの保守や、VBA/COM との連携に使います。 | .rvb、.vbs |
| Script Editor 経由の RhinoCommon(C#/.NET) | パフォーマンスが重要なループ、複雑なジオメトリ、.NET ライブラリの活用に使います。 | .cs |
| コマンドマクロ | 既存の Rhino コマンドだけを使う単純な一連の操作に使います。ロジックは含みません。 | toolbar/alias |
マクロはスクリプトではありません。コマンドラインに入力する文字列です(例:! _-Line 0,0,0 10,0,0 _Enter)。変数、ループ、条件分岐が必要になった時点で、スクリプトを使ってください。
前提条件
- Rhino 7 以降(Rhino 8 を強く推奨します。統合 Script Editor では、1 つのウィンドウで Python 3、VB、C# を使用できます)。
- Script Editor:
_ScriptEditor(Rhino 8)、または_EditPythonScript/_EditScript(旧バージョン)と入力します。 - 保存したファイルをコマンドラインから実行するには、
_-RunPythonScript、または_LoadScript+_RunScriptを使います。
基本パターン
Python:最小限のひな形
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def main():
obj_id = rs.GetObject("Select a curve", filter=rs.filter.curve, preselect=True)
if not obj_id:
return
length = rs.CurveLength(obj_id)
print("Length: {0:.4f}".format(length))
if __name__ == "__main__":
main()
Python:RhinoCommon を直接使用する
import Rhino
import scriptcontext as sc
doc = sc.doc # Rhino.RhinoDoc.ActiveDoc
tol = doc.ModelAbsoluteTolerance
circle = Rhino.Geometry.Circle(Rhino.Geometry.Point3d(0, 0, 0), 5.0)
curve_id = doc.Objects.AddCircle(circle)
doc.Views.Redraw()
VBScript:最小限のひな形
Option Explicit
Call Main()
Sub Main()
Dim strObject
strObject = Rhino.GetObject("Select a curve", 4) ' 4 = curve filter
If IsNull(strObject) Then Exit Sub
Rhino.Print "Length: " & Rhino.CurveLength(strObject)
End Sub
カスタムフィルターを使ったオブジェクトの選択(Python、RhinoCommon)
import Rhino
import scriptcontext as sc
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt("Select breps")
go.GeometryFilter = Rhino.DocObjects.ObjectType.Brep
go.SubObjectSelect = False
go.GetMultiple(1, 0)
if go.CommandResult() != Rhino.Commands.Result.Success:
pass
else:
ids = [go.Object(i).ObjectId for i in range(go.ObjectCount)]
手順ごとのワークフロー
多数のオブジェクトをすばやく一括変更する
- 再描画を無効にします:
rs.EnableRedraw(False)。 - 変更を 1 つの取り消し記録で囲みます:
undo = doc.BeginUndoRecord("My Op")…doc.EndUndoRecord(undo)。 - ループ内では RhinoCommon を直接使います(
rhinoscriptsyntaxのオーバーヘッドを省きます)。 - クラッシュでビューポートがフリーズしたままにならないよう、
try/finally内で再描画を有効にし、doc.Views.Redraw()を呼び出します。
チームメイトにスクリプトを配布する
.py/.rvbファイルをディスク上の任意の場所に保存します。- Rhino が名前でスクリプトを見つけられるよう、フォルダーを
Options → Files → Search pathsに追加します。 - ツールバーボタンまたはエイリアスを作成し、マクロに次のいずれかを設定します。
- Python:
! _-RunPythonScript "MyScript.py" - RhinoScript:
! _-LoadScript "MyScript.rvb" _-RunScript MySubName
- Python:
- 先頭の
!は実行中のコマンドをキャンセルします。-はコマンドをスクリプト(ダイアログなし)モードで実行します。
Rhino の起動時にコードを実行する
.rvb/.pyファイルを検索パスに配置します。Tools → Options → RhinoScript(またはPython)→ Startup リストに追加します。ファイルはセッションごとに 1 回実行されます。
注意点
rhinoscriptsyntaxは GUID を返し、RhinoCommon はオブジェクトを返します。 混在して使っても問題ありませんが、doc.Objects.Find(guid)がrs.*の ID からRhinoObjectへの橋渡しになります。- 座標の形式はサーフェスによって異なります。 Python では
(x, y, z)タプルまたはRhino.Geometry.Point3dを使い、VBScript では3要素のArray(x, y, z)を使います。COM 経由で Python のリストを VBScript ヘルパーに渡してはいけません。 - VBScript ではデフォルトで
Option Explicitが無効です。 タイプミスをしても、黙って新しい変数が作成されます。.rvbファイルの先頭には必ずOption Explicitを追加してください。 - VBScript にはブロックスコープがありません。
Sub内のすべてのDimは、プロシージャの先頭に繰り上げられます。ループカウンターはスコープ外にも残ります。 - VBScript では
Nothing、Empty、Nullはそれぞれ異なる値です。Rhino.GetObjectの失敗にはIsNull、未初期化のVariantにはIsEmpty、オブジェクト参照にはIs Nothingを使ってください。 - 括弧によって VBScript の呼び出しの意味が変わります。
Call Foo(a, b)とFoo a, bは有効ですが、Foo(a, b)(Callなしで括弧あり)はSubの呼び出しではありません。複数引数のSubでは構文エラーになり、単一引数の場合は強制的にByValになります。 - 許容差はドキュメントごとに異なります。
0.001をハードコードせず、必ずdoc.ModelAbsoluteToleranceを読み取ってください。ユーザーは mm、m、インチなど、さまざまな単位で作業しています。 - 長いループでは
Rhino.RhinoApp.EscapeKeyPressedを確認し、ユーザーがキャンセルできるようにしてください。 そうしないと、Rhino がフリーズしたように見えます。 - GUID 文字列と
System.Guidは別のものです。rhinoscriptsyntaxはどちらも受け付けますが、RhinoCommon ではSystem.Guidが必要です。必要に応じてSystem.Guid(str_id)で変換してください。 - 高頻度で繰り返すループ内では
doc.Views.Redraw()を呼び出さないでください。 再描画の切り替えはループの外で一度だけ行ってください。 .rvbは、Rhino 固有の拡張子に変更した.vbsファイルにすぎません。 Rhino のLoadScriptが認識できるようにするためのものです。VBScript エンジンは同じです。- 古い Rhino 8 ビルドには
Rhino.RhinoApp.IsHeadlessが存在しない場合があります。getattr(Rhino.RhinoApp, "IsHeadless", None)を使い、使用前にNoneでないことを確認してください。フォールバックとしてヒューリスティック(例:sc.doc.Views.Count == 0)を使うか、GUI があるものとして扱ってください。 RhinoMathはRhino.DocObjects.RhinoMathではなくRhino.RhinoMathにあります。Rhino.DocObjects.RhinoMathにアクセスするとAttributeErrorが発生します。doc.Objects.AddBrep()は失敗するとSystem.Guid.Emptyを返します。 Rhino 8 CPython ではSystem名前空間を直接インポートできない場合があります。戻り値を文字列として確認してください:str(obj_id) == "00000000-0000-0000-0000-000000000000"。rhinoscriptsyntaxには型スタブがありません。 静的解析ツール(Pylance/Pyright)はimport rhinoscriptsyntax as rsを解決できないと警告します。モジュールは Rhino の実行時には常に利用できるため、インポート行に# type: ignoreを付けて抑制してください。- Python 標準ライブラリのモジュールと同じ名前をスクリプトに付けないでください(例:
random.py、math.py、os.py)。IronPython 2.7(_-RunPythonScript)は標準ライブラリより先にスクリプトのディレクトリを検索するため、標準ライブラリ内でのimport random(例:tempfileは内部でrandomをインポートします)も、代わりに自分のファイルを見つけてCannot import name <X>で失敗します。CPython 3(rhinocode)には影響ありません。スクリプト名を変更するか、名前が衝突するモジュールを読み込むモジュールのインポートを避けてください。 - Em ダッシュなどの非 ASCII 文字は、
_-RunPythonScript(IronPython 2.7)を気付かれないまま壊します。rhinocode scriptは CPython 3(デフォルトで UTF-8)を使うため、同じファイルがそちらでは動作し、問題が分かりにくくなります。IronPython 2.7 では、最初に問題となるバイト位置でSyntaxError: Non-ASCII character '\xe2'が発生します。最もよくある原因は em ダッシュ です(多くのエディターが--を自動的に--に変換します)。両方のランタイムで実行する必要があるすべてのスクリプトの1行目に# -*- coding: utf-8 -*-を追加し、字形上の文字を ASCII 相当の文字に置き換えてください:em ダッシュは--、矢印は->、乗算記号はx。
トラブルシューティング
| 症状 | 対処方法 |
|---|---|
rs.GetObject がすぐに None を返す | ユーザーが Escape キーを押したか、filter がすべてを除外しています。rs.filter.* フラグを確認してください。 |
| 名前を指定して実行すると「Unable to find script」と表示される | フォルダーが Options → Files → Search paths に含まれていません。 |
VBScript で座標に対して Type mismatch が発生する | 2 要素の配列を渡しています。Rhino では 3 要素の Array(x, y, z) が必要です。 |
Python で ImportError: No module named Rhino が発生する | Rhino の外部で CPython を実行しています。RhinoCommon を利用できるのは、Rhino に組み込まれた Python のみです(読み取り専用のファイル操作には rhino3dm を使用できます)。 |
| 作成したジオメトリが表示されない | doc.Views.Redraw() を呼び出していないか、rs.EnableRedraw(False) を再度有効にしていません。 |
| 一括処理のオブジェクトが最後の 1 つしか元に戻せない | 一括処理を BeginUndoRecord / EndUndoRecord で囲んでください。 |
| スクリプト単体では動作するのに、スタートアップスクリプトとしては失敗する | スタートアップスクリプトはドキュメントが開く前に実行されます。早めに終了するか、sc.doc is None の場合はドキュメントに依存する処理をスキップしてください。 |
rs.Command("...") が False を返す | マクロ文字列の形式が正しくありません。先頭に ! と - を付け、各プロンプトの末尾に _Enter または値を指定してください。 |
AttributeError: type object 'RhinoApp' has no attribute 'IsHeadless' | このプロパティは、後の Rhino 8 ビルドで追加されました。getattr(Rhino.RhinoApp, "IsHeadless", None) を使用し、None の場合に備えて処理してください。 |
rhinocode script がスクリプトパス以降の引数を無視する | rhinocode は追加のトークンをファイル URI に連結します。一時ファイルまたは Rhino のダイアログを介してデータを渡してください。references/macros-and-loading.md を参照してください。 |
_-RunPythonScript の実行時に、標準ライブラリ内(例:tempfile、os)で Cannot import name <X> が発生する | スクリプトのファイル名が標準ライブラリのモジュール名と競合しています(例:random.py は random の名前を隠します)。IronPython 2.7 は標準ライブラリより先にスクリプトのディレクトリを検索します。スクリプト名を変更するか、競合するモジュールを読み込む import を削除し、直接的な代替手段に置き換えてください(例:import tempfile の代わりに os.environ を使って %TEMP% を読み取る)。 |
SyntaxError: Non-ASCII character '\xe2' ... but no encoding declared | IronPython 2.7(_-RunPythonScript)が、em dash などの文字に遭遇しています。1 行目に # -*- coding: utf-8 -*- を追加するか、その文字を置き換えてください。em dash は --、矢印は -> に置き換えます。同じファイルでも rhinocode(CPython 3)では問題が発生しません。 |
参考資料
- references/rhinoscriptsyntax-cheatsheet.md — カテゴリ別にまとめた、よく使う
rs.*関数。 - references/rhinocommon-map.md — タスクごとにインポートする名前空間。
- references/macros-and-loading.md — コマンドラインのマクロ構文、
LoadScript/RunScript、検索パス。 - references/vbscript-quirks.md — RhinoScript で注意が必要な VBScript 固有の問題。
上流のドキュメント
- RhinoScript の概要:https://docs.mcneel.com/rhino/8/help/en-us/information/rhinoscripting.htm
- 開発者向けハブ:https://developer.rhino3d.com/
- RhinoCommon API インデックス:https://mcneel.github.io/rhinocommon-api-docs/api/RhinoCommon/html/R_Project_RhinoCommon.htm
- サンプルスクリプトのリポジトリ:https://github.com/mcneel/rhino-developer-samples/tree/8/rhinoscript
コメント
Markdown 対応