mirror of
https://github.com/gumyr/build123d.git
synced 2026-01-30 04:10:34 -08:00
Added import_stl as Solid
This commit is contained in:
parent
55b6119104
commit
5f4e14da82
3 changed files with 90 additions and 11 deletions
|
|
@ -43,7 +43,8 @@ dependencies = [
|
|||
"numpy >= 1.24.1, <2",
|
||||
"svgpathtools >= 1.5.1, <2",
|
||||
"anytree >= 2.8.0, <3",
|
||||
"ezdxf >= 1.0.0, < 2"
|
||||
"ezdxf >= 1.0.0, < 2",
|
||||
"numpy-stl >= 3.0.0, <4"
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
|
|
|
|||
|
|
@ -30,15 +30,26 @@ license:
|
|||
|
||||
import os
|
||||
from math import degrees
|
||||
from stl.mesh import Mesh
|
||||
from svgpathtools import svg2paths
|
||||
from typing import Union
|
||||
from OCP.TopoDS import TopoDS_Face, TopoDS_Shape
|
||||
from OCP.BRep import BRep_Builder
|
||||
from OCP.BRepTools import BRepTools
|
||||
from OCP.STEPControl import STEPControl_Reader
|
||||
import OCP.IFSelect
|
||||
from OCP.RWStl import RWStl
|
||||
from OCP.BRepBuilderAPI import (
|
||||
BRepBuilderAPI_MakeEdge,
|
||||
BRepBuilderAPI_MakeFace,
|
||||
BRepBuilderAPI_MakeSolid,
|
||||
BRepBuilderAPI_MakeVertex,
|
||||
BRepBuilderAPI_MakeWire,
|
||||
BRepBuilderAPI_Sewing,
|
||||
)
|
||||
from OCP.gp import gp_Pnt
|
||||
|
||||
from build123d.topology import Compound, Edge, Face, Shape, ShapeList
|
||||
from build123d.topology import Compound, Edge, Face, Shape, ShapeList, Solid, downcast
|
||||
|
||||
|
||||
def import_brep(file_name: str) -> Shape:
|
||||
|
|
@ -98,27 +109,78 @@ def import_step(file_name: str) -> Compound:
|
|||
return Compound.make_compound(solids)
|
||||
|
||||
|
||||
def import_stl(file_name: str) -> Face:
|
||||
def import_stl(file_name: str, for_reference: bool = True) -> Union[Face, Solid]:
|
||||
"""import_stl
|
||||
|
||||
Extract shape from an STL file and return them as a Face object.
|
||||
Extract shape from an STL file and return them as a Solid object.
|
||||
|
||||
Args:
|
||||
file_name (str): file path of STL file to import
|
||||
for_reference (bool, optional): only create an uneditable mesh object
|
||||
for use as a reference. Otherwise, create an editable Solid object.
|
||||
Note that creating a reference is very fast while creating an editable
|
||||
model may take minutes depending on the size of the STL file.
|
||||
Defaults to True.
|
||||
|
||||
Raises:
|
||||
ValueError: Could not import file
|
||||
|
||||
Returns:
|
||||
Face: contents of STL file
|
||||
Union[Face, Solid]: STL model
|
||||
"""
|
||||
# Now read and return the shape
|
||||
reader = RWStl.ReadFile_s(file_name)
|
||||
face = TopoDS_Face()
|
||||
if for_reference:
|
||||
# Now read and return the shape
|
||||
reader = RWStl.ReadFile_s(file_name)
|
||||
face = TopoDS_Face()
|
||||
BRep_Builder().MakeFace(face, reader)
|
||||
stl_obj = Face.cast(face)
|
||||
else:
|
||||
# Read the file with numpy-stl
|
||||
try:
|
||||
stl_mesh = Mesh.from_file(file_name)
|
||||
except:
|
||||
raise ValueError("Invalid file")
|
||||
|
||||
BRep_Builder().MakeFace(face, reader)
|
||||
faces = []
|
||||
|
||||
return Face.cast(face)
|
||||
for facet in stl_mesh.vectors:
|
||||
# Create OCC vertices
|
||||
ocp_vertices = [
|
||||
downcast(BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, z)).Vertex())
|
||||
for x, y, z in facet
|
||||
]
|
||||
|
||||
# Create OCC edges
|
||||
ocp_edges = [
|
||||
BRepBuilderAPI_MakeEdge(v1, v2).Edge()
|
||||
for v1, v2 in zip(ocp_vertices, ocp_vertices[1:] + [ocp_vertices[0]])
|
||||
]
|
||||
|
||||
# Create OCC wire
|
||||
wire_builder = BRepBuilderAPI_MakeWire()
|
||||
for edge in ocp_edges:
|
||||
wire_builder.Add(edge)
|
||||
ocp_wire = wire_builder.Wire()
|
||||
|
||||
# Create OCC face
|
||||
face_builder = BRepBuilderAPI_MakeFace(ocp_wire)
|
||||
ocp_face = face_builder.Face()
|
||||
|
||||
# Store the faces
|
||||
faces.append(ocp_face)
|
||||
|
||||
# Create a shell
|
||||
shell_builder = BRepBuilderAPI_Sewing()
|
||||
for face in faces:
|
||||
shell_builder.Add(face)
|
||||
shell_builder.Perform()
|
||||
occ_shell = downcast(shell_builder.SewedShape())
|
||||
|
||||
# Create a solid
|
||||
solid_builder = BRepBuilderAPI_MakeSolid(occ_shell)
|
||||
stl_obj = Solid(solid_builder.Solid())
|
||||
|
||||
return stl_obj
|
||||
|
||||
|
||||
def import_svg_as_buildline_code(file_name: str) -> tuple[str, str]:
|
||||
|
|
|
|||
|
|
@ -1141,7 +1141,7 @@ class TestFunctions(unittest.TestCase):
|
|||
self.assertEqual(plug[0], cyl)
|
||||
|
||||
|
||||
class TestImportExport(unittest.TestCase):
|
||||
class TestImportExport(DirectApiTestCase):
|
||||
def test_import_export(self):
|
||||
original_box = Solid.make_box(1, 1, 1)
|
||||
original_box.export_step("test_box.step")
|
||||
|
|
@ -1157,6 +1157,22 @@ class TestImportExport(unittest.TestCase):
|
|||
with self.assertRaises(ValueError):
|
||||
step_box = import_step("test_box.step")
|
||||
|
||||
def test_import_stl(self):
|
||||
original_box = Solid.make_box(1, 2, 3)
|
||||
original_box.export_stl("test_box.stl")
|
||||
stl_box = import_stl("test_box.stl", for_reference=False).clean()
|
||||
self.assertEqual(len(stl_box.vertices()), 8)
|
||||
self.assertEqual(len(stl_box.edges()), 12)
|
||||
self.assertEqual(len(stl_box.faces()), 6)
|
||||
self.assertAlmostEqual(stl_box.volume, 1 * 2 * 3, 5)
|
||||
|
||||
stl_box = import_stl("test_box.stl", for_reference=True)
|
||||
self.assertVectorAlmostEquals(stl_box.position, (0, 0, 0), 5)
|
||||
|
||||
os.remove("test_box.stl")
|
||||
with self.assertRaises(ValueError):
|
||||
import_stl("test_box.stl", for_reference=False)
|
||||
|
||||
|
||||
class TestJoints(DirectApiTestCase):
|
||||
def test_rigid_joint(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue