Contours on BSPSurface

Hi,

I am trying to convert some surfaces with boundaries/contours to meshes. I understand how to create a surface (thanks to the constructors of Geom_BSPSurface, Geom_Plane, Geom_ConicalSurface, Geom_SphericalSurface, Geom_ToroidalSurface ...) but I do not understand how to set the constraints on the boundaries/contours : I have boundaries compound by BSP curves, lines, ellipses, ... How can I add these boundaries on my surface so I can tessellate it to eventually get a mesh ?

Best regards,

MLR

 

Guido van Hilst not specified's picture

Hi Marc,

It depends on the type of the constrained curves:

If the curves are given in 2D, as curves in the parametric space of the surface,  then you can use BRepBuilderAPI_MakeEdge and BRepBuilderAPI_Makeface to construct the faces from the surfaces.

I have made an example : CurveOnSurface

If the curves are defined as 3D-curves (unrelated to the surfaces) you first have to project the 3D curves on the surface to obtain a parametric curve on the surface.

To get a triangulation of a shape see example: MakeMeshFromShape

Hope this points you in the right direction? :)

Best regards,

Guido

Marc LE RENARD's picture

Thanks a lot Guido !

I better understand (I think) the way to set the boundaries. I "just" have to implement that now :).

The tessellation process is more explicit too : I identified the BRepMesh_IncrementalMesh class but I had no idea how to parse the triangles.

I will  try that on monday now, have a nice WE.

Marc

Guido van Hilst not specified's picture

Hi Marc, Thank you for your replay!

I have made the code a bit more generic.

There is a function: OCTopoDS_Face face = FaceFromSurfaceAndCurves(cylinder, new OCGeom2d_Curve[] { lTop, lBottom, lLeft, lRight });

See: CurveOnSurface

​Have a nice WK too :)

Guido

Marc LE RENARD's picture

Hi,

The code is working pretty well ! Thanks a lot it has been fast to develop with your example. I used it (modifying it a bit) to manage various kind of surfaces & boundaries.

But ... :) ... using the process to cut planes is OK but when I try to do that with BSP surfaces, the tessellation is not working any more.

You can find below 3 parts of simplified code :

- one to generate the wire of a closed boundary (TopoDS_Wire)

- one to generate the BRep surface (topoDS_Face) adding the boundaries

- one to tessellate the BRep surface

Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape();
        
    for(unsigned int i = 0; i < curves.size(); i++)
    {
            Handle(Geom_Curve) c = curves[i];
                        
            // Project the curve on the surface ?
            //Handle(Geom_Curve) c2 = GeomProjLib::Project(c,p_surf);

            BRepBuilderAPI_MakeEdge me(c, c->FirstParameter(),c->LastParameter());
            BRepLib::BuildCurve3d(me.Edge());
            Edges->Append(me.Edge());
        }
    }
    
    // weld the edges to have only 1 wire for the boundary

    Handle(TopTools_HSequenceOfShape) Wires = new TopTools_HSequenceOfShape();
    // Connect all the edges to create a single wire
    ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Edges, WELD_TOLERANCE, false, Wires); 
    

    Handle(TopTools_HSequenceOfShape) ClosedWires = new TopTools_HSequenceOfShape();
    Handle(TopTools_HSequenceOfShape) OpenWires = new TopTools_HSequenceOfShape();
    ShapeAnalysis_FreeBounds::SplitWires(Wires,WELD_TOLERANCE,false,ClosedWires,OpenWires);
    Standard_Integer nbWires = ClosedWires->Length();
    
    if(nbWires>1) 
    {
        printf("Error : too much wires for the current boundary\n");
    }
    else if( nbWires==0)
    {
        printf("Error : no wire for the current boundary\n");
        return false;
    }

    TopoDS_Wire w= TopoDS::Wire(ClosedWires->Value(1));

     BRepBuilderAPI_MakeFace mf(m_surf,outerBoundary); // outerBoundaries[i] is a TopoDS_Wire 

    for(unsigned int i = 1; i < innerBoundaries.size(); i++)
    {
            mf.Add( innerBoundaries[i] ); // innerBoundaries[i] is a TopoDS_Wire 
    }
    
    TopoDS_Face f = mf;

     BRepMesh_IncrementalMesh im(f,0.2);

    im.Perform();

    TopLoc_Location faceLocation;

    Handle(Poly_Triangulation)   tri = BRep_Tool::Triangulation(f, faceLocation);

