diff --git a/cadquery/occ_impl/exporters/dxf.py b/cadquery/occ_impl/exporters/dxf.py index 8a1cab57..89648205 100644 --- a/cadquery/occ_impl/exporters/dxf.py +++ b/cadquery/occ_impl/exporters/dxf.py @@ -76,16 +76,23 @@ def _dxf_spline(e: Edge, msp: ezdxf.layouts.Modelspace, plane: Plane): curve, adaptor.FirstParameter(), adaptor.LastParameter(), CURVE_TOLERANCE ) + # need to apply the transform on the geometry level + spline.Transform(plane.fG.wrapped.Trsf()) + order = spline.Degree() + 1 knots = list(spline.KnotSequence()) poles = [(p.X(), p.Y(), p.Z()) for p in spline.Poles()] + weights = ( + [spline.Weight(i) for i in range(1, spline.NbPoles() + 1)] + if spline.IsRational() + else None + ) - weights = list(spline.Weights()) if spline.IsRational() else None + if spline.IsPeriodic(): + pad = spline.NbKnots() - spline.LastUKnotIndex() + poles += poles[:pad] - if spline.IsClosed(): - dxf_spline = ezdxf.math.BSplineClosed(poles, order, knots, weights) - else: - dxf_spline = ezdxf.math.BSpline(poles, order, knots, weights) + dxf_spline = ezdxf.math.BSpline(poles, order, knots, weights) msp.add_spline().apply_construction_tool(dxf_spline) diff --git a/tests/test_exporters.py b/tests/test_exporters.py index 23ab95ad..52ff3322 100644 --- a/tests/test_exporters.py +++ b/tests/test_exporters.py @@ -9,6 +9,8 @@ import io from cadquery import * from cadquery import exporters, importers from tests import BaseTest +from OCP.GeomConvert import GeomConvert +from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge class TestExporters(BaseTest): @@ -168,6 +170,43 @@ class TestExporters(BaseTest): self.assertAlmostEqual(s4.val().Area(), s4_i.val().Area(), 6) self.assertAlmostEqual(s4.edges().size(), s4_i.edges().size()) + # test periodic spline + w = Workplane().spline([(1, 1), (2, 2), (3, 2), (3, 1)], periodic=True) + exporters.dxf.exportDXF(w, "res5.dxf") + + w_i = importers.importDXF("res5.dxf") + + self.assertAlmostEqual(w.val().Length(), w_i.wires().val().Length(), 6) + + # test rational spline + c = Edge.makeCircle(1) + adaptor = c._geomAdaptor() + curve = GeomConvert.CurveToBSplineCurve_s(adaptor.Curve().Curve()) + + e = Workplane().add(Edge(BRepBuilderAPI_MakeEdge(curve).Shape())) + exporters.dxf.exportDXF(e, "res6.dxf") + + e_i = importers.importDXF("res6.dxf") + + self.assertAlmostEqual(e.val().Length(), e_i.wires().val().Length(), 6) + + # test non-planar section + s5 = ( + Workplane() + .spline([(0, 0), (1, 0), (1, 1), (0, 1)]) + .close() + .extrude(1, both=True) + .translate((-3, -4, 0)) + ) + + s5.plane = Plane(origin=(0, 0.1, 0.5), normal=(0.05, 0.05, 1)) + s5 = s5.section() + exporters.dxf.exportDXF(s5, "res7.dxf") + + s5_i = importers.importDXF("res7.dxf") + + self.assertAlmostEqual(s5.val().Area(), s5_i.val().Area(), 4) + def testTypeHandling(self): with self.assertRaises(ValueError):