From 3bbc40b9bb43d0bc91d056747722dbf4fb75a61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=B6ftner?= Date: Tue, 27 Jun 2023 17:12:04 +0200 Subject: [PATCH] Path: fix g-code orientation Path.Op.Profile in case effective offset is 0.0 --- src/Mod/Path/CMakeLists.txt | 2 + src/Mod/Path/Path/Op/Profile.py | 5 +- src/Mod/Path/PathTests/TestPathProfile.py | 200 ++++++++++++++++++++++ src/Mod/Path/PathTests/test_profile.fcstd | Bin 0 -> 10086 bytes src/Mod/Path/TestPathApp.py | 4 + 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 src/Mod/Path/PathTests/TestPathProfile.py create mode 100644 src/Mod/Path/PathTests/test_profile.fcstd diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 1468aeee3b..e29026adc6 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -279,6 +279,7 @@ SET(PathTests_SRCS PathTests/drill_test1.FCStd PathTests/PathTestUtils.py PathTests/test_adaptive.fcstd + PathTests/test_profile.fcstd PathTests/test_centroid_00.ngc PathTests/test_filenaming.fcstd PathTests/test_geomop.fcstd @@ -306,6 +307,7 @@ SET(PathTests_SRCS PathTests/TestPathOpUtil.py PathTests/TestPathPost.py PathTests/TestPathPreferences.py + PathTests/TestPathProfile.py PathTests/TestPathPropertyBag.py PathTests/TestPathRotationGenerator.py PathTests/TestPathSetupSheet.py diff --git a/src/Mod/Path/Path/Op/Profile.py b/src/Mod/Path/Path/Op/Profile.py index 3eff30c6e3..2d9adaf588 100644 --- a/src/Mod/Path/Path/Op/Profile.py +++ b/src/Mod/Path/Path/Op/Profile.py @@ -352,7 +352,10 @@ class ObjectProfile(PathAreaOp.ObjectOp): else: params["orientation"] = 1 - if not obj.UseComp: + offset = obj.OffsetExtra.Value + if obj.UseComp: + offset = self.radius + obj.OffsetExtra.Value + if offset == 0.0: if direction == "CCW": params["orientation"] = 1 else: diff --git a/src/Mod/Path/PathTests/TestPathProfile.py b/src/Mod/Path/PathTests/TestPathProfile.py new file mode 100644 index 0000000000..e6cdab9bea --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathProfile.py @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2023 Robert Schöftner * +# * Copyright (c) 2021 Russell Johnson (russ4262) * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +import FreeCAD +import Part +import Path.Op.Profile as PathProfile +import Path.Main.Job as PathJob +from PathTests.PathTestUtils import PathTestBase +from PathTests.TestPathAdaptive import getGcodeMoves + +if FreeCAD.GuiUp: + import Path.Main.Gui.Job as PathJobGui + import Path.Op.Gui.Profile as PathProfileGui + + +class TestPathProfile(PathTestBase): + """Unit tests for the Adaptive operation.""" + + @classmethod + def setUpClass(cls): + """setUpClass()... + This method is called upon instantiation of this test class. Add code and objects here + that are needed for the duration of the test() methods in this class. In other words, + set up the 'global' test environment here; use the `setUp()` method to set up a 'local' + test environment. + This method does not have access to the class `self` reference, but it + is able to call static methods within this same class. + """ + cls.needsInit = True + + @classmethod + def initClass(cls): + # Open existing FreeCAD document with test geometry + cls.needsInit = False + cls.doc = FreeCAD.open( + FreeCAD.getHomePath() + "Mod/Path/PathTests/test_profile.fcstd" + ) + + # Create Job object, adding geometry objects from file opened above + cls.job = PathJob.Create("Job", [cls.doc.Body], None) + cls.job.GeometryTolerance.Value = 0.001 + if FreeCAD.GuiUp: + cls.job.ViewObject.Proxy = PathJobGui.ViewProvider(cls.job.ViewObject) + + # Instantiate an Profile operation for querying available properties + cls.prototype = PathProfile.Create("Profile") + cls.prototype.Base = [(cls.doc.Body, ["Face4"])] + cls.prototype.Label = "Prototype" + _addViewProvider(cls.prototype) + + cls.doc.recompute() + + @classmethod + def tearDownClass(cls): + """tearDownClass()... + This method is called prior to destruction of this test class. Add code and objects here + that cleanup the test environment after the test() methods in this class have been executed. + This method does not have access to the class `self` reference. This method + is able to call static methods within this same class. + """ + # FreeCAD.Console.PrintMessage("TestPathAdaptive.tearDownClass()\n") + + # Close geometry document without saving + if not cls.needsInit: + FreeCAD.closeDocument(cls.doc.Name) + + # Setup and tear down methods called before and after each unit test + def setUp(self): + """setUp()... + This method is called prior to each `test()` method. Add code and objects here + that are needed for multiple `test()` methods. + """ + if self.needsInit: + self.initClass() + + def tearDown(self): + """tearDown()... + This method is called after each test() method. Add cleanup instructions here. + Such cleanup instructions will likely undo those in the setUp() method. + """ + pass + + # Unit tests + def test00(self): + """test00() Empty test.""" + return + + def test01(self): + """test01() Verify path generated on Face4.""" + + # Instantiate a Profile operation and set Base Geometry + profile = PathProfile.Create("Profile") + profile.Base = [(self.doc.Body, ["Face4"])] # (base, subs_list) + profile.Label = "test01+" + profile.Comment = "test01() Verify path generated on Face4." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + profile.processCircles = True + profile.processHoles = True + profile.UseComp = True + profile.Direction = "CW" + _addViewProvider(profile) + self.doc.recompute() + + moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) + operationMoves = "; ".join(moves) + FreeCAD.Console.PrintMessage("test01_moves: " + operationMoves + "\n") + + expected_moves = "G1 X7.07 Y7.07 Z10.0; G3 I-7.07 J-7.07 K0.0 X-1.56 Y9.87 Z10.0; G3 I1.56 J-9.87 K0.0 X1.56 Y-9.87 Z10.0; G3 I-1.56 J9.87 K0.0 X7.07 Y7.07 Z10.0; G1 X19.44 Y19.44 Z10.0; G2 I-19.44 J-19.44 K0.0 X3.15 Y-27.32 Z10.0; G2 I-3.15 J27.32 K0.0 X-3.15 Y27.32 Z10.0; G2 I3.15 J-27.32 K0.0 X19.44 Y19.44 Z10.0" + + self.assertTrue(expected_moves == operationMoves, + "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves)) + + def test02(self): + """test02() Verify path generated on Face4.""" + + # Instantiate a Profile operation and set Base Geometry + profile = PathProfile.Create("Profile2") + profile.Base = [(self.doc.Body, ["Face4"])] # (base, subs_list) + profile.Label = "test02+" + profile.Comment = "test02() Verify path generated on Face4." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + profile.processCircles = True + profile.processHoles = True + profile.UseComp = False + profile.Direction = "CW" + _addViewProvider(profile) + self.doc.recompute() + + moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) + operationMoves = "; ".join(moves) + FreeCAD.Console.PrintMessage("test02_moves: " + operationMoves + "\n") + + expected_moves = "G1 X8.84 Y8.84 Z10.0; G3 I-8.84 J-8.84 K0.0 X-0.0 Y12.5 Z10.0; G3 I0.0 J-12.5 K0.0 X0.0 Y-12.5 Z10.0; G3 I-0.0 J12.5 K0.0 X8.84 Y8.84 Z10.0; G1 X17.68 Y17.68 Z10.0; G2 I-17.68 J-17.68 K0.0 X0.0 Y-25.0 Z10.0; G2 I-0.0 J25.0 K0.0 X-0.0 Y25.0 Z10.0; G2 I0.0 J-25.0 K0.0 X17.68 Y17.68 Z10.0" + + self.assertTrue(expected_moves == operationMoves, + "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves)) + + def test03(self): + """test03() Verify path generated on Face4.""" + + # Instantiate a Profile operation and set Base Geometry + profile = PathProfile.Create("Profile3") + profile.Base = [(self.doc.Body, ["Face4"])] # (base, subs_list) + profile.Label = "test03+" + profile.Comment = "test03() Verify path generated on Face4." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + profile.processCircles = True + profile.processHoles = True + profile.UseComp = True + profile.Direction = "CW" + profile.OffsetExtra = -profile.OpToolDiameter / 2.0 + _addViewProvider(profile) + self.doc.recompute() + + moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) + operationMoves = "; ".join(moves) + FreeCAD.Console.PrintMessage("test03_moves: " + operationMoves + "\n") + + expected_moves = "G1 X8.84 Y8.84 Z10.0; G3 I-8.84 J-8.84 K0.0 X-0.0 Y12.5 Z10.0; G3 I0.0 J-12.5 K0.0 X0.0 Y-12.5 Z10.0; G3 I-0.0 J12.5 K0.0 X8.84 Y8.84 Z10.0; G1 X17.68 Y17.68 Z10.0; G2 I-17.68 J-17.68 K0.0 X0.0 Y-25.0 Z10.0; G2 I-0.0 J25.0 K0.0 X-0.0 Y25.0 Z10.0; G2 I0.0 J-25.0 K0.0 X17.68 Y17.68 Z10.0" + + self.assertTrue(expected_moves == operationMoves, + "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves)) + + +def _addViewProvider(profileOp): + if FreeCAD.GuiUp: + PathOpGui = PathProfileGui.PathOpGui + cmdRes = PathProfileGui.Command.res + profileOp.ViewObject.Proxy = PathOpGui.ViewProvider( + profileOp.ViewObject, cmdRes + ) + diff --git a/src/Mod/Path/PathTests/test_profile.fcstd b/src/Mod/Path/PathTests/test_profile.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..6e9c058b9d1370da5e141f7e2da2a77384f9ae9c GIT binary patch literal 10086 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 literal 0 HcmV?d00001 diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 88fb9307a8..3b905aab84 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -22,6 +22,8 @@ import TestApp +from PathTests.TestPathProfile import TestPathProfile + from PathTests.TestPathAdaptive import TestPathAdaptive from PathTests.TestPathCore import TestPathCore from PathTests.TestPathDepthParams import depthTestCases @@ -47,6 +49,7 @@ from PathTests.TestPathPost import TestBuildPostList from PathTests.TestPathPost import TestOutputNameSubstitution from PathTests.TestPathPreferences import TestPathPreferences +from PathTests.TestPathProfile import TestPathProfile from PathTests.TestPathPropertyBag import TestPathPropertyBag from PathTests.TestPathRotationGenerator import TestPathRotationGenerator from PathTests.TestPathSetupSheet import TestPathSetupSheet @@ -92,6 +95,7 @@ False if TestPathOpUtil.__name__ else True # False if TestPathPost.__name__ else True False if TestPathPostUtils.__name__ else True False if TestPathPreferences.__name__ else True +False if TestPathProfile.__name__ else True False if TestPathPropertyBag.__name__ else True False if TestPathRotationGenerator.__name__ else True False if TestPathSetupSheet.__name__ else True