GhPythonコンポーネント間でPythonオブジェクトをやりとりする

3 min read読了の目安(約2800字

はじめに

GhPythonでコンポーネントを作る場合、1つのコンポーネント内でプログラムを完結させることもできますが、インプットが増えすぎて管理しにくくなったり、プラグイン化したときの汎用性がなくなったりすることがあります。
かといって、複数のコンポーネントに分けてGhPythonコンポーネント間でデータをやりとりするために、毎回リストやツリーに変換すると結果的に余計な処理が増えたりコードがわかりにくくなってしまいます。
今回はその解決策として、PythonのPythonのディクショナリをGhPythonコンポーネント間でやり取りする方法をご紹介します。

やりとりするデータ

例として、数字・ポイント・ラインのリストをディクショナリにしてデータを送ってみようと思います。

import Rhino.Geometry as rg

ids = [i for i in range(5)]
points = [rg.Point3d(i,0,0) for i in range(4)]
lines = [rg.Line(rg.Point3d(i,0,0),rg.Point3d(i+1,1,0)) for i in range(3)]

data = {}

data["ids"] = ids
data["points"] = points
data["lines"] = lines

result = data

このようなディクショナリになります。

{
    'lines': [<Rhino.Geometry.Line object at 0x000000000000009E [0,0,0,1,1,0]>, <Rhino.Geometry.Line object at 0x000000000000009F [1,0,0,2,1,0]>, <Rhino.Geometry.Line object at 0x00000000000000A0 [2,0,0,3,1,0]>], 
    'points': [<Rhino.Geometry.Point3d object at 0x00000000000000A1 [0,0,0]>, <Rhino.Geometry.Point3d object at 0x00000000000000A2 [1,0,0]>, <Rhino.Geometry.Point3d object at 0x00000000000000A3 [2,0,0]>, <Rhino.Geometry.Point3d object at 0x00000000000000A4 [3,0,0]>], 
    'ids': [0, 1, 2, 3, 4]
}

このままアウトプットすると?

このままアウトプットすると、このようにkeyのリストとして出力されてしまいます。

クラスにしてアウトプットする

持っていきたいデータをクラスの変数にしてアウトプットすると、クラスのまま持っていくことができデータを展開することができます。

import Rhino.Geometry as rg

ids = [i for i in range(5)]
points = [rg.Point3d(i,0,0) for i in range(4)]
lines = [rg.Line(rg.Point3d(i,0,0),rg.Point3d(i+1,1,0)) for i in range(3)]

data = {}

data["ids"] = ids
data["points"] = points
data["lines"] = lines

class result:
    pass
    
result.data = data

受け取った先のコンポーネントで展開してみると、しっかりオブジェクトが入っていることがわかります。

lines = result.data["lines"]
points = result.data["points"]
ids = result.data["ids"]

注意点

rhinoscriptsyntaxでオブジェクトを作る場合、GUIDオブジェクトとして作ると持っていけません。
例えば、先ほどのラインを下記のようにrhinoscriptsyntaxで作るとGUIDオブジェクトになるのですが、その状態でクラスに入れて持っていこうとすると、
1. Solution exception:オブジェクト参照がオブジェクト インスタンスに設定されていません。
というエラーが出てしまいます。
bakeされていないGUIDオブジェクトはコンポーネント内でしか参照できないからなのでしょうか?
詳しい方いたら教えてください。

import rhinoscriptsyntax as rs
lines = [rs.AddLine(rg.Point3d(i,0,0),rg.Point3d(i+1,1,0)) for i in range(3)]

さいごに

クラスで持っていくことができれば、いちいちリストごとにアウトプットをつくったりする必要なく、1つのデータでやり取りできるので便利です。
ほかにもディクショナリに[]をつける方法もあるようですが、GhPython内でしか動かないコードになってしまう可能性があるので今回は割愛しました。
参考のページにはそちらの方法も載っています。

参考

How to access the exported dictionary in ghPython?