Python Object Tree?

In diesem Forum Fragen und Diskussionen in Deutsch
Forum rules
Foren-Regeln und hilfreiche Informationen

WICHTIG: Bitte zuerst lesen, bevor Sie posten
ubit
Posts: 57
Joined: Mon Dec 15, 2014 8:58 am

Python Object Tree?

Postby ubit » Thu Feb 19, 2015 10:29 am

Hi,

ich habe mich jetzt totgesucht, aber irgendwie finde ich nichts. Ich möchte die Baumstruktur des aktuellen Dokuments "abgrasen", finde aber kein Funktionalität dafür.

App.ActiveDocument.Objects ist eine Liste aller Objekte - allerdings "flach", also ohne die Hierachieinformationen.

Jedes Objekt darin hat eine "OutList" woraus ich die Kinder ermitteln kann.

Soweit so gut. Nur: Wie finde ich die "Wurzel" des Baums, also den Knoten "über" den obersten Einträgen in der Baumstruktur? Natürlich könnte ich App.ActiveDocuments.Objects komplett durchsuchen und alle Objekte die eine leere "InList" haben (also keine "Väter") sind dann die gesuchten Objekte. Das ist aber doof, weil langsam.

Gibt es da keine sinnvollere API mit der ich direkt auf die Baumstruktur (und möglichst NUR diese) zugreifen kann? Sowas braucht FreeCAD doch intern für das Widget welches den Baum darstellt auch, oder? Muss es also irgendwo geben.

Ciao, Udo
jreinhardt
Posts: 329
Joined: Mon Sep 09, 2013 6:08 pm

Re: Python Object Tree?

Postby jreinhardt » Thu Feb 19, 2015 10:36 am

Meines Wissens gibt es nichts direkteres als die Objects mit ihren OutLists. Und so langsam ist es nicht, wenn richtig implementiert hoechstens linear in der Anzahl an Objekten, und die ist selbst bei sehr komplexen Modellen nicht allzu gross. Die Rechenzeit die dafuer draufgeht, wird durch Geometrieoperationen in der Regel voellig dominiert. Da wuerde ich mir keine allzu grossen Sorgen machen.
BOLTS, standard parts library for FreeCAD Thread, Help with Translation
ubit
Posts: 57
Joined: Mon Dec 15, 2014 8:58 am

Re: Python Object Tree?

Postby ubit » Thu Feb 19, 2015 10:56 am

Ich möchte die Baumstruktur abgrasen und daraus eine Art Stückliste erstellen. Und das bei komplexen Modellen mit sehr vielen Teilen. Das dauert in Python schon eine ganze Weile, wenn es viele Objekte sind.

Wundert mich jetzt doch sehr, dass so eine zentrale Komponente der Benutzeroberfläche und des Konzepts von FreeCAD wie die Objekthierarchie keine Abbildung in der API finden soll.

Ciao, Udo
ickby
Posts: 2985
Joined: Wed Oct 05, 2011 7:36 am

Re: Python Object Tree?

Postby ickby » Thu Feb 19, 2015 11:12 am

Wundert mich jetzt doch sehr, dass so eine zentrale Komponente der Benutzeroberfläche und des Konzepts von FreeCAD wie die Objekthierarchie keine Abbildung in der API finden soll.
Es gibt keine baumförmige Objekthierarchie in FreeCAD, die Objekte sind in einem gerichteten nicht-circularen Graphen organisiert (directed acyclic graph - DAG). Die Baumansicht ist nur eine Hilfsstruktur um eine (unzureichende) Visualisierung zu geben. Entsprechend geben die in- und outlist auch keine Baumstrucktur wieder sondern den Graphen. Um an den Baum zu kommen must du die Viewprovider und deren funktion claimChildren nutzen, diese wird verwended um den Baum aufzustellen. Sie gibt für jedes Object diejenigen Objekte wieder die unter ihm gruppiert werden sollen.

Du hast mehrere Möglichkeiten:
1. mittels claimChildren() der Viewprovider den Baum "abgrasen"
2. Du kannst dir das Qt TreeWidget holen und dann die sehr umfangreiche QT Api verwenden um die Baumstruktur zu durchforsten
3. Mit dem Graphen arbeiten. Dann musst du aber damit leben das das kein Baum ergibt
User avatar
shoogen
Posts: 2823
Joined: Thu Dec 01, 2011 5:24 pm

Re: Python Object Tree?

Postby shoogen » Thu Feb 19, 2015 11:30 am

von claimChildren und dem TreeViewwürde ich abraten und stattdessen die OutList (s) durchgehen.
ubit
Posts: 57
Joined: Mon Dec 15, 2014 8:58 am

Re: Python Object Tree?

Postby ubit » Thu Feb 19, 2015 11:52 am

shoogen wrote:von claimChildren und dem TreeViewwürde ich abraten und stattdessen die OutList (s) durchgehen.
Warum? BTW: Den ViewProvider finde ich irgendwie nicht.

