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 _bounding_box(self, obj, tol=1e-5): bbox = Bnd_Box() if self.optimal: BRepTools.Clean_s(obj) BRepBndLib.AddOptimal_s(obj, bbox) else: BRepBndLib.Add_s(obj, bbox) values = bbox.Get() return (values[0], values[3], values[1], values[4], values[2], values[5])
def _getPnt(self, arg: Shape) -> gp_Pnt: # check for infinite face if isinstance(arg, Face) and any( Precision.IsInfinite_s(x) for x in BRepTools.UVBounds_s(arg.wrapped) ): # fall back to gp_Pln center pln = arg.toPln() center = Vector(pln.Location()) else: center = arg.Center() return center.toPnt()
def _bounding_box(self, obj, tol=1e-6): bbox = Bnd_Box() if self.optimal: BRepTools.Clean_s(obj) BRepBndLib.AddOptimal_s(obj, bbox) else: BRepBndLib.Add_s(obj, bbox) if not bbox.IsVoid(): values = bbox.Get() return (values[0], values[3], values[1], values[4], values[2], values[5]) else: c = self._center_of_mass(obj) bb = (c[0] - tol, c[0] + tol, c[1] - tol, c[1] + tol, c[2] - tol, c[2] + tol) print("\nVoid Bounding Box", bb) return bb
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), )