Wrong normals in triangulation from IGES-file

Hello,

I am trying to use OpenCascade to build a mesh (OpenMesh) from an IGES-file.
My first try was to mesh the imported shape with BRepMesh_IncrementalMesh or BRepMesh_Discret.
In both triangulations there were wrong normals.
I dont see any errors in OpenCascade, but when I export the mesh to OpenMesh, it sais there are complex edges.
This means there are edges that have 3 neighbouring faces.

In my second attempt I wrote an STL-File with StlAPI_Writer and imported the stlfile to OpenMesh with the included stl-reader.
The effect was the same. I guess StlAPI_Writer uses the triangulation created by BRepMesh.

I dont really know what is wrong here.

Searching this forum I noticed there are many problems with normals in triangulations from IGES files, so I guess this is the problem.

Does anyone know how to fix the wrong normals?

Best regards,
Matthias

Matthias Teich's picture

I forgot to mention that I already use shapehealing to sew faces.

Everything seems to be fine when I use STEP files instead.

Matthias Teich's picture

Oh, fine was exaggerated. Lets say its better :(

dvdjimmy's picture

Hi Matthias,

check the Face Orientation. If the Orientation is different between different faces then also the normals of the mesh you generate will point to the wrong side.

I did quite a lot of mesh stuff with OCC and this was the way I used to solve that problems.

Take care,

dvdjimmy

Matthias Teich's picture

Hello,

thanks for your answer.
Can you elaborate a bit on this?

I am getting my triangulation of a face with

const Handle_Poly_Triangulation& triangulation = BRep_Tool::Triangulation(F,L);

and then I check its orientation with
if(F.Orientation() = TopAbs_REVERSED )
//add vertices counterclockwise to the Openmesh Datastructure
else
//add vertices clockwise

Then Openmesh calculates the normal by itself.

Do you mean I should set the orientation of each face to either Reversed or Forward?

Best Regards,
Matthias

Matthias Teich's picture

I just tried it, the normals are also messed up when all TopoDS_faces have the same orientation :(

dvdjimmy's picture

You can invert them to a specific direction if a certain treshold value is reached. For example if 60% of the normals show in one direction you can use this direction as the "guiding" direction and invert all the other triangle normals as well.

Before we do it like that we check the orientation agains 0,0,1 and then decide to which direction we invert the normals.

dvdjimmy

Matthias Teich's picture

I played a bit with the triangulation of OpenCascade and I came to the conclusion that the normals are not the problem.

This is a snippet of my code:

BRepTools::Clean(tshape);
BRepMesh_Discret(10, tshape, 5, true, true);
BRep_Builder builder;
TopoDS_Compound Comp;
builder.MakeCompound(Comp);

//für jedes Face im tshape
for (TopExp_Explorer ex(tshape,TopAbs_FACE); ex.More(); ex.Next()) {
const TopoDS_Face &F = TopoDS::Face(ex.Current());
TopLoc_Location L;
const Handle_Poly_Triangulation& triangulation = BRep_Tool::Triangulation(F,L);

//tab: Array mit den Vertices der Triangulation vom aktuellen Face
const TColgp_Array1OfPnt& tab = triangulation->Nodes();

const Poly_Array1OfTriangle &triangles = triangulation->Triangles();
for (Standard_Integer i=1; i<=(triangulation->NbTriangles()); i++)
{
const Poly_Triangle &triangle = triangles(i);
vector gp_Pnts(3);
for (int i = 0; i < 3; i++)
gp_Pnts[i] = tab(triangle(i+1));
BRepBuilderAPI_MakeEdge ME1 (gp_Pnts[0], gp_Pnts[1]);
if (ME1.IsDone())
builder.Add(Comp,(ME1.Edge()));
BRepBuilderAPI_MakeEdge ME2 (gp_Pnts[0], gp_Pnts[2]);
if (ME2.IsDone())
builder.Add(Comp,(ME2.Edge()));
BRepBuilderAPI_MakeEdge ME3 (gp_Pnts[1], gp_Pnts[2]);
if (ME3.IsDone())
builder.Add(Comp,(ME3.Edge()));
}
}

//display Comp

When I use this code, I get invalid triangulations like these:

[URL=http://img329.imageshack.us/my.php?image=stlnj5.jpg][IMG]http://img329.i...

Does anyone know what is going wrong with my code?

Best regards, Matthias

Matthias Teich's picture

Sorry for the ugly URL, I thought codes would work in this forum.
The url for the picture is
http://img329.imageshack.us/my.php?image=stlnj5.jpg

Rob Bachrach's picture

I am not sure if this is your problem, but you are not accounting for the face location in your triangulation. It is possible that 2 faces share the same triangulation but one is a transformed version of the other. Your points need to be transformed as well:

const Handle_Poly_Triangulation& triangulation = BRep_Tool::Triangulation(F,L);
gp_Trsf xloc = L;
.....
for (int i=0; i<3; ++i) {
gp_XYZ coord = tab(triangle(i+1)).Coord();
xloc.Transforms(coord);
gp_Pnts[i] = coord;
}
.....
}

Matthias Teich's picture

Hi,

thanks for your hint.
I just modified my code in the way you proposed.
The problem seems to be somewhere else, nothing changed :(

Now I use Netgen as a mesh generator, but nevertheless it would be interesting to know why the code did not work.
So if anyone has an idea..please let me know.

Best Regards,
Matthias Teich

Ling's picture

if (face.Orientation() == TopAbs_REVERSED)
{
triangles(j).Get(v1,v3,v2);
mesh.add_face( OpenMesh::VertexHandle(index+v1-1), OpenMesh::VertexHandle(index+v2-1), OpenMesh::VertexHandle(index+v3-1));
}
else
{
triangles(j).Get(v1,v2,v3);
mesh.add_face( OpenMesh::VertexHandle(index+v1-1), OpenMesh::VertexHandle(index+v2-1), OpenMesh::VertexHandle(index+v3-1));
}

the problem is face.Orientation() is always TopAbs_FORWARD,that the order of vetex is wrong,,so the normal is wrong ...