Please help me, wrong located shapes.

Hi everyone !
I am making an import STEP module via OCC (my software don't uses OCC). Import is working perfectly with nearly all test files, but some have some shapes put on wrong locations. Not every shapes, but two similar shapes will be placed on the same spot.
Here is the general algorithm:

1. Get free shapes
2. Recursively explore nodes with TDF_ChildIDIterator
3. Get info from label (name,color...) & shape of each leaf with GetShape(label, shape)
4. Build a mesh with BRepMesh_IncrementalMesh
5. Get faces and edge with TopExp_Explorer then build the item in my soft.

What could I possibly forget ? Where can be the missing translation ? As I am quite new to OCC maybe I forgot a basic thing ...

Any help would be very appreciated.
Thanks in advance !

Paul Jimenez's picture
A.Zentsov's picture

Thank you for your answer.

I am doing like this :

Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);
gp_Pnt pt;

for (j = 1 ... triangulation->NbTriangles() ){

Poly_Triangle triangle = (triangulation -> Triangles())(j);
for (k = 1; k <= 3; k++){

pt = (triangulation -> Nodes())(triangle(k)).Transformed(loc);


I tried using "gp_Trsf xloc = loc;" and then "xloc.Transforms(x,y,z);" but the shape is still in the wrong spot.

Any other ideas ?

Paul Jimenez's picture

Sorry, no more ideas from my side. Maybe you could check the code from a project that uses OpenCASCADE with its own visualization framework. I think HeeksCAD does that.

dvdjimmy's picture

Take a look at this code. Its working quite nice and as you can see we get the orientation directly from the topoface and afterwards apply the transformation again on the resulting mesh.

for (aExpFace.Init(aShape,TopAbs_FACE);aExpFace.More();aExpFace.Next())
TopoDS_Face aFace = TopoDS::Face(aExpFace.Current());
TopLoc_Location aLocation;
// takes the triangulation of the face aFace:
Handle_Poly_Triangulation aTr = BRep_Tool::Triangulation(aFace,aLocation);
if (!aTr.IsNull()) // if this triangulation is not NULL
// takes the array of nodes for this triangulation:
const TColgp_Array1OfPnt& aNodes = aTr->Nodes();
// takes the array of triangles for this triangulation:
const Poly_Array1OfTriangle& triangles = aTr->Triangles();
// create array of node points in absolute coordinate system
TColgp_Array1OfPnt aPoints(1, aNodes.Length());
for ( Standard_Integer i = 1; i < aNodes.Length()+1; i++)
aPoints(i) = aNodes(i).Transformed(aLocation);
// Takes the node points of each triangle of this triangulation.
// takes a number of triangles:
Standard_Integer nnn = aTr->NbTriangles();
Standard_Integer nt,n1,n2,n3;
for ( nt = 1 ; nt < nnn+1 ; nt++)
// takes the node indices of each triangle in n1,n2,n3:
// takes the node points:
gp_Pnt aPnt1 = aPoints(n1);
gp_Pnt aPnt2 = aPoints(n2);
gp_Pnt aPnt3 = aPoints(n3);
// give the occ faces to the internal mesh structure of freecad
MeshCore::MeshGeomFacet Face(Points[0],Points[1],Points[2]);




A.Zentsov's picture

Thank you both for your answers !

Joachim, I tried your code but it doesn't work any better than mine, the shape is still on the wrong spot. It seems that the transformation I missed is upper in the hierarchy. I looked for references and locations of every label and shapes I found with ChildIDIterator, in vain. Do you know other ways I could have forgot ?

Paul, I looked in the code of HeeksCAD and it uses a STEPControl_Reader instead of STEPCAFControl_Reader. I will look in others OpenSource codes though, its a good idea.

Again thank you both.
If anyone has any clue let me know.

Pawel's picture


a suggestion: check this post from Roman:

Especially, the comments. There are two relevant locations that influence the final location of a face (or it's vertices). Maybe if you combine them you will get it right.

Just a guess...

Roman Lygin's picture

Hi Aleksander,

Could you elaborate on your problem a bit ? Are your points (retrieved from triangulation) displayed in a wrong location ? What happens if you display both the shape and the points in the same 3D view - are they coincide or in different locations ? What makes you believe that location is wrong (e.g. how are you confident in your original STEP files) ? Could you make a snapshot to demonstrate the problem ?
Could you try CAD Exchanger (it internally uses STEPCAFControl_Reader) to check if shape locations are as expected ?


P.S. You seem to misspell your name in your profile - Alenksander ;-)

--- - the Open CASCADE blog - CAD Exchanger, your 3D data translator

A.Zentsov's picture

Hi, thanks for answering.

Yea I'm sure shapes are not correctly located, I tried with several visualization tool. Here's with your CAD exchanger :
And mine :

The shapes displayed on the left & right on yours are both on left on mine. It goes quite the same with your "omni_wheel.stp" test file. All same elements are on the same spot :

I have this problem on some step file only, and didn't had it with STEPControl_Reader. For instance I import perfectly the step I exported myself. There must be a certain kind of Location I don't treat right.

Pawel, I tried to combine the locations as you suggested. I did like this :
TopLoc_Location loc, loc2;
Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);
loc2 = face.Location();
loc = loc2 * loc;
But it doesn't work either.

Thanks again for your help.

PS: I will correct my name if it disturbs you, I indeed made a mistake typing in. ^^

Pawel's picture

Hi Aleksander,

can you make your files available for download somewhere? Maybe this would bring some new insights into your case.


A.Zentsov's picture
Pawel's picture

Hi Aleksander,

your shape is built of 3 compounds which have no transformation (identity matrix) and one that is transformed (if you want to see what I mean get a copy of Total Engineer [] and browse the structure of your STEP file).

My guess is, you don't apply the location you get with BRep_Tool::Triangulation (face, loc);
properly for the one compound...

I have a method computing curvatures for shapes (prior to that meshes are obtained). I applied it for your file and it worked fine. Try checking your code...


A.Zentsov's picture

Hi Pawel, thanks for all you help !

I apply transformation like this :
"gp_Pnt pt = (triangulation -> Nodes())(triangle(k)).Transformed(loc);"

where loc, triangulation and triangle are obtained like this :
"Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc);"
"Poly_Triangle triangle = (triangulation -> Triangles())(j);"

I also tried with Zettler's code.

And tried to combine Face and TFace Locations by adding these lines :
"loc2 = face.Location();
loc = loc2 * loc;"

Isn't this the right way to apply transformations ?


Pawel's picture

I guess it is the right way to apply transformations.

However, I made a small test: I skipped the transformation in my code and obtained models with the same problem that you have (except for the colors;) with yours:

So, that's why I suspect there's a problem with applying the transformation...

By the way, don't try combining of the locations - I checked that in the meantime. This suggestion was wrong. BRep_Tool will provide a location that is already combined with the transformation of the parent shape (or at least it was so in my case).

A.Zentsov's picture

I'm getting crazy ...

When you say "skipped the transformation" you mean the one obtained by "BRep_Tool::Triangulation" ? As its the whole compound that is transformed, maybe the transformation must be read before.

When I go down in the assembly hierarchy, I read TopLoc_Location of TDF_Label with "TopLoc_Location loc = myAssembly_->GetLocation( label );" and combine it with his father's Location like this : "loc = loc$ * loc;" (where loc$ is his father's location).
Then when I get to the shape I apply it like this:
"gp_Trsf transformation(loc$);
shape = BRepBuilderAPI_Transform(shape, transformation, Standard_True);"

