Fixed problem with hollow STL files
Some checks are pending
benchmarks / benchmarks (macos-14, 3.12) (push) Waiting to run
benchmarks / benchmarks (macos-15-intel, 3.12) (push) Waiting to run
benchmarks / benchmarks (ubuntu-latest, 3.12) (push) Waiting to run
benchmarks / benchmarks (windows-latest, 3.12) (push) Waiting to run
Upload coverage reports to Codecov / run (push) Waiting to run
pylint / lint (3.10) (push) Waiting to run
Run type checker / typecheck (3.10) (push) Waiting to run
Run type checker / typecheck (3.13) (push) Waiting to run
Wheel building and publishing / Build wheel on ubuntu-latest (push) Waiting to run
Wheel building and publishing / upload_pypi (push) Blocked by required conditions
tests / tests (macos-14, 3.10) (push) Waiting to run
tests / tests (macos-14, 3.13) (push) Waiting to run
tests / tests (macos-15-intel, 3.10) (push) Waiting to run
tests / tests (macos-15-intel, 3.13) (push) Waiting to run
tests / tests (ubuntu-latest, 3.10) (push) Waiting to run
tests / tests (ubuntu-latest, 3.13) (push) Waiting to run
tests / tests (windows-latest, 3.10) (push) Waiting to run
tests / tests (windows-latest, 3.13) (push) Waiting to run

This commit is contained in:
gumyr 2025-12-02 20:25:34 -05:00
parent 17ccdd01cc
commit 6605b676a3
2 changed files with 30 additions and 11 deletions

View file

@ -106,15 +106,23 @@ from OCP.BRepGProp import BRepGProp
from OCP.BRepMesh import BRepMesh_IncrementalMesh from OCP.BRepMesh import BRepMesh_IncrementalMesh
from OCP.gp import gp_Pnt from OCP.gp import gp_Pnt
from OCP.GProp import GProp_GProps from OCP.GProp import GProp_GProps
from OCP.Standard import Standard_TypeMismatch
from OCP.TopAbs import TopAbs_ShapeEnum from OCP.TopAbs import TopAbs_ShapeEnum
from OCP.TopExp import TopExp_Explorer from OCP.TopExp import TopExp_Explorer
from OCP.TopLoc import TopLoc_Location from OCP.TopLoc import TopLoc_Location
from OCP.TopoDS import TopoDS_Compound from OCP.TopoDS import TopoDS, TopoDS_Compound, TopoDS_Shell
from lib3mf import Lib3MF from lib3mf import Lib3MF
from build123d.build_enums import MeshType, Unit from build123d.build_enums import MeshType, Unit
from build123d.geometry import TOLERANCE, Color from build123d.geometry import TOLERANCE, Color
from build123d.topology import Compound, Shape, Shell, Solid, downcast from build123d.topology import (
Compound,
Shape,
Shell,
Solid,
downcast,
unwrap_topods_compound,
)
class Mesher: class Mesher:
@ -466,7 +474,9 @@ class Mesher:
# Convert to a list of gp_Pnt # Convert to a list of gp_Pnt
ocp_vertices = [gp_pnts[tri_indices[i]] for i in range(3)] ocp_vertices = [gp_pnts[tri_indices[i]] for i in range(3)]
# Create the triangular face using the polygon # Create the triangular face using the polygon
polygon_builder = BRepBuilderAPI_MakePolygon(*ocp_vertices, Close=True) polygon_builder = BRepBuilderAPI_MakePolygon(
ocp_vertices[0], ocp_vertices[1], ocp_vertices[2], Close=True
)
face_builder = BRepBuilderAPI_MakeFace(polygon_builder.Wire()) face_builder = BRepBuilderAPI_MakeFace(polygon_builder.Wire())
facet = face_builder.Face() facet = face_builder.Face()
facet_properties = GProp_GProps() facet_properties = GProp_GProps()
@ -479,19 +489,27 @@ class Mesher:
occ_sewed_shape = downcast(shell_builder.SewedShape()) occ_sewed_shape = downcast(shell_builder.SewedShape())
if isinstance(occ_sewed_shape, TopoDS_Compound): if isinstance(occ_sewed_shape, TopoDS_Compound):
occ_shells = [] bd_shells = []
explorer = TopExp_Explorer(occ_sewed_shape, TopAbs_ShapeEnum.TopAbs_SHELL) explorer = TopExp_Explorer(occ_sewed_shape, TopAbs_ShapeEnum.TopAbs_SHELL)
while explorer.More(): while explorer.More():
occ_shells.append(downcast(explorer.Current())) # occ_shells.append(downcast(explorer.Current()))
bd_shells.append(Shell(TopoDS.Shell_s(explorer.Current())))
explorer.Next() explorer.Next()
else: else:
occ_shells = [occ_sewed_shape] assert isinstance(occ_sewed_shape, TopoDS_Shell)
bd_shells = [Shell(occ_sewed_shape)]
# Create a solid if manifold outer_shell = max(bd_shells, key=lambda s: math.prod(s.bounding_box().size))
shape_obj = Shell(occ_sewed_shape) inner_shells = [s for s in bd_shells if s is not outer_shell]
if shape_obj.is_manifold:
solid_builder = BRepBuilderAPI_MakeSolid(*occ_shells) # The the shell isn't water tight just return it else create a solid
shape_obj = Solid(solid_builder.Solid()) if not outer_shell.is_manifold:
return outer_shell
solid_builder = BRepBuilderAPI_MakeSolid(outer_shell.wrapped)
for inner_shell in inner_shells:
solid_builder.Add(inner_shell.wrapped)
shape_obj = Solid(solid_builder.Solid())
return shape_obj return shape_obj

View file

@ -210,6 +210,7 @@ class TestHollowImport(unittest.TestCase):
importer = Mesher() importer = Mesher()
stl = importer.read("test.stl") stl = importer.read("test.stl")
self.assertTrue(stl[0].is_valid) self.assertTrue(stl[0].is_valid)
self.assertAlmostEqual(test_shape.volume, stl[0].volume, 0)
class TestImportDegenerateTriangles(unittest.TestCase): class TestImportDegenerateTriangles(unittest.TestCase):