Skip to content

Latest commit

 

History

History
121 lines (91 loc) · 4.01 KB

File metadata and controls

121 lines (91 loc) · 4.01 KB

✅ Correction du problème de NaN - Parcours des nœuds XML

🐛 Problème identifié

Les vertices étaient complètement corrompus avec des valeurs énormes :

vertex 1.05418891e+11  -5.78377524e-09  2.72147074e+12
vertex -3.4351764e+34  55170036  -6.48697832e-11

Et les normales étaient NaN.

🔍 Cause racine

Le code C++ utilisait getElementsByTagName("Vertices") qui retourne tous les nœuds Vertices du document entier, alors que le code Python parcourt les nœuds un par un dans l'ordre :

Code Python (référence)

for node in pg:
    for sub_node in node:
        if sub_node.tag in ['CA','CC']:  # Parcourt CA et CC dans l'ordre
            for g_node in sub_node:
                if g_node.tag == 'Vertices':
                    # Lit les vertices de CE nœud CA/CC spécifique
                    ...

Code C++ (AVANT - incorrect)

// Cherche TOUS les nœuds Vertices dans tout le document
Poco::AutoPtr<Poco::XML::NodeList> caNodes = 
    binaryElement->getElementsByTagName("Vertices");

// Prend le PREMIER trouvé (peut être le mauvais !)
auto caElement = dynamic_cast<Poco::XML::Element*>(caNodes->item(0));

Cela signifiait que si le fichier DCM avait plusieurs nœuds CA/CC, on pouvait lire les vertices d'un mauvais nœud, ou d'un nœud incomplet, causant la corruption des données.

✅ Solution appliquée

Modifier ParseVertices() et ParseFacets() pour parcourir les nœuds enfants comme le Python :

// Parcourir les nœuds enfants
Poco::AutoPtr<Poco::XML::NodeList> childNodes = binaryElement->childNodes();

for (unsigned long i = 0; i < childNodes->length(); ++i)
{
    auto childElement = dynamic_cast<Poco::XML::Element*>(childNodes->item(i));
    if (childElement)
    {
        std::string tagName = childElement->nodeName();
        
        // Chercher dans les nœuds CA ou CC
        if (tagName == "CA" || tagName == "CC")
        {
            // Chercher Vertices DANS ce nœud CA/CC spécifique
            Poco::AutoPtr<Poco::XML::NodeList> verticesNodes = 
                childElement->getElementsByTagName("Vertices");
            
            if (verticesNodes->length() > 0)
            {
                // Parse les vertices de CE nœud
                ...
                return floatData;  // Retourne (écrase les précédents comme Python)
            }
        }
    }
}

📊 Impact

Cette correction assure que :

  • ✅ Les nœuds CA/CC sont parcourus dans le bon ordre
  • ✅ Les Vertices et Facets sont lus du même nœud CA/CC
  • ✅ Le comportement est identique au parser Python
  • ✅ Les fichiers avec plusieurs nœuds CA/CC sont correctement gérés

🧪 Tests

# Recompiler
cd /Users/Romain/CLionProjects/Open3SDCM/cmake-build-debug
cmake --build . --target Open3SDCMCLI -j 8

# Tester Scan-01 (devrait maintenant avoir des vertices valides)
cd /Users/Romain/CLionProjects/Open3SDCM
./cmake-build-debug/bin/Open3SDCMCLI -i ./TestData/Scan-01 -o ./TestOutput -f stl

# Vérifier le fichier STL généré
# Ne devrait plus avoir de NaN ni de valeurs énormes

🎯 Résultats attendus

Après cette correction :

  • ✅ Les vertices doivent être dans une plage raisonnable (quelques mm/cm)
  • ✅ Plus de valeurs NaN dans les normales
  • ✅ Plus de valeurs énormes comme 1e+34
  • ✅ Le fichier STL devrait être valide et ouvrable dans MeshLab/Blender

📝 Fichiers modifiés

  • /Users/Romain/CLionProjects/Open3SDCM/Lib/src/ParseDcm.cpp
    • ParseVertices() : Lignes ~126-170
    • ParseFacets() : Lignes ~356-400

💡 Leçon apprise

Lors de la conversion de code Python vers C++, il est crucial de respecter exactement l'ordre de parcours des nœuds XML, car :

  • Les méthodes comme getElementsByTagName() peuvent retourner des nœuds dans un ordre différent
  • Le parcours séquentiel des nœuds enfants est parfois important pour la logique
  • Les fichiers XML peuvent avoir une structure complexe avec plusieurs nœuds similaires

Date : 6 décembre 2025
Statut : ✅ CORRECTION APPLIQUÉE - À TESTER