From abdb4eea86809eb632360dcf9c5bf73f00d16224 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Tue, 15 Mar 2022 23:20:26 -0500 Subject: [PATCH 1/5] Path: Fix roughly equal depth entries Add code block to remove first of any two consecutive, roughly equal depth values (twin values). Add two unit tests to support new code block and use cases. --- src/Mod/Path/PathScripts/PathUtils.py | 66 ++++++++++++++++++- src/Mod/Path/PathTests/TestPathDepthParams.py | 40 +++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 419855bdb2..adaaa49112 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -609,7 +609,11 @@ class depth_params(object): self.__step_down = math.fabs(step_down) self.__z_finish_step = math.fabs(z_finish_step) self.__final_depth = final_depth - self.__user_depths = user_depths + self.__user_depths = ( + None + if user_depths is None + else self.__filter_roughly_equal_depths(user_depths) + ) self.data = self.__get_depths(equalstep=equalstep) self.index = 0 @@ -718,7 +722,65 @@ class depth_params(object): )[1:] depths.reverse() - return depths + + if len(depths) < 2: + return depths + + return self.__filter_roughly_equal_depths(depths) + + def __filter_roughly_equal_depths(self, depths): + """Depths arrive sorted from largest to smallest, positive to negative. + Return unique list of depths, using PathGeom.isRoughly() method to determine + if the two values are equal. Only one of two consecutive equals are removed. + + The assumption is that there are not enough consecutively roughly-equal depths + to be removed, so as to eliminate an effective step-down depth with the removal + of repetitive roughly-equal values.""" + + if len(depths) == 2: + if PathGeom.isRoughly(depths[0], depths[1]): + return [depths[1]] + return depths + + # print("raw depths: {}".format(depths)) + + uniqueDepths = depths + lastDepth = None + maxLoops = 0 + while maxLoops < 10: + # print("\nStart scan... uniqueDepths: {}".format(uniqueDepths)) + stop = True + keep = [] + # Filter out unique values from consecutive pairs + for i in range(0, len(uniqueDepths) - 1): + dep1 = uniqueDepths[i] + dep2 = uniqueDepths[i + 1] + # print("comparing: {} and {}".format(dep1, dep2)) + # print("lastDepth: {}".format(lastDepth)) + + if PathGeom.isRoughly(dep1, dep2): + if PathGeom.isRoughly(lastDepth, dep2): + keep.pop() + keep.append(dep2) + # Cycle again if a roughly-equal pair is found + stop = False + else: + if lastDepth is None: + keep.append(dep1) + else: + if not PathGeom.isRoughly(lastDepth, dep1): + keep.append(dep1) + keep.append(dep2) + + lastDepth = dep2 + # Efor + uniqueDepths = keep + maxLoops += 1 + if stop: + break + + # print("uniqueDepths: {}".format(uniqueDepths)) + return uniqueDepths def __equal_steps(self, start, stop, max_size): """returns a list of depths beginning with the bottom (included), ending diff --git a/src/Mod/Path/PathTests/TestPathDepthParams.py b/src/Mod/Path/PathTests/TestPathDepthParams.py index fed0779fc8..cc25ec0088 100644 --- a/src/Mod/Path/PathTests/TestPathDepthParams.py +++ b/src/Mod/Path/PathTests/TestPathDepthParams.py @@ -211,3 +211,43 @@ class depthTestCases(unittest.TestCase): "user_depths": None, } self.assertRaises(ValueError, PathUtils.depth_params, **args) + + def test90(self): + """stepping down with single stepdown exactly equal to total depth""" + args = { + "clearance_height": 20.0, + "safe_height": 15.0, + "start_depth": 10.0, + "step_down": 10.0, + "z_finish_step": 0.0, + "final_depth": 0.0, + "user_depths": None, + } + + expected = [0] + + d = PathUtils.depth_params(**args) + r = [i for i in d] + self.assertListEqual( + r, expected, "Expected {}, but result of {}".format(expected, r) + ) + + def test100(self): + """stepping down with single stepdown roughly equal to total depth""" + args = { + "clearance_height": 20.0, + "safe_height": 15.0, + "start_depth": 10.000000001, + "step_down": 10.0, + "z_finish_step": 0.0, + "final_depth": 0.0, + "user_depths": None, + } + + expected = [0] + + d = PathUtils.depth_params(**args) + r = [i for i in d] + self.assertListEqual( + r, expected, "Expected {}, but result of {}".format(expected, r) + ) From 0c63eb2d942dc5deaba5d9a7168b3aca03997d1b Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Wed, 16 Mar 2022 22:03:43 -0500 Subject: [PATCH 2/5] Path: Add additional roughly-equal depths unit tests --- src/Mod/Path/PathTests/TestPathDepthParams.py | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/Mod/Path/PathTests/TestPathDepthParams.py b/src/Mod/Path/PathTests/TestPathDepthParams.py index cc25ec0088..a1d36eb9e3 100644 --- a/src/Mod/Path/PathTests/TestPathDepthParams.py +++ b/src/Mod/Path/PathTests/TestPathDepthParams.py @@ -251,3 +251,63 @@ class depthTestCases(unittest.TestCase): self.assertListEqual( r, expected, "Expected {}, but result of {}".format(expected, r) ) + + def test110(self): + """two custom user depths roughly equal to final depth""" + args = { + "clearance_height": 20.0, + "safe_height": 15.0, + "start_depth": 9.0, + "step_down": 3.0, + "z_finish_step": 0.0, + "final_depth": 0.0, + "user_depths": [0.00000001, 0.0], + } + + expected = [0] + + d = PathUtils.depth_params(**args) + r = [i for i in d] + self.assertListEqual( + r, expected, "Expected {}, but result of {}".format(expected, r) + ) + + def test120(self): + """four custom user depths with two roughly equal included""" + args = { + "clearance_height": 20.0, + "safe_height": 15.0, + "start_depth": 9.0, + "step_down": 3.0, + "z_finish_step": 0.0, + "final_depth": 0.0, + "user_depths": [6.0, 3.00000001, 3.0, 0.0], + } + + expected = [6.0, 3.0, 0.0] + + d = PathUtils.depth_params(**args) + r = [i for i in d] + self.assertListEqual( + r, expected, "Expected {}, but result of {}".format(expected, r) + ) + + def test130(self): + """five custom user depths with three roughly equal included""" + args = { + "clearance_height": 20.0, + "safe_height": 15.0, + "start_depth": 9.0, + "step_down": 3.0, + "z_finish_step": 0.0, + "final_depth": 0.0, + "user_depths": [6.0, 3.00000002, 3.00000001, 3.0, 0.0], + } + + expected = [6.0, 3.0, 0.0] + + d = PathUtils.depth_params(**args) + r = [i for i in d] + self.assertListEqual( + r, expected, "Expected {}, but result of {}".format(expected, r) + ) From 6b9312c567e23002d8b5d3368733c9d22367eff8 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Fri, 18 Mar 2022 17:57:22 -0500 Subject: [PATCH 3/5] Path: Renumber unit tests per triple-digit schema per request of Sliptonic --- src/Mod/Path/PathTests/TestPathDepthParams.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Mod/Path/PathTests/TestPathDepthParams.py b/src/Mod/Path/PathTests/TestPathDepthParams.py index a1d36eb9e3..e334dbe18c 100644 --- a/src/Mod/Path/PathTests/TestPathDepthParams.py +++ b/src/Mod/Path/PathTests/TestPathDepthParams.py @@ -43,7 +43,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test10(self): + def test001(self): """Stepping from zero to a negative depth""" args = { @@ -62,7 +62,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test20(self): + def test002(self): """Start and end are equal or start lower than finish""" args = { @@ -89,7 +89,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test30(self): + def test003(self): """User Parameters passed in""" args = { "clearance_height": 10, @@ -107,7 +107,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test40(self): + def test004(self): """z_finish_step passed in.""" args = { "clearance_height": 10, @@ -125,7 +125,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test50(self): + def test005(self): """stepping down with equalstep=True""" args = { "clearance_height": 10, @@ -144,7 +144,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test60(self): + def test006(self): """stepping down with equalstep=True and a finish depth""" args = { "clearance_height": 10, @@ -162,7 +162,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test70(self): + def test007(self): """stepping down with stepdown greater than total depth""" args = { "clearance_height": 10, @@ -180,7 +180,7 @@ class depthTestCases(unittest.TestCase): r = [i for i in d] self.assertListEqual(r, expected) - def test80(self): + def test008(self): """Test handling of negative step-down, negative finish step, and relative size of step/finish""" # negative steps should be converted to positive values @@ -212,7 +212,7 @@ class depthTestCases(unittest.TestCase): } self.assertRaises(ValueError, PathUtils.depth_params, **args) - def test90(self): + def test009(self): """stepping down with single stepdown exactly equal to total depth""" args = { "clearance_height": 20.0, @@ -232,7 +232,7 @@ class depthTestCases(unittest.TestCase): r, expected, "Expected {}, but result of {}".format(expected, r) ) - def test100(self): + def test010(self): """stepping down with single stepdown roughly equal to total depth""" args = { "clearance_height": 20.0, @@ -252,7 +252,7 @@ class depthTestCases(unittest.TestCase): r, expected, "Expected {}, but result of {}".format(expected, r) ) - def test110(self): + def test011(self): """two custom user depths roughly equal to final depth""" args = { "clearance_height": 20.0, @@ -272,7 +272,7 @@ class depthTestCases(unittest.TestCase): r, expected, "Expected {}, but result of {}".format(expected, r) ) - def test120(self): + def test012(self): """four custom user depths with two roughly equal included""" args = { "clearance_height": 20.0, @@ -292,7 +292,7 @@ class depthTestCases(unittest.TestCase): r, expected, "Expected {}, but result of {}".format(expected, r) ) - def test130(self): + def test013(self): """five custom user depths with three roughly equal included""" args = { "clearance_height": 20.0, From cf64b06c89f4b70c1242039cbf357352e6e39e71 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Thu, 17 Mar 2022 18:13:52 -0500 Subject: [PATCH 4/5] simpler way to filter roughly equal depth values --- src/Mod/Path/PathScripts/PathUtils.py | 87 +++++++++++++++------------ 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index adaaa49112..6c29871bdb 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -737,50 +737,59 @@ class depth_params(object): to be removed, so as to eliminate an effective step-down depth with the removal of repetitive roughly-equal values.""" - if len(depths) == 2: - if PathGeom.isRoughly(depths[0], depths[1]): - return [depths[1]] - return depths + depthcopy = depths.copy() #make a copy so we don't touch original + depthcopy.reverse() # reverse it low to high + keep = [depthcopy[0]] # initialize keep list with first element + for depth in depthcopy[1:]: # iterate the list from second element on + if not PathGeom.isRoughly(depth, keep[-1]): #Compare each to the last kept item + keep.append(depth) # if different, add to keep + keep.reverse() # reverse results back high to low + return keep - # print("raw depths: {}".format(depths)) + # if len(depths) == 2: + # if PathGeom.isRoughly(depths[0], depths[1]): + # return [depths[1]] + # return depths - uniqueDepths = depths - lastDepth = None - maxLoops = 0 - while maxLoops < 10: - # print("\nStart scan... uniqueDepths: {}".format(uniqueDepths)) - stop = True - keep = [] - # Filter out unique values from consecutive pairs - for i in range(0, len(uniqueDepths) - 1): - dep1 = uniqueDepths[i] - dep2 = uniqueDepths[i + 1] - # print("comparing: {} and {}".format(dep1, dep2)) - # print("lastDepth: {}".format(lastDepth)) + # # print("raw depths: {}".format(depths)) - if PathGeom.isRoughly(dep1, dep2): - if PathGeom.isRoughly(lastDepth, dep2): - keep.pop() - keep.append(dep2) - # Cycle again if a roughly-equal pair is found - stop = False - else: - if lastDepth is None: - keep.append(dep1) - else: - if not PathGeom.isRoughly(lastDepth, dep1): - keep.append(dep1) - keep.append(dep2) + # uniqueDepths = depths + # lastDepth = None + # maxLoops = 0 + # while maxLoops < 10: + # # print("\nStart scan... uniqueDepths: {}".format(uniqueDepths)) + # stop = True + # keep = [] + # # Filter out unique values from consecutive pairs + # for i in range(0, len(uniqueDepths) - 1): + # dep1 = uniqueDepths[i] + # dep2 = uniqueDepths[i + 1] + # # print("comparing: {} and {}".format(dep1, dep2)) + # # print("lastDepth: {}".format(lastDepth)) - lastDepth = dep2 - # Efor - uniqueDepths = keep - maxLoops += 1 - if stop: - break + # if PathGeom.isRoughly(dep1, dep2): + # if PathGeom.isRoughly(lastDepth, dep2): + # keep.pop() + # keep.append(dep2) + # # Cycle again if a roughly-equal pair is found + # stop = False + # else: + # if lastDepth is None: + # keep.append(dep1) + # else: + # if not PathGeom.isRoughly(lastDepth, dep1): + # keep.append(dep1) + # keep.append(dep2) - # print("uniqueDepths: {}".format(uniqueDepths)) - return uniqueDepths + # lastDepth = dep2 + # # Efor + # uniqueDepths = keep + # maxLoops += 1 + # if stop: + # break + + # # print("uniqueDepths: {}".format(uniqueDepths)) + # return uniqueDepths def __equal_steps(self, start, stop, max_size): """returns a list of depths beginning with the bottom (included), ending From 50117a57de477834ca9661a20172e0197e59987e Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 19 Mar 2022 22:20:29 -0500 Subject: [PATCH 5/5] Path: Simplify changes per developer conversations Also update TestPathDepthParams.py to reflect simplification of changes. Remove some comments. Employ `sorted()` function per MLampert suggestion --- src/Mod/Path/PathScripts/PathUtils.py | 62 ++----------------- src/Mod/Path/PathTests/TestPathDepthParams.py | 50 +-------------- 2 files changed, 9 insertions(+), 103 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 6c29871bdb..7914c0a54c 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -609,11 +609,7 @@ class depth_params(object): self.__step_down = math.fabs(step_down) self.__z_finish_step = math.fabs(z_finish_step) self.__final_depth = final_depth - self.__user_depths = ( - None - if user_depths is None - else self.__filter_roughly_equal_depths(user_depths) - ) + self.__user_depths = user_depths self.data = self.__get_depths(equalstep=equalstep) self.index = 0 @@ -737,60 +733,14 @@ class depth_params(object): to be removed, so as to eliminate an effective step-down depth with the removal of repetitive roughly-equal values.""" - depthcopy = depths.copy() #make a copy so we don't touch original - depthcopy.reverse() # reverse it low to high - keep = [depthcopy[0]] # initialize keep list with first element - for depth in depthcopy[1:]: # iterate the list from second element on - if not PathGeom.isRoughly(depth, keep[-1]): #Compare each to the last kept item - keep.append(depth) # if different, add to keep + depthcopy = sorted(depths) # make a copy and sort low to high + keep = [depthcopy[0]] + for depth in depthcopy[1:]: + if not PathGeom.isRoughly(depth, keep[-1]): + keep.append(depth) keep.reverse() # reverse results back high to low return keep - # if len(depths) == 2: - # if PathGeom.isRoughly(depths[0], depths[1]): - # return [depths[1]] - # return depths - - # # print("raw depths: {}".format(depths)) - - # uniqueDepths = depths - # lastDepth = None - # maxLoops = 0 - # while maxLoops < 10: - # # print("\nStart scan... uniqueDepths: {}".format(uniqueDepths)) - # stop = True - # keep = [] - # # Filter out unique values from consecutive pairs - # for i in range(0, len(uniqueDepths) - 1): - # dep1 = uniqueDepths[i] - # dep2 = uniqueDepths[i + 1] - # # print("comparing: {} and {}".format(dep1, dep2)) - # # print("lastDepth: {}".format(lastDepth)) - - # if PathGeom.isRoughly(dep1, dep2): - # if PathGeom.isRoughly(lastDepth, dep2): - # keep.pop() - # keep.append(dep2) - # # Cycle again if a roughly-equal pair is found - # stop = False - # else: - # if lastDepth is None: - # keep.append(dep1) - # else: - # if not PathGeom.isRoughly(lastDepth, dep1): - # keep.append(dep1) - # keep.append(dep2) - - # lastDepth = dep2 - # # Efor - # uniqueDepths = keep - # maxLoops += 1 - # if stop: - # break - - # # print("uniqueDepths: {}".format(uniqueDepths)) - # return uniqueDepths - def __equal_steps(self, start, stop, max_size): """returns a list of depths beginning with the bottom (included), ending with the top (not included). diff --git a/src/Mod/Path/PathTests/TestPathDepthParams.py b/src/Mod/Path/PathTests/TestPathDepthParams.py index e334dbe18c..a8ccd95579 100644 --- a/src/Mod/Path/PathTests/TestPathDepthParams.py +++ b/src/Mod/Path/PathTests/TestPathDepthParams.py @@ -252,60 +252,16 @@ class depthTestCases(unittest.TestCase): r, expected, "Expected {}, but result of {}".format(expected, r) ) - def test011(self): - """two custom user depths roughly equal to final depth""" args = { "clearance_height": 20.0, "safe_height": 15.0, - "start_depth": 9.0, - "step_down": 3.0, + "start_depth": 10.0, + "step_down": 9.9999999, "z_finish_step": 0.0, "final_depth": 0.0, - "user_depths": [0.00000001, 0.0], + "user_depths": None, } - expected = [0] - - d = PathUtils.depth_params(**args) - r = [i for i in d] - self.assertListEqual( - r, expected, "Expected {}, but result of {}".format(expected, r) - ) - - def test012(self): - """four custom user depths with two roughly equal included""" - args = { - "clearance_height": 20.0, - "safe_height": 15.0, - "start_depth": 9.0, - "step_down": 3.0, - "z_finish_step": 0.0, - "final_depth": 0.0, - "user_depths": [6.0, 3.00000001, 3.0, 0.0], - } - - expected = [6.0, 3.0, 0.0] - - d = PathUtils.depth_params(**args) - r = [i for i in d] - self.assertListEqual( - r, expected, "Expected {}, but result of {}".format(expected, r) - ) - - def test013(self): - """five custom user depths with three roughly equal included""" - args = { - "clearance_height": 20.0, - "safe_height": 15.0, - "start_depth": 9.0, - "step_down": 3.0, - "z_finish_step": 0.0, - "final_depth": 0.0, - "user_depths": [6.0, 3.00000002, 3.00000001, 3.0, 0.0], - } - - expected = [6.0, 3.0, 0.0] - d = PathUtils.depth_params(**args) r = [i for i in d] self.assertListEqual(