def AddVerticesToScene(self, pnt_list, vertex_color, vertex_width=5): """ shp is a list of gp_Pnt """ vertices_list = [] # will be passed to pythreejs BB = BRep_Builder() compound = TopoDS_Compound() BB.MakeCompound(compound) for vertex in pnt_list: vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape() BB.Add(compound, vertex_to_add) vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()]) # map the Points and the AIS_PointCloud # and to the dict of shapes, to have a mapping between meshes and shapes point_cloud_id = "%s" % uuid.uuid4().hex self._shapes[point_cloud_id] = compound vertices_list = np.array(vertices_list, dtype=np.float32) attributes = { "position": BufferAttribute(vertices_list, normalized=False) } mat = PointsMaterial(color=vertex_color, sizeAttenuation=True, size=vertex_width) geom = BufferGeometry(attributes=attributes) points = Points(geometry=geom, material=mat, name=point_cloud_id) return points
class Model (plotocc): def __init__(self): super().__init__() self.builder = BRep_Builder() self.compound = TopoDS_Compound() self.builder.MakeCompound(self.compound) schema = 'AP203' assembly_mode = 1 self.writer = STEPControl_Writer() self.fp = self.writer.WS().TransferWriter().FinderProcess() Interface_Static_SetCVal('write.step.schema', schema) Interface_Static_SetCVal('write.step.unit', 'M') Interface_Static_SetCVal('write.step.assembly', str(assembly_mode)) def AddShape(self, shp, name="shape"): Interface_Static_SetCVal('write.step.product.name', name) status = self.writer.Transfer(shp, STEPControl_AsIs) if int(status) > int(IFSelect_RetError): raise Exception('Some Error occurred') # This portion is not working as I hoped item = stepconstruct_FindEntity(self.fp, shp) if not item: raise Exception('Item not found') def export_stp_with_name(self): status = self.writer.Write(self.tempname + ".stp") if int(status) > int(IFSelect_RetError): raise Exception('Something bad happened')
def occ_triangle_mesh(event=None): # # Mesh the shape # BRepMesh_IncrementalMesh(aShape, 0.1) builder = BRep_Builder() Comp = TopoDS_Compound() builder.MakeCompound(Comp) ex = TopExp_Explorer(aShape, TopAbs_FACE) while ex.More(): F = topods_Face(ex.Current()) L = TopLoc_Location() facing = (BRep_Tool().Triangulation(F, L)) tab = facing.Nodes() tri = facing.Triangles() for i in range(1, facing.NbTriangles() + 1): trian = tri.Value(i) #print trian index1, index2, index3 = trian.Get() for j in range(1, 4): if j == 1: M = index1 N = index2 elif j == 2: N = index3 elif j == 3: M = index2 ME = BRepBuilderAPI_MakeEdge(tab.Value(M), tab.Value(N)) if ME.IsDone(): builder.Add(Comp, ME.Edge()) ex.Next() display.DisplayShape(Comp, update=True)
def write_target_edges(self,filename): comp = TopoDS_Compound() builder = BRep_Builder() builder.MakeCompound(comp) for shape in self.target_edges: builder.Add(comp, shape) breptools_Write(comp,filename)
def face_mesh_triangle(comp=TopoDS_Shape(), isR=0.1, thA=0.1): # Mesh the shape BRepMesh_IncrementalMesh(comp, isR, True, thA, True) bild1 = BRep_Builder() comp1 = TopoDS_Compound() bild1.MakeCompound(comp1) bt = BRep_Tool() ex = TopExp_Explorer(comp, TopAbs_FACE) while ex.More(): face = topods_Face(ex.Current()) location = TopLoc_Location() facing = bt.Triangulation(face, location) tab = facing.Nodes() tri = facing.Triangles() print(facing.NbTriangles(), facing.NbNodes()) for i in range(1, facing.NbTriangles() + 1): trian = tri.Value(i) index1, index2, index3 = trian.Get() for j in range(1, 4): if j == 1: m = index1 n = index2 elif j == 2: n = index3 elif j == 3: m = index2 me = BRepBuilderAPI_MakeEdge(tab.Value(m), tab.Value(n)) if me.IsDone(): bild1.Add(comp1, me.Edge()) ex.Next() return comp1
def create_compound(nodes): aRes = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound(aRes) for n in nodes: aBuilder.Add(aRes, n.solid()) return aRes
def _unify_compound(proto): builder = BRep_Builder() comp = TopoDS_Compound() builder.MakeCompound(comp) explorer = TopExp_Explorer() explorer.Init(proto.Shape(), TopAbs_SOLID) while explorer.More(): builder.Add(comp, _unify_solid(Shape(explorer.Current())).Solid()) explorer.Next() explorer.Init(proto.Shape(), TopAbs_SHELL, TopAbs_SOLID) while explorer.More(): builder.Add(comp, _unify_shell(Shape(explorer.Current())).Shell()) explorer.Next() faces = [] explorer.Init(proto.Shape(), TopAbs_FACE, TopAbs_SHELL) while explorer.More(): faces.append(Shape(explorer.Current())) explorer.Next() faces_new = _unify_faces_array(faces) for f in faces_new: builder.Add(comp, f.Shape()) return Shape(comp)
def export_file(self): builder = BRep_Builder() compound = TopoDS_Compound() builder.MakeCompound(compound) builder.Add(compound, self.b1) builder.Add(compound, self.b2) builder.Add(compound, make_polygon(self.pts)) self.export_stp(compound)
def make_comp_selcted(self): bild = BRep_Builder() comp = TopoDS_Compound() bild.MakeCompound(comp) for shp in self.selected_shape: print(shp) bild.Add(comp, shp) return comp
def export_file(self): builder = BRep_Builder() compound = TopoDS_Compound() builder.MakeCompound(compound) builder.Add(compound, self.b1) builder.Add(compound, self.b2) builder.Add(compound, make_polygon(self.pts)) write_step_file(compound, "./tmp/test.stp")
def __init__(self, shapes): topods_compound = TopoDS_Compound() builder = BRep_Builder() builder.MakeCompound(topods_compound) for shape in shapes: shape = Shape.to_shape(shape) if isinstance(shape, Shape): builder.Add(topods_compound, shape.object) self._cp = Compound(topods_compound)
class GenCompound(object): def __init__(self): self.builder = BRep_Builder() self.compound = TopoDS_Compound() self.builder.MakeCompound(self.compound) def add_shapes(self, shps=[]): for shp in shps: self.builder.Add(self.compound, shp)
def export_stp_selected(self): if self.touch == True: builder = BRep_Builder() compound = TopoDS_Compound() builder.MakeCompound(compound) for shp in self.selected_shape: print(shp) builder.Add(compound, shp) self.export_stp(compound)
def compound(self): """ Create and returns a compound from the _shapes list""" # Create a compound compound = TopoDS_Compound() brep_builder = BRep_Builder() brep_builder.MakeCompound(compound) # Populate the compound for shape in self._shapes: brep_builder.Add(compound, shape) return compound
def read_iges_file(filename, return_as_shapes=False, verbosity=False, visible_only=False): """ read the IGES file and returns a compound filename: the file path return_as_shapes: optional, False by default. If True returns a list of shapes, else returns a single compound verbosity: optionl, False by default. """ if not os.path.isfile(filename): raise FileNotFoundError("%s not found." % filename) iges_reader = IGESControl_Reader() iges_reader.SetReadVisible(visible_only) status = iges_reader.ReadFile(filename) _shapes = [] if status == IFSelect_RetDone: # check status if verbosity: failsonly = False iges_reader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity) iges_reader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity) iges_reader.TransferRoots() nbr = iges_reader.NbRootsForTransfer() for n in range(1, nbr + 1): nbs = iges_reader.NbShapes() if nbs == 0: print("At least one shape in IGES cannot be transfered") elif nbr == 1 and nbs == 1: a_res_shape = iges_reader.Shape(1) if a_res_shape.IsNull(): print("At least one shape in IGES cannot be transferred") else: _shapes.append(a_res_shape) else: for i in range(1, nbs + 1): a_shape = iges_reader.Shape(i) if a_shape.IsNull(): print( "At least one shape in STEP cannot be transferred") else: _shapes.append(a_shape) # if not return as shapes # create a compound and store all shapes if not return_as_shapes: builder = BRep_Builder() compound = TopoDS_Compound() builder.MakeCompound(compound) for s in _shapes: builder.Add(compound, s) _shapes = compound return _shapes
def move_to_box(iname, cname, wname, visualize=False): """Move foam to periodic box. Works on BREP files. Information about physical volumes is lost. Args: iname (str): input filename cname (str): output filename with cells wname (str): output filename with walls visualize (bool): show picture of foam morphology in box if True """ cells = TopoDS_Shape() builder = BRep_Builder() breptools_Read(cells, iname, builder) texp = TopologyExplorer(cells) solids = list(texp.solids()) cells = TopoDS_Compound() builder.MakeCompound(cells) box = BRepPrimAPI_MakeBox(gp_Pnt(1, -1, -1), 3, 3, 3).Shape() vec = gp_Vec(-1, 0, 0) solids = slice_and_move(solids, box, vec) box = BRepPrimAPI_MakeBox(gp_Pnt(-3, -1, -1), 3, 3, 3).Shape() vec = gp_Vec(1, 0, 0) solids = slice_and_move(solids, box, vec) box = BRepPrimAPI_MakeBox(gp_Pnt(-1, 1, -1), 3, 3, 3).Shape() vec = gp_Vec(0, -1, 0) solids = slice_and_move(solids, box, vec) box = BRepPrimAPI_MakeBox(gp_Pnt(-1, -3, -1), 3, 3, 3).Shape() vec = gp_Vec(0, 1, 0) solids = slice_and_move(solids, box, vec) box = BRepPrimAPI_MakeBox(gp_Pnt(-1, -1, 1), 3, 3, 3).Shape() vec = gp_Vec(0, 0, -1) solids = slice_and_move(solids, box, vec) box = BRepPrimAPI_MakeBox(gp_Pnt(-1, -1, -3), 3, 3, 3).Shape() vec = gp_Vec(0, 0, 1) solids = slice_and_move(solids, box, vec) create_compound(solids, cells, builder) breptools_Write(cells, cname) if visualize: display, start_display, _, _ = init_display() display.DisplayShape(cells, update=True) start_display() box = BRepPrimAPI_MakeBox(gp_Pnt(0, 0, 0), 1, 1, 1).Shape() walls = BRepAlgoAPI_Cut(box, cells).Shape() breptools_Write(walls, wname) if visualize: display, start_display, _, _ = init_display() display.DisplayShape(walls, update=True) start_display()
def make_compound(parts): """ Takes a list of parts and returns a TopoDS_Compound from the parts' shapes. :param parts: A list of Part instances :return: a TopoDS_Compound from all of the parts' shapes """ compound = TopoDS_Compound() builder = BRep_Builder() builder.MakeCompound(compound) for part in parts: builder.Add(compound, part._shape) return compound
def read_step_file(filename, return_as_shapes=False, verbosity=True): """ read the STEP file and returns a compound filename: the file path return_as_shapes: optional, False by default. If True returns a list of shapes, else returns a single compound verbosity: optional, False by default. """ if not os.path.isfile(filename): raise FileNotFoundError("%s not found." % filename) step_reader = STEPControl_Reader() status = step_reader.ReadFile(filename) if status == IFSelect_RetDone: # check status if verbosity: failsonly = False step_reader.PrintCheckLoad(failsonly, IFSelect_ItemsByEntity) step_reader.PrintCheckTransfer(failsonly, IFSelect_ItemsByEntity) shapes_to_return = [] for root_num in range(1, step_reader.NbRootsForTransfer() + 1): transfer_result = step_reader.TransferRoot(root_num) if not transfer_result: raise AssertionError("Transfer failed.") shape = step_reader.Shape(root_num) if shape.IsNull(): raise AssertionError("Shape is null.") shapes_to_return.append(shape) if return_as_shapes: return shapes_to_return builder = BRep_Builder() compound_shape = TopoDS_Compound() builder.MakeCompound(compound_shape) for shape in shapes_to_return: builder.Add(compound_shape, shape) return compound_shape else: raise AssertionError("Error: can't read file.")
def by_shapes(shapes): """ Create a new compound from a collection of shapes. :param collections.Sequence(afem.topology.entities.Shape) shapes: The shapes. :return: The new compound. :rtype: afem.topology.entities.Compound """ topods_compound = TopoDS_Compound() builder = BRep_Builder() builder.MakeCompound(topods_compound) for shape in shapes: if isinstance(shape, Shape): builder.Add(topods_compound, shape.object) return Compound(topods_compound)
def list_of_shapes_to_compound(list_of_shapes): """ takes a list of shape in input, gather all shapes into one compound returns the compund and a boolean, True if all shapes were added to the compund, False otherwise """ all_shapes_converted = True the_compound = TopoDS_Compound() the_builder = BRep_Builder() the_builder.MakeCompound(the_compound) for shp in list_of_shapes: # first ensure the shape is not Null if shp.IsNull(): all_shapes_converted = False continue else: the_builder.Add(the_compound, shp) return the_compound, all_shapes_converted
class Cap(plotocc): def __init__(self): plotocc.__init__(self) self.compound = TopoDS_Compound() self.builder = BRep_Builder() self.builder.MakeCompound(self.compound) box = BRepPrimAPI_MakeBox(100, 200, 300).Shape() self.display.DisplayShape(box) con = BRepPrimAPI_MakeCone(gp_Ax2(gp_Pnt(500, 0, 0), gp_Dir(0, 0, 1)), 100, 200, 300).Shape() self.display.DisplayShape(con) # https://www.opencascade.com/doc/occt-7.4.0/refman/html/class_graphic3d___camera.html self.camera = self.display.View.Camera() print(self.camera.Scale(), dir_to_vec(self.camera.OrthogonalizedUp())) print(self.camera.ViewDimensions()) def export_capture(self): self.display.FitAll() self.display.View.Dump(self.tmpdir + "cap.png") self.camera.OrthogonalizeUp() self.camera.SetUp(gp_Dir(0, 0, 1)) print(self.camera.Scale(), self.camera.Eye(), self.camera.Center()) self.camera.SetDirection(gp_Dir(-1, 0, 0)) print(self.camera.Scale(), self.camera.Eye(), self.camera.Center()) self.display.View.SetCamera(self.camera) self.display.View.Dump(self.tmpdir + "cap_x.png") self.camera.SetDirection(gp_Dir(0, -1, 0)) print(self.camera.Scale(), self.camera.Eye(), self.camera.Center()) self.display.View.SetCamera(self.camera) self.display.View.Dump(self.tmpdir + "cap_y.png") self.camera.SetDirection(gp_Dir(0.001, 0, -1)) print(self.camera.Scale(), self.camera.Eye(), self.camera.Center()) self.display.View.SetCamera(self.camera) self.display.View.Dump(self.tmpdir + "cap_z.png") def display_Plane(self): self.show_axs_pln(scale=200.0) self.export_capture() self.start_display()
def simple_mesh(): # # Create the shape # theBox = BRepPrimAPI_MakeBox(200, 60, 60).Shape() theSphere = BRepPrimAPI_MakeSphere(gp_Pnt(100, 20, 20), 80).Shape() shape = BRepAlgoAPI_Fuse(theSphere, theBox).Shape() # # Mesh the shape # BRepMesh_IncrementalMesh(shape, 0.8) builder = BRep_Builder() comp = TopoDS_Compound() builder.MakeCompound(comp) bt = BRep_Tool() ex = TopExp_Explorer(shape, TopAbs_FACE) while ex.More(): face = topods_Face(ex.Current()) location = TopLoc_Location() facing = (bt.Triangulation(face, location)).GetObject() tab = facing.Nodes() tri = facing.Triangles() for i in range(1, facing.NbTriangles() + 1): trian = tri.Value(i) index1, index2, index3 = trian.Get() for j in range(1, 4): if j == 1: m = index1 n = index2 elif j == 2: n = index3 elif j == 3: m = index2 me = BRepBuilderAPI_MakeEdge(tab.Value(m), tab.Value(n)) if me.IsDone(): builder.Add(comp, me.Edge()) ex.Next() display.EraseAll() display.DisplayShape(shape) display.DisplayShape(comp, update=True)
class ODE1(plotocc): def __init__(self): plotocc.__init__(self) self.compound = TopoDS_Compound() self.builder = BRep_Builder() self.builder.MakeCompound(self.compound) mmat = math_Matrix(1, 4, 1, 3, 0.0) mmat.SetDiag(1.0) print(mmat.Determinant()) print(mmat.DumpToString()) mvec = math_Vector(1, 3) print(mvec.Norm()) print(mvec.DumpToString()) def export_file(self): write_step_file(self.compound, "./tmp/ODE1.stp") def display_Plane(self): self.show_axs_pln(scale=1.0) self.show()
def compound(self): """ Create and returns a compound from the _shapes list Returns ------- TopoDS_Compound Notes ----- Importing an iges box results in: 0 solid 0 shell 6 faces 24 edges """ # Create a compound compound = TopoDS_Compound() brep_builder = BRep_Builder() brep_builder.MakeCompound(compound) # Populate the compound for shape in self._shapes: brep_builder.Add(compound, shape) return compound
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 construct_fitter(input_file): print("fitting", input_file) obj_mesh = trimesh.load(input_file) print(len(obj_mesh.faces)) if len(obj_mesh.faces) > 15000: sobj_mesh = obj_mesh.simplify_quadratic_decimation( len(obj_mesh.faces) // 20) else: sobj_mesh = obj_mesh print(len(sobj_mesh.faces)) print(sobj_mesh.scale) sobj_mesh.apply_scale(286 / sobj_mesh.scale) print(sobj_mesh.scale) trimesh.repair.fix_inversion(sobj_mesh) def get_simplified_slice(sobj_mesh): nice_slice = sobj_mesh.section(plane_origin=sobj_mesh.centroid + np.array([0, 0, 30]), plane_normal=[0.55, 0, 1]) sobj_mesh.visual.face_colors = [255, 170, 120, 255] simp_slice = nice_slice.to_planar()[0].simplify_spline() return simp_slice, nice_slice simp_slice, nice_slice = get_simplified_slice(sobj_mesh) total_y_rotation = 0 rotation_deg_interval = 5 from scipy.spatial.transform import Rotation as R r = R.from_euler('xyz', [[0, rotation_deg_interval, 0]], degrees=True) trans_mat = r.as_matrix() full_trans_mat = np.eye(4) full_trans_mat[:3, :3] = trans_mat # if not working, try rotating the image while len(simp_slice.entities) != 1 or len(nice_slice.entities) != 1: sobj_mesh.apply_transform(full_trans_mat) simp_slice, nice_slice = get_simplified_slice(sobj_mesh) total_y_rotation += rotation_deg_interval if total_y_rotation != 0: # add one more for good measure r = R.from_euler('xyz', [[0, rotation_deg_interval / 2, 0]], degrees=True) trans_mat = r.as_matrix() full_trans_mat = np.eye(4) full_trans_mat[:3, :3] = trans_mat sobj_mesh.apply_transform(full_trans_mat) simp_slice, nice_slice = get_simplified_slice(sobj_mesh) total_y_rotation += rotation_deg_interval node_list = simp_slice.entities[0].nodes ordered_vertices = np.array( [simp_slice.vertices[p] for p in simp_slice.entities[0].points]) ordered_vertices *= 1.15 print('total y rotation:', total_y_rotation) RADIUS = 1.2 def filletEdges(ed1, ed2): f = ChFi2d_AnaFilletAlgo() f.Init(ed1, ed2, gp_Pln()) f.Perform(RADIUS - 0.4) return f.Result(ed1, ed2) def make_vertices(vertices, close_loop=False, smooth_vertices=False): if smooth_vertices: filter_vec = np.array([0.2, 0.6, 0.2]) else: filter_vec = np.array([0, 1, 0]) pnts = [] prev_coords = None for i in range(len(vertices)): if i == 0: if close_loop: row = np.array( [vertices[-1], vertices[i], vertices[i + 1]]) coords_list = row.T.dot(filter_vec) else: edge_filter_vec = filter_vec[1:] edge_filter_vec[0] += filter_vec[0] coords_list = vertices[i:i + 2].T.dot(edge_filter_vec) elif i == len(vertices) - 1: if close_loop: row = np.array([vertices[i - 1], vertices[i], vertices[0]]) coords_list = row.T.dot(filter_vec) else: edge_filter_vec = filter_vec[:-1] edge_filter_vec[-1] += filter_vec[-1] coords_list = vertices[i - 1:i + 1].T.dot(edge_filter_vec) else: coords_list = vertices[i - 1:i + 2].T.dot(filter_vec) # print(coords_list) coords_list = list(coords_list) # raise Exception if prev_coords is None or coords_list != prev_coords: # print(coords_list) pnts.append(gp_Pnt(coords_list[0], coords_list[1], 0)) prev_coords = coords_list return pnts def vertices_to_edges(pnts): edges = [ BRepBuilderAPI_MakeEdge(pnts[i - 1], pnts[i]).Edge() for i in range(1, len(pnts)) ] return edges def edges_to_fillets(edges): fillets = [] for i in range(1, len(edges)): try: fillets.append(filletEdges(edges[i - 1], edges[i])) except Exception: print(i - 1) print(edges[i - 1]) print(edges[i]) raise Exception return fillets def make_wire(edges, fillets=None): # the wire # print("adding wire") makeWire = BRepBuilderAPI_MakeWire() makeWire.Add(edges[0]) if fillets is None: for edge in edges[1:]: makeWire.Add(edge) else: for fillet, edge in zip(fillets, edges[1:]): makeWire.Add(fillet) makeWire.Add(edge) # print("build wire") makeWire.Build() # print("make wire") try: wire = makeWire.Wire() except RuntimeError as e: print(type(makeWire)) raise e return wire def make_pipe(wire, p1, p2): # the pipe if p2 is not None: direction_coords = np.array(p2.XYZ().Coord()) - np.array( p1.XYZ().Coord()) direction_coords /= np.linalg.norm(direction_coords) direction = gp_Dir(*list(direction_coords)) else: direction = gp_Dir(1, 0, 0) # print(p1.XYZ().Coord(), p2.XYZ().Coord()) circle = gp_Circ(gp_Ax2(p1, direction), RADIUS) profile_edge = BRepBuilderAPI_MakeEdge(circle).Edge() profile_wire = BRepBuilderAPI_MakeWire(profile_edge).Wire() profile_face = BRepBuilderAPI_MakeFace(profile_wire).Face() pipe = BRepOffsetAPI_MakePipe(wire, profile_face).Shape() return pipe def filter_vertices(pnts, close_loop): good_pnts = [] if close_loop: pnts.extend(pnts[:2]) else: good_pnts = pnts[:2] for i in range(2, len(pnts)): # print("testing vertices:", pnts[i-2].XYZ().Coord(), pnts[i-1].XYZ().Coord(), pnts[i].XYZ().Coord()) good_pnts.append(pnts[i]) continue matrix = np.array([ pnts[i - 2].XYZ().Coord(), pnts[i - 1].XYZ().Coord(), pnts[i].XYZ().Coord() ]) np.savetxt('filter_vertices.txt', matrix) import subprocess cmd = subprocess.run( ["python", "test_point.py", "filter_vertices.txt"], capture_output=True) stdout = cmd.stdout.decode() # bytes => str if 'good' in stdout: print("good point", i) good_pnts.append(pnts[i]) else: print(stdout) return good_pnts def compose_wire(pnts, close_loop=False, smooth_vertices=False, add_fillets=True): # print("makevert") pnts = make_vertices(pnts, close_loop, smooth_vertices) print("filtvert") pnts = filter_vertices(pnts, close_loop) # close the loop if close_loop: pnts.append(pnts[0]) # the edges print("makeedge with", len(pnts), "vertices") edges = vertices_to_edges(pnts) # [:len(pnts)//4]) if add_fillets: print("makefillets") fillets = edges_to_fillets(edges) print("makewire") if add_fillets: wire = make_wire(edges, fillets) else: wire = make_wire(edges, fillets=None) return wire, pnts def compose_pipe(vertices, close_loop=False, smooth_vertices=False, add_fillets=True): wire, pnts = compose_wire(vertices, close_loop, smooth_vertices, add_fillets) pipe = make_pipe(wire, pnts[0], pnts[1]) return pipe def render_pipe(pipe): my_renderer = JupyterRenderer(compute_normals_mode=NORMAL.CLIENT_SIDE) my_renderer.DisplayShape(pipe, shape_color="blue", topo_level="Face", quality=1.) # default quality print(my_renderer) from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeSphere def make_sphere(centre, radius): pnt = gp_Pnt(*list(centre)) sphere = BRepPrimAPI_MakeSphere(pnt, radius).Shape() return sphere # In[7]: wire, pnts = compose_wire(ordered_vertices, close_loop=False, smooth_vertices=True) pipe = make_pipe(wire, pnts[0], pnts[1]) recovered_vertices = np.array([pnt.XYZ().Coord() for pnt in pnts]) recovered_vertices.mean(axis=0), recovered_vertices.max( axis=0), recovered_vertices.min(axis=0) # In[8]: # def create_handles """ make new ring that is scaled up version of original atan2(3/4), -atan2(3/4) atan(3/-2) + pi, -(atan(3/-2) + pi) find vertex with greatest normalized dot product with [3,4,0] in +y, use as cutoffs with above and below zero then add even vertices from cutoffs to max x and min x points in bigger """ y_axis_flip = np.array([1, -1, 1]) ur_angle = np.array([7, 3, 0]) dr_angle = ur_angle * y_axis_flip angle_prods = recovered_vertices.dot(ur_angle) / np.linalg.norm( recovered_vertices, axis=1) ur_vertex = recovered_vertices[angle_prods.argmax()] angle_prods = recovered_vertices.dot(dr_angle) / np.linalg.norm( recovered_vertices, axis=1) dr_vertex = recovered_vertices[angle_prods.argmax()] ul_angle = np.array([-3, 3, 0]) dr_angle = ul_angle * y_axis_flip angle_prods = recovered_vertices.dot(ul_angle) / np.linalg.norm( recovered_vertices, axis=1) ul_vertex = recovered_vertices[angle_prods.argmax()] angle_prods = recovered_vertices.dot(dr_angle) / np.linalg.norm( recovered_vertices, axis=1) dl_vertex = recovered_vertices[angle_prods.argmax()] print(ur_vertex, ul_vertex) exp_vertices = recovered_vertices * 1.15 upper_verts = exp_vertices[exp_vertices[:, 1] > 0] upper_verts = upper_verts[upper_verts[:, 0] >= ul_vertex[0]] upper_verts = upper_verts[upper_verts[:, 0] <= ur_vertex[0]] upper_verts = upper_verts[upper_verts[:, 0].argsort()] lower_verts = exp_vertices[exp_vertices[:, 1] < 0] lower_verts = lower_verts[lower_verts[:, 0] >= ul_vertex[0]] lower_verts = lower_verts[lower_verts[:, 0] <= ur_vertex[0]] lower_verts = lower_verts[lower_verts[:, 0].argsort()] ul_verts = np.array([ul_vertex, upper_verts[0]]) ur_verts = np.array([ur_vertex, upper_verts[-1]])[::-1] dl_verts = np.array([dl_vertex, lower_verts[0]]) dr_verts = np.array([dr_vertex, lower_verts[-1]])[::-1] u_pipe = compose_pipe(upper_verts, close_loop=False, smooth_vertices=False) l_pipe = compose_pipe(lower_verts, close_loop=False, smooth_vertices=False) ul_pipe = compose_pipe(ul_verts, close_loop=False, smooth_vertices=False, add_fillets=False) ur_pipe = compose_pipe(ur_verts, close_loop=False, smooth_vertices=False, add_fillets=False) dl_pipe = compose_pipe(dl_verts, close_loop=False, smooth_vertices=False, add_fillets=False) dr_pipe = compose_pipe(dr_verts, close_loop=False, smooth_vertices=False, add_fillets=False) ul_sphere = make_sphere(upper_verts[0], RADIUS) ur_sphere = make_sphere(upper_verts[-1], RADIUS) dl_sphere = make_sphere(lower_verts[0], RADIUS) dr_sphere = make_sphere(lower_verts[-1], RADIUS) from OCC.Core.TopoDS import TopoDS_Compound from OCC.Core.BRep import BRep_Builder aCompound = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound(aCompound) aBuilder.Add(aCompound, pipe) aBuilder.Add(aCompound, u_pipe) aBuilder.Add(aCompound, l_pipe) aBuilder.Add(aCompound, ul_pipe) aBuilder.Add(aCompound, ur_pipe) aBuilder.Add(aCompound, dl_pipe) aBuilder.Add(aCompound, dr_pipe) aBuilder.Add(aCompound, ul_sphere) aBuilder.Add(aCompound, ur_sphere) aBuilder.Add(aCompound, dl_sphere) aBuilder.Add(aCompound, dr_sphere) from OCC.Extend.DataExchange import write_stl_file output_file = '.'.join(input_file.split('.')[:-1]) + '_fitter' output_stl = output_file + '.stl' output_obj = output_file + '_bracket.obj' write_stl_file(aCompound, output_stl) print("Written to", output_stl) output_mesh = trimesh.load_mesh(output_stl) output_mesh = output_mesh.simplify_quadratic_decimation( len(output_mesh.faces) // 25) trimesh.repair.fix_inversion(output_mesh) def create_trans_mat(x, y, z): r = R.from_euler('xyz', [[x, y, z]], degrees=True) trans_mat = r.as_matrix() full_trans_mat = np.eye(4) full_trans_mat[:3, :3] = trans_mat return full_trans_mat full_trans_mat = create_trans_mat(0, 0, -90) output_mesh.apply_transform(full_trans_mat) # add bracket brac_mesh = trimesh.load_mesh('3d_files/bracket_insert_bent.STL') brac_mesh = brac_mesh.simplify_quadratic_decimation( len(brac_mesh.faces) // 2) print(len(brac_mesh.faces)) trimesh.repair.fix_inversion(brac_mesh) full_trans_mat = create_trans_mat(-90, 10, 180) brac_mesh.apply_transform(full_trans_mat) brac_mesh.vertices = brac_mesh.vertices * 0.86 + np.array([35, 10, 35]) brac_fitter = trimesh.util.concatenate([brac_mesh, output_mesh]) brac_fitter.apply_transform(np.diag(np.array([-1, 1, 1, 1]))) brac_fitter.export(output_obj) print("Written to", output_obj) return output_obj
def generate_stl(self, min_length=None, max_length=None, outfile_stl=None): """ Generate and export the .STL surface mesh for the blade as a whole, including the upper face, lower face and tip. The method utilizes modules from OCC SMESH which is standalone mesh framework based on SALOME mesher project. Please refer to https://github.com/tpaviot and http://docs.salome-platform.org/7/gui/SMESH/index.html for further details. This method requires PythonOCC and SMESH to be installed. :param double min_length: smallest distance between two nodes. Default value is None :param double max_length: largest distance between two nodes. Default value is None :param string outfile_stl: if string is passed then the method exports the generated 2D surface mesh into .stl file holding the name <outfile_stl>.stl. Default value is None We note that since the current implementation performs triangulation based on a topological compound that combines the blade 3 generated shapes without "fusion", it may happen that the generated triangulation of the upper and lower blade faces do not share the same exact nodes on the joint edge/wire resulting from the faces intersection. The current implementation can be enough for visualization purpose. However if the generated mesh is intended for computational analysis then a manual mesh healing is recommended by the user (e.g. see "Repair > Sewing" in SALOME GUI) for a proper mesh closure. """ from OCC.Core.SMESH import SMESH_Gen from OCC.Core.StdMeshers import (StdMeshers_Arithmetic1D, StdMeshers_TrianglePreference, StdMeshers_Regular_1D, StdMeshers_MEFISTO_2D) from OCC.Core.BRep import BRep_Builder from OCC.Core.TopoDS import TopoDS_Shape, TopoDS_Compound if min_length <= 0 or max_length <= 0: raise ValueError('min_length and max_length must be positive.') if min_length >= max_length: raise ValueError('min_length can not be greater than max_length') # First we check that blade shapes are generated, otherwise we generate # them. After that we combine the generated_upper_face, # generated_lower_face, and generated_tip into a topological compound # that we use to compute the surface mesh if (self.generated_upper_face is None) or not isinstance( self.generated_upper_face, TopoDS_Shape): # Upper face is generated with a maximal U degree = 1 self._generate_upper_face(maxDeg=1) if (self.generated_lower_face is None) or not isinstance( self.generated_lower_face, TopoDS_Shape): # Upper face is generated with a maximal U degree = 1 self._generate_lower_face(maxDeg=1) if (self.generated_tip is None) or not isinstance( self.generated_tip, TopoDS_Shape): # Upper face is generated with a maximal U degree = 1 self._generate_tip(maxDeg=1) # Now we regroup all the shapes into a TopoDS_Compound aCompound = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound(aCompound) # Add shapes aBuilder.Add(aCompound, self.generated_upper_face) aBuilder.Add(aCompound, self.generated_lower_face) aBuilder.Add(aCompound, self.generated_tip) # In the following we build the surface mesh according to the given # hypotheses aMeshGen = SMESH_Gen() aMesh = aMeshGen.CreateMesh(0, True) # Adding 1D hypothesis and algorithms # Wire discretization. Nodes are distributed based on Arithmetic1D # hypothesis which allows to split edges into segments with a length # that changes in arithmetic progression (Lk = Lk-1 + d) beginning # from a given min length and up to a given max length. More about # 1D hypotheses can be viewed through: # http://docs.salome-platform.org/7/gui/SMESH/a1d_meshing_hypo_page.html an1DHypothesis = StdMeshers_Arithmetic1D(0, 0, aMeshGen) # Smallest distance between 2 points an1DHypothesis.SetLength(min_length, False) # Longest distance between 2 points an1DHypothesis.SetLength(max_length, True) # Regular Interpolation an1DAlgo = StdMeshers_Regular_1D(1, 0, aMeshGen) # Adding 2D hypothesis and algorithms # 2D surface mesh -- Triangulations a2dHypothseis = StdMeshers_TrianglePreference(2, 0, aMeshGen) a2dAlgo = StdMeshers_MEFISTO_2D(3, 0, aMeshGen) #Calculate mesh for the topological compound containing the 3 shapes aMesh.ShapeToMesh(aCompound) #Assign hyptothesis to mesh aMesh.AddHypothesis(aCompound, 0) aMesh.AddHypothesis(aCompound, 1) aMesh.AddHypothesis(aCompound, 2) aMesh.AddHypothesis(aCompound, 3) if outfile_stl is not None: if not isinstance(outfile_stl, str): raise ValueError('outfile_stl must be a valid string.') #Compute the data aMeshGen.Compute(aMesh, aMesh.GetShapeToMesh()) # Export STL aMesh.ExportSTL(outfile_stl + '.stl', False)
class GenCompound(object): def __init__(self): self.builder = BRep_Builder() self.compound = TopoDS_Compound() self.builder.MakeCompound(compound)
def DisplayMesh(self, part: "Part", edge_color=None, vertex_color=None, vertex_width=2): from OCC.Core.BRep import BRep_Builder from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeVertex from OCC.Core.gp import gp_Pnt from OCC.Core.TopoDS import TopoDS_Compound # edge_color = format_color(*part.colour) if edge_color is None else edge_color rgb = randint(0, 255), randint(0, 255), randint(0, 255) edge_color = format_color(*rgb) if edge_color is None else edge_color vertex_color = self._default_vertex_color if vertex_color is None else vertex_color pmesh_id = "%s" % uuid.uuid4().hex BB = BRep_Builder() compound = TopoDS_Compound() BB.MakeCompound(compound) vertices_list = [] def togp(n_): return gp_Pnt(float(n_[0]), float(n_[1]), float(n_[2])) for vertex in map(togp, part.fem.nodes): vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape() BB.Add(compound, vertex_to_add) vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()]) attributes = { "position": BufferAttribute(vertices_list, normalized=False) } mat = PointsMaterial(color=vertex_color, sizeAttenuation=False, size=vertex_width) geom = BufferGeometry(attributes=attributes) points_geom = Points(geometry=geom, material=mat, name=pmesh_id) lmesh_id = "%s" % uuid.uuid4().hex edges_nodes = list( chain.from_iterable( filter( None, [get_vertices_from_elem(el) for el in part.fem.elements]))) np_edge_vertices = np.array(edges_nodes, dtype=np.float32) np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32) vertex_col = tuple([x / 255 for x in rgb]) edge_geometry = BufferGeometry( attributes={ "position": BufferAttribute(np_edge_vertices), "index": BufferAttribute(np_edge_indices), "color": BufferAttribute( [vertex_col for n in np_edge_vertices]), }) edge_material = LineBasicMaterial(vertexColors="VertexColors", linewidth=5) edge_geom = LineSegments( geometry=edge_geometry, material=edge_material, type="LinePieces", name=lmesh_id, ) output = [points_geom, edge_geom] for elem in output: self._shapes[elem.name] = compound self._refs[elem.name] = part self._displayed_pickable_objects.add(elem) self._fem_sets_opts.options = ["None"] + [ f"{part.fem.name}.{s.name}" for s in filter( lambda x: "internal" not in x.metadata.keys(), part.fem.sets) ] self._fem_refs[part.fem.name] = (part.fem, edge_geometry)
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 bottle = TopoDS_Compound() aBuilder = BRep_Builder() aBuilder.MakeCompound(bottle) aBuilder.Add(bottle, myBody_step3.Shape()) aBuilder.Add(bottle, myThreading) print("bottle created") export_shape_to_svg(bottle, "./test_mypy_classic_occ_bottle.svg") write_step_file(bottle, "./test_mypy_classic_occ_bottle.stp")