def list_face(shape): ''' input shape: TopoDS_Shape output fset: {TopoDS_Face} ''' fset = set() exp = TopExp_Explorer(shape,TopAbs_FACE) while exp.More(): s = exp.Current() exp.Next() face = topods.Face(s) fset.add(face) return list(fset)
def get_background_elements(self): total_product_shapes = len(self.product_shapes) n = 0 intersections = [] compound = TopoDS.TopoDS_Compound() builder = BRep.BRep_Builder() builder.MakeCompound(compound) for product, shape in self.product_shapes: builder.Add(compound, shape) print('{}/{} background elements processed ...'.format( n, total_product_shapes), end='\r', flush=True) #print('Processing product {} '.format(product.Name)) n += 1 intersection = BRepAlgoAPI.BRepAlgoAPI_Common( self.section_box['shape'], shape).Shape() intersection_edges = self.get_booleaned_edges(intersection) if len(intersection_edges) <= 0: continue intersections.append(intersection) transformed_intersection = BRepBuilderAPI.BRepBuilderAPI_Transform( intersection, self.transformation) intersection = transformed_intersection.Shape() edge_face_map = TopTools.TopTools_IndexedDataMapOfShapeListOfShape( ) TopExp.topexp.MapShapesAndAncestors(intersection, TopAbs.TopAbs_EDGE, TopAbs.TopAbs_FACE, edge_face_map) exp = TopExp.TopExp_Explorer(intersection, TopAbs.TopAbs_FACE) while exp.More(): face = topods.Face(exp.Current()) normal = self.get_normal(face) # Cull back-faces if normal.Z() <= 0: exp.Next() continue zpos, zmax = self.calculate_face_zpos(face) self.build_new_face(face, zpos, product) self.get_split_edges(edge_face_map, face, zmax, product) exp.Next()
def combine_faces(compshape, sew_tolerance): """ Method to combine faces in a shell by adding connectivity and continuity :param compshape: TopoDS_Shape :param sew_tolerance: tolerance for sewing :return: Topo_Shell """ offsew = BRepOffsetAPI_FindContigousEdges(sew_tolerance) sew = BRepBuilderAPI_Sewing(sew_tolerance) face_explorers = TopExp_Explorer(compshape, TopAbs_FACE) n_faces = 0 # cycle on Faces while face_explorers.More(): tface = topods.Face(face_explorers.Current()) sew.Add(tface) offsew.Add(tface) n_faces += 1 face_explorers.Next() offsew.Perform() offsew.Dump() sew.Perform() shell = sew.SewedShape() sew.Dump() shell = topods.Shell(shell) shell_fixer = ShapeFix_Shell() shell_fixer.FixFaceOrientation(shell) """ if shell_fixer.Perform(): print("{} shells fixed! ".format(shell_fixer.NbShells())) else: print "Shells not fixed! " new_shell = shell_fixer.Shell() if brepalgo_IsValid(new_shell): print "Shell valid! " else: print "Shell failed! " """ return new_shell
def startBottle(startOnly=True): # minus the neck fillet, shelling & threads partName = "Bottle-start" # The points we'll use to create the profile of the bottle's body aPnt1 = gp_Pnt(-width / 2.0, 0, 0) aPnt2 = gp_Pnt(-width / 2.0, -thickness / 4.0, 0) aPnt3 = gp_Pnt(0, -thickness / 2.0, 0) aPnt4 = gp_Pnt(width / 2.0, -thickness / 4.0, 0) aPnt5 = gp_Pnt(width / 2.0, 0, 0) aArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4) aSegment1 = GC_MakeSegment(aPnt1, aPnt2) aSegment2 = GC_MakeSegment(aPnt4, aPnt5) # Could also construct the line edges directly using the points # instead of the resulting line. aEdge1 = BRepBuilderAPI_MakeEdge(aSegment1.Value()) aEdge2 = BRepBuilderAPI_MakeEdge(aArcOfCircle.Value()) aEdge3 = BRepBuilderAPI_MakeEdge(aSegment2.Value()) # Create a wire out of the edges aWire = BRepBuilderAPI_MakeWire(aEdge1.Edge(), aEdge2.Edge(), aEdge3.Edge()) # Quick way to specify the X axis xAxis = gp_OX() # Set up the mirror aTrsf = gp_Trsf() aTrsf.SetMirror(xAxis) # Apply the mirror transformation aBRespTrsf = BRepBuilderAPI_Transform(aWire.Wire(), aTrsf) # Get the mirrored shape back out of the transformation # and convert back to a wire aMirroredShape = aBRespTrsf.Shape() # A wire instead of a generic shape now aMirroredWire = topods.Wire(aMirroredShape) # Combine the two constituent wires mkWire = BRepBuilderAPI_MakeWire() mkWire.Add(aWire.Wire()) mkWire.Add(aMirroredWire) myWireProfile = mkWire.Wire() # The face that we'll sweep to make the prism myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile) # We want to sweep the face along the Z axis to the height aPrismVec = gp_Vec(0, 0, height) myBody = BRepPrimAPI_MakePrism(myFaceProfile.Face(), aPrismVec) # Add fillets to all edges through the explorer mkFillet = BRepFilletAPI_MakeFillet(myBody.Shape()) anEdgeExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_EDGE) while anEdgeExplorer.More(): anEdge = topods.Edge(anEdgeExplorer.Current()) mkFillet.Add(thickness / 12.0, anEdge) anEdgeExplorer.Next() myBody = mkFillet.Shape() # Create the neck of the bottle neckLocation = gp_Pnt(0, 0, height) neckAxis = gp_DZ() neckAx2 = gp_Ax2(neckLocation, neckAxis) myNeckRadius = thickness / 4.0 myNeckHeight = height / 10.0 mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2, myNeckRadius, myNeckHeight) myBody = BRepAlgoAPI_Fuse(myBody, mkCylinder.Shape()) if startOnly: # quit here uid = win.getNewPartUID(myBody.Shape(), name=partName) win.redraw() return partName = "Bottle-complete" # Our goal is to find the highest Z face and remove it faceToRemove = None zMax = -1 # We have to work our way through all the faces to find the highest Z face aFaceExplorer = TopExp_Explorer(myBody.Shape(), TopAbs_FACE) while aFaceExplorer.More(): aFace = topods.Face(aFaceExplorer.Current()) if face_is_plane(aFace): aPlane = geom_plane_from_face(aFace) # We want the highest Z face, so compare this to the previous faces aPnt = aPlane.Location() aZ = aPnt.Z() if aZ > zMax: zMax = aZ faceToRemove = aFace aFaceExplorer.Next() facesToRemove = TopTools_ListOfShape() facesToRemove.Append(faceToRemove) myBody = BRepOffsetAPI_MakeThickSolid(myBody.Shape(), facesToRemove, -thickness / 50.0, 0.001) # Set up our surfaces for the threading on the neck neckAx2_Ax3 = gp_Ax3(neckLocation, gp_DZ()) aCyl1 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 0.99) aCyl2 = Geom_CylindricalSurface(neckAx2_Ax3, myNeckRadius * 1.05) # Set up the curves for the threads on the bottle's neck aPnt = gp_Pnt2d(2.0 * math.pi, myNeckHeight / 2.0) aDir = gp_Dir2d(2.0 * math.pi, myNeckHeight / 4.0) anAx2d = gp_Ax2d(aPnt, aDir) aMajor = 2.0 * math.pi aMinor = myNeckHeight / 10.0 anEllipse1 = Geom2d_Ellipse(anAx2d, aMajor, aMinor) anEllipse2 = Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4.0) anArc1 = Geom2d_TrimmedCurve(anEllipse1, 0, math.pi) anArc2 = Geom2d_TrimmedCurve(anEllipse2, 0, math.pi) anEllipsePnt1 = anEllipse1.Value(0) anEllipsePnt2 = anEllipse1.Value(math.pi) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2) # Build edges and wires for threading anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1) anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment.Value(), aCyl1) anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2) anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment.Value(), aCyl2) threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1.Edge(), anEdge2OnSurf1.Edge()) threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2.Edge(), anEdge2OnSurf2.Edge()) # Compute the 3D representations of the edges/wires breplib.BuildCurves3d(threadingWire1.Shape()) breplib.BuildCurves3d(threadingWire2.Shape()) # Create the surfaces of the threading aTool = BRepOffsetAPI_ThruSections(True) aTool.AddWire(threadingWire1.Wire()) aTool.AddWire(threadingWire2.Wire()) aTool.CheckCompatibility(False) myThreading = aTool.Shape() # Build the resulting compound aRes = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound(aRes) aBuilder.Add(aRes, myBody.Shape()) aBuilder.Add(aRes, myThreading) uid = win.getNewPartUID(aRes, name=partName) win.redraw()
def Face(self): return topods.Face(self._shp) def Vertex(self): return topods.Vertex(self._shp)
neckAx2 = gp_Ax2(neckLocation, neckAxis) myNeckRadius = thickness / 4.0 myNeckHeight = height / 10.0 mkCylinder = BRepPrimAPI_MakeCylinder(neckAx2, myNeckRadius, myNeckHeight) myBody_step2 = BRepAlgoAPI_Fuse(mkFillet.Shape(), mkCylinder.Shape()) # Our goal is to find the highest Z face and remove it zMax = -1. # We have to work our way through all the faces to find the highest Z face so we can remove it for the shell aFaceExplorer = TopExp_Explorer(myBody_step2.Shape(), TopAbs_FACE) while aFaceExplorer.More(): aFace = topods.Face(aFaceExplorer.Current()) if face_is_plane(aFace): aPlane = geom_plane_from_face(aFace) # We want the highest Z face, so compare this to the previous faces aPntLoc = aPlane.Location() aZ = aPntLoc.Z() if aZ > zMax: zMax = aZ aFaceExplorer.Next() facesToRemove = TopTools_ListOfShape() facesToRemove.Append(aFace) myBody_step3 = BRepOffsetAPI_MakeThickSolid(myBody_step2.Shape(), facesToRemove, -thickness / 50.0,
# Read the file and get the shape reader = STEPControl_Reader() tr = reader.WS().TransferReader() reader.ReadFile('geometry_names.stp') reader.TransferRoots() shape = reader.OneShape() # Explore the faces of the shape (these are known to be named) exp = TopExp_Explorer(shape, TopAbs_FACE) while exp.More(): s = exp.Current() exp.Next() # Converting TopoDS_Shape to TopoDS_Face face = topods.Face(s) # Working on the geometry face_adaptor = BRepAdaptor_Surface(face) face_type = face_adaptor.GetType() if face_type == GeomAbs_Cylinder: cylinder = face_adaptor.Cylinder() entity = {} entity['type'] = 'cylinder' entity['location'] = cylinder.Axis().Location().Coord() entity['direction'] = cylinder.Axis().Direction().Coord() entity['radius'] = cylinder.Radius() entity['coefficients'] = cylinder.Coefficients() print('cylinder:', entity) # Working on the name
def read_step_file_withnames( filename, breadface=False, breadedge=False ): #Read a step file with names attached to solid, faces (can be extended to edges) """""[Read a step file with names attached to solid, faces (can be extended to edges)] Arguments: filename {[type]} -- [path to the .stp file] Keyword Arguments: breadface {bool} -- [read the faces' names] (default: {False}) breadedge {bool} -- [read the edges' names] (default: {False}) Returns: (dSolids, dFaces, dEdges) -- [two dicts with name (int) as key and aShape as value] """ "" reader = STEPControl_Reader() #tr = reader.WS().GetObject().TransferReader().GetObject() tr = reader.WS().GetObject().TransferReader() reader.ReadFile(filename) reader.TransferRoots() shape = reader.OneShape() dSolids = dict( ) #solids initial as a dict with name (int) as key and aShape as value dFaces = dict( ) #faces initial as a dict with name (int) as key and aShape as value dEdges = dict( ) #edges initial as a dict with name (int) as key and aShape as value #read the solid names exp = TopExp_Explorer(shape, TopAbs_SOLID) while exp.More(): s = exp.Current() exp.Next() #Converting TopoDS_Shape to TopoDS_Face solid = topods.Solid(s) #Working on the name item = tr.EntityFromShapeResult(s, 1) if item == None: continue #item = Handle_StepRepr_RepresentationItem.DownCast(item).GetObject() item = StepRepr_RepresentationItem.DownCast(item) name = item.Name().ToCString() if name: print('Found entity named: {}: {}.'.format(name, s)) nameid = int(name.split('_')[-1]) dSolids[nameid] = solid # read the face names if breadface: exp = TopExp_Explorer(shape, TopAbs_FACE) while exp.More(): s = exp.Current() exp.Next() #Converting TopoDS_Shape to TopoDS_Face face = topods.Face(s) #Working on the name item = tr.EntityFromShapeResult(s, 1) if item.IsNull(): continue #item = Handle_StepRepr_RepresentationItem.DownCast(item).GetObject() item = StepRepr_RepresentationItem.DownCast(item) name = item.Name().GetObject().ToCString() if name: # print('Found entity named: {}: {}.'.format(name, s)) nameid = int(name.split('_')[-1]) dFaces[nameid] = face # read the edge names if breadedge: exp = TopExp_Explorer(shape, TopAbs_EDGE) while exp.More(): s = exp.Current() exp.Next() #Converting TopoDS_Shape to TopoDS_Face edge = topods.Edge(s) #Working on the name item = tr.EntityFromShapeResult(s, 1) if item.IsNull(): continue #item = Handle_StepRepr_RepresentationItem.DownCast(item).GetObject() item = StepRepr_RepresentationItem.DownCast(item) name = item.Name().GetObject().ToCString() if name: # print('Found entity named: {}: {}.'.format(name, s)) nameid = int(name.split('_')[-1]) dEdges[nameid] = edge ret = (dSolids, dFaces, dEdges) return ret
def write_shape(self, l_shells, filename, tol): """ Method to recreate a TopoDS_Shape associated to a geometric shape after the modification of points of each Face. It returns a TopoDS_Shape (Shape). :param l_shells: the list of shells after initial parsing :param filename: the output filename :param tol: tolerance on the surface creation after modification :return: None """ self.outfile = filename # global compound containing multiple shells global_compound_builder = BRep_Builder() global_comp = TopoDS_Compound() global_compound_builder.MakeCompound(global_comp) if self.check_topo == 0: # cycle on shells (multiple objects) shape_shells_explorer = TopExp_Explorer( self.shape.Oriented(TopAbs_FORWARD), TopAbs_SHELL) ishell = 0 while shape_shells_explorer.More(): per_shell = topods_Shell(shape_shells_explorer.Current()) # a local compound containing a shell compound_builder = BRep_Builder() comp = TopoDS_Compound() compound_builder.MakeCompound(comp) # cycle on faces faces_explorer = TopExp_Explorer( per_shell.Oriented(TopAbs_FORWARD), TopAbs_FACE) iface = 0 while faces_explorer.More(): topoface = topods.Face(faces_explorer.Current()) newface = self.write_face(l_shells[ishell][iface][0], l_shells[ishell][iface][1], topoface, tol) # add face to compound compound_builder.Add(comp, newface) iface += 1 faces_explorer.Next() new_shell = self.combine_faces(comp, 0.01) itype = TopoDS_Shape.ShapeType(new_shell) # add the new shell to the global compound global_compound_builder.Add(global_comp, new_shell) # TODO #print("Shell {0} of type {1} Processed ".format(ishell, itype)) #print "==============================================" ishell += 1 shape_shells_explorer.Next() else: # cycle on faces # a local compound containing a shell compound_builder = BRep_Builder() comp = TopoDS_Compound() compound_builder.MakeCompound(comp) # cycle on faces faces_explorer = TopExp_Explorer( self.shape.Oriented(TopAbs_FORWARD), TopAbs_FACE) iface = 0 while faces_explorer.More(): topoface = topods.Face(faces_explorer.Current()) newface = self.write_face(l_shells[0][iface][0], l_shells[0][iface][1], topoface, tol) # add face to compound compound_builder.Add(comp, newface) iface += 1 faces_explorer.Next() new_shell = self.combine_faces(comp, 0.01) itype = TopoDS_Shape.ShapeType(new_shell) # add the new shell to the global compound global_compound_builder.Add(global_comp, new_shell) # TODO print to logging # print("Shell {0} of type {1} Processed ".format(0, itype)) # print "==============================================" self.write_shape_to_file(global_comp, self.outfile)
def write_face(self, points_face, list_points_edge, topo_face, toledge): """ Method to recreate a Face associated to a geometric surface after the modification of Face points. It returns a TopoDS_Face. :param points_face: the new face points array. :param list_points_edge: new edge points :param topo_face: the face to be modified :param toledge: tolerance on the surface creation after modification :return: TopoDS_Face (Shape) :rtype: TopoDS_Shape """ # convert Face to Geom B-spline Surface nurbs_converter = BRepBuilderAPI_NurbsConvert(topo_face) nurbs_converter.Perform(topo_face) nurbs_face = nurbs_converter.Shape() topo_nurbsface = topods.Face(nurbs_face) h_geomsurface = BRep_Tool.Surface(topo_nurbsface) h_bsurface = geomconvert_SurfaceToBSplineSurface(h_geomsurface) bsurface = h_bsurface nb_u = bsurface.NbUPoles() nb_v = bsurface.NbVPoles() # check consistency if points_face.shape[0] != nb_u * nb_v: raise ValueError("Input control points do not have not have the " "same number as the geometric face!") # cycle on the face points indice_cpt = 0 for iu in range(1, nb_u + 1): for iv in range(1, nb_v + 1): cpt = points_face[indice_cpt] bsurface.SetPole(iu, iv, gp_Pnt(cpt[0], cpt[1], cpt[2])) indice_cpt += 1 # create modified new face new_bspline_tface = BRepBuilderAPI_MakeFace() toler = precision_Confusion() new_bspline_tface.Init(bsurface, False, toler) # cycle on the wires face_wires_explorer = TopExp_Explorer( topo_nurbsface.Oriented(TopAbs_FORWARD), TopAbs_WIRE) ind_edge_total = 0 while face_wires_explorer.More(): # get old wire twire = topods_Wire(face_wires_explorer.Current()) # cycle on the edges ind_edge = 0 wire_explorer_edge = TopExp_Explorer( twire.Oriented(TopAbs_FORWARD), TopAbs_EDGE) # check edges order on the wire mode3d = True tolerance_edges = toledge wire_order = ShapeAnalysis_WireOrder(mode3d, tolerance_edges) # an edge list deformed_edges = [] # cycle on the edges while wire_explorer_edge.More(): tedge = topods_Edge(wire_explorer_edge.Current()) new_bspline_tedge = self.write_edge( list_points_edge[ind_edge_total], tedge) deformed_edges.append(new_bspline_tedge) analyzer = topexp() vfirst = analyzer.FirstVertex(new_bspline_tedge) vlast = analyzer.LastVertex(new_bspline_tedge) pt1 = BRep_Tool.Pnt(vfirst) pt2 = BRep_Tool.Pnt(vlast) wire_order.Add(pt1.XYZ(), pt2.XYZ()) ind_edge += 1 ind_edge_total += 1 wire_explorer_edge.Next() # grouping the edges in a wire, then in the face # check edges order and connectivity within the wire wire_order.Perform() # new wire to be created stol = ShapeFix_ShapeTolerance() new_bspline_twire = BRepBuilderAPI_MakeWire() for order_i in range(1, wire_order.NbEdges() + 1): deformed_edge_i = wire_order.Ordered(order_i) if deformed_edge_i > 0: # insert the deformed edge to the new wire new_edge_toadd = deformed_edges[deformed_edge_i - 1] stol.SetTolerance(new_edge_toadd, toledge) new_bspline_twire.Add(new_edge_toadd) if new_bspline_twire.Error() != 0: stol.SetTolerance(new_edge_toadd, toledge * 10.0) new_bspline_twire.Add(new_edge_toadd) else: deformed_edge_revers = deformed_edges[ np.abs(deformed_edge_i) - 1] stol.SetTolerance(deformed_edge_revers, toledge) new_bspline_twire.Add(deformed_edge_revers) if new_bspline_twire.Error() != 0: stol.SetTolerance(deformed_edge_revers, toledge * 10.0) new_bspline_twire.Add(deformed_edge_revers) # add new wire to the Face new_bspline_tface.Add(new_bspline_twire.Wire()) face_wires_explorer.Next() return topods.Face(new_bspline_tface.Face())
def parse_shape(self, filename): """ Method to parse a Shape with multiple objects (1 compound = multi-shells and 1 shell = multi-faces) It returns a list of matrix with all the coordinates of control points of each Face and a second list with all the control points related to Edges of each Face. :param str filename: the input filename. :return: list of (mesh_points: `n_points`-by-3 matrix containing the coordinates of the control points of the Face (surface), edge_points: it is a list of numpy.narray) :rtype: a list of shells """ self.infile = filename self.shape = self.load_shape_from_file(filename) self.check_topology() # parse and get control points l_shells = [] # an empty list of shells n_shells = 0 if self.check_topo == 0: shells_explorer = TopExp_Explorer(self.shape, TopAbs_SHELL) # cycle on shells while shells_explorer.More(): topo_shell = topods.Shell(shells_explorer.Current()) shell_faces_explorer = TopExp_Explorer(topo_shell, TopAbs_FACE) l_faces = [] # an empty list of faces per shell # cycle on faces while shell_faces_explorer.More(): topo_face = topods.Face(shell_faces_explorer.Current()) mesh_point, edge_point = self.parse_face(topo_face) l_faces.append((mesh_point, edge_point)) shell_faces_explorer.Next() l_shells.append(l_faces) n_shells += 1 shells_explorer.Next() else: # cycle only on faces shell_faces_explorer = TopExp_Explorer(self.shape, TopAbs_FACE) l_faces = [] # an empty list of faces per shell while shell_faces_explorer.More(): topo_face = topods.Face(shell_faces_explorer.Current()) mesh_point, edge_point = self.parse_face(topo_face) l_faces.append((mesh_point, edge_point)) shell_faces_explorer.Next() l_shells.append(l_faces) n_shells += 1 return l_shells
def parse_face(topo_face): """ Method to parse a single `Face` (a single patch nurbs surface). It returns a matrix with all the coordinates of control points of the `Face` and a second list with all the control points related to the `Edges` of the `Face.` :param Face topo_face: the input Face. :return: control points of the `Face`, control points related to `Edges`. :rtype: tuple(numpy.ndarray, list) """ # get some Face - Edge - Vertex data map information mesh_points_edge = [] face_exp_wire = TopExp_Explorer(topo_face, TopAbs_WIRE) # loop on wires per face while face_exp_wire.More(): twire = topods_Wire(face_exp_wire.Current()) wire_exp_edge = TopExp_Explorer(twire, TopAbs_EDGE) # loop on edges per wire while wire_exp_edge.More(): edge = topods_Edge(wire_exp_edge.Current()) bspline_converter = BRepBuilderAPI_NurbsConvert(edge) bspline_converter.Perform(edge) bspline_tshape_edge = bspline_converter.Shape() h_geom_edge = BRep_Tool_Curve( topods_Edge(bspline_tshape_edge))[0] h_bspline_edge = geomconvert_CurveToBSplineCurve(h_geom_edge) bspline_geom_edge = h_bspline_edge nb_poles = bspline_geom_edge.NbPoles() # Edge geometric properties edge_ctrlpts = TColgp_Array1OfPnt(1, nb_poles) bspline_geom_edge.Poles(edge_ctrlpts) points_single_edge = np.zeros((0, 3)) for i in range(1, nb_poles + 1): ctrlpt = edge_ctrlpts.Value(i) ctrlpt_position = np.array( [[ctrlpt.Coord(1), ctrlpt.Coord(2), ctrlpt.Coord(3)]]) points_single_edge = np.append(points_single_edge, ctrlpt_position, axis=0) mesh_points_edge.append(points_single_edge) wire_exp_edge.Next() face_exp_wire.Next() # extract mesh points (control points) on Face mesh_points_face = np.zeros((0, 3)) # convert Face to Geom B-spline Face nurbs_converter = BRepBuilderAPI_NurbsConvert(topo_face) nurbs_converter.Perform(topo_face) nurbs_face = nurbs_converter.Shape() h_geomsurface = BRep_Tool.Surface(topods.Face(nurbs_face)) h_bsurface = geomconvert_SurfaceToBSplineSurface(h_geomsurface) bsurface = h_bsurface # get access to control points (poles) nb_u = bsurface.NbUPoles() nb_v = bsurface.NbVPoles() ctrlpts = TColgp_Array2OfPnt(1, nb_u, 1, nb_v) bsurface.Poles(ctrlpts) for indice_u_direction in range(1, nb_u + 1): for indice_v_direction in range(1, nb_v + 1): ctrlpt = ctrlpts.Value(indice_u_direction, indice_v_direction) ctrlpt_position = np.array( [[ctrlpt.Coord(1), ctrlpt.Coord(2), ctrlpt.Coord(3)]]) mesh_points_face = np.append(mesh_points_face, ctrlpt_position, axis=0) return mesh_points_face, mesh_points_edge