Triangulation using C# wrapper by Gerhard Hofmann

I try to do triangulation of a box using the C# wrapper provided by Gerhard Hofmann. It fails with Access violation. Here is the code:

TopoDS.Shape topoShape = new BRepPrimAPI.MakeBox(200, 40, 40).Shape();
//BRepMesh.General.Mesh(topoShape, 0.1);
TopExp.Explorer ex = new TopExp.Explorer(topoShape, TopAbs.ShapeEnum.FACE, TopAbs.ShapeEnum.SHAPE);

// Loop all faces
while (ex.More())
{
// Triangulate current face
TopoDS.Face F = TopoDS.General.Face(ex.Current());
TopLoc.Location L = new TopLoc.Location();
Poly.Triangulation facing = BRep.Tool.Triangulation(F, L);
if (facing != null)
{
int nbtris = facing.NbTriangles();

-------

It fails on facing.NbTriangles() with exception "Access violation in OpenCascade". What am I doing wrong?

Gerhard Hofmann's picture

Hello John,

I checked some old code where I used the triangulation. After the construction of the Poly.Triangulation object I called:
Poly.Array1OfTriangle arrayOfTriangle = triangulation.Triangles();
TColgp.Array1OfPnt p3d = triangulation.Nodes();
I also tried BRepMesh.Discret, which also worked.
Let me know if triangulation.Triangles() works, if not I will try to run your code.
Gerhard

rhymer's picture

Hello Gerhard,

Thank you for your reply. The call to Triangulation seems to work but exception occurs when I try to get count of triangles. The goal is to create 2 lists, one with vertices and one with triangles defined by those vertices (an indexed mesh). I have tried to convert C++ samples found in this forum to your C# wrapper. Complete code below:

------

using System;
using System.Collections.Generic;
using System.Text;

namespace OpenCASCADE
{
class Point3D
{
public double X;
public double Y;
public double Z;
}

class Mesh
{

public static void CreateMesh()
{

// The resulting lists containing vertices and triangle definition by index pointers to vertices
List vertices = new List();
List indecies = new List();

TopoDS.Shape topoShape = new BRepPrimAPI.MakeBox(200, 40, 40).Shape();
//BRepMesh.General.Mesh(topoShape, 0.1);
TopExp.Explorer ex = new TopExp.Explorer(topoShape, TopAbs.ShapeEnum.FACE, TopAbs.ShapeEnum.SHAPE);

// Loop all faces
while (ex.More())
{
// Triangulate current face
TopoDS.Face F = TopoDS.General.Face(ex.Current());
TopLoc.Location L = new TopLoc.Location();
Poly.Triangulation facing = BRep.Tool.Triangulation(F, L);
if (facing != null)
{
int nbtris = facing.NbTriangles();
//Poly.Array1OfTriangle tris = new Poly.Array1OfTriangle(1, nbtris);
Poly.Array1OfTriangle tris = facing.Triangles();
for (int i = 1; i <= nbtris; i++)
{
Poly.Triangle tri = tris.Value(i);
int index0 = 0, index1 = 0, index2 = 0;
tri.Get(ref index0, ref index1, ref index2);
indecies.Add(index0);
indecies.Add(index1);
indecies.Add(index2);
}

int nbnodes = facing.NbNodes();
//TColgp.Array1OfPnt nodes = new TColgp.Array1OfPnt(1, nbnodes);
TColgp.Array1OfPnt nodes = facing.Nodes();
for (int i = 1; i <= nbnodes; i++)
{
gp.Pnt node = nodes.Value(i);
Point3D p = new Point3D();
p.X = node.x;
p.Y = node.y;
p.Z = node.z;
vertices.Add(p);
}
}

ex.Next();
}

}
}

}

-----

The exception is "Access violation in OpenCascade" in the line "int nbtris = facing.NbTriangles();". I think I am using a pointer in the wrong way or something?

Gerhard Hofmann's picture

Hello John,
it is funny, when checking my old code there is never a call to NbTriangles, maybe I had the same problem. It is certainly not a wrong use of a pointer (which is not possible with this interface), it is more likely somethin uninitialized in that class which is only initialized after a call to a method, but I don't know...
So here is the code I used to accomplish the same task as you are trying to implement:

-------------
Poly.Triangulation triangulation = BRep.Tool.Triangulation(face, new TopLoc.Location());
Poly.Array1OfTriangle arrayOfTriangle = triangulation.Triangles();
TColgp.Array1OfPnt p3d = triangulation.Nodes();
points = new GeoPoint3D[p3d.Length()];
for (int i = 0; i < points.Length; ++i)
{
points[i] = p3d.Value(i + 1);
}
if (location != null)
{
gp.Trsf trsf = location.Transformation();
for (int i = 0; i < points.Length; ++i)
{
trsf.Transforms(out points[i].x, out points[i].y, out points[i].z);
}
}
TColgp.Array1OfPnt2d p2d = triangulation.UVNodes();
if (p2d != null)
{
uvpoints = new GeoPoint2D[p2d.Length()];
for (int i = 0; i < uvpoints.Length; ++i)
{
uvpoints[i] = p2d.Value(i + 1);
}
}
else
{
uvpoints = null;
}
triangles = new int[arrayOfTriangle.Length() * 3];
int l = arrayOfTriangle.Length();
for (int i = 0; i < l; ++i)
{
Poly.Triangle t = arrayOfTriangle.Value(i + 1);
triangles[3 * i] = t.Value(1) - 1;
triangles[3 * i + 1] = t.Value(2) - 1;
triangles[3 * i + 2] = t.Value(3) - 1;
}
--------------

Now I implemented the triangulation myself, because I needed more control and multithreading.

Gerhard

Gerhard Hofmann's picture

... does it work this way ...?

rhymer's picture

Gerhard, thank you for your help and fast replies! Actually I did my own C++ DLL which is callable from C# and implemented the code in C++ instead and it worked.

Willy Wuff's picture

I've got the same problem. "p3d.Length()" causes an access violation somewhere inside of the OpenCascade6.2.dll.

I need to use OCC for boolean operations and I have to get the result back to managed code. It Seems that I also have to write my own dll or is there any community code available?

Regards

Gilles Haiat's picture

Hi Willy
I have the same objective.

Did you find a solution?
Cheers

Artem Chernetzov's picture

Hello, Gerhard!

I try your code:

TColgp.Array1OfPnt p3d = triangulation.Nodes();
// points = new GeoPoint3D[p3d.Length()];
gp.Pnt[] points = new gp.Pnt[p3d.Length()];
//(I suppose GeoPoint3D is gp.Pnt, is it?...)

It throws "Access violation" exception in the line:
"points = new gp.Pnt[p3d.Length()];", at the p3d.Length() method...

Looks like Array1Of...(Points or Triangles) class causes this problem... Maybe someone find solution, how to convert Shape to Mesh?

Thanks for your help, Gerhard! ...

Gerhard Hofmann's picture

Hello Artem,

probably triangulation.Nodes() returns an invalid Array1OfPnt. The GeoPoint3D our own class, but that doesn't make a difference. I would expect there is some problem with the face, actually I used this method for a while but it was too less control and not very reliable. So I wrote my own method. Do you always have the access violation when calling p3d.Length() or only in certain circumstances?

Gerhard

P.S. write me an email when answering in the forum, the notification doesnt work

Artem Chernetzov's picture

When I manually create and fill Array1OfPnt all works, so you are right, Nodes() returns invalid array. Thanks, I'll search another method

Stephen Leary's picture

I also have this problem.

If the wrapper was open sourced we could find the problem and fix it.

Stephen

Gerhard Hofmann's picture

This is not a wrapper problem, try to make the same thing in C++ and you will get the same failure.
The wrapper code is automatically generated, so there would be no help in changing that code...
regards
Gerhard

Pawel's picture

if anyone still needs it - the solution is to call

BRepMesh.General.Mesh(topoShape, 0.01);

prior to any triangulation

Yaron Holdstein's picture

thanks a LOT, Pawel!