From 2bca01f0cf819b7f97004ea48c64dca94cccb8ab Mon Sep 17 00:00:00 2001 From: PhaseLoop Date: Sun, 23 Mar 2025 23:38:14 +0100 Subject: [PATCH] unit tests for array dressup --- src/Mod/CAM/CAMTests/TestPathDressupArray.py | 150 +++++++++++++++++++ src/Mod/CAM/Path/Dressup/Array.py | 16 +- 2 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 src/Mod/CAM/CAMTests/TestPathDressupArray.py diff --git a/src/Mod/CAM/CAMTests/TestPathDressupArray.py b/src/Mod/CAM/CAMTests/TestPathDressupArray.py new file mode 100644 index 0000000000..aa470391f6 --- /dev/null +++ b/src/Mod/CAM/CAMTests/TestPathDressupArray.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2025 phaseloop * +# * * +# * 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 Path +from Path.Dressup.Array import DressupArray +import Path.Main.Job as PathJob +import Path.Op.Profile as PathProfile + +from CAMTests.PathTestUtils import PathTestBase + + +class TestEngrave: + def __init__(self, path): + self.Path = Path.Path(path) + self.ToolController = None # default tool 5mm + self.CoolantMode = "None" + self.Name = "Engrave" + + def isDerivedFrom(self, type): + if type == "Path::Feature": + return True + return False + +class TestFeature: + def __init__(self): + self.Path = Path.Path() + self.Name = "" + + def addProperty(self, typ, name, category, tip): + setattr(self, name, None) + + def setEditorMode(self, prop, mode): + pass + + +class TestDressupArray(PathTestBase): + """Unit tests for the Array dressup.""" + + def test00(self): + """Verify array with zero copies provides original path.""" + + source_gcode = ( + "G0 X0 Y0 Z0\n" + "G1 X10 Y10 Z0\n" + ) + + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + ) + + base = TestEngrave(source_gcode) + obj = TestFeature() + da = DressupArray(obj, base, None) + da.execute(obj) + self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") + + def test01(self): + """Verify linear x/y/z 1D array with 1 copy.""" + + source_gcode = ( + "G0 X0 Y0 Z0\n" + "G1 X10 Y10 Z0\n" + ) + + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + + "G0 X12.000000 Y12.000000 Z5.000000\n" + "G1 X22.000000 Y22.000000 Z5.000000\n" + ) + + base = TestEngrave(source_gcode) + obj = TestFeature() + da = DressupArray(obj, base, None) + obj.Copies = 1 + obj.Offset = FreeCAD.Vector(12, 12, 5) + + da.execute(obj) + self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") + + def test01(self): + """Verify linear x/y/z 2D array.""" + + source_gcode = ( + "G0 X0 Y0 Z0\n" + "G1 X10 Y10 Z0\n" + ) + + expected_gcode = ( + "G0 X0.000000 Y0.000000 Z0.000000\n" + "G1 X10.000000 Y10.000000 Z0.000000\n" + + "G0 X0.000000 Y6.000000 Z0.000000\n" + "G1 X10.000000 Y16.000000 Z0.000000\n" + + "G0 X12.000000 Y6.000000 Z0.000000\n" + "G1 X22.000000 Y16.000000 Z0.000000\n" + + "G0 X12.000000 Y0.000000 Z0.000000\n" + "G1 X22.000000 Y10.000000 Z0.000000\n" + + "G0 X24.000000 Y0.000000 Z0.000000\n" + "G1 X34.000000 Y10.000000 Z0.000000\n" + + "G0 X24.000000 Y6.000000 Z0.000000\n" + "G1 X34.000000 Y16.000000 Z0.000000\n" + ) + + base = TestEngrave(source_gcode) + obj = TestFeature() + da = DressupArray(obj, base, None) + obj.Type = "Linear2D" + obj.Copies = 0 + obj.CopiesX = 2 + obj.CopiesY = 1 + + obj.Offset = FreeCAD.Vector(12, 6, 0) + + da.execute(obj) + self.assertTrue(obj.Path.toGCode() == expected_gcode, "Incorrect g-code generated") + + + + + + + diff --git a/src/Mod/CAM/Path/Dressup/Array.py b/src/Mod/CAM/Path/Dressup/Array.py index 4e860989cc..4a421ae8d3 100644 --- a/src/Mod/CAM/Path/Dressup/Array.py +++ b/src/Mod/CAM/Path/Dressup/Array.py @@ -22,13 +22,9 @@ import FreeCAD -import FreeCADGui import Path -import PathScripts import PathScripts.PathUtils as PathUtils from Path.Dressup.Base import DressupBase -from PySide import QtCore -import math import random from PySide.QtCore import QT_TRANSLATE_NOOP @@ -124,7 +120,13 @@ class DressupArray(DressupBase): obj.Base = base obj.Active = True + # assigning array tells the type of possible enum choices obj.Type = ["Linear1D", "Linear2D", "Polar"] + # assign value + obj.Type = "Linear1D" + + obj.Copies = 0 + obj.JitterPercent = 0 self.setEditorModes(obj) obj.Proxy = self @@ -186,7 +188,7 @@ class DressupArray(DressupBase): Path.Log.error(translate("PathArray", "Base is empty or an invalid object.")) return None - # Do not generate paths and clear current Path data if operation not + # Do not generate paths and clear current Path data if operation not active if not obj.Active: if obj.Path: obj.Path = Path.Path() @@ -270,7 +272,9 @@ class PathArray: base = self.base # build copies - output = "" + # initially output contains original base path, copies are added on top of that + output = PathUtils.getPathWithPlacement(base).toGCode() + random.seed(self.seed) if self.arrayType == "Linear1D":