Step file translator can't read subshapes

I'm working on a small application that translates STEP files to other file types. The problem is, some shapes have children but their respective label does not. I was creating functions iterating over labels, so that's a problem. I tried solving it in a few ways, but they were all a mess, so I'd appreciate some help. I was testing with the attached file called Combine_Harvester.STEP.

First, the code reads a STEP file, which is basically the one in openCascade's user guides:

Handle(TDocStd_Document) readFile(char* filename) {
    STEPCAFControl_Reader aReader;

    aReader.SetColorMode(true);
    aReader.SetLayerMode(true);
    aReader.SetNameMode(true);

    IFSelect_ReturnStatus aReadStat = aReader.ReadFile(filename);
    if (aReadStat != IFSelect_RetDone) { std::cout << "Error: couldn't read file \n"; }

    //Creates the TDocStd_Document, with it's usual parameters.
    Handle(TDocStd_Document) aDoc;
    Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
    BinXCAFDrivers::DefineFormat(anApp);
    XmlXCAFDrivers::DefineFormat(anApp);
    anApp->NewDocument("BinXCAF", aDoc);

    //Transfer the data from aReader to aDoc.
    if (!aReader.Transfer(aDoc)) {
        std::cout << "Cannot read any relevant data from the STEP file\n";
    }
    return aDoc;

}

After reading the file, I call the function translate file, that gets the Head of the assembly and builds the assembly tree over it, and the recursive function buildTree that builds the assembly tree:

void translateFile(Handle(TDocStd_Document) doc, char* filename) {
    //ITreeNode is the structure I'm translating the STEP file to
    ITreeNode* head;
    head->SetName(filename);

    Handle(XCAFDoc_ShapeTool) myAssembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
    TDF_LabelSequence labels;
    myAssembly->GetFreeShapes(labels);

    //Iterates over the main shapes to build the node of the tree
    for (TDF_LabelSequence::Iterator aLabIter(labels); aLabIter.More(); aLabIter.Next()) {
        ITreeNode* children = node->GetChildren()->Emplace();
        buildTree(doc, children, aLabIter.Value());
    }
}

void buildTree(Handle(TDocStd_Document) doc, ITreeNode* parent, TDF_Label aLabel) {

    Handle(XCAFDoc_ShapeTool) myAssembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());
    Handle(XCAFDoc_ColorTool) myColor = XCAFDoc_DocumentTool::ColorTool(doc->Main());

    TopoDS_Shape shape;
    shape = myAssembly->GetShape(aLabel);
        //GetNameFromShape is an auxiliar function that either get the name of the shape or returns "UNNAMED_SHAPE" 
    parent->SetName(GetNameFromShape(shape, myAssembly));   

    float RGBcolors[4];
        //GetColorFromShape is an auxiliar function that either get the color of the shape or returns the default color.
    Quantity_ColorRGBA color = GetColorFromShape(shape, myAssembly);
    Quantity_Color rgb = color.GetRGB();
    RGBcolors[0] = rgb.Red();
    RGBcolors[1] = rgb.Blue();
    RGBcolors[2] = rgb.Green();
    RGBcolors[3] = color.Alpha();

        //translateShape gets the data from the shape to the Tree, it is working as intended. 
    translateShape(parent, shape, RGBcolors);

    for (TDF_ChildIterator cit(aLabel, true); cit.More(); cit.Next()) {
        ITreeNode* children = parent->GetChildren()->Emplace();
        buildTree(doc, children, cit.Value());
    }
}

The main problem is that, from what i've seen, the information on some shapes is divided between two labels. When I translate the STEP file this way, some shapes have subshapes but their labels don't have, so the buildTree() iteration stops before it should. The resulting tree from the file I gave looks something like in the attached image "Combine_Harvester_1.jpeg". If I change the line "myAssembly->GetFreeShapes(labels)" from the function translateFile() to "myAssembly->GetShapes()", the labels with the shapes and subshapes appear, but they are not under the Head node, as seen in the image "Combine_Harvester_2.jpeg". Looking at both images, it's possible to see that the figure "Kerangka ..." has no children when it is under "Combine_Harvester", but has two children when it has no parents. Is there a way to put all the children under "Combine_Harvester"?

Attachments: 
Dmitrii Pasukhin's picture

Hello,

I think you means assembly shapes, it is a shape, that connects only labels(no shapes) with some attributes and connections, that has reference to the simple shape or assemble.
If it is correct, you need to check type of shape label. If it is has reference, you need go to reference.

I have been attached some code sample. Please check it.

Additionally, you can find a lot of information in the Extended Data Exchange (XDE) - Open CASCADE Technology Documentation and OCAF - Open CASCADE Technology Documentation

If you work with OCCT, you can find some code sample within XCAFPrs.cxx or any XCAFDoc_Editor.cxx or any XCAF read/write classes such as STEPCAFControl_Writer, STEPCAFControl_Reader, RWObj_CafWriter.

Best regards, Dmitrii.

Attachments: 
Lucas Guimaraes's picture

Hi,

Thanks Dmitrii, that solved the problem i was having at the time, it was indeed about referred shapes.

I am now trying to read colors as well, and despite reading the XDE link you shared, i couldn't make it work properly for every case. The problem is that once i reach the leaf of the tree, a simple shape, the color of that shape can be stored in the shape itself, in the shape subshapes or in the shape faces. To get the mesh, my program already iterates over the face and the shape, so getting the color from them is not a problem. The problem arises when i try to get colors from the subshape.

My initial idea was to also iterate over the subshapes, so instead of iterating the faces from the shape like this

for(TopExp_Explorer aFaceIt(shape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
{
   translateFace(/*unrelated parameters*/);
}

, i tried doing like this

TDF_Label label = myAssembly->FindShape(shape);
TDF_LabelSequence labels;
myAssembly->GetSubShapes(label, labels);
for (TDF_LabelSequence::Iterator Iter(labels); Iter.More(); Iter.Next()) 
{
      for (TopExp_Explorer aFaceIt(shape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) 
      {
               translateFace(/*unrelated parameters*/);
      }
}

but the problem was that not every subShape had a label, so the exported file was not complete, with some mesh missing. Then i tried to do something like this:

for (TopoDS_Iterator aSubShapeIt(shape); aSubShapeIt.More(); aSubShapeIt.Next()) {
      for(TopExp_Explorer aFaceIt(aSubShapeIt.Value(), TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) 
      {
               translateFace(/*unrelated parameters*/);
      }

}

In this case the mesh was complete but i couldn't get the colors in the subShape, because despite having the same meshes as when iterating over the TDF_LabelSequence, the subShapes had different identifiers, so this happened

Handle(XCAFDoc_ColorTool) myColor = XCAFDoc_DocumentTool::ColorTool(doc->Main());;
Handle(XCAFDoc_ShapeTool)myAssembly = XCAFDoc_DocumentTool::ShapeTool(doc->Main());;
Quantity_ColorRGBA theColor;
...
//Iterator from TDF_LabelSequence
myColor->GetColor(Iter.Value(), XCAFDoc_ColorSurf, theColor); //in this case, theColor returns the right color
...
//Iterator from TopoDS_Iterator
TDF_Label aLabel = myAssembly->FindShape(aSubShapeIt.Value());
myColor->GetColor(aLabel, XCAFDoc_ColorSurf, theColor); //In this case, theColor doesn't get any color
...

I tried some other thing too, like adding a label to every subShape, but none of them worked, so i think it wouldn't be helpful to share them, so i'd like to ask what's the right way to get the color from a subshape. In the attached file, there are the images of the code running on a step file representing a drone, with the expected result and how each case differs from the result.

Attachments: