exploring a compound

Hello forum,

I known that this topic was already discussed in the past, but I have not been able to find a clear answer to my question,

apart from "read the documentation"; which honestly is very clear.

I generated with an external tool a step file containing a cube (TopoDS_Solid), a shell (TopoDS_Shell), a face (TopoDS_Face),

a wire (TopoDS_Wire), and finally an edge (TopoDS_Edge).

The shapes are separated in space, not connected in any way: I attached a skectch and the .step file.

When reading the file using the STEPControl_ reader::oneShape I get one shape, which is of TopoDS_Compound type (type 0).

Then I would like to explore it, and retrieve the list of "main" shapes, that is the original solid, shell, face, wire, edge.

It seems that the ShapeExtend_Explorer is the right tool, since documentation claims:

"This class is intended to explore shapes and convert different representations (list, sequence, compound)

of complex shapes. It provides tools for:obtaining type of the shapes in context of TopoDS_Compoung [...]"​

So I tried the following simple code,

#define FILENAME "D:\\000000000_mixed.stp"

 
//! OCC
#include <STEPControl_Reader.hxx>
#include <TopoDS_Shape.hxx>
#include <IFSelect_ReturnStatus.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <ShapeExtend_Explorer.hxx>

 
//! C++
#include <iostream>
using namespace std;

 
//! Qt
#include <QString>

 
int main()
{
    //! ------------------------
    //! load the file from disk
    //! ------------------------
    STEPControl_Reader aReader;
    IFSelect_ReturnStatus stat = aReader.ReadFile(FILENAME);

 
    if(stat!=IFSelect_RetDone)
    {
        cout<<"____error in loading the file____"<<endl;
        return 1;
    }

 
    aReader.TransferRoots();
    TopoDS_Shape aShape = aReader.OneShape();
    if(!aShape.IsNull())
    {
        cout<<"____shape type: "<<aShape.ShapeType()<<"____"<<endl;

 
        Handle(TopTools_HSequenceOfShape) seqShape = new TopTools_HSequenceOfShape;
        Handle(TopTools_HSequenceOfShape) compounds, compsolids, solids, shells, faces, wires, edges, vertices;

 
        ShapeExtend_Explorer anExp;

 
        anExp.SeqFromCompound(aShape,false);
        anExp.DispatchList(seqShape,vertices,edges,wires,faces,shells,solids,compsolids,compounds);
        cout<<"____Nb compounds: "<<compounds->Length()<<"____"<<endl;
        cout<<"____Nb compsolids: "<<compsolids->Length()<<"____"<<endl;
        cout<<"____Nb solids: "<<solids->Length()<<"____"<<endl;
        cout<<"____Nb shells: "<<shells->Length()<<"____"<<endl;
        cout<<"____Nb faces: "<<faces->Length()<<"____"<<endl;
        cout<<"____Nb wires: "<<wires->Length()<<"____"<<endl;
        cout<<"____Nb edges: "<<edges->Length()<<"____"<<endl;
        cout<<"____Nb vertices: "<<vertices->Length()<<"____"<<endl;
    }
}

The output is

____shape type: 0____
____Nb compounds: 0____
____Nb compsolids: 0____
____Nb solids: 0____
____Nb shells: 0____
____Nb faces: 0____
____Nb wires: 0____
____Nb edges: 0____
____Nb vertices: 0____

which is not correct.

Were did I wrong?

Any help is strongly appreciated

Giovanni

Any help 

 

 

Giovanni Bettega's picture

Hello

I would like to share my solution.