Is it correct to do like this ?


Roman Lygin's picture


As your display is wrong, your error is likely somewhere upstream, before you explore Triangulations.
Here is a sequence of command in DRAWEXE that correctly displays your shape:
Draw > pload ALL
Draw > NewDoc d XmlXCAF
Draw > ReadStep d C:/temp/yourfile.stp
Draw > XGetFreeShapes a # this returns your free shape(s). In your case it's a single compound.
Draw > small
Draw > fit

The shape in your file is a single TopoDS_Compound consisting of 4 TopoDS_Solids. On your screenshots you show that one is misplaced. This means that you display not the entire original shape but rather explore it and display subshapes. Is this the case ? How do you iterate ?
Do you use somewhere TopoDS_Iterator with cumLoc = Standard_False ? That could be an explanation.


--- - the Open CASCADE blog - CAD Exchanger, your 3D data translator

A.Zentsov's picture


I don't use TopoDS_Iterator anywhere. Yes I explore subshapes, and construct a hierarchy in my software in the meantime. I used the same iteration as Xdump function in DRAW, adding lately (as my shapes where misplaced) locations combination:

// loc$ is the TopLoc_Location given by "label"'s father
TopLoc_Location loc = myAssembly_->GetLocation( label );
loc = loc$ * loc;

// Recursive iteration :
for (TDF_ChildIDIterator NodeIterator(label, XCAFDoc::ShapeRefGUID()); NodeIterator.More(); NodeIterator.Next())

