Module piecad.utilities
Miscellaneous (but important) functions
Functions
def load(filename: str) ‑> Obj2d | Obj3d
-
Expand source code
def load(filename: str) -> Obj3d | Obj2d: """ Load a 3d object from a file. The format read from `filename` is determined by the file's extention. The available formats for 3D are: | Type | Extension | |:------------|:------------:| | 3MF | .3mf | | GLB | .glb | | GLTF | .gltf | | OBJ | .obj | | PLY | .ply | | STL | .stl_ascii | | STL binary | .stl | \\(See [https://github/mikedh/trimesh] for more formats.\\) Currently 2d objects are not supported. """ dot_idx = filename.rindex(".") ext = filename[dot_idx + 1 :] mesh = trimesh.exchange.load.load(filename, ext, force="mesh") if type(mesh) == trimesh.path.Path2D: raise ValidationError("Currently 2d objects are no supported.") else: o = Obj3d(_m.Manifold.create_from_verts_and_faces(mesh.vertices, mesh.faces)) return o
Load a 3d object from a file.
The format read from
filename
is determined by the file's extention.The available formats for 3D are:
Type Extension 3MF .3mf GLB .glb GLTF .gltf OBJ .obj PLY .ply STL .stl_ascii STL binary .stl (See [https://github/mikedh/trimesh] for more formats.)
Currently 2d objects are not supported.
def save(filename: str,
*objs: Obj2d | Obj3d) ‑> None-
Expand source code
def save(filename: str, *objs: Obj3d | Obj2d) -> None: """ Save a 3d or 2d object in a file suitable for printing, etc. The format placed in [p:filename] is determined by the file's extention. The available formats for 3D are: | Type | Extension | |:------------|:------------:| | 3MF | .3mf | | GLB | .glb | | GLTF | .gltf | | OBJ | .obj | | PLY | .ply | | STL | .stl_ascii | | STL binary | .stl | \\(See [https://github/mikedh/trimesh] for more formats.\\) For 2D, only the SVG (.svg) format is available. """ _chkGE("len(objs)", len(objs), 1) dot_idx = filename.rindex(".") ext = filename[dot_idx + 1 :] if type(objs[0]) == Obj3d: if len(objs) == 1: obj = objs[0] mesh = obj.mo.to_mesh() if mesh.vert_properties.shape[1] > 3: vertices = mesh.vert_properties[:, :3] else: vertices = mesh.vert_properties mesh_output = trimesh.Trimesh( vertices=vertices, faces=mesh.tri_verts, process=False ) if obj._color != None: mesh_output.visual.vertex_colors = obj._color # Manifold3d has a different definition than Trimesh if not mesh_output.is_watertight: print("WARNING: output mesh is not watertight") trimesh.exchange.export.export_mesh(mesh_output, filename, ext) else: scene = trimesh.Scene() for obj in objs: mesh = obj.mo.to_mesh() if mesh.vert_properties.shape[1] > 3: vertices = mesh.vert_properties[:, :3] else: vertices = mesh.vert_properties mesh_output = trimesh.Trimesh( vertices=vertices, faces=mesh.tri_verts, process=False ) if obj._color != None: mesh_output.visual.vertex_colors = obj._color # Manifold3d has a different definition than Trimesh if not mesh_output.is_watertight: print("WARNING: output mesh is not watertight") scene.add_geometry(mesh_output) trimesh.exchange.export.export_scene(scene, filename, ext) # trimesh obj file export does not end with newline # currently this upsets prusa_slicer if ext == "obj": with open(filename, "a") as f: f.write("\n") else: # Obj2d if ext != "svg": raise (ValidationError("Only the SVG format is supported for Obj2d.")) _save_svg(filename, *objs)
Save a 3d or 2d object in a file suitable for printing, etc.
The format placed in [p:filename] is determined by the file's extention.
The available formats for 3D are:
Type Extension 3MF .3mf GLB .glb GLTF .gltf OBJ .obj PLY .ply STL .stl_ascii STL binary .stl (See [https://github/mikedh/trimesh] for more formats.)
For 2D, only the SVG (.svg) format is available.
def view(obj: Obj2d | Obj3d,
title: str = '') ‑> None-
Expand source code
def view(obj: Obj3d | Obj2d, title: str = "") -> None: """ Use CADView protocol to display the geometry object. Returns obj unchanged... so that it works well in return statements. """ global _view_thread if _viewer_available == False: return _chkGO("obj", obj) if title == "": title = _info_str("view") if type(obj) == Obj2d: color = obj._color obj = Obj2d(_m.Manifold.extrude(obj.mo, 0.1)) obj._color = color if _view_thread == None: _view_thread = threading.Thread(target=_view_handler, daemon=True) _view_thread.start() atexit.register(_tell_view_handler_to_exit) mesh = obj.mo.to_mesh() if mesh.vert_properties.shape[1] > 3: vertices = mesh.vert_properties[:, :3] else: vertices = mesh.vert_properties faces = mesh.tri_verts view_data = {} view_data["title"] = title view_data["color"] = [210, 180, 140] if obj._color == None else obj._color view_data["vertices"] = vertices.tolist() fl = faces.tolist() # for one in fl: # one.insert(0, len(one)) # fl.insert(0, len(fl)) view_data["faces"] = fl _view_queue.put(view_data) return obj
Use CADView protocol to display the geometry object.
Returns obj unchanged… so that it works well in return statements.
def winding(lt: list[tuple[float, float]]) ‑> str
-
Expand source code
def winding(lt: list[tuple[float, float]]) -> str: """ String description of winding of a 2D polygon. Returns one of `"cw"`, `"ccw"`, `"zero"` or `"too small"`. """ def wstr(winding): if winding > 0: return "cw" if winding < 0: return "ccw" return "zero" length = len(lt) if length < 3: return "too small" winding = 0.0 for i in range(0, length): winding += (lt[(i + 1) % length][0] - lt[i][0]) * ( lt[(i + 1) % length][1] + lt[i][1] ) return wstr(winding)
String description of winding of a 2D polygon.
Returns one of
"cw"
,"ccw"
,"zero"
or"too small"
.