Build TopoDS_Shape from triangulation

Hello,

I know how to get the Poly_Triangulation from a given TopoDS_Shape ; but is it possible to do the inverse : build a TopoDS_Shape from a given Poly_Triangulation ?

Thank in advance

Bruno

Rob Bachrach's picture

Yes, but through brute force. Create edges from all the edges in your triangulation (BRepBuilderAPI_MakeEdge), wires from each triangle (BRepBuilderAPI_MakeWire), and faces from each wire BRepBuilderAPI_MakeFace with the OnlyPlane option set to Standard_True). Then, you can create a shell and use a BRep_Builder to add the faces to the shell. If necessary, a solid can be created from the shell with BRepBuilderAPI_MakeSolid.

If you do it correctly, you should end up with a properly connected shell. Your other option is to create the faces independantly (i.e., without sharing common edges) and then sew the faces together. This is a little easier to code, but will take longer to run.

Ideally, you would probably combine some of your triangles into polygons first, to minimize the total number of faces created.

Good luck.

Rob

Jeff Moody's picture

Rob,
I am trying to create a TopoDS_Shape from a triangulated mesh (in order to perform boolean operations). The mesh I'm using is from another API.
I have enough information to create a Poly_Triangulation (if your approach works, I won't need to use a Poly_Triangulation).

This solution seems fine, except for the following:
"Then, you can create a shell and use a BRep_Builder to add the faces to the shell."

I don't see any methods in BRep_Builder for adding faces to a shell.
How should this be done?

Also, how should the normals for the vertices be set?

Thanks.

Rob Bachrach's picture

Granted, it took a while to find the functionality, but here it is...

BRep_Builder shellBuilder;
TopoDS_Shell shell;
shellBuilder.MakeShell(shell);
for (...loop over triangular faces...) {
shellBuilder.Add(shell, thisFace);
}

You should not need to add normals to vertices. The only normals are those of the faces, which are governed by the order in which you add your vertices to the wire of the face. You can always call ShapeFix_Shell to try to fix normal directions after the fact.

Rob

Jeff Moody's picture

Thanks Rob.
The information I have about the mesh is what faces, vertices, and normals need to be in the mesh. The problem is that I don't know when to reverse the order of the vertex indices to create a face.

Do you know of a way to figure out what order to add the vertices based on the points and normals of the vertices?

Paul Jimenez's picture

If the order of the vertices is important to you, you must use cross and dot product.

Having the vertices v1, v2 and v3 of a triangle, if the [cross product] of the vectors (v1 to v2) and (v2 to v3) [dot product] any of the normals (N) is positive, then that's the right order. If it's negative, just add them in reverse order.

It would look like this: ( Vect(v1, v2) x Vect(v2, v3) ) dot N

I think that's the right equation...

Another option would be to create the TopoDS_Face from the three vertices then compare the normal of the face with that of any of the vertices. If it points in the wrong direction, just reverse the face (you can use dot product here too).

Jeff Moody's picture

Thanks Paul.
This seems to be the right equation.

I'm now have a case where there are faces to be added with the vertices added in reverse order. However, after creating the shape, when I try to iterate over the faces, I'm getting an exception when accessing these faces.

I created a method called IsReverse() which performs the calculation that you suggested.

Here's how I'm creating the face:
TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(point1);
TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(point2);
TopoDS_Vertex v3 = BRepBuilderAPI_MakeVertex(point3);
TopoDS_Wire wire;
if (IsReverse(mesh->GetFaceNormal(faceIndex), point1, point2, point3))
{
wire = BRepBuilderAPI_MakePolygon(v3, v2, v1, Standard_True);
}
else
{
wire = BRepBuilderAPI_MakePolygon(v1, v2, v3, Standard_True);
}
face = BRepBuilderAPI_MakeFace(wire, Standard_True);
~~~~~~~~~~~~~~

I'm also needing to use BRepOffsetAPI_Sewing and adding the faces to it in order to create either a shell or composite shape (since the faces I'm iterating over may not be added in the correct order).

I then triangulate the shape as:
BRepMesh::Mesh(shape, 1);

Then, I'm iterating over the faces as follows:
for (TopExp_Explorer ex(shape, TopAbs_FACE); ex.More(); ex.Next())
{
TopoDS_Shape currentShape = ex.Current();
TopoDS_Face face = TopoDS::Face(currentShape);
Handle (Poly_Triangulation) facing = BRep_Tool::Triangulation(face, location);
facing->NbTriangles();
}
~~~~~~~~~~~~

When it gets to the reversed face, the last line here throws an exception- presumably because the face is invalid. I.e. calling methods on facing throws an exception.

Do you know of another call that I may be missing when adding the face, or anything else you can tell that I'm doing wrong? I've tried calling the following just after creating the face (if it is reversed):
face.Orientation(TopAbs_REVERSED);

I'm still seeing the same behavior.

Jeff Moody's picture

Nevermind... I found out that for some reason, I'm seeing faces with vertex1 equal to vertex3.
Must be something else going on.