As you can see I did not project the curves (which are all "Geom_Curve") on my surface (I store all the surfaces as "Geom_Surface") before creating the wire for the boundary. I tried to do it but without success.

I was wondering if this is the reason why the tessellation fails (the surface is created, the wires for the boundaries seems to be OK too but the result of triangulation is NULL). Have you got any idea to solve this issue ? By the way, without boundaries the tessellation is working.

Guido van Hilst not specified's picture

Hi Marc,

I am not sure,but I think the inner boundaries are not related to the surface. (has PCurve on surface)

In my example the edges of the boundary and edges of the  innner wires are already related to the surface.

If surface is a plane I think BRepBuilderAPI_MakeFace can handle direct without PCurve.

If you attach a more complete code snipped, I can see if I can make it work?

Best regards,

Guido

Marc LE RENARD's picture

Hi,

I can eventually tessellate planes & others surfaces but the major issue I have got is to represent the curves (& surfaces but mostly the curves) in OCC.

I have to manage the following surfaces: BSplineSurfaces, Planes, Cones, Cylinders, Torus, Sphere, ruled surface, revolution, projection.

And boundaries can be set as combination of various kind of curves : BSplineCurve, polyline, ellipse, segment, and a "complex curve" which is a combination of any kind of curve.

I have chosen to store all the surfaces as "Geom_Surface". To do that I'd like to use the following classes or methods :

  • BSPlineSurface : Geom_BSplineSurface (working)
  • ​Planes : Geom_Plane (working)
  • Torus : Geom_ToroidalSurface (working)
  • Sphere : Geom_SphericalSurface (working)
  • Revolution: Geom_SurfaceOfRevolution (working)
  • Projection : Geom_SurfaceOfLinearExtrusion (working)
  • Ruled  surface : GeomFill::Surface (working)
  • Cones : GC_MakeTrimmedCone (not implemented/working) <<<<< 
  • Cylinders : BRepPrimAPI_MakeCylinder & BRep_Tool::Surface (error while trying to use the Face() method to give it to the BRep_Tool::Surface method )

I have chosen to store all the curves as "Geom_Curve". To do that I use the following process

  • BSplineCurve : Geom_BSplineCurve
  • ​PolyLine : Geom_BSplineCurve
  • Ellipse : gp_Elips / GC_MakeArcOfEllipse which enable me to get a Geom_TrimmedCurve
  • segment : GC_MakeSegment which enables me to get a Geom_TrimmedCurve
  • complex curve : get the curves (spline, polyline, segment, ellipse) and weld them using GeomConvert::CurveToBSplineCurve and GeomConvert::ConcatG1 to get a single curve 

I then apply the meshing process defined earlier in this thread without having to look at the type of surface/curve, everything "should" become generic (it will be great when everything will work ;) ).

What do you think about this representation and construction method ?

Best regards,

Marc

Marc LE RENARD's picture

Hi,

I have done a "generic" code to address any kind of surface I give to my program as Geom_Surface and to tessellate it (using its boundaries first to create a TopoDS_Face). Most of the surfaces seem to be tessellated a good way, but some of them are doing all the process (from Geom_Surface to TopoDS_Face) but triangulation fails (the result is empy - isNull() is true). It is difficult for me to know where I should look to solve that issue since no error message is given by Triangulation. Have you got any idea ? (modifying the parameters of tessellation ?)

Sometimes it fails while creating the projected boundary : BuildCurve3D raises an access violation on NULL address but everything goes well till BRepBuilderAPI_MakeEdge. ​ What kind of test should I do on BRepBuilderAPI_MakeEdge to check Edge validity before asking for BuildCurve3D ? Am I doing the process the right way ?

Here is my source code to process the Geom_Surface with its boundaries (array of Geom_Curve) into vertices & faces. It is a bit "raw" but should illustrate well the full process.