Node = Handle(TDataStd_TreeNode)::DownCast(NodeIterator.Value());
if (Node->HasFather())

if (Node->Father()->Label().HasChild())
// Recursive call to this function
Explore(Node->Father()->Label(), loc );
// Apply loc and add simple shape
AddShape(Node->Father()->Label(), loc);

I noticed DRAW was detecting the same label 2 times, for this file something like:

I guessed it was because it actually is the same shape but positioned differently. Now I wonder if its the right way to explore subshapes ...


Roman Lygin's picture

Then it you likely incorrectly explore XDE document. In fact, once you get free shapes you should explore only them and should not use child labels. You need to rely on XDE API to retrieve data you need rather than inspecting the document on your own. Theoretically there is no guarantee that doc structure will forever remain the same, it is API's purpose to ensure compatibility.

So you need to:

1. Get free shapes
TDF_LabelSequence Labels;
Handle(XCAFDoc_ShapeTool) STool = XCAFDoc_DocumentTool::ShapeTool(Doc->Main());
2. Explore them using TopoDS_Iterator or TopExp_Explorer
const TopoDS_Shape& aSubShape = ...;
3. Get attributes from XDE, e.g.
XCAFDoc_ColorType aType = ...;
if (XCAFDoc_ColorTool::IsSet (aSubShape, aType)) {
Quantity_Color aColor;
XCAFDoc_ColorTool::GetColor (aSubShape, aType, aColor);

Hope this helps.

--- - the Open CASCADE blog - CAD Exchanger, your 3D data translator

A.Zentsov's picture

It works quite well now, thank you !

I thought it was the right way as DRAW does like that to dump informations, and XDE doc is all about Labels ...

Thanks to all of you for your help, sorry I made you loose your time on such a basic error.

Giuseppe Belgenio's picture

Hi,i am new to OOC.
Please can you explain me how to navigate LabelsSequence with TopoDS_Iterator or TopExp_Explorer.
I am only able to navigate through shapes.

Thank you

A.Zentsov's picture

Hi, thats how I did. Hope it hepls you :

TDF_LabelSequence SeqLabels;

for (int i = 1; i<=SeqLabels.Length(); i++)
TopoDS_Shape aShape;
if ( SeqLabels.Value(i).IsNull() )

aShape = myAssembly_->GetShape( SeqLabels.Value(i) );
if (aShape.IsNull())

for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
if ( (it.Value()).ShapeType() == TopAbs_SOLID || (it.Value()).ShapeType() == TopAbs_SHELL )
else if ( (it.Value()).ShapeType() == TopAbs_COMPOUND )