MainWindow::MainWindow(QMainWindow *parent):QMainWindow(parent)
{
    //! ---------
    //! a viewer
    //! ---------
    occViewPort aViewer = new occViewPort(this);
    if(aViewer->getContext().IsNull()) aViewer->init();
    this->setCentralWidget(aViewer);

    //! ------------------------
    //! load the file from disk
    //! ------------------------
    STEPControl_Reader aReader;
    IFSelect_ReturnStatus stat = aReader.ReadFile(FILENAME);

    if(stat!=IFSelect_RetDone) exit(1);

    aReader.TransferRoots();
    TopoDS_Shape aShape = aReader.OneShape();

    //! ----------------
    //! list of shapes
    //! ----------------
    QList<TopoDS_Shape> csolids;
    QList<TopoDS_Shape> solids;
    QList<TopoDS_Shape> wires;
    QList<TopoDS_Shape> edges;
    QList<TopoDS_Shape> shells;
    QList<TopoDS_Shape> faces;

    for(TopoDS_Iterator anIt(aShape); anIt.More(); anIt.Next())
    {
        const TopoDS_Shape &curShape = anIt.Value();
        TopAbs_ShapeEnum type = curShape.ShapeType();

        if(type==TopAbs_COMPOUND)
        {
            cout<<"____COMPOUND____"<<endl;

            TopoDS_Builder aShellBuilder;
            TopoDS_Shell aShell;

            TopoDS_Builder aWireBuilder;
            TopoDS_Wire aWire;

            aShellBuilder.MakeShell(aShell);
            aWireBuilder.MakeWire(aWire);

            int faceCount = 0;
            int edgeCount = 0;

            for(TopoDS_Iterator anExp(curShape); anExp.More(); anExp.Next())
            {
                const TopoDS_Shape &curShape1 = anExp.Value();
                TopAbs_ShapeEnum type1 = curShape1.ShapeType();

                if(type1==TopAbs_SHELL)
                {
                    for(TopExp_Explorer anExp(curShape1,TopAbs_FACE);anExp.More();anExp.Next())
                    {
                        const TopoDS_Shape &curShape2 = anExp.Current();
                        aShellBuilder.Add(aShell,curShape2);
                        faceCount++;
                    }
                }

                if(type1==TopAbs_EDGE)
                {
                    aWireBuilder.Add(aWire,curShape1);
                    edgeCount++;
                }
            }

            if(faceCount>1) shells<<aShell;
            if(edgeCount>1) wires<<aWire;
            else if(edgeCount==1)
            {
                //! --------------------------------------
                //! remove "aWire" from the list of wires
                //! --------------------------------------
                wires.removeOne(aWire);
                for(TopExp_Explorer anExp(aWire,TopAbs_EDGE); anExp.More(); anExp.Next())
                {
                    const TopoDS_Shape &curEdge = anExp.Current();
                    edges<<curEdge;
                }
            }
        }

        //! -----------------
        //! composite solids
        //! -----------------
        if(type==TopAbs_COMPSOLID)
        {
            cout<<"____COMPSOLID____"<<endl;
            csolids<<curShape;
        }

        //! -------
        //! solids
        //! -------
        if(type==TopAbs_SOLID)
        {
            solids<<curShape;
        }

        //! ------
        //! faces
        //! ------
        if(type==TopAbs_SHELL)
        {
            for(TopExp_Explorer anExp(curShape,TopAbs_FACE);anExp.More();anExp.Next())
            {
                const TopoDS_Shape &curShape1 = anExp.Current();
                faces<<curShape1;
            }
        }
    }

    cout<<"____Nb solids: "<<solids.length()<<"____"<<endl;
    cout<<"____Nb shells: "<<shells.length()<<"____"<<endl;
    cout<<"____Nb faces: "<<faces.length()<<"____"<<endl;
    cout<<"____Nb wires: "<<wires.length()<<"____"<<endl;
    cout<<"____Nb edges: "<<edges.length()<<"____"<<endl;

    //! --------
    //! display
    //! --------
    QList<TopoDS_Shape> listOfShapes;
    listOfShapes<<csolids<<solids<<shells<<faces<<wires<<edges;
    for(int i=0; i<listOfShapes.length(); i++)
    {
        const Handle(AIS_Shape) &anAIS_Shape = new AIS_Shape(listOfShapes.at(i));
        aViewer->getContext()->Display(anAIS_Shape,AIS_Shaded,-1,true,false);
    }
    aViewer->FitAll();
    aViewer->setAction3D_Rotation();
}

It gives

____Nb solids: 1____
____Nb shells: 2____
____Nb faces: 1____
____Nb wires: 1____
____Nb edges: 1____

for file 000000000_mixed_1

and

____Nb solids: 1____
____Nb shells: 1____
____Nb faces: 3____
____Nb wires: 1____
____Nb edges: 1____

for 000000000_mixed_2.stp

Giovanni

Vin Yovanovich's picture

What if there are some coordinate systems in stp files and one wants obtain those?

#4=AXIS2_PLACEMENT_3D('PRT_CSYS_DEF',#1,#2,#3);
#8=AXIS2_PLACEMENT_3D('CS0',#5,#6,#7);
...

Is that something to do with setting read.step.constructivegeom.relationship on?

In the doc there is code
STEPControl_Reader aReader;
... // translate file and parse STEP model to find relevant axis entity
Handle(StepGeom_Axis2Placement3d) aSTEPAxis = ...;
Handle(Transfer_Binder) aBinder = aReader->WS()->TransferReader()->TransientProcess()->Find(aSTEPAxis);
Handle(TransferBRep_ShapeBinder) aShBinder = Handle(TransferBRep_ShapeBinder)::DownCast(aBinder);

But I don't know how to add it to your solution.

Vin Yovanovich's picture

This is why this kind of "free" kernel doesn't work and it's better to pay for a high quality supported kernel such as Parasold and get to do things right away.

Vera Sdobnova's picture

Hello Vin,

As an open source project, OCCT gives community the possibility of fixing bugs and extending functionality, but so far, the main development is driven by Open Cascade developers, which in turn depends on requests and feedback from commercial projects and customers.

OCCT is open to any kind of contribution, however we haven’t received bugs or improvements submitted by you. If you have anything to contribute, feel free to share it via OCCT Bug Tracker. If your query is urgent, you may consider using support services.