Pivy ist eine Python-Bindungsbibliothek für Coin, die 3D-Rendering-Bibliothek, die in FreeCAD verwendet wird, um Dinge in einer 3D-Ansicht anzuzeigen. Coin ist eine quelloffene Implementierung der "Open Inventor"-Spezifikation zur Handhabung von Grafiken. Daher beziehen sich in FreeCAD die Begriffe "Pivy", "Coin" oder "Open Inventor" im Wesentlichen auf die gleiche Sache.
Wenn Pivy in einen laufenden Python-Interpreter importiert wird, können wir direkt mit jedem laufenden Coin-Szenengraph kommunizieren, wie z. B. der 3D-Ansicht, oder sogar neue zu erstellen. Pivy ist nicht erforderlich, um FreeCAD zu kompilieren, aber es wird zur Laufzeit benötigt, wenn auf Python basierende Arbeitsbereiche ausgeführt werden, die Formen auf dem Bildschirm erstellen, wie die Arbeitsbereiche Draft und BIM. Aus diesem Grund wird Pivy normalerweise bei der Installation einer FreeCAD-Distribution mitinstalliert.
Die Coin Bibliothek ist in mehrere Teile unterteilt, Coin selbst zur Manipulation von Szenegraphen und Bindungen für verschiedene GUI Systeme wie Windows und Qt. Falls auf dem System vorhanden, sind diese Module auch für Pivy verfügbar. Das Coin Modul ist immer vorhanden, und wir werden es sowieso verwenden, da wir uns nicht darum kümmern müssen, unsere 3D Darstellung in irgendeiner Schnittstelle zu verankern, was bereits von FreeCAD getan wird. Alles, was wir tun müssen, ist dies:
from pivy import coin
Wir haben auf der Szenengraph-Seite gesehen, wie eine typische Coin-Szene organisiert ist. Alles, was in einer 3D-Ansicht erscheint, ist ein Coin-Szenegraph, der auf die gleiche Weise organisiert ist. Wir haben einen Wurzelknoten, und alle Objekte auf dem Bildschirm sind seine Unterelemente.
FreeCAD hat eine einfache Möglichkeit, auf den Wurzel-Knoten eines 3D-Ansicht-Szenengraphs zugreifen:
sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
print(sg)
Dies gibt den Wurzel-Knoten aus:
<pivy.coin.SoSelection; proxy of <Swig Object of type 'SoSelection *' at 0x360cb60> >
Wir können die unmittelbaren Unterelemente unserer Szene untersuchen:
for node in sg.getChildren():
print(node)
Einige dieser Knoten, wie SoSeparator oder SoGroup, können selbst Unterelemente haben. Die vollständige Liste der verfügbaren Coin-Objekte findet man in der offiziellen Coin-Dokumentation.
Lasst uns versuchen, jetzt etwas zu unserem Szenengraph hinzuzufügen. Wir fügen einen schönen roten Würfel ein:
col = coin.SoBaseColor()
col.rgb = (1, 0, 0)
cub = coin.SoCube()
myCustomNode = coin.SoSeparator()
myCustomNode.addChild(col)
myCustomNode.addChild(cub)
sg.addChild(myCustomNode)
Versuchen wir Folgendes:
col.rgb = (1, 1, 0)
Wie du siehst, ist alles nach wie vor zugänglich und gleichzeitig veränderbar. Du musst nichts neu berechnen oder neu zeichnen, Coin kümmert sich um alles. Du kannst deinem Szenegraphen Sachen hinzufügen, Eigenschaften ändern, Sachen ausblenden, temporäre Objekte anzeigen, alles. Dies betrifft natürlich nur die Darstellung in der 3D-Ansicht. Diese Anzeige wird von FreeCAD bei geöffneter Datei neu berechnet, und wenn ein Objekt neu berechnet werden muss. Wenn du also den Aspekt eines bestehenden FreeCAD-Objekts änderst, gehen diese Änderungen verloren, wenn das Objekt neu berechnet wird oder wenn du die Datei erneut öffnest.
Wie bereits erwähnt, ist in einem openInventor-Szenegraphen die Reihenfolge wichtig. Ein Knoten beeinflusst, was als nächstes kommt. Wenn wir zum Beispiel die Möglichkeit haben wollen, unseren Würfel zu bewegen, müssen wir einen SoTranslation-Knoten vor dem Würfel hinzufügen:
col = coin.SoBaseColor()
col.rgb = (1, 0, 0)
trans = coin.SoTranslation()
trans.translation.setValue([0, 0, 0])
cub = coin.SoCube()
myCustomNode = coin.SoSeparator()
myCustomNode.addChild(col)
myCustomNode.addChild(trans)
myCustomNode.addChild(cub)
sg.addChild(myCustomNode)
Um unseren Würfel zu bewegen, können wir jetzt folgendes tun:
trans.translation.setValue([2, 0, 0])
Das Entfernen erfolgt schließlich mit:
sg.removeChild(myCustomNode)
Eine Rückruffunktion ist ein System, das es einer Bibliothek, wie z. B. unserer Coin-Bibliothek, erlaubt, sie zurückzurufen, d. h. eine bestimmte Funktion von deinem aktuell laufenden Python Objekt aus aufzurufen. Auf diese Weise kann Coin darüber informieren, dass ein bestimmtes Ereignis in der Szene aufgetreten ist. Coin kann sehr unterschiedliche Dinge beobachten, wie z. B. Mausposition, Mausklicks, das Drücken von Tasten auf der Tastatur und vieles mehr.
FreeCAD bietet eine einfache Möglichkeit, solche Rückrufe zu verwenden:
from pivy import coin
class ButtonTest:
def __init__(self):
self.view = FreeCADGui.ActiveDocument.ActiveView
self.callback = self.view.addEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.getMouseClick)
def getMouseClick(self, event_cb):
event = event_cb.getEvent()
if event.getState() == coin.SoMouseButtonEvent.DOWN:
print("Alert!!! A mouse button has been improperly clicked!!!")
self.view.removeEventCallbackPivy(coin.SoMouseButtonEvent.getClassTypeId(), self.callback)
ButtonTest()
Die Rückmeldung muss von einem Objekt initiiert werden, da dieses Objekt zum Zeitpunkt der Rückmeldung noch laufen muss. Siehe auch die komplette Liste von möglichen Ereignissen und deren Parametern, oder die offizielle Coin-Dokumentation.
Leider verfügt Pivy nicht über eine eigene Dokumentation. Da es sich jedoch um einen genauen Wrapper der Coin-Bibliothek handelt, kann zur Information die C++-Referenz gelesen werde. In diesem Fall muss man den C++-Klassennamensstil in Python-Stil übersetzen.
In C++:
SoFile::getClassTypeId()
In Pivy:
SoFile.getClassId()
Diese Links stellen die Referenz-Dokumentation für Coin v3.x dar. Die Unterschiede zur v4.x sind minimal, daher sind sie trotzdem hilfreich.