Warum ist das eigentlich kein Baum bzw. was ist im Bezug auf FreeCAD der Unterschied zwischen Baum und DAG? Ich baue doch normalerweise eine "reinrassige" Hierarchie auf, wenn ich Boolesche Operationen mache oder Groups einsetze und Objekte darin zusammenfasse. Wie erzeugt man einen DAG der KEIN Baum ist? Kann mir dafür mal jemand ein Beispiel "konstruieren"? Meine Scripte sollten ja dann am Besten auch mit solchen Nicht-Bäumen sinnvolle Ergebnisse liefern.

BTW: Auch ein DAG muss doch irgendwo "aufgehängt" sein, also einen oder mehrere Root-Knoten haben. Wie finde/identifiziere ich die denn?

Also neue Frage: Wie und wo finde ich diesen DAG und wie kann ich da navigieren? "Schleifen" sollte es ja keine geben - möglicherweise aber Objekte die mehrfach auftauchen?

Ciao, Udo
User avatar
shoogen
Posts: 2823
Joined: Thu Dec 01, 2011 5:24 pm

Re: Python Object Tree?

Postby shoogen » Thu Feb 19, 2015 12:02 pm

Den DAG hab ich auch noch nicht gefunden. Um den aufzufassen muss man wohl erst durch eine Menge boost durch.
Einen groben Überblick vermittelt der DepedencyGraph. (Und auch die Funktion um den zwecks Darstellung zu exportieren)
Also das mit der Wurzel würde ich nicht so ernst nehmen. Soweit ich weiß liegen die Objekte erst mal gleichwertig nebeneinander. Root ist für mich ein Objekt das keine Objekte in seiner InList hat.

PS: wenn du das mit dem Graphen durchblickt hast, könntest du mir helfen issue #1957 zu implementieren. ;)
ubit
Posts: 57
Joined: Mon Dec 15, 2014 8:58 am

Re: Python Object Tree?

Postby ubit » Thu Feb 19, 2015 12:31 pm

Hi,

bleibt dabei, dass ich mich wundere, warum sowas zentrales wie der DAG nicht zugreifbar ist *g*

Helfen werde ich Dir wohl nicht können. Erstmal will ich mein "kleines" Projekt auf die Reihe bekommen.

Ich beschreib' mal kurz, was ich vor habe:

Angefangen hat alles damit, dass ich mir einen eigenen 3D-Drucker konstruieren möchte.... Da habe ich dann festgestellt, dass das mit FreeCAD wohl zu gehen scheint, aber unglaublich aufwändig ist. Daher habe ich mir gedacht, ich mache FreeCAD erstmal zu einem für mich brauchbaren Werkzeug.

Ich möchte eine neue Workbench - Arbeitstitel "RepRap Workbench" - bauen.

Diese Workbench soll es erlauben "Standardobjekte" zu erzeugen und zu platzieren. Also z.B. Schrittmotoren, Schrauben, Muttern, Unterlegscheiben etc.

Die Objekte werden in einer sqlite Datenbank definiert und über FeaturePython in FreeCAD eingefügt.

Alle so erzeugten Objekte haben ein Attribut "BOM=true/false" der darüber auskunft gibt ob sie in die Stückliste gehören oder nicht.

Alle so erzeugten Objekte haben ein Attribut "Comment" mit dem man Kommentare für die Stückliste erzeugen kann.

Neben den eigentlichen Objekten soll es "Bearbeitungen" geben, also z.B. Bohrungen und Gewinde die man typischerweise von anderen Objekten "abzieht".

Platziert werden die Objekte über einen "Placer" bei dem man per Selection zunächst auswählt wo ein Objekt drangepappt werden soll und dann über einen Dialog die genaue Position und Orientierung festlegt. Wenn man also z.B. eine viereckige Fläche anklickt zur Platzierung, bietet der Dialog die 4 Ecken an sowie die Orientierung entsprechend der Normalen sowie "umgedreht". Zusätzlich kann man lokale Offsets X/Y/Z und eine lokale Drehung angeben - relativ zu der Platzierung. Im Prinzip ScrewMaker Macro mit etwas zusätzlichem Dialog drumherum.

Man soll die Objekte in unterschiedlichem Detaillierungsgrad darstellen können. Noch ein Attribut.

Am Ende soll man eine Stückliste erstellen können (Spreadsheet Workbench) in der sowohl die Objekte als auch die Bearbeitungen aufgelistet werden inkl. der ggf. hinzugefügten Kommentare.

Dazu ein paar Hilfsfunktionen um z.B. die Detailierung in einem (Teil-)Graph umschalten zu können zwischen "ich arbeite" und "ich will sehen wie es wirklich aussieht".

Bisher habe ich da nur ein paar Baustellen:

Datenbankerstellung und Datenbankzugriff funktioniert.

Mögliche Positionen aus Selection herausfischen funktioniert, Orientierung und lokale Transformation fehlen noch.

