Pivy/ja

PivyはFreeCADで使われている3DレンダリングライブラリであるCoin3d用のPythonのバインディングライブラリです. 実行中のPythonインタプリタにインポートするとFreeCADの3DビューアーなどのCoin3dシーングラフと直に対話処理を行ったり、新しい3Dビューアーを作成することさえできます. Pivyは標準のFreeCADインストールに同梱されています.

Coinライブラリはいくつかに分割されています. Coin自体はシーングラフの操作を担い、Windowsといった複数のGUIシステム用のパッケージがありますが私たちの場合はQt用になります. これらの分割されたモジュールもシステム上に存在する場合にはPivyから利用することができます. Coinモジュールは常駐していて自由に利用することができます. 既にFreeCADによって行われているので3D表示をどのインターフェイスに紐付けするのか気にする必要はありません. 私たちがやらなければならないのは以下のコマンドを実行することだけです：

シーングラフへのアクセスと変更
典型的なCoinシーンがどの様に構成されているかはシーングラフページで見ました. FreeCADの3Dビューに表示されているものは全てCoinシーングラフであり、同じやり方で構成されています. ルートのノードが一つあり、画面上のオブジェクトは全てその子ノードです.

FreeCADでは3Dビューシーングラフのルートノードに簡単にアクセスすることができます：

こうするとルートノードが返されます.

シーンの直下の子ノードを調べることもできます.

SoSeparatorsやSoGroupsといったこれらノードは自身の子ノードを持ちます. 利用可能なCoinオブジェクトの全リストはCoin公式ドキュメントにあります.

今度はシーングラフに何か追加してみましょう. すてきな赤い立方体を追加してみることにしましょう：

（すてきな）赤い立方体ができました. 以下を試してみてください：

わかったでしょうか？実行中であっても全てのものに対してアクセスと変更を行うことができるのです. 再計算や再描画は必要ありません. Coinが全て面倒を見てくれます. 物体のシーングラフへの追加、プロパティの変更、物体の非表示、一時的なオブジェクトの表示、何でもできます. もちろん3Dビューに関係したことだけですが. この表示はFreeCADがファイルを開いた時とオブジェクトが必要とした時に再計算されます. 従って既存のFreeCADオブジェクトの外見を変更した場合、その変更はオブジェクトが再計算されるかファイルを再度開いた瞬間に失われます.

スクリプトでシーングラフを操作する場合の鍵となるのは必要な際に追加したノードの特定のプロパティにアクセスできるということなのです. 例えば立方体を動かしたいとしましょう. 自作のノードにSoTranslationノードを追加することになるでしょう. ちょうどこんな具合です：

OpenInventorのシーングラフではその順番が重要であるということを思い出してください. ノードは以降のノードに影響を与えます. color red、cube、color yellow、sphere とすれば赤い立方体と黄色い球が表示されます. もし今、既存の自作ノードに移動を追加すると移動は立方体の後になり、立方体に影響を与えません. 上記のように作成時に挿入しておけば次のようにできます：

trans.translation.setValue([2,0,0])

こうすると立方体が2単位分、右に移動します. 最後に何かを取り除くには次のようにします：

sg.removeChild(myCustomNode)

コールバック機能の使用
コールバック機能とはCoinライブラリの様な現在使用しているライブラリがコールバック、つまり現在実行中のPythonオブジェクトから特定の関数を呼び出すことを可能にするシステムのことです. これは非常に便利です. これを使うとシーンで何か特定のイベントが起きた場合にCoinからあなたへ通知することができるのです. Coinでは色々なものを監視することができます. マウスの位置、マウスボタンのクリック、キーボードのキーが押されたかどうか、まだまだ他にもあります.

FreeCADではそういったコールバックを簡単に使うための機能があります：

class ButtonTest: def __init__(self): self.view = FreeCADGui.ActiveDocument.ActiveView self.callback = self.view.addEventCallbackPivy(SoMouseButtonEvent.getClassTypeId,self.getMouseClick) def getMouseClick(self,event_cb): event = event_cb.getEvent if event.getState == SoMouseButtonEvent.DOWN: print "Alert!!! A mouse button has been improperly clicked!!!" self.view.removeEventCallbackSWIG(SoMouseButtonEvent.getClassTypeId,self.callback) ButtonTest

コールバックが起きた時にもオブジェクトは実行され続けなければならないのでコールバックはオブジェクトで初期化されなけれればなりません. 利用可能なイベントとパラメータの全リストまたはCoin公式ドキュメントを参照してください.

ドキュメント
残念ながらPivy自体にはちゃんとしたドキュメントがまだありません. しかしPivyはCoinと正確に対応するのでC++スタイルをPythonスタイルに読み替えれば（例えばSoFile::getClassTypeIdはPivyではSoFile.getClassIdとなるでしょう）Coinドキュメントをリファレンスとして安全に使用できます.