Datei von XML zu STL mit C++



  • 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 plate

    Wie 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 vertex in der XML Datei repräsentiert? Wie ein outer 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.cpp

    Anmerkung:
    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
    -Limit

    Da 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_nodes scheint 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. 
    }
    


  • Hey Leute

    Erstmal danke an Comonad.
    Ich sitz immernoch an meinem Programm fest.

    Hab zur Zeit es hinbekommen, dass die Schleife nur bis zu einem bestimmten Punkt arbeitet, jedoch bekomm ich das einlesen der Punkte nicht hin.

    Könnt ihr mir da vielleich auf die Sprünge helfen, was falsch ist?

    das System sieht so aus (XML)

    <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"/>

    der anfang lautet
    ----------------------------------------------------------------------------
    pugi::xpath_node_set tools = document.select_nodes("Ship/Block/PlanePanel/Boundary/Limit/StartPoint2d");

    for (pugi::xpath_node_set::const_iterator it = tools.begin(); it != tools.end(); ++it)
    {
    pugi::xpath_node limit_node = *it;
    double U = tools.attribute("U").as_double();
    output << "vertex " << U << std::endl;
    }
    ----------------------------------------------------------------------------

    oder

    ----------------------------------------------------------------------------
    pugi::xpath_node_set tools = document.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;
    pugi::xpath_node originNode2 = tools.child("StartPoint2d");
    double U = originNode2.attribute("U").as_double();
    output << "vertex " << U << std::endl;
    }
    ----------------------------------------------------------------------------

    ich weiß leider nicht genau, wie ich das definier muss, damit die Punkte eingelesen werden können.
    Hoffe ihr könnt mir helfen



  • Tut mir leid, Juwe, aber so wird das nichts.
    Deine Fragen zeigen, dass du den Beispielcode nur ansatzweise verstehst. Bevor du weitermachst, kauf dir ein gutes C++ Buch (z.B. den C++ Primer oder "Der C++ Programmierer"), ansonsten kommst du einfach nicht weiter. Wenn du dich mal in die Grundlagen eingelesen hast, wird das Verstehen des Quelltextes kein Problem mehr sein.



  • Hey Leute

    Ich komm gerade nicht weiter und hoffe, dass ihr mir einen Tipp geben könnt.

    So sieht mein Code aus

    cout << "\nX=: " << node.node().attribute("X").value();

    und gibt mir aus
    X=: 7.650000 E003
    X=: 0.000000 E000
    usw.

    jedoch kann ich den Wert nicht vergleichen lassen.
    so in etwa

    if(node.node().attribute("X").value()>0)
    {}

    das funktiert leider nicht und ich hab auch schon versucht den Wert zu übergeben
    int o;
    o=*node.node().attribute("X").value();

    leider auch ohne den gewünschten erfolg.

    Kann mir mal bitte jemand sagen, wie ich das schreiben kann, damit ich den Wert richtig übergebe und somit vergleichen kann?

    Danke schonmal im vorraus.



  • Hat sich erledigt, hab einen Weg gefunden



  • Hey Leute.

    Ich hoffe ihr könnt mir mit eurer Erfahrung helfen.
    Hab ein Programm geschrieben, dass Punkte aus einer Datei raussucht und in ein .txt file speichert.

    Mein Problem ist nun, dass das Programm bis zu über 100 Punkte ordentlich macht und dann auf einmal Fehler macht, obwohl er immernoch das selbe macht.
    Vllt hab ich ja einen Fehler bei der Definition der Variablen gemacht.
    Weiß vielleicht einer von euch, woran das liegen könnte???

    Ich kann euch auch den Code schreiben, aber ist halt etwas länger.
    Danke schon mal



  • Was für eine Art Fehler ist es denn? Hast du schonmal versucht den Fehler mit Hilfe eines Debuggers zu lokalisieren?



  • ja, dass ist das Problem.
    es wir nicht als Fehler erkannt.
    Er rechnet weiter, aber gibt falsche ergebnisse aus.

    also:

    ich lass das Programm werte einlesen und auf eine txt-datei ausgeben
    nun ist das Problem, dass er in der mitte der gesamten datei auf einmal sagt, das alle werte null sind und somit falsche ausgelesen werden



  • Wie gesagt: Schmeiß den Debugger an und finde den Bug!
    Wenn du nicht weißt wie das geht, lies dir ein Tutorial deiner Wahl durch.


Anmelden zum Antworten