def write_stl_file(compound, filename, tolerance=None, angular_tolerance=None): # Remove previous mesh data BRepTools.Clean_s(compound) mesh = BRepMesh_IncrementalMesh(compound, tolerance, True, angular_tolerance) mesh.Perform() writer = StlAPI_Writer() result = writer.Write(compound, filename) # Remove the mesh data again BRepTools.Clean_s(compound) return result
def compute( self, shape, quality, angular_tolerance, tessellate=True, compute_edges=True, normals_len=0, debug=False, ): self.shape = shape self.normals_len = normals_len self.edges = [] count = self.number_solids(shape) with Timer(debug, "", f"mesh incrementally {'(parallel)' if count > 1 else ''}", 3): # Remove previous mesh data BRepTools.Clean_s(shape) BRepMesh_IncrementalMesh(shape, quality, False, angular_tolerance, count > 1) if tessellate: with Timer(debug, "", "get nodes, triangles and normals", 3): self.tessellate() if compute_edges: with Timer(debug, "", "get edges", 3): self.compute_edges()
def _fromTopoDS( cls: Type["BoundBox"], shape: TopoDS_Shape, tol: Optional[float] = None, optimal: bool = True, ): """ Constructs a bounding box from a TopoDS_Shape """ tol = TOL if tol is None else tol # tol = TOL (by default) bbox = Bnd_Box() if optimal: BRepBndLib.AddOptimal_s( shape, bbox ) # this is 'exact' but expensive - not yet wrapped by PythonOCC else: mesh = BRepMesh_IncrementalMesh(shape, tol, True) mesh.Perform() # this is adds +margin but is faster BRepBndLib.Add_s(shape, bbox, True) return cls(bbox)
def tessellate(shape, tolerance: float, angularTolerance: float = 0.1): # Remove previous mesh data BRepTools.Clean_s(shape) triangulated = BRepTools.Triangulation_s(shape, tolerance) if not triangulated: # this will add mesh data to the shape and prevent calculating an exact bounding box after this call BRepMesh_IncrementalMesh(shape, tolerance, True, angularTolerance) vertices = [] triangles = [] normals = [] offset = 0 for face in get_faces(shape): loc = TopLoc_Location() poly = BRep_Tool.Triangulation_s(face, loc) Trsf = loc.Transformation() reverse = face.Orientation() == TopAbs_Orientation.TopAbs_REVERSED internal = face.Orientation() == TopAbs_Orientation.TopAbs_INTERNAL # add vertices if poly is not None: vertices += [(v.X(), v.Y(), v.Z()) for v in (v.Transformed(Trsf) for v in poly.Nodes())] # add triangles triangles += [( t.Value(1) + offset - 1, t.Value(3 if reverse else 2) + offset - 1, t.Value(2 if reverse else 3) + offset - 1, ) for t in poly.Triangles()] # add normals if poly.HasUVNodes(): prop = BRepGProp_Face(face) uvnodes = poly.UVNodes() for uvnode in uvnodes: p = gp_Pnt() n = gp_Vec() prop.Normal(uvnode.X(), uvnode.Y(), p, n) if n.SquareMagnitude() > 0: n.Normalize() if internal: n.Reverse() normals.append((n.X(), n.Y(), n.Z())) offset += poly.NbNodes() if not triangulated: # Remove the mesh data again BRepTools.Clean_s(shape) return ( np.asarray(vertices, dtype=np.float32), np.asarray(triangles, dtype=np.uint32), np.asarray(normals, dtype=np.float32), )