bool CBoundary::getWire(Handle(Geom_Surface) &p_surf,Handle(TopTools_HSequenceOfShape) & p_wire, bool p_projection)

{

        if(m_curves.size() == 0) // m_curves is a vector of curves describing a boundary (curves have "CCurve*" type : a CCurve can be a BSpline, a segment, a polyline, an ellipse,  group of CCurve, ...)

        {

                printf("Boundary is not valid\n");

                return false;

        }

        // Get all curves that compound the boundary and create a vector of edges

        TopoDS_Face f;

        if(p_projection) // we only need "f" if we have to project the curves on surface "m_surf" which is a Geom_Surface

        {

                try{

                        BRep_Builder aBuilder;

                        aBuilder.MakeFace (f, m_surf, Precision::Confusion() );

                }catch(Standard_Failure sf)

                {

                        printf("Error while creating TopoDS_Face from surface\n");

                        return false;

                }

        }

        Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape();

        for(unsigned int i = 0; i < m_curves.size(); i++)

        {

                CCurve * curve = dynamic_cast<CCurve*>(m_curves[i]);

                if(curve)

                {

                        Handle(Geom_Curve) c = curve->getCurve(); 

                        if(c.IsNull())

                                continue;

                        // DO we need to project the curves on the surface before (for non plane surfaces) ?

                        if(p_projection)

                        {

                                Handle(Geom2d_Curve) c2 = NULL;

                                // project the curve on surface (get a Geom2D_Curve as result)

                                try{

                                        Standard_Real tol = 1.0;

                                        BOPTools_AlgoTools2D::MakePCurveOnFace(f, c, c->FirstParameter(), c->LastParameter(), c2,tol);

                                }catch(Standard_Failure sf)

                                {

                                        printf("Error while projecting boundary's curve on surface\n");

                                        continue;

                                }

        

                                if(c2.IsNull())

                                {

                                        printf("Error with projected curve on surface\n");

                                        continue;

                                }

                                // build the edges from the Geom2D_Curve (result of the projection of the 3D curve on the surface)

                                BRepBuilderAPI_MakeEdge me(c2, p_surf);

                                try{

                                        TopoDS_Edge e = me.Edge();

                                        if(!e.IsNull())

                                        {

                                                if(BRepLib::BuildCurve3d(e))

                                                        Edges->Append(e);

                                        }

                                        else

                                        {

                                                printf("Error while building 3D curve (Edges) from projected boundary's curve\n");

                                                continue;

                                        }

                                }catch(Standard_Failure sf)

                                {

                                        printf("Error while creating edge from projected boundary's curve\n");

                                        continue;

                                }

                        }

                        else

                        {

                                // use the curve as if, it is mostly used for planes

                                BRepBuilderAPI_MakeEdge me(c, c->FirstParameter(),c->LastParameter());

                                try{

                                        TopoDS_Edge e = me.Edge();

                                        if(BRepLib::BuildCurve3d(e))

                                                Edges->Append(e);

                                        else

                                        {

                                                printf("Error while building 3D curve (Edges) from boundary's curve\n");

                                        }

                                }catch(Standard_Failure sf)

                                {

                                        printf("Error while creating edge from boundary's curve\n");

                                        continue;

                                }

                        }

                }

        }

        // weld the edges to have only 1 wire for the boundary

        Handle(TopTools_HSequenceOfShape) Wires = new TopTools_HSequenceOfShape();

        // Connect all the edges to create a single wire

        try{

                ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Edges, WELD_TOLERANCE, false, Wires); // if shared = true , the connection is done only if the vertices are the same

        }catch(Standard_Failure sf)

        {

                printf("Error while creating wires from Edges\n");

                return false;

        }

        if(Wires.IsNull() || Wires->Length()==0)

                return false;

        return true;

}

bool CSurfaceWithBoundaries::getFace(TopoDS_Face & p_face)​

{

        if(!m_surf)

                return false;

        // Get inner boundaries in a list

        Handle(TopTools_HSequenceOfShape) outerBoundary;

        CPlane * p = dynamic_cast<CPlane*>(this);

        if(!m_boundaries[0]->getWire( m_surf , outerBoundary , p?false:true)) // m_boundaries is a vector of boundaries (the first one is the outer one, all the others are inner)

        {

                printf("No boundary for the surface \n");

                return false;

        }

        BRepBuilderAPI_MakeFace mf(m_surf, TopoDS::Wire(outerBoundary->Value(1)) );

        for(int k = 1; k < outerBoundary->Length(); k++)

                mf.Add( TopoDS::Wire(outerBoundary->Value(k+1)) );   // Not sure about that, the wires shouldn't be added while constructing the face (BRepBuilderAPI_MakeFace

        Handle(TopTools_HSequenceOfShape) innerBoundary;

        for(unsigned int i = 1; i < m_boundaries.size(); i++)

        {

                if(m_boundaries[i]->getWire(m_surf, innerBoundary))

                {

                        for(int k = 0; k < innerBoundary->Length(); k++)

                                mf.Add( TopoDS::Wire(innerBoundary->Value(k+1)) );

                }

        }

        try{

                p_face = mf.Face();

        }catch(Standard_Failure sf)

        {

                printf("Error while constructing face from Geom_Surface & boundaries\n");

                return false;

        }

        return true;

}

bool CSurfaceWithBoundaries::getMesh(double p_lineDeflection, bool p_isRelative, double p_angleDeflection, bool p_isInParallel, bool p_adaptiveMin)

{

        if(p_vertices)

        {

                free(p_vertices);

                p_vertices = NULL;

        }

        if(p_faces)

        {

                free(p_faces);

                p_faces = NULL;

        }

        p_nbVertices = p_nbFaces = 0;

        TopoDS_Face f;

        if(!getFace(f))

                return false;

        BRepMesh_IncrementalMesh im(f,p_lineDeflection, p_isRelative,p_angleDeflection,p_isInParallel,p_adaptiveMin);

        im.Perform();

        if(!im.IsDone())

        {

                printf("No way to create a mesh from the surface [%s]\n",m_name.c_str());

                return false;

        }

        TopLoc_Location faceLocation;

        Handle(Poly_Triangulation) tri;

        try{

                tri = BRep_Tool::Triangulation(f, faceLocation);

        }catch(Standard_Failure sf)

        {

                printf("No triangulation available [%s]\n",m_name.c_str());

        }

        bool reversed = ( f.Orientation() == TopAbs_Orientation::TopAbs_REVERSED );

        if (!tri.IsNull())

        {

                Poly_Array1OfTriangle triangles = tri->Triangles();

                TColgp_Array1OfPnt nodes = tri->Nodes();

                // Store the processed mesh there

         }

        else

        {

                printf("No triangulation available for this surface [%s]\n", this->m_name.c_str());

                return false;

        }

        return true;

}

Marc LE RENARD's picture

