mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Compare commits
2 commits
3474dc61d2
...
6605b676a3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6605b676a3 | ||
|
|
17ccdd01cc |
5 changed files with 40 additions and 21 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue