Tessellate edges from a TopoDS_Shape

Hi,

I posted this question already in the old forum and was adviced, that I shall use the new one. Therefore, I post my question here. I will also add all answers so far.

my original question

I need to get all contours which are within a STEP file and to process them. I need the curves as point list. Therefore, I need to tessellate the edges of my shape.

Atm I read the step file and iterate over the edges. I found some examples how to triangulate a face, but nothing about the edges.

So how can I get a nice tessellation of my edges?

STEPControl_Reader reader;
if (reader.ReadFile("pipe.stp") != IFSelect_RetDone)
    return -1;

// Root transfers
reader.TransferRoots();

//
auto nbs = reader.NbShapes();
for (Standard_Integer i = 1; i <= nbs; ++i)
{
    auto shape = reader.Shape(i);

    TopExp_Explorer ex_ed;
    for (ex_ed.Init(aMesh.Shape(), TopAbs_EDGE); ex_ed.More(); ex_ed.Next())
    {
        BRepAdaptor_Curve adapt_crv = BRepAdaptor_Curve(TopoDS::Edge(ex_ed.Current()));

        //how to tesselate my edge/curve into a vector of points
    }        
}

Answer from Kirill Gavrilov

BRepMesh_IncrementalMesh creates tessellation for both - Faces and Edges.
The latter hold Poly_Polygon3D (defining polyline) or Poly_PolygonOnTriangulation (defining indexes of Poly_Triangulation nodes on a Face)
and accessible in the same matter as triangulation of Face - using methods BRep_Tool::Polygon3D() and BRep_Tool::PolygonOnTriangulation().

You may also use tools like GCPnts_TangentialDeflection/GCPnts_QuasiUniformDeflection on specific curve if you don't want to use BRepMesh_IncrementalMesh.

My following  question:

OK, I found a general solution with GCPnts_TangentialDeflection (see example code below).

But I have a problem with a pipe. My pipe is defined by end contours (outer and inner on the left and on the right) which are connected. So you got 2 cylindrical surfaces and 2 connecting surfaces (a special case would be a hollow cylinder)

I only want  to have the curves which defines the contours. But when iterating over the content of my STEP file with the below code, I also got connection lines between the left and right contours.

Why is OC introducing these curves? How can I prevent this?

auto nbs = reader.NbShapes();
for (Standard_Integer i = 1; i <= nbs; ++i)
{
	auto shape = reader.Shape(i);	
	
	TopExp_Explorer ex_ed;
	for (ex_ed.Init(shape, TopAbs_EDGE); ex_ed.More(); ex_ed.Next())
	{

		BRepAdaptor_Curve adapt_crv = BRepAdaptor_Curve(TopoDS::Edge(ex_ed.Current()));
		auto type = adapt_crv.GetType();

		GCPnts_TangentialDeflection discretizer(adapt_crv, 0.5, 0.1);
		if (discretizer.NbPoints() > 1)
		{
			for (int i = 2; i <= discretizer.NbPoints(); ++i)
			{
				gp_Pnt p_0 = discretizer.Value(i - 1);
				gp_Pnt p_1 = discretizer.Value(i);

				dxf_writer.addLine(0, nullptr, Wm5::Vector3d(p_0.X(), p_0.Y(), p_0.Z()), Wm5::Vector3d(p_1.X(), p_1.Y(), p_1.Z()));
			}
		}
	}	
}	

Answer from Mikhail Sazonov

These lines are so-named 'seam' edges. They are needed to close the cylinder in 2D parametric space. Without them the shape would be considered invalid from point of view of OCCT data model. You can ignore them in your code by querying BRep_Tool::IsClosed (edge, face). For that, you need to explore your shape on faces, then explore each face on edges.

Marco's picture

And here my current question and last post in the old forum:

Hi Mikhail Sazonov,

thank you very much. That works!

One further question. Must I take care about getting the same edges multiple times? When iterating over the faces of the shapes, I suppose that I get every edge twice, because the faces share edges. Is this right?

 
Thank you!

Giovanni Bettega's picture

Hi, use TopExp::mapShapes in order to have unique subshapes. 

Marco's picture

Hi,

TopExp::mapShapes didn't help. To detect 'seam' edges I iterate over the faces and then over the edge of every face. I suppose mapShapes would only work if I get the edges directly from the solid without iterating over the faces.

I tried another way: I push every written edge to a vector and check every egde if it isn't in the container yet by using IsEqual:

if (std::find_if(written_edges.begin(), written_edges.end(), [&edge](auto& other) { return other.IsEqual(edge); }) != written_edges.end())
	continue;

written_edges.emplace_back(edge);

But this doesn't work. If I have TopoDS_Edge objects: how can I check if they reference the same edge in my solid? IsEqual doesn't work.

The whole loop code:

int count_writes{};

//
std::vector<TopoDS_Edge> written_edges;
auto nbs = reader.NbShapes();
for (Standard_Integer i = 1; i <= nbs; ++i)
{
	auto shape = reader.Shape(i);

	//we must iterate over the faces to check for closed loops to recognize 'seam' edges
	TopExp_Explorer ex_face;
	for (ex_face.Init(shape, TopAbs_FACE); ex_face.More(); ex_face.Next())
	{
		auto face = TopoDS::Face(ex_face.Current());

		TopExp_Explorer ex_ed;
		
		for (ex_ed.Init(ex_face.Current(), TopAbs_EDGE); ex_ed.More(); ex_ed.Next())
		{
			auto edge = TopoDS::Edge(ex_ed.Current());
		
			//check if the edge is really and egde and not a seam
			if (BRep_Tool::IsClosed(edge, face))
				continue;

			if (std::find_if(written_edges.begin(), written_edges.end(), [&edge](auto& other) { return other.IsEqual(edge); }) != written_edges.end())
				continue;

			written_edges.emplace_back(edge);

			BRepAdaptor_Curve adapt_crv = BRepAdaptor_Curve(edge);
			auto type = adapt_crv.GetType();

			GCPnts_TangentialDeflection discretizer(adapt_crv, 0.5, 0.1);
			if (discretizer.NbPoints() > 1)
			{
				for (int i = 2; i <= discretizer.NbPoints(); ++i)
				{
					gp_Pnt p_0 = discretizer.Value(i - 1);
					gp_Pnt p_1 = discretizer.Value(i);

					dxf_writer.addLine(0, nullptr, Wm5::Vector3d(p_0.X(), p_0.Y(), p_0.Z()), Wm5::Vector3d(p_1.X(), p_1.Y(), p_1.Z()));
					++count_writes;
				}
			}
			//BRepMesh_CurveTessellator crv_tess(adapt_crv,);
		}
	}
}