I won't be able to send you code before next wednesday :'( ... I will try to write you a full (but simple) example of what I'd like to do on wednesday. Thanks again for the help.

EDIT : It seems I do not understand well the process to create the boundaries on surfaces from Geom_Curve objects. I tried to project the curves on the surface to create the boundaries but it was not really efficient. To summarize : I have an object (Geom_Surface) & some boundaries (Geom_Curves) and I would like to cut the surface with the boundaries (I have uploaded a drawing to illustrate the process I would like to achieve). I have implemented the process following your advises :

- get the surface & boundaries and store them

- convert each boundary as a wire (*)

              - using BRepBuilderAPI_MakeEdge to get edges from each curve of the boundary

              -  ShapeAnalysis_FreeBounds::ConnectEdgesToWires to create a single wire (and ShapeAnalysis_FreeBounds::SplitWires to get the first closed wire)

- create a Face using BRepBuilderAPI_MakeFace and add each boundary as wire (with the Add method)

- then I tessellate the face using BRepMesh_IncrementalMesh & BRep_Tool::Triangulation

(*) I tried to use BOPTools_AlgoTools2D::MakePCurveOnFace to project the Geom_curve as Geom2d_curve (inspired by the following post :  https://www.opencascade.com/content/topodsedge-built-geom2dcurve-and-geomsurface-has-not-pcurve-face but It is not working on planes any more :), and it gives a result on BSP surfaces but not the one I waited for; when I "mesh" it, only the boundaries are used to create the triangles, it seems to not take into account the BSplineSurface).

It is quite difficult to get a source code from my project since it is developed to be quite generic and create the surfaces/curves from files (surfaces & curves creation checked displaying them in the open cascade MFC sample app Geometry). I will try to create an example in a single file and post it there asap.

Do you think I am on the right way to apply boundaries on any kind of surfaces to tessellate them or should I rewrite the full process ?

re - EDIT ! Eventually, it seems that tessellation is working with other surfaces than planes when projection is done ... I did set the angle degeneration too high in BRepMesh_IncrementalMesh !

Marc LE RENARD's picture

Eventually I identified one of the surface I import which raises an exception in the program. I wrote a code to set it as raw data and do the process I would like to achieve. You may be able to see better where is my mistake (because I must be doing one but no way to have a clue on that !).

The code should generate a tessellated "Arc" of cylinder as final result (if using the triangles & nodes arrays).

You can find the full source code below. The exception is raised while trying to call BuildCurve3D (for the first curve, the first segment):

#include "Geom_CylindricalSurface.hxx"
#include "TopoDS_Edge.hxx"
#include "TopoDS_Wire.hxx"
#include "gp_Ax2.hxx"
#include "gp_Ax3.hxx"
#include "BRep_Builder.hxx"
#include "BOPTools_AlgoTools2D.hxx"
#include "BRepBuilderAPI_MakeEdge.hxx"
#include "GC_MakeSegment.hxx"
#include "gp_Elips.hxx"
#include "GC_MakeArcOfEllipse.hxx"
#include "BRepLib.hxx"
#include "ShapeAnalysis_FreeBounds.hxx"
#include "BRepBuilderAPI_MakeFace.hxx"
#include "TopoDS.hxx"
#include "BRepMesh_IncrementalMesh.hxx"


int main(int argc, char ** argv)
{

	gp_Pnt cent(141.920000, 3.679000, 0.268000);

	gp_Dir norm(1.000000, 0.000000, 0.000000);

	gp_Vec mAxis(0.000000, -0.012000, 0.000000);

	double r = mAxis.Magnitude();

	gp_Dir xAxis(mAxis);

	gp_Ax3 axis(cent,norm,xAxis);

	Handle(Geom_Surface) surf = new Geom_CylindricalSurface(axis,r);





	BRep_Builder aBuilder;

	TopoDS_Face f;

	aBuilder.MakeFace(f, surf, Precision::Confusion() );





	std::vector<Handle(Geom_Curve)> outerBoundary;



	gp_Pnt b1(141.920000,3.691000,0.268000);

	gp_Pnt e1(156.980000,3.691000,0.268000);

	GC_MakeSegment mkSeg(b1,e1);

	outerBoundary.push_back(mkSeg.Value());





	gp_Pnt el1Center(156.980000, 3.679000, 0.268000);

	gp_Dir el1Norm(-1.000000, 0.000000, 0.000000);

	gp_Vec el1MAxis(0.000000, -0.012000, 0.000000);

	gp_Dir el1xAxis(el1MAxis);

	gp_Ax2 el1Axis(el1Center, el1Norm, el1xAxis);

	double radius = el1MAxis.Magnitude();

	gp_Elips el1(el1Axis,radius, radius);

	GC_MakeArcOfEllipse aoe1(el1,3.141593,4.188790,Standard_True);

	outerBoundary.push_back(aoe1.Value());





	gp_Pnt b2(156.980000,3.685000,0.257608);

	gp_Pnt e2(141.920000,3.685000,0.257608);

	GC_MakeSegment mkSeg2(b2,e2);

	outerBoundary.push_back(mkSeg2.Value());





	gp_Pnt el2Center(141.920000, 3.679000, 0.268000);

	gp_Dir el2Norm(1.000000, 0.000000, 0.000000);

	gp_Vec el2MAxis(0.000000, -0.012000, 0.000000);

	gp_Dir el2xAxis(el2MAxis);

	gp_Ax2 el2Axis(el2Center, el2Norm, el2xAxis);

	double radius2 = el2MAxis.Magnitude();

	gp_Elips el2(el2Axis,radius2, radius2);

	GC_MakeArcOfEllipse aoe2(el2,2.094395,3.141593,Standard_True);

	outerBoundary.push_back(aoe2.Value());





	Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape();

	std::vector<Handle(Geom_Curve)>::iterator it = outerBoundary.begin();

	for(;it!=outerBoundary.end(); it++)

	{

		Handle(Geom_Curve) c = *it;

		Handle(Geom2d_Curve) c2 = NULL;

		Standard_Real tol = 1.0;

		BOPTools_AlgoTools2D::MakePCurveOnFace(f, c, c->FirstParameter(), c->LastParameter(), c2,tol);

		// build the edges from the Geom2D_Curve (result of the projection of the 3D curve on the surface)

		BRepBuilderAPI_MakeEdge me(c2, surf);

		TopoDS_Edge e = me.Edge();

		BRepLib::BuildCurve3d(e);   // Exception raised : first chance exception, access violation reading at address 0x0000000000000000 (but I cannot find the null pointer in "e")

		Edges->Append(e);

	}



	Handle(TopTools_HSequenceOfShape) Wires = new TopTools_HSequenceOfShape();

	// Connect all the edges to create a single wire

	ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Edges, 0.0001, false, Wires); // if shared = true , the connection is done only if the vertices are the same





	BRepBuilderAPI_MakeFace mf(surf, TopoDS::Wire(Wires->Value(1)) );

	for(int k = 1; k < Wires->Length(); k++)

		mf.Add( TopoDS::Wire(Wires->Value(k+1)) );   // should not be called since only 1 wire may be generated



	TopoDS_Face face2Tessellate = mf.Face();





	BRepMesh_IncrementalMesh im(face2Tessellate,0.1, true ,0.1 ,false, false);

	im.Perform();

	TopLoc_Location faceLocation; // faceLocation will not be used 

	Handle(Poly_Triangulation) tri;

	tri = BRep_Tool::Triangulation(f, faceLocation);

	if(!tri.IsNull())

	{

		Poly_Array1OfTriangle triangles = tri->Triangles();

		TColgp_Array1OfPnt nodes = tri->Nodes();

	}

	return 0;
}
Marc LE RENARD's picture

Hi,

I am beginning to understand which is not working (but not why for the moment :) ).

I tried various way of projecting the curves on surfaces using BRep_Tool::CurveOnSurface / BOPTools_AlgoTools2D::MakePCurveOnFace / GeomProjLib::Project + GeomProjLib::Curve2D and it seems the first one is faster than the others BUT, for some reasons I cannot explain, using it for cylindrical surfaces will crash the program (as far as I want to buildCurve3D from the resulting Edges). I use GeomProjLib for cylindrical surface and it seems to work quite well for some of them. 

Have you ever encounter this issue projecting on this kind of surfaces ?

Guido van Hilst not specified's picture

If you can isolate the problem for witch surface and curve it goes wrong, I can have a look?

Marc LE RENARD's picture

Hi Guido,

You can find an example of the surface which does not work well with the process I developed in one of my previous post. I replaced BOPTools_AlgoTools2D::MakePCurveOnFace by BRep_Tool::CurveOnSurface, but then the resulting 2D curve is null. All the curves I use are defined so they are already described to be on the surface (but I still need to project them to process BRepBuilderAPI_MakeFace) since they are from another BRep description (but not using the same surface description as OpenCascade does). I will post you the OBJ export so you can view the result if it is working for you. I think the process I developed should not be the correct one to address any kind of surfaces (when you look at it what do you think about the way I project on surface & create the boundaries/triangulation ?).

NB : As most of my cylinder surfaces are described with simple boundary (arc of ellipse, segment following the axis of the cylinder, arc of ellipse , segment following the cylinder axis), I just created a GeomFill::Surface between the 2 arcs of ellipse. But this is more a trick than a solution. This enables me to get more surfaces but not all of them.

