Compare commits

...

2 commits

Author SHA1 Message Date
gumyr
6605b676a3 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
2025-12-02 20:25:34 -05:00
gumyr
17ccdd01cc Fixing OCCT typing problems 2025-12-02 20:24:55 -05:00
5 changed files with 40 additions and 21 deletions

View file

@ -37,6 +37,7 @@ from enum import Enum, auto
from io import BytesIO
from os import PathLike, fsdecode
from typing import Any, TypeAlias
from typing import cast as tcast
from warnings import warn
from collections.abc import Callable, Iterable
@ -48,7 +49,7 @@ from ezdxf.colors import RGB, aci2rgb
from ezdxf.math import Vec2
from OCP.BRepLib import BRepLib
from OCP.BRepTools import BRepTools_WireExplorer
from OCP.Geom import Geom_BezierCurve
from OCP.Geom import Geom_BezierCurve, Geom_BSplineCurve
from OCP.GeomConvert import GeomConvert
from OCP.GeomConvert import GeomConvert_BSplineCurveToBezierCurve
from OCP.gp import gp_Ax2, gp_Dir, gp_Pnt, gp_Vec, gp_XYZ
@ -757,7 +758,7 @@ class ExportDXF(Export2D):
# Extract the relevant segment of the curve.
spline = GeomConvert.SplitBSplineCurve_s(
curve,
tcast(Geom_BSplineCurve, curve),
u1,
u2,
Export2D.PARAMETRIC_TOLERANCE,
@ -1136,7 +1137,7 @@ class ExportSVG(Export2D):
)
while explorer.More():
topo_edge = explorer.Current()
loose_edges.append(Edge(topo_edge))
loose_edges.append(Edge(TopoDS.Edge_s(topo_edge)))
explorer.Next()
# print(f"{len(loose_edges)} loose edges")
loose_edge_elements = [self._edge_element(edge) for edge in loose_edges]
@ -1263,7 +1264,7 @@ class ExportSVG(Export2D):
(u0, u1) = (lp, fp) if reverse else (fp, lp)
start = self._path_point(curve.Value(u0))
end = self._path_point(curve.Value(u1))
radius = complex(radius, radius)
radius = complex(radius, radius) # type: ignore[assignment]
rotation = math.degrees(gp_Dir(1, 0, 0).AngleWithRef(x_axis, gp_Dir(0, 0, 1)))
if curve.IsClosed():
midway = self._path_point(curve.Value((u0 + u1) / 2))
@ -1316,7 +1317,7 @@ class ExportSVG(Export2D):
(u0, u1) = (lp, fp) if reverse else (fp, lp)
start = self._path_point(curve.Value(u0))
end = self._path_point(curve.Value(u1))
radius = complex(major_radius, minor_radius)
radius = complex(major_radius, minor_radius) # type: ignore[assignment]
rotation = math.degrees(gp_Dir(1, 0, 0).AngleWithRef(x_axis, gp_Dir(0, 0, 1)))
if curve.IsClosed():
midway = self._path_point(curve.Value((u0 + u1) / 2))
@ -1361,7 +1362,7 @@ class ExportSVG(Export2D):
# According to the OCCT 7.6.0 documentation,
# "ParametricTolerance is not used."
converter = GeomConvert_BSplineCurveToBezierCurve(
spline, u1, u2, Export2D.PARAMETRIC_TOLERANCE
tcast(Geom_BSplineCurve, spline), u1, u2, Export2D.PARAMETRIC_TOLERANCE
)
def make_segment(bezier: Geom_BezierCurve, reverse: bool) -> PathSegment:

View file

@ -244,7 +244,7 @@ def export_gltf(
messenger = Message.DefaultMessenger_s()
for printer in messenger.Printers():
printer.SetTraceLevel(Message_Gravity(Message_Gravity.Message_Fail))
printer.SetTraceLevel(Message_Gravity.Message_Fail)
status = writer.Perform(doc, index_map, progress)
@ -297,7 +297,7 @@ def export_step(
# Disable writing OCCT info to console
messenger = Message.DefaultMessenger_s()
for printer in messenger.Printers():
printer.SetTraceLevel(Message_Gravity(Message_Gravity.Message_Fail))
printer.SetTraceLevel(Message_Gravity.Message_Fail)
session = XSControl_WorkSession()
writer = STEPCAFControl_Writer(session, False)
@ -328,7 +328,7 @@ def export_step(
if not isinstance(file_path, BytesIO):
status = (
writer.Write(fspath(file_path)) == IFSelect_ReturnStatus.IFSelect_RetDone
writer.Write(fsdecode(file_path)) == IFSelect_ReturnStatus.IFSelect_RetDone
)
else:
status = writer.WriteStream(file_path) == IFSelect_ReturnStatus.IFSelect_RetDone

View file

@ -106,15 +106,23 @@ from OCP.BRepGProp import BRepGProp
from OCP.BRepMesh import BRepMesh_IncrementalMesh
from OCP.gp import gp_Pnt
from OCP.GProp import GProp_GProps
from OCP.Standard import Standard_TypeMismatch
from OCP.TopAbs import TopAbs_ShapeEnum
from OCP.TopExp import TopExp_Explorer
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 build123d.build_enums import MeshType, Unit
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:
@ -466,7 +474,9 @@ class Mesher:
# Convert to a list of gp_Pnt
ocp_vertices = [gp_pnts[tri_indices[i]] for i in range(3)]
# 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())
facet = face_builder.Face()
facet_properties = GProp_GProps()
@ -479,19 +489,27 @@ class Mesher:
occ_sewed_shape = downcast(shell_builder.SewedShape())
if isinstance(occ_sewed_shape, TopoDS_Compound):
occ_shells = []
bd_shells = []
explorer = TopExp_Explorer(occ_sewed_shape, TopAbs_ShapeEnum.TopAbs_SHELL)
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()
else:
occ_shells = [occ_sewed_shape]
assert isinstance(occ_sewed_shape, TopoDS_Shell)
bd_shells = [Shell(occ_sewed_shape)]
# Create a solid if manifold
shape_obj = Shell(occ_sewed_shape)
if shape_obj.is_manifold:
solid_builder = BRepBuilderAPI_MakeSolid(*occ_shells)
shape_obj = Solid(solid_builder.Solid())
outer_shell = max(bd_shells, key=lambda s: math.prod(s.bounding_box().size))
inner_shells = [s for s in bd_shells if s is not outer_shell]
# The the shell isn't water tight just return it else create a 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

View file

@ -60,7 +60,6 @@ import sys
import warnings
from collections.abc import Iterable, Iterator, Sequence
from itertools import combinations
from typing import TypeVar
from typing_extensions import Self

View file

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