From fe0a449993792d4e44b863ed8c800eb9ee569672 Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Tue, 31 Aug 2021 08:46:52 +0200 Subject: [PATCH 1/4] Handle periodic splines properly --- cadquery/occ_impl/exporters/dxf.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cadquery/occ_impl/exporters/dxf.py b/cadquery/occ_impl/exporters/dxf.py index 8a1cab57..9268667a 100644 --- a/cadquery/occ_impl/exporters/dxf.py +++ b/cadquery/occ_impl/exporters/dxf.py @@ -79,13 +79,13 @@ def _dxf_spline(e: Edge, msp: ezdxf.layouts.Modelspace, plane: Plane): order = spline.Degree() + 1 knots = list(spline.KnotSequence()) poles = [(p.X(), p.Y(), p.Z()) for p in spline.Poles()] - weights = list(spline.Weights()) if spline.IsRational() else None - if spline.IsClosed(): - dxf_spline = ezdxf.math.BSplineClosed(poles, order, knots, weights) - else: - dxf_spline = ezdxf.math.BSpline(poles, order, knots, weights) + if spline.IsPeriodic(): + pad = spline.NbKnots() - spline.LastUKnotIndex() + poles += poles[:pad] + + dxf_spline = ezdxf.math.BSpline(poles, order, knots, weights) msp.add_spline().apply_construction_tool(dxf_spline) From 3337b81ff93badb821f67bee52a5c213d5f8a395 Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Tue, 31 Aug 2021 08:58:51 +0200 Subject: [PATCH 2/4] Add tests --- tests/test_exporters.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/test_exporters.py b/tests/test_exporters.py index 23ab95ad..fbdd9486 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,26 @@ 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 = cq.Workplane().spline([(1, 1), (2, 2), (3, 2), (4, 1)], periodic=True) + exporters.dxf.exportDXF(w, "res4.dxf") + + w_i = importers.importDXF("res4.dxf") + + self.assertAlmostEqual(w.val().Length(), w_i.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(w, "res5.dxf") + + e_i = importers.importDXF("res5.dxf") + + self.assertAlmostEqual(e.val().Length(), e_i.val().Length(), 6) + def testTypeHandling(self): with self.assertRaises(ValueError): From 9fc403ef5c3642ba88361306cc74911b21c4025d Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Tue, 31 Aug 2021 18:34:49 +0200 Subject: [PATCH 3/4] Transfrom and crash fix --- cadquery/occ_impl/exporters/dxf.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cadquery/occ_impl/exporters/dxf.py b/cadquery/occ_impl/exporters/dxf.py index 9268667a..89648205 100644 --- a/cadquery/occ_impl/exporters/dxf.py +++ b/cadquery/occ_impl/exporters/dxf.py @@ -76,10 +76,17 @@ 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 = list(spline.Weights()) if spline.IsRational() else None + weights = ( + [spline.Weight(i) for i in range(1, spline.NbPoles() + 1)] + if spline.IsRational() + else None + ) if spline.IsPeriodic(): pad = spline.NbKnots() - spline.LastUKnotIndex() From 6f52d88cfa97fe7a541c57b3421625b620311abb Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Tue, 31 Aug 2021 18:35:01 +0200 Subject: [PATCH 4/4] More tests + fixes --- tests/test_exporters.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/tests/test_exporters.py b/tests/test_exporters.py index fbdd9486..52ff3322 100644 --- a/tests/test_exporters.py +++ b/tests/test_exporters.py @@ -171,12 +171,12 @@ class TestExporters(BaseTest): self.assertAlmostEqual(s4.edges().size(), s4_i.edges().size()) # test periodic spline - w = cq.Workplane().spline([(1, 1), (2, 2), (3, 2), (4, 1)], periodic=True) - exporters.dxf.exportDXF(w, "res4.dxf") + w = Workplane().spline([(1, 1), (2, 2), (3, 2), (3, 1)], periodic=True) + exporters.dxf.exportDXF(w, "res5.dxf") - w_i = importers.importDXF("res4.dxf") + w_i = importers.importDXF("res5.dxf") - self.assertAlmostEqual(w.val().Length(), w_i.val().Length(), 6) + self.assertAlmostEqual(w.val().Length(), w_i.wires().val().Length(), 6) # test rational spline c = Edge.makeCircle(1) @@ -184,11 +184,28 @@ class TestExporters(BaseTest): curve = GeomConvert.CurveToBSplineCurve_s(adaptor.Curve().Curve()) e = Workplane().add(Edge(BRepBuilderAPI_MakeEdge(curve).Shape())) - exporters.dxf.exportDXF(w, "res5.dxf") + exporters.dxf.exportDXF(e, "res6.dxf") - e_i = importers.importDXF("res5.dxf") + e_i = importers.importDXF("res6.dxf") - self.assertAlmostEqual(e.val().Length(), e_i.val().Length(), 6) + 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):