Best regards

Marc

Marc LE RENARD's picture

Hi,

Back on this issue ! I isolated a simple case : projection of a circle on a cylinder

I just cannot understand why I cannot project an ellipse on a cylindrical surface ? I tried to but the Geom2d_Curve returned is always empty (null).

The little section of code I used to test that is the following one : I create a cylindrical surface and an ellipse with exactly the same parameters (axis, radius, center).

	gp_Pnt center(0.0, 0.0, 0.0);
	gp_Dir normal(0.0, 0.0, 1.0);
	gp_Dir xAxis(1.0, 0.0, 0.0 );
	gp_Ax3 axis(center, normal, xAxis);
	double r = 1.0;


	Handle(Geom_Surface) surf = new Geom_CylindricalSurface(axis, r);
	BRepBuilderAPI_MakeFace mf(surf, Precision::Confusion());
	TopoDS_Face f = mf.Face();

	gp_Elips el1(axis, r, r);
	GC_MakeArcOfEllipse aoe1(el1, 0.0, 2 * M_PI,Standard_True);
	Handle(Geom_Curve) bottom = aoe1.Value();
	BRepBuilderAPI_MakeEdge eBottom(bottom);
	double first = bottom->FirstParameter();
	double last = bottom->LastParameter();
	Handle(Geom2d_Curve) bottom2D = BRep_Tool::CurveOnSurface(eBottom.Edge(), f, first, last);

But the ellipse projection fails : bottom2D is always null ! :( "Something is rotten in the state of Denmark" :). Seriously, may I use another method to project any curve on my cylinder (projection of segments on cylinder is null too), or should I create the cylinder surface another way ?

I hope someone could help me ( Guido :) ? )

Guido van Hilst not specified's picture

Hi Marc,

In your example (above), there is no relation between the Edge and the Face. The edge is "on" the surface but they are unrelated.

To get the "CurveOnSurface" you have to project the edge on the Face. the result is an new edge that contains a CurveOnSurface on the surface of the face.

Here is the example: EdgeOnFace

​The edge now contains a 3DCurve(Ellipse with same radii) and a CurveOnSurface(BSplineCurve) (see dump below)

​the curve on surface is theoretical a 2D straight line in the parametric space of the surface from (0,0) to (2*PI,0)

But in the dump below you can see that the projection has made a BSplineCurve representation of the straight line.

Hopes it get you on track? 

Best regards, Guido

Dump:
Shape : 2, FORWARD

Dump of 2 TShapes

-----------------

Flags : Free, Modified, Checked, Orientable, Closed, Infinite, Convex

TShape # 1 : EDGE      0101000 0000000129C3A0F0
    +2 -2 
    Tolerance : 0.0001
     same parametrisation of curves
     same range on curves
    - Curve 3D : 1, range : 0 6.28319
    - PCurve : 1 on surface 1, range : 0 6.28319

  UV Points : 0, 0 6.28319, 0

TShape # 2 : VERTEX    0101101 000000012A2A8E70
    
    Tolerance : 0.0001
    - Point 3D : 1, 0, 0

 -------
Dump of 1 Curve2ds 
 -------

   1 : Trimmed curve
Parameters : 0 6.28319
Basis curve :
BSplineCurve
  Degree 1, 2 Poles, 2  KnotsPoles :

   1 : 0, 0 
   2 : 6.28319, 0 
Knots :

   1 : 0 2
   2 : 6.28319 2

 -------
Dump of 1 Curves 
 -------

   1 : Ellipse
  Center :0, 0, 0 
  Axis   :0, 0, 1 
  XAxis  :1, 0, -0 
  YAxis  :-0, 1, 0 
  Radii  :1, 1

 -------
Dump of 0 Polygon3Ds
 -------
 -------
Dump of 0 PolygonOnTriangulations
 -------

 -------
Dump of 1 surfaces 
 -------

   1 : CylindricalSurface
  Origin :0, 0, 0 
  Axis   :0, 0, 1 
  XAxis  :1, 0, -0 
  YAxis  :-0, 1, 0 
  Radius :1

 -------
Dump of 0 Triangulations
 -------

 -------
 Dump of 0 Locations
 -------

Marc LE RENARD's picture

Thanks a lot for your help ! I try that immediately.

Marc LE RENARD's picture

2D curves are all generated properly ! Thanks again.

I now try to generate wires from these curves to generate a finite surface but it seems I still misunderstood something. Here is the code I wrote :

	Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape();

	gp_Pnt center(0.0, 0.0, 0.0);
	gp_Dir normal(0.0, 0.0, 1.0);
	gp_Dir xAxis(1.0, 0.0, 0.0);
	gp_Ax3 axis(center, normal, xAxis);
	double r = 1.0;
	Handle(Geom_Surface) surf = new Geom_CylindricalSurface(axis, r);
	BRepBuilderAPI_MakeFace mf(surf, Precision::Confusion());
	TopoDS_Face f = mf.Face();
	BRepOffsetAPI_NormalProjection pr(f);

	gp_Pnt el1Center(0.0, 0.0, 0.0);
	gp_Dir el1Norm(0.0, 0.0, 1.0);
	gp_Dir el1xAxis(1.0, 0.0, 0.0);
	gp_Ax2 el1Axis(el1Center, el1Norm, el1xAxis);
	gp_Elips el1(el1Axis, r, r);
	GC_MakeArcOfEllipse aoe1(el1, 0.0, 2 * M_PI, Standard_True);
	Handle(Geom_Curve) bottom = aoe1.Value();
	BRepBuilderAPI_MakeEdge eBottom(bottom);
	pr.Add(eBottom);

	gp_Pnt el2Center(0.0, 0.0, 1.0);
	gp_Dir el2Norm(0.0, 0.0, -1.0);
	gp_Dir el2xAxis(1.0, 0.0, 0.0);
	gp_Ax2 el2Axis(el2Center, el2Norm, el2xAxis);
	gp_Elips el2(el2Axis, r, r);
	GC_MakeArcOfEllipse aoe2(el2, 0.0, 2 * M_PI, Standard_True);
	Handle(Geom_Curve) top = aoe2.Value();
	BRepBuilderAPI_MakeEdge eTop(top);
	pr.Add(eTop);

	pr.Build();

	if (pr.IsDone())
	{
		TopoDS_Shape s = pr.Projection();
		TopExp_Explorer exp(s, TopAbs_EDGE);
		for (; exp.More(); exp.Next())
		{
			TopoDS_Edge edge = TopoDS::Edge(exp.Current());
			double first, last;
			Handle(Geom2d_Curve) c2D = BRep_Tool::CurveOnSurface(edge, f, first, last);
			if (!c2D.IsNull())
			{
				TopoDS_Edge edge2D = BRepBuilderAPI_MakeEdge(c2D, surf);
				if (!edge2D.IsNull() && BRepLib::BuildCurve3d(edge2D))
						Edges->Append(edge2D);
			}
		}

		Handle(TopTools_HSequenceOfShape) Wires = new TopTools_HSequenceOfShape();
		ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Edges, Precision::Confusion(), Standard_False, Wires);

		for (unsigned int i = 0; i < Wires->Length(); i++)
			mf.Add(TopoDS::Wire(Wires->Value(i + 1)));

		mf.Build();

		if (mf.IsDone())
		{
			TopoDS_Face face2Tessellate = mf.Face();
			BRepMesh_IncrementalMesh im(face2Tessellate, 1.0, true, 1.5, false, false);
			im.Perform();
			TopLoc_Location faceLocation; // faceLocation will not be used 
			Handle(Poly_Triangulation) tri;
			tri = BRep_Tool::Triangulation(face2Tessellate, faceLocation);
			if (tri.IsNull())
			{
				printf("No way to apply triangulation\n");
			}
			else
			{
				Poly_Array1OfTriangle triangles = tri->Triangles();
				TColgp_Array1OfPnt nodes = tri->Nodes();
			}
		}
	}

The triangulation does not work even if wires are generated :(. I tried on other surfaces and tessellation is never generated while using the normalProjection method on boundary curves.