Datei von XML zu STL mit C++
-
Hallo Leute
Hab gerade in der Uni die Aufgabe bekommen, eine XML-Datei in eine STL-Datei umzuwandeln und soll ein eigenes Programm schreiben.
Ich bin Maschinenbauer und besitzte leider rudimentäre Kenntnisse über C++ und wollte daher euch um Hilfe bitten(eine Schleife kann ich schon schreiben).Ich hab mich schon über XML Parser schlau gemacht, sehe da aber leider nicht so durch.
Könnt ihr mir bitte helfen oder mir den richtigen Weg weisen.
Eine Dankeschön schon mal im vorraus.
-
Das musst Du wohl ein wenig genauer Beschreiben, ich weiss nämlich nicht was eine STL-Datei sein soll.
-
Zur genaueren Beschreibung
Die XML-Datei ist eine Schiffssection, in der Platten, Löcher, Cutouts und noch einiges mehr drin stehen.
Die Daten beinhalten die Eckpunkte der Platten, erzeugt vektoren, um die Kontur darzustellen und daraufhin werden Löcher reingemacht oder etwas anderes drauf.
Die STL-Datei halbiert die Platten. Die stellt alles mit Dreiecken dar. Außerdem benötigt diese Datei viel weniger informationen, um die Schiffssection wieder darzustellen.
Ich glaube zwar nicht, dass ich deine Frage beantwortet habe. Wenn also nicht, bitte etwas genauer.
-
- Muss es unbedingt C++ sein? Ich denk mal, dass dir z.B. C# sehr viel leichter fallen würde. Dank .NET hättest du XML dort auch schon out of the box verfügbar.
- Wo genau liegt jetzt dein Problem?
-
Es muss nicht C++ sein. Nur mit dem Programm kenne ich mich am besten aus.
Wenn du/ihr was besseres wisst, um das Problem besser und schneller zu lösen, dann bloß her damit.Mein Problem:
Ich weiß nicht, wie ich einem Programm sage: Nimm die Informationen raus(XML), die ich brauche und schreibe sie in ein STL-Format. Beim STL-Format könnte es auch sein, dass ich dem Programm den Quellcode vorgebeob das hilft, ist eine andere Frage, aber so ähnlich könnte das STL-Format am ende aussehen
solid plate
facet normal nx1 ny1 nz1
outer loop
vertex x1 y1 z1
vertex x2 y2 z2
vertex x4 y4 z4
endloop
endfacet
facet normal nx2 ny2 nz2
outer loop
vertex x2 y2 z2
vertex x3 y3 z3
vertex x4 y4 z4
endloop
endfacet
endsolid plate
-
Wie sieht denn das zu parsende XML aus?
Wieviel Programmiererfahrung hast du denn? Hast du überhaupt schonmal ein Programm geschrieben, das mit Dateien arbeitet!?
Dass du C++ als "Programm" bezeichnest, würd ich mal als Zeichen dafür werten, dass du bei einer anderen Sprache besser aufgehoben wärst
-
Das wäre eine einfach Platte
<Ship Version="1.3">
<Material Grade="Default" Density="7840" YoungsModulus="206000" PoissonRatio="0.3" YieldStress="220" UltimateStress="360"/><Block ObjId="TRAIN0">
<Extent>
<Min X="-1.0000000000E000" Y="-1.0000000000E000" Z="-1.0000000000E000"/>
<Max X="1.0000000000E000" Y="1.0000000000E000" Z="1.0000000000E000"/>
</Extent>
<PlanePanel ObjId="TRAIN0-PLATE1" DataType="101" Instance="AsDefined"><Extent>
<Min X="7.9200000000E004" Y="2.5100000000E003" Z="1.4000000000E003"/>
<Max X="7.9212000000E004" Y="5.7100000000E003" Z="2.8000000000E003"/>
</Extent>
<CoordSys>
<Origin X="7.9200000000E004" Y="0.0000000000E000" Z="0.0000000000E000"/>
<Waxis X="1.0000000000E000" Y="0.0000000000E000" Z="0.0000000000E000"/>
<Uaxis X="0.0000000000E000" Y="1.0000000000E000" Z="0.0000000000E000"/></CoordSys>
<Boundary>
<Limit CompId="1">
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
</Limit>
<Limit CompId="2">
<StartPoint2d U="2.5100000000E003" V="1.4000000000E003"/>
</Limit>
<Limit CompId="3">
<StartPoint2d U="5.7100000000E003" V="1.4000000000E003"/>
</Limit>
<Limit CompId="4"><StartPoint2d U="5.7100000000E003" V="2.8000000000E003"/></Limit>
<SimpleContour>
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="2.8000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="2.8000000000E003"/>
</Segment2d>
</SimpleContour>
<DetailedContour>
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="2.8000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="2.8000000000E003"/>
</Segment2d>
</DetailedContour>
</Boundary>
<PlateGroup GroupId="4">
<Material Grade="Default">
<Thickness>12.0</Thickness>
</Material>
<MaterialSide>Forward</MaterialSide>
<Plate CompId="1">
<Limit>
<ModelRef ObjType="PlanePanel" ObjId="TRAIN0-PLATE1" CompType="Limit" CompId="1"/>
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
</Limit>
<Limit>
<ModelRef ObjType="PlanePanel" ObjId="TRAIN0-PLATE1" CompType="Limit" CompId="2"/>
<StartPoint2d U="2.5100000000E003" V="1.4000000000E003"/>
</Limit>
<Limit>
<ModelRef ObjType="PlanePanel" ObjId="TRAIN0-PLATE1" CompType="Limit" CompId="3"/>
<StartPoint2d U="5.7100000000E003" V="1.4000000000E003"/>
</Limit>
<Limit>
<ModelRef ObjType="PlanePanel" ObjId="TRAIN0-PLATE1" CompType="Limit" CompId="4"/>
<StartPoint2d U="5.7100000000E003" V="2.8000000000E003"/>
</Limit>
<SimpleContour>
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="2.8000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="2.8000000000E003"/>
</Segment2d>
</SimpleContour>
<DetailedContour>
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="1.4000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="5.7100000000E003" V="2.8000000000E003"/>
</Segment2d>
<Segment2d>
<Amplitude2d U="0.0000000000E000" V="0.0000000000E000"/>
<Node2d U="2.5100000000E003" V="2.8000000000E003"/>
</Segment2d>
</DetailedContour>
</Plate>
</PlateGroup>
</PlanePanel>
</Block>
</Ship>hat etwas länger gedauert, dass alles ordentlich aufzuschreiben
-
Nein, ich hab noch nie ein Programm geschrieben, dass eine andere Datei einbezieht
Für Ratschläge bin ich immer zu haben
-
Naja, je nachdem wieviel Zeit du investieren kannst und willst, würd ich dir dazu raten, erstmal die Basics von C# zu lernen. Je nachdem wieviel Programmiererfahrung du schon hast, kann das eine Weile dauern. Auf jeden Fall solltest du zuerst in ein paar Übungsprogrammen den Umgang mit Dateien lernen.
Wenn du nicht soviel Zeit hast, dann ist es vielleicht besser, einfach jemanden zu suchen, der dir das Programm macht (nachdem du Maschinenbauer bist, geh ich mal davon aus, dass es sich da nicht um eine Übungsaufgabe handelt).Da du wohl sowieso noch nicht besonders viel Zeit in C++ investiert hast, würd ich davon eher abraten. Mit C# wirst du dein Ziel vermutlich sehr viel schneller und einfacher erreichen. Rein prinzipiell lässt sich dein Problem jedenfalls in jeder beliebigen general-purpose Programmiersprache lösen.
C# bekommst du hier: http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-csharp-express
Ein, dem Hörensagen nach, ganz brauchbares Buch gibts hier: http://openbook.galileocomputing.de/visual_csharp_2010/
-
Ok, dann schlage ich dir den PugiXml Parser vor.
(http://pugixml.org/)Dann gehts so:
- XML File einlesen
- Die interne Repräsentation des XML Files (=DOM) prozessieren
- Daraus die STL Datei generieren
-
Also eine Übungsaufgabe ist das nicht.
Wegen PugiXml. Ich schau mir das mal an.
=DOM prozessieren
Was meinst du damit? So zusagen die relevanten Daten rausfiltern und aufschreiben.Auch wenn ich kein Idiot bin, aber schreibt es mir doch bitte Idiotensicher auf.
-
solid plate
facet normal nx1 ny1 nz1
outer loop
vertex x1 y1 z1
vertex x2 y2 z2
vertex x4 y4 z4
endloop
endfacet
facet normal nx2 ny2 nz2
outer loop
vertex x2 y2 z2
vertex x3 y3 z3
vertex x4 y4 z4
endloop
endfacet
endsolid plateWie sähe denn die dazugehörige XML Datei aus? Einen Zusammmenhang zu dem Beispiel das du gepostet hast, kann ich nicht erkennen.
Das wäre nämlich der erste Schritt: Überlege dir wie die generell von der XML Datei zur STL Datei kommen kannst. Wie wird z.B. ein
vertexin der XML Datei repräsentiert? Wie einouter loop? Etc.=DOM prozessieren
Was meinst du damit? So zusagen die relevanten Daten rausfiltern und aufschreiben.XML Parser erzeugen ein DOM - eine baumartige Repräsentation deiner XML Datei (siehe hier). Und mit diesem DOM kannst du dann arbeiten, z.B. indem du in einer Schleife durch alle <Segment2d> Knoten iterierst. Dabei hilft dir dann die XML Bibliothek deiner Wahl, in die du dich dann wohl oder übel einarbeiten musst.
-
Und gerade darum rate ich ihm zu C#. Denn er hat mit C++ sowieso noch praktisch keine Erfahrung wie es aussieht. Bis er also die XML Bibliothek am Laufen und sich eingearbeitet hat, könnte er wohl genausogut einfach C# lernen, wo das ganze dann imo sehr viel einfacher realisierbar ist. Vielleicht garnicht soviel einfacher was die Codemenge angeht, aber zumindest in einer Umgebung die nicht an jeder Ecke hunderte Fallstricke gespannt hat...
Ich würde auch mal meinen, dass ein DOM für das Problem hier nicht nötig ist. Ein einfacher XmlReader sollte imo völlig ausreichend sein.
-
Hier mal ein minimal Bsp. (voraussetzung ist, dass die drei PugiXml Files eingebunden sind).
Die Zuordnung von XML Elementen nach STL File habe ich geraten und liege wahrscheinlich daneben:
Es muss ein File Platte.xml mit dem XML Inhalt existieren, daraus wird eine Datei Platte.txt erzeugt.
#include <iostream> #include <fstream> #include "pugixml.hpp" // STL file format (eg.) // ========================== // solid plate // facet normal nx1 ny1 nz1 // outer loop // vertex x1 y1 z1 // vertex x2 y2 z2 // vertex x4 y4 z4 // endloop // endfacet // facet normal nx2 ny2 nz2 // outer loop // vertex x2 y2 z2 // vertex x3 y3 z3 // vertex x4 y4 z4 // endloop // endfacet // endsolid plate int main() { pugi::xml_document document; pugi::xml_parse_result result = document.load_file("Platte.xml"); if (!result) { std::cerr << "Could not open XML file: " << result << std::endl; return 1; } std::ofstream output("Platte.txt"); if (!output) { std::cerr << "Could not open STL file." << std::endl; return 1; } pugi::xml_node coordSysNode = document.select_single_node("Ship/Block/PlanePanel/CoordSys").node(); pugi::xml_node originNode = coordSysNode.child("Origin"); double originX = originNode.attribute("X").as_double(); double originY = originNode.attribute("Y").as_double(); double originZ = originNode.attribute("Z").as_double(); output << "vertex " << originX << " " << originY << " " << originZ << std::endl; pugi::xml_node waxisNode = coordSysNode.child("Waxis"); double waxisX = waxisNode.attribute("X").as_double(); double waxisY = waxisNode.attribute("Y").as_double(); double waxisZ = waxisNode.attribute("Z").as_double(); output << "vertex " << waxisX << " " << waxisY << " " << waxisZ << std::endl; pugi::xml_node uaxisNode = coordSysNode.child("Uaxis"); double uaxisX = uaxisNode.attribute("X").as_double(); double uaxisY = uaxisNode.attribute("Y").as_double(); double uaxisZ = uaxisNode.attribute("Z").as_double(); output << "vertex " << uaxisX << " " << uaxisY << " " << uaxisZ << std::endl; return 0; }Edit:
Die 3 PugiXMml Files wären: pugiconfig.hpp, pugixml.hpp, pugixml.cppAnmerkung:
Im File Platte.txt steht anschliessend:vertex 79200 0 0 vertex 1 0 0 vertex 0 1 0
-
Hey Leute
Ich werd grad etwas überschlagen von Fragen und Antworten.
Das von theta werd ich erstmal probieren.Wenn ansonsten C# so empfohlen wird, könnte ich es auch auf diese Weise versuchen. Erstmal danke.
Ich meld mich ansonsten später nochmal
-
Hey theta
das ding hat ja sogar bei mir funktioniert. Echt super. Muss mal sehn, dass ich den Code nun weiterschreibe, damit auch der Rest der Informationen gespeichert werden können.
Aber schonmal vielen Dank, natürlich auch an dot.
Schön Abend euch noch
-
Hallo.
Ich hätte noch zwei Fragen wegen meinem Thema
Und zwar ist meine XML-Datei Ebenenbasiert:
Also
-Ship
-Block
-PlanePanel
-Boundary
-LimitDa es nun weiteres Limits gibt, in dem Punkte gespeichert sind, kann mir bitte jemand sagen, wie ich dem Programm sage, dass er das zweite, dritte, vierte Limit auswählen soll?
der Code von C++
pugi::xml_node coordSysNode2 = document.select_single_node("Ship/Block/PlanePanel/Boundary/Limit").node();
pugi::xml_node originNode2 = coordSysNode2.child("StartPoint2d");
double U = originNode2.attribute("U").as_double();
double V = originNode2.attribute("V").as_double();
output << "U/V " << U << " " << V << std::endl;die XML-Datei
<Boundary>
<Limit CompId="1">
<StartPoint2d U="2.5100000000E003" V="2.8000000000E003"/>
</Limit>
<Limit CompId="2">
<StartPoint2d U="2.5100000000E003" V="1.4000000000E003"/>
</Limit>
<Limit CompId="3">
<StartPoint2d U="5.7100000000E003" V="1.4000000000E003"/>
</Limit>
<Limit CompId="4"><StartPoint2d U="5.7100000000E003" V="2.8000000000E003"/>hoffe, ihr könnt mir helfen.
-
Ich kenne PugiXml nicht, aber schau dir mal das Beispiel hier an: http://pugixml.googlecode.com/svn/tags/latest/docs/manual/xpath.html#manual.xpath.select
select_nodesscheint das zu sein was du suchst.
-
Danke für die Antwort.
Jedoch ist mir diese Beschreibung zu speziell/kompliziert.
Ich würde mich freuen, wenn mir jemand ein Beispiel aufschreiben würde.Es dann auf meine Bedürfnisse umzuschreiben ist dann das geringste Problem
-
Komm schon, du musst doch in der Lage sein folgenden Code auf dein Problem zuzuschneiden:
pugi::xpath_node_set tools = doc.select_nodes("/Profile/Tools/Tool[@AllowRemote='true' and @DeriveCaptionFrom='lastparam']"); std::cout << "Tools:"; for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it) { pugi::xpath_node node = *it; std::cout << " " << node.node().attribute("Filename").value(); } pugi::xpath_node build_tool = doc.select_single_node("//Tool[contains(Description, 'build system')]"); std::cout << "\nBuild tool: " << build_tool.node().attribute("Filename").value() << "\n";Hier mal ein bisschen für dich umgeschrieben, damit klarer wird wie das mit deinem Problem zusammenhängt:
pugi::xpath_node_set tools = doc.select_nodes("Ship/Block/PlanePanel/Boundary/Limit"); for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it) { pugi::xpath_node limit_node = *it; // Hier muss jetzt das hin, was du mit dem <Limit ...> Knoten (limit_node) machen möchtest. }