Getting surface trim parameters

I have a solid with a NURBS face, loaded from a STEP file, and I want to slice it with a vertical plane using the volume maker class (BOPAlgo_MakerVolume). The resulting shape was correct that it contains 2 solids, each with a half of the initial NURBS. However, when I tried to retrieve the underlying surfaces of these new NURBS faces using BRep_Tool::Surface(), I seem to always get the original NURBS surface, while I was expecting to get two halves of it. I suppose there must be new u and v parameters to trim the surface, like how after a spline curve is trimmed, the new u parameters are extracted using BRep_Tool::Curve(). However, there are no such arguments with BRep_Tool::Surface(). Is there any way to get these parameters, or it is supposed to be done differently?

The snippet is available below, and some screenshots are attached.

  • input-solid-with-nurbs-face.png --> the input solid
  • output-2-solids-with-nurbs-faces.png --> the whole output solid
  • output-1-solid-only.png --> one of the output solid's two halves
  • output-face-from-surface.png --> the output face in question. Please note that the output face was generated by performing the conversion output face --> extract surface --> create a face, not the first generated face, to give a visualisation of the extracted surface.

I use OCCT version 7.2.0.

// Load the input NURBS solid
STEPControl_Reader reader;
reader.ReadFile("input//nurbs_solid.stp");
reader.TransferRoots();
TopoDS_Shape nurbsSolid = reader.OneShape();

// Save the input face to a STEP file
TopExp_Explorer occtExplorer1;
for (occtExplorer1.Init(nurbsSolid, TopAbs_FACE); occtExplorer1.More(); occtExplorer1.Next())
{
	const TopoDS_Shape& occtCurrent = occtExplorer1.Current();
	TopoDS_Face occtFace = TopoDS::Face(occtCurrent);
	Handle(Geom_Surface) pOcctSurface = BRep_Tool::Surface(occtFace);

	Handle(Geom_BSplineSurface) pOcctBSplineSurface = Handle_Geom_BSplineSurface::DownCast(pOcctSurface);
	if (!pOcctBSplineSurface.IsNull())
	{
		TopoDS_Face bSplineFace = BRepBuilderAPI_MakeFace(pOcctBSplineSurface, 0.0);
		STEPControl_Writer writer;
		writer.Transfer(bSplineFace, STEPControl_AsIs);
		writer.Write("output//nurbs_solid_slice_out_only_NURBS_input_face.stp");
		continue;
	}
}

// build the cutting plane
gp_Pnt p1(-10,5,-10);
gp_Pnt p2(20, 5, -10);
gp_Pnt p3(20, 5, 20);
gp_Pnt p4(-10, 5, 20);

TopoDS_Vertex v1 = BRepBuilderAPI_MakeVertex(p1);
TopoDS_Vertex v2 = BRepBuilderAPI_MakeVertex(p2);
TopoDS_Vertex v3 = BRepBuilderAPI_MakeVertex(p3);
TopoDS_Vertex v4 = BRepBuilderAPI_MakeVertex(p4);

TopoDS_Edge e_1_2 = BRepBuilderAPI_MakeEdge(v1, v2);
TopoDS_Edge e_2_3 = BRepBuilderAPI_MakeEdge(v2, v3);
TopoDS_Edge e_3_4 = BRepBuilderAPI_MakeEdge(v3, v4);
TopoDS_Edge e_4_1 = BRepBuilderAPI_MakeEdge(v4, v1);

TopoDS_Wire w = BRepBuilderAPI_MakeWire(e_1_2, e_2_3, e_3_4, e_4_1);
TopoDS_Face f = BRepBuilderAPI_MakeFace(w);

// slice the NURBS solid with the plane
BOPAlgo_MakerVolume volumeMaker;
BOPCol_ListOfShape shapes;
shapes.Append(nurbsSolid);
shapes.Append(f);
volumeMaker.SetRunParallel(Standard_False);
volumeMaker.SetIntersect(Standard_True);
volumeMaker.SetFuzzyValue(0.0);
volumeMaker.SetArguments(shapes);
	
volumeMaker.Perform(); //perform the operation
if (volumeMaker.HasErrors() || volumeMaker.HasWarnings()) { //check error status
		
}

const TopoDS_Shape& aResult = volumeMaker.Shape(); // result of the operation
	
// get the first NURBS face from the output solid and save it to a STEP file
TopExp_Explorer occtExplorer2;
for (occtExplorer2.Init(aResult, TopAbs_FACE); occtExplorer2.More(); occtExplorer2.Next())
{
	const TopoDS_Shape& occtCurrent = occtExplorer2.Current();
	TopoDS_Face occtFace = TopoDS::Face(occtCurrent);
	Handle(Geom_Surface) pOcctSurface = BRep_Tool::Surface(occtFace);

	Handle(Geom_BSplineSurface) pOcctBSplineSurface = Handle_Geom_BSplineSurface::DownCast(pOcctSurface);
	if (!pOcctBSplineSurface.IsNull())
	{
		STEPControl_Writer writer;
		writer.Transfer(occtFace, STEPControl_AsIs);
		writer.Write("output//nurbs_solid_slice_out_only_NURBS_face.stp");
		continue;
	}
}

TopExp_Explorer occtExplorer3;
int i = 1;
for (occtExplorer3.Init(aResult, TopAbs_SOLID); occtExplorer3.More(); occtExplorer3.Next())
{
	std::ostringstream ss;
	ss << "output//nurbs_solid_slice_out_only_solid_" << i++ << ".stp";
	const TopoDS_Shape& occtCurrent = occtExplorer3.Current();
	TopoDS_Solid occtSolid = TopoDS::Solid(occtCurrent);
	STEPControl_Writer writer;
	writer.Transfer(occtSolid, STEPControl_AsIs);
	writer.Write(ss.str().c_str());
}

// save the output solid to a STEP file
STEPControl_Writer writer;
writer.Transfer(aResult, STEPControl_AsIs);
writer.Write("output//nurbs_solid_slice_out.stp");

 

Daniel Woodman's picture

I found that the right method is ShapeAnalysis::GetFaceUVBounds().