Suchfunktion/Dialog für die Datenbank funktioniert.

Objekte erstellen funktioniert aktuell für Unterlegscheiben, 6-Kant-Muttern und ein paar Schraubentypen. More ist einfach Fleißarbeit.

Objekte auflisten funktioniert im Prinzip.

Stückliste in Spreadsheet eintragen funktioniert im Prinzip (momentan werden nur die Namen aufgelistet).

Das Ganze ist aktuell eine Sammlung von einzelnen Scripten/Macros die noch keinen Zusammenhang haben und noch keine Workbench bilden. Ich muss das noch alles zusammenfügen, ein paar sinnvolle Erweiterungen machen die mir unterwegs so unterkommen und natürlich die eigentlichen Objekte implementieren.

Im Ergebnis sollte dann eine Kombination aus ScrewMaker, Bolts, Spreadsheet und eine Art "Simple-Assembly Workbench ohne Constraints" dabei herauskommen.

Ciao, Udo
ickby
Posts: 2985
Joined: Wed Oct 05, 2011 7:36 am

Re: Python Object Tree?

Postby ickby » Thu Feb 19, 2015 12:36 pm

BTW: Den ViewProvider finde ich irgendwie nicht.

Code: Select all

>>> App.ActiveDocument.ActiveObject.ViewObject
<View provider object at 00000000043C86E0>
>>> Gui.ActiveDocument.ActiveObject
<View provider object at 00000000043C86E0>
Warum ist das eigentlich kein Baum bzw. was ist im Bezug auf FreeCAD der Unterschied zwischen Baum und DAG
Ein Baum würde zu große Einschränkung mit sich bringen. Als einfaches Beispiel eines DAG der kein Baum ist:

1.Box erstellen
2.Box Spiegel
3.Box und Spiegelbild Fusionieren.

Das ergibt dann ein Object welches 2 Objecte referenziert welche beide wieder das gleiche dritte Referenzieren. Auch wenn in FreeCAD wohl selten genutzt funktioniert es z.B. zwei Objekte mit einem Tool zu bearbeiten, z.B. zwei Boxen mit dem gleichen Zylinder auszuschneiden. Das kann der Baum nicht mehr darstellen, da dann der Zylinder zwei Väter hat, ist aber ein gültiger DAG. Die zwei kann man dann wieder Fusionieren und so beliebig komplexe Graphen aufbauen. Das wird alles noch wichtier wenn assembly kommt oder die geplanten Expressions.
Auch ein DAG muss doch irgendwo "aufgehängt" sein, also einen oder mehrere Root-Knoten haben
Nein, muss er nicht. Du gehst von einer "linked list" aus, es gibt aber unzählige Möglichkeiten einen Graphen anders darzustellen. Z.B. mit edge und vertex lists. In FreeCAD ist er allerdings eine "linked list", wird dann zum verarbeiten aber in einen boost graph umgewandelt, welcher dann mit edge und vertex lists arbeitet.

Hinzu kommt das ein root objeckt nur für einen Baum definiert ist, nicht aber für einen DAG: Dort können mehrere Objekte die Eigenschaft eines Root Objektes haben und die einzelnen Pfade können dann sogar zusammenwachsen. Deshalb macht es keinen sinn Root Objekte separat zu speichern, eine Änderung im Graph könnte jederzeit neue Roots erschaffen bzw. alte zu nicht roots machen. Es ist daher müßig eine solche Liste zu bauen und aktuell zu halten.
Also neue Frage: Wie und wo finde ich diesen DAG und wie kann ich da navigieren?
Die Document Objects sind die Knoten (Vertex), die in/outlist gibt dir die Kanten (Edge) (beides nicht mit den FreeCAD topology datentypen Vertex und Edge zu verwechseln, diese namen sind in der Graphentheory so üblich). Das ist deine Datenstruktur. Wie du damit umgehst und welche Algorithmen man verwenden kann findest du dann in der allgemeinen Graphentheorie, da existieren reichlich Abhandlungen darüber.
"Schleifen" sollte es ja keine geben
Richtig
möglicherweise aber Objekte die mehrfach auftauchen
Nein, nur Objekte die mehrere Kanten haben. Es kann also sein das du beim gleichen Objekt mehrfach aufschlägst.
ubit
Posts: 57
Joined: Mon Dec 15, 2014 8:58 am

Re: Python Object Tree?

Postby ubit » Thu Feb 19, 2015 12:41 pm

Trotzdem muss es sowas wie (mehrere) Root-Knoten doch geben. Das Tree-View Widget stellt den Baum schließlich dar und das was ich suche sind die obersten Knoten in diesem TreeView. Bzw. halt alle Knoten des DAG die keine Einträge in ihrer InList haben. Klar kann ich mir die aus Doc.Objects heraussuchen, aber eine eingebaute C++-Funktion wäre sicherlich flotter.

Ciao, Udo