From 228fce273bf67b6330da9e9a61fb67b151ef7f5b Mon Sep 17 00:00:00 2001 From: sliptonic Date: Wed, 23 Feb 2022 09:07:26 -0600 Subject: [PATCH] black format --- src/Mod/Path/PathScripts/PathThreadMilling.py | 185 +++++++--- .../Path/PathScripts/PathThreadMillingGui.py | 29 +- .../Path/PathTests/TestPathThreadMilling.py | 340 ++++++++++-------- 3 files changed, 343 insertions(+), 211 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathThreadMilling.py b/src/Mod/Path/PathScripts/PathThreadMilling.py index 178145bbef..e742122d32 100644 --- a/src/Mod/Path/PathScripts/PathThreadMilling.py +++ b/src/Mod/Path/PathScripts/PathThreadMilling.py @@ -72,6 +72,7 @@ def threadRadii(internal, majorDia, minorDia, toolDia, toolCrest): toolTip = innerTip - toolCrest * SQRT_3_DIVIDED_BY_2 return ((majorDia + toolDia) / 2.0, toolTip + toolDia / 2.0) + def threadPasses(count, radii, internal, majorDia, minorDia, toolDia, toolCrest): PathLog.track(count, radii, internal, majorDia, minorDia, toolDia, toolCrest) # the logic goes as follows, total area to be removed: @@ -98,23 +99,29 @@ def threadPasses(count, radii, internal, majorDia, minorDia, toolDia, toolCrest) def elevatorRadius(obj, center, internal, tool): - '''elevatorLocation(obj, center, internal, tool) ... return suitable location for the tool elevator''' + """elevatorLocation(obj, center, internal, tool) ... return suitable location for the tool elevator""" if internal: dy = float(obj.MinorDiameter - tool.Diameter) / 2 - 1 if dy < 0: - if (obj.MinorDiameter < tool.Diameter): - PathLog.error("The selected tool is too big (d={}) for milling a thread with minor diameter D={}".format(tool.Diameter, obj.MinorDiameter)) + if obj.MinorDiameter < tool.Diameter: + PathLog.error( + "The selected tool is too big (d={}) for milling a thread with minor diameter D={}".format( + tool.Diameter, obj.MinorDiameter + ) + ) dy = 0 else: dy = float(obj.MajorDiameter + tool.Diameter) / 2 + 1 return dy + def comment(path, msg): if False: path.append(Path.Command("(------- {} -------)".format(msg))) + class _Thread(object): """Helper class for dealing with different thread types""" @@ -154,9 +161,9 @@ class _Thread(object): def isUp(self): """isUp() ... returns True if the thread goes from the bottom up""" return self.pitch > 0 - + def g4Opposite(self): - return 'G2' if self.isG3() else 'G3' + return "G2" if self.isG3() else "G3" def g4LeadInOut(self): if self.internal: @@ -166,7 +173,10 @@ class _Thread(object): def g4Start2Elevator(self): return self.g4Opposite() -def threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, start): + +def threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, start +): """threadCommands(center, cmd, zStart, zFinal, pitch, radius) ... returns the g-code to mill the given internal thread""" thread = _Thread(cmd, zStart, zFinal, pitch, radius > elevator) @@ -178,20 +188,41 @@ def threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevat # into position first, and then drop to the start height. If there is any material in the way this # op hasn't been setup properly. if leadInOut: - comment(path, 'lead-in') + comment(path, "lead-in") if start is None: path.append(Path.Command("G0", {"X": center.x, "Y": center.y + elevator})) path.append(Path.Command("G0", {"Z": thread.zStart})) else: - path.append(Path.Command(thread.g4Start2Elevator(), {"X": center.x, "Y": center.y + elevator, "Z" : thread.zStart, "I": (center.x - start.x) / 2, "J": (center.y + elevator - start.y) / 2, "K" : (thread.zStart - start.z) / 2})) - path.append(Path.Command(thread.g4LeadInOut(), {"Y": yMax, "J": (yMax - (center.y + elevator)) / 2})) - comment(path, 'lead-in') + path.append( + Path.Command( + thread.g4Start2Elevator(), + { + "X": center.x, + "Y": center.y + elevator, + "Z": thread.zStart, + "I": (center.x - start.x) / 2, + "J": (center.y + elevator - start.y) / 2, + "K": (thread.zStart - start.z) / 2, + }, + ) + ) + path.append( + Path.Command( + thread.g4LeadInOut(), + {"Y": yMax, "J": (yMax - (center.y + elevator)) / 2}, + ) + ) + comment(path, "lead-in") else: if start is None: path.append(Path.Command("G0", {"X": center.x, "Y": center.y + elevator})) path.append(Path.Command("G0", {"Z": thread.zStart})) else: - path.append(Path.Command("G0", {"X": center.x, "Y": center.y + elevator, "Z": thread.zStart})) + path.append( + Path.Command( + "G0", {"X": center.x, "Y": center.y + elevator, "Z": thread.zStart} + ) + ) path.append(Path.Command("G1", {"Y": yMax})) z = thread.zStart @@ -219,38 +250,39 @@ def threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevat dx = math.sin(k * math.pi) y = thread.adjustY(center.y, r * dy) x = thread.adjustX(center.x, r * dx) - comment(path, 'finish-thread') + comment(path, "finish-thread") path.append( Path.Command(thread.cmd, {"X": x, "Y": y, "Z": thread.zFinal, "J": r}) ) - comment(path, 'finish-thread') + comment(path, "finish-thread") a = math.atan2(y - center.y, x - center.x) dx = math.cos(a) * (radius - elevator) dy = math.sin(a) * (radius - elevator) - PathLog.debug('') + PathLog.debug("") PathLog.debug("a={}: dx={:.2f}, dy={:.2f}".format(a / math.pi * 180, dx, dy)) elevatorX = x - dx elevatorY = y - dy - PathLog.debug("({:.2f}, {:.2f}) -> ({:.2f}, {:.2f})".format(x, y, elevatorX, elevatorY)) + PathLog.debug( + "({:.2f}, {:.2f}) -> ({:.2f}, {:.2f})".format(x, y, elevatorX, elevatorY) + ) if leadInOut: - comment(path, 'lead-out') + comment(path, "lead-out") path.append( Path.Command( thread.g4LeadInOut(), {"X": elevatorX, "Y": elevatorY, "I": -dx / 2, "J": -dy / 2}, ) ) - comment(path, 'lead-out') + comment(path, "lead-out") else: path.append(Path.Command("G1", {"X": elevatorX, "Y": elevatorY})) return (path, FreeCAD.Vector(elevatorX, elevatorY, thread.zFinal)) - class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): """Proxy object for thread milling operation.""" @@ -271,14 +303,14 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): ThreadOrientations = [LeftHand, RightHand] ThreadTypeData = { - ThreadTypeImperialExternal2A : 'imperial-external-2A.csv', - ThreadTypeImperialExternal3A : 'imperial-external-3A.csv', - ThreadTypeImperialInternal2B : 'imperial-internal-2B.csv', - ThreadTypeImperialInternal3B : 'imperial-internal-3B.csv', - ThreadTypeMetricExternal4G6G : 'metric-external-4G6G.csv', - ThreadTypeMetricExternal6G : 'metric-external-6G.csv', - ThreadTypeMetricInternal6H : 'metric-internal-6H.csv', - } + ThreadTypeImperialExternal2A: "imperial-external-2A.csv", + ThreadTypeImperialExternal3A: "imperial-external-3A.csv", + ThreadTypeImperialInternal2B: "imperial-internal-2B.csv", + ThreadTypeImperialInternal3B: "imperial-internal-3B.csv", + ThreadTypeMetricExternal4G6G: "metric-external-4G6G.csv", + ThreadTypeMetricExternal6G: "metric-external-6G.csv", + ThreadTypeMetricInternal6H: "metric-internal-6H.csv", + } ThreadTypesExternal = [ ThreadTypeCustomExternal, @@ -286,24 +318,24 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): ThreadTypeImperialExternal3A, ThreadTypeMetricExternal4G6G, ThreadTypeMetricExternal6G, - ] + ] ThreadTypesInternal = [ ThreadTypeCustomInternal, ThreadTypeImperialInternal2B, ThreadTypeImperialInternal3B, ThreadTypeMetricInternal6H, - ] + ] ThreadTypesImperial = [ ThreadTypeImperialExternal2A, ThreadTypeImperialExternal3A, ThreadTypeImperialInternal2B, ThreadTypeImperialInternal3B, - ] + ] ThreadTypesMetric = [ ThreadTypeMetricExternal4G6G, ThreadTypeMetricExternal6G, ThreadTypeMetricInternal6H, - ] + ] ThreadTypes = ThreadTypesInternal + ThreadTypesExternal Directions = [DirectionClimb, DirectionConventional] @@ -322,23 +354,62 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): # Enumeration lists for App::PropertyEnumeration properties enums = { "ThreadType": [ - (translate("Path_ThreadMilling", "Custom External"), ObjectThreadMilling.ThreadTypeCustomExternal), - (translate("Path_ThreadMilling", "Custom Internal"), ObjectThreadMilling.ThreadTypeCustomInternal), - (translate("Path_ThreadMilling", "Imperial External (2A)"), ObjectThreadMilling.ThreadTypeImperialExternal2A), - (translate("Path_ThreadMilling", "Imperial External (3A)"), ObjectThreadMilling.ThreadTypeImperialExternal3A), - (translate("Path_ThreadMilling", "Imperial Internal (2B)"), ObjectThreadMilling.ThreadTypeImperialInternal2B), - (translate("Path_ThreadMilling", "Imperial Internal (3B)"), ObjectThreadMilling.ThreadTypeImperialInternal3B), - (translate("Path_ThreadMilling", "Metric External (4G6G)"), ObjectThreadMilling.ThreadTypeMetricExternal4G6G), - (translate("Path_ThreadMilling", "Metric External (6G)"), ObjectThreadMilling.ThreadTypeMetricExternal6G), - (translate("Path_ThreadMilling", "Metric Internal (6H)"), ObjectThreadMilling.ThreadTypeMetricInternal6H), + ( + translate("Path_ThreadMilling", "Custom External"), + ObjectThreadMilling.ThreadTypeCustomExternal, + ), + ( + translate("Path_ThreadMilling", "Custom Internal"), + ObjectThreadMilling.ThreadTypeCustomInternal, + ), + ( + translate("Path_ThreadMilling", "Imperial External (2A)"), + ObjectThreadMilling.ThreadTypeImperialExternal2A, + ), + ( + translate("Path_ThreadMilling", "Imperial External (3A)"), + ObjectThreadMilling.ThreadTypeImperialExternal3A, + ), + ( + translate("Path_ThreadMilling", "Imperial Internal (2B)"), + ObjectThreadMilling.ThreadTypeImperialInternal2B, + ), + ( + translate("Path_ThreadMilling", "Imperial Internal (3B)"), + ObjectThreadMilling.ThreadTypeImperialInternal3B, + ), + ( + translate("Path_ThreadMilling", "Metric External (4G6G)"), + ObjectThreadMilling.ThreadTypeMetricExternal4G6G, + ), + ( + translate("Path_ThreadMilling", "Metric External (6G)"), + ObjectThreadMilling.ThreadTypeMetricExternal6G, + ), + ( + translate("Path_ThreadMilling", "Metric Internal (6H)"), + ObjectThreadMilling.ThreadTypeMetricInternal6H, + ), ], "ThreadOrientation": [ - (translate("Path_ThreadMilling", "LeftHand"), ObjectThreadMilling.LeftHand), - (translate("Path_ThreadMilling", "RightHand"), ObjectThreadMilling.RightHand), + ( + translate("Path_ThreadMilling", "LeftHand"), + ObjectThreadMilling.LeftHand, + ), + ( + translate("Path_ThreadMilling", "RightHand"), + ObjectThreadMilling.RightHand, + ), ], "Direction": [ - (translate("Path_ThreadMilling", "Climb"), ObjectThreadMilling.DirectionClimb), - (translate("Path_ThreadMilling", "Conventional"), ObjectThreadMilling.DirectionConventional), + ( + translate("Path_ThreadMilling", "Climb"), + ObjectThreadMilling.DirectionClimb, + ), + ( + translate("Path_ThreadMilling", "Conventional"), + ObjectThreadMilling.DirectionConventional, + ), ], } @@ -478,9 +549,9 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): return (cmd, zbegin, zend) # need to reverse direction for external threads - if cmd == 'G2': - return ('G3', zbegin, zend) - return ('G2', zbegin, zend) + if cmd == "G2": + return ("G3", zbegin, zend) + return ("G2", zbegin, zend) def threadPassRadii(self, obj): PathLog.track(obj.Label) @@ -498,7 +569,9 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): PathLog.track(obj.Label, loc, gcode, zStart, zFinal, pitch) elevator = elevatorRadius(obj, loc, self._isThreadInternal(obj), self.tool) - move2clearance = Path.Command("G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid}) + move2clearance = Path.Command( + "G0", {"Z": obj.ClearanceHeight.Value, "F": self.vertRapid} + ) self.commandlist.append(move2clearance) start = None @@ -511,13 +584,27 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp): float(self.tool.Diameter), float(self.tool.Crest), ): - if not start is None and not self._isThreadInternal(obj) and not obj.LeadInOut: + if ( + not start is None + and not self._isThreadInternal(obj) + and not obj.LeadInOut + ): # external thread without lead in/out have to go up and over # in other words we need a move to clearance and not take any # shortcuts when moving to the elevator position self.commandlist.append(move2clearance) start = None - commands, start = threadCommands(loc, gcode, zStart, zFinal, pitch, radius, obj.LeadInOut, elevator, start) + commands, start = threadCommands( + loc, + gcode, + zStart, + zFinal, + pitch, + radius, + obj.LeadInOut, + elevator, + start, + ) for cmd in commands: p = cmd.Parameters diff --git a/src/Mod/Path/PathScripts/PathThreadMillingGui.py b/src/Mod/Path/PathScripts/PathThreadMillingGui.py index 522bc22bdb..7b98ebe34e 100644 --- a/src/Mod/Path/PathScripts/PathThreadMillingGui.py +++ b/src/Mod/Path/PathScripts/PathThreadMillingGui.py @@ -48,6 +48,7 @@ else: translate = FreeCAD.Qt.translate + def fillThreads(form, dataFile, defaultSelect): form.threadName.blockSignals(True) select = form.threadName.currentText() @@ -58,7 +59,7 @@ def fillThreads(form, dataFile, defaultSelect): ) as fp: reader = csv.DictReader(fp) for row in reader: - form.threadName.addItem(row['name'], row) + form.threadName.addItem(row["name"], row) if select: form.threadName.setCurrentText(select) elif defaultSelect: @@ -138,10 +139,10 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): self._updateFromThreadType() def _isThreadCustom(self): - return ( - self.form.threadType.currentData() - in [PathThreadMilling.ObjectThreadMilling.ThreadTypeCustomInternal, PathThreadMilling.ObjectThreadMilling.ThreadTypeCustomExternal] - ) + return self.form.threadType.currentData() in [ + PathThreadMilling.ObjectThreadMilling.ThreadTypeCustomInternal, + PathThreadMilling.ObjectThreadMilling.ThreadTypeCustomExternal, + ] def _isThreadImperial(self): return ( @@ -156,10 +157,16 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): ) def _isThreadInternal(self): - return self.form.threadType.currentData() in PathThreadMilling.ObjectThreadMilling.ThreadTypesInternal + return ( + self.form.threadType.currentData() + in PathThreadMilling.ObjectThreadMilling.ThreadTypesInternal + ) def _isThreadExternal(self): - return self.form.threadType.currentData() in PathThreadMilling.ObjectThreadMilling.ThreadTypesExternal + return ( + self.form.threadType.currentData() + in PathThreadMilling.ObjectThreadMilling.ThreadTypesExternal + ) def _updateFromThreadType(self): @@ -186,7 +193,13 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage): self.form.threadTPI.setEnabled(True) self.form.threadTPILabel.setEnabled(True) self.pitch.updateSpinBox(0) - fillThreads(self.form, PathThreadMilling.ObjectThreadMilling.ThreadTypeData[self.form.threadType.currentData()], self.obj.ThreadName) + fillThreads( + self.form, + PathThreadMilling.ObjectThreadMilling.ThreadTypeData[ + self.form.threadType.currentData() + ], + self.obj.ThreadName, + ) self._updateFromThreadName() def _updateFromThreadName(self): diff --git a/src/Mod/Path/PathTests/TestPathThreadMilling.py b/src/Mod/Path/PathTests/TestPathThreadMilling.py index 5ce7118c88..bc29512301 100644 --- a/src/Mod/Path/PathTests/TestPathThreadMilling.py +++ b/src/Mod/Path/PathTests/TestPathThreadMilling.py @@ -47,226 +47,258 @@ class TestPathThreadMilling(PathTestBase): def test00(self): """Verify internal radii.""" - self.assertRadii(PathThreadMilling.radiiInternal(20, 18, 2, 0), (8, 9.2)) - self.assertRadii(PathThreadMilling.radiiInternal(20, 19, 2, 0), (8.5, 9.1)) + self.assertRadii(PathThreadMilling.threadRadii(True, 20, 18, 2, 0), (8, 9.2)) + self.assertRadii(PathThreadMilling.threadRadii(True, 20, 19, 2, 0), (8.5, 9.1)) def test01(self): """Verify internal radii with tool crest.""" - self.assertRadii(PathThreadMilling.threadRadii(True, 20, 18, 2, 0.1), (8, 9.113397)) + self.assertRadii( + PathThreadMilling.threadRadii(True, 20, 18, 2, 0.1), (8, 9.113397) + ) def test10(self): - '''Verify internal thread passes.''' - self.assertList(PathThreadMilling.threadPasses(1, radii, True, 10, 9, 0, 0), [10]) - self.assertList(PathThreadMilling.threadPasses(2, radii, True, 10, 9, 0, 0), [9.707107, 10]) - self.assertList(PathThreadMilling.threadPasses(5, radii, True, 10, 9, 0, 0), [9.447214, 9.632456, 9.774597, 9.894427, 10]) + """Verify internal thread passes.""" + self.assertList( + PathThreadMilling.threadPasses(1, radii, True, 10, 9, 0, 0), [10] + ) + self.assertList( + PathThreadMilling.threadPasses(2, radii, True, 10, 9, 0, 0), [9.707107, 10] + ) + self.assertList( + PathThreadMilling.threadPasses(5, radii, True, 10, 9, 0, 0), + [9.447214, 9.632456, 9.774597, 9.894427, 10], + ) def test20(self): - '''Verify external radii.''' - self.assertRadii(PathThreadMilling.threadRadii(False, 20, 18, 2, 0), (11, 9.6)) + """Verify external radii.""" + self.assertRadii(PathThreadMilling.threadRadii(False, 20, 18, 2, 0), (11, 9.6)) self.assertRadii(PathThreadMilling.threadRadii(False, 20, 19, 2, 0), (11, 10.3)) def test21(self): - '''Verify external radii with tool crest.''' - self.assertRadii(PathThreadMilling.threadRadii(False, 20, 18, 2, 0.1), (11, 9.513397)) + """Verify external radii with tool crest.""" + self.assertRadii( + PathThreadMilling.threadRadii(False, 20, 18, 2, 0.1), (11, 9.513397) + ) def test30(self): - '''Verify external thread passes.''' - self.assertList(PathThreadMilling.threadPasses(1, radii, False, 10, 9, 0, 0), [9]) - self.assertList(PathThreadMilling.threadPasses(2, radii, False, 10, 9, 0, 0), [9.292893, 9]) - self.assertList(PathThreadMilling.threadPasses(5, radii, False, 10, 9, 0, 0), [9.552786, 9.367544, 9.225403, 9.105573, 9]) + """Verify external thread passes.""" + self.assertList( + PathThreadMilling.threadPasses(1, radii, False, 10, 9, 0, 0), [9] + ) + self.assertList( + PathThreadMilling.threadPasses(2, radii, False, 10, 9, 0, 0), [9.292893, 9] + ) + self.assertList( + PathThreadMilling.threadPasses(5, radii, False, 10, 9, 0, 0), + [9.552786, 9.367544, 9.225403, 9.105573, 9], + ) def test40(self): - '''Verify thread commands for a single thread''' + """Verify thread commands for a single thread""" - center = FreeCAD.Vector() - cmd = 'G2' - zStart = 0 - zFinal = 1 - pitch = 1 - radius = 3 - leadInOut = False - elevator = 2 + center = FreeCAD.Vector() + cmd = "G2" + zStart = 0 + zFinal = 1 + pitch = 1 + radius = 3 + leadInOut = False + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - 'G1 Y3.000000', - 'G2 J-3.000000 Y-3.000000 Z0.500000', - 'G2 J3.000000 Y3.000000 Z1.000000', - 'G1 X0.000000 Y2.000000', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + "G1 Y3.000000", + "G2 J-3.000000 Y-3.000000 Z0.500000", + "G2 J3.000000 Y3.000000 Z1.000000", + "G1 X0.000000 Y2.000000", + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(0, 2, zFinal)) def test41(self): - '''Verify thread commands for a thwo threads''' + """Verify thread commands for a thwo threads""" - center = FreeCAD.Vector() - cmd = 'G2' - zStart = 0 - zFinal = 2 - pitch = 1 - radius = 3 - leadInOut = False - elevator = 2 + center = FreeCAD.Vector() + cmd = "G2" + zStart = 0 + zFinal = 2 + pitch = 1 + radius = 3 + leadInOut = False + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - 'G1 Y3.000000', - 'G2 J-3.000000 Y-3.000000 Z0.500000', - 'G2 J3.000000 Y3.000000 Z1.000000', - 'G2 J-3.000000 Y-3.000000 Z1.500000', - 'G2 J3.000000 Y3.000000 Z2.000000', - 'G1 X0.000000 Y2.000000', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + "G1 Y3.000000", + "G2 J-3.000000 Y-3.000000 Z0.500000", + "G2 J3.000000 Y3.000000 Z1.000000", + "G2 J-3.000000 Y-3.000000 Z1.500000", + "G2 J3.000000 Y3.000000 Z2.000000", + "G1 X0.000000 Y2.000000", + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(0, 2, zFinal)) def test42(self): - '''Verify thread commands for a one and a half threads''' + """Verify thread commands for a one and a half threads""" - center = FreeCAD.Vector() - cmd = 'G2' - zStart = 0 - zFinal = 1.5 - pitch = 1 - radius = 3 - leadInOut = False - elevator = 2 + center = FreeCAD.Vector() + cmd = "G2" + zStart = 0 + zFinal = 1.5 + pitch = 1 + radius = 3 + leadInOut = False + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - 'G1 Y3.000000', - 'G2 J-3.000000 Y-3.000000 Z0.500000', - 'G2 J3.000000 Y3.000000 Z1.000000', - 'G2 J-3.000000 Y-3.000000 Z1.500000', - 'G1 X0.000000 Y-2.000000', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + "G1 Y3.000000", + "G2 J-3.000000 Y-3.000000 Z0.500000", + "G2 J3.000000 Y3.000000 Z1.000000", + "G2 J-3.000000 Y-3.000000 Z1.500000", + "G1 X0.000000 Y-2.000000", + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(0, -2, zFinal)) def test43(self): - '''Verify thread commands for a one and 3 quarter threads''' + """Verify thread commands for a one and 3 quarter threads""" - center = FreeCAD.Vector() - cmd = 'G2' - zStart = 0 - zFinal = 1.75 - pitch = 1 - radius = 3 - leadInOut = False - elevator = 2 + center = FreeCAD.Vector() + cmd = "G2" + zStart = 0 + zFinal = 1.75 + pitch = 1 + radius = 3 + leadInOut = False + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - 'G1 Y3.000000', - 'G2 J-3.000000 Y-3.000000 Z0.500000', - 'G2 J3.000000 Y3.000000 Z1.000000', - 'G2 J-3.000000 Y-3.000000 Z1.500000', - #'(------- finish-thread -------)', - 'G2 J3.000000 X-3.000000 Y0.000000 Z1.750000', - #'(------- finish-thread -------)', - 'G1 X-2.000000 Y0.000000', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + "G1 Y3.000000", + "G2 J-3.000000 Y-3.000000 Z0.500000", + "G2 J3.000000 Y3.000000 Z1.000000", + "G2 J-3.000000 Y-3.000000 Z1.500000", + #'(------- finish-thread -------)', + "G2 J3.000000 X-3.000000 Y0.000000 Z1.750000", + #'(------- finish-thread -------)', + "G1 X-2.000000 Y0.000000", + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(-2, 0, zFinal)) def test44(self): - '''Verify thread commands for a one and 3 quarter threads - CCW''' + """Verify thread commands for a one and 3 quarter threads - CCW""" - center = FreeCAD.Vector() - cmd = 'G3' - zStart = 0 - zFinal = 1.75 - pitch = 1 - radius = 3 - leadInOut = False - elevator = 2 + center = FreeCAD.Vector() + cmd = "G3" + zStart = 0 + zFinal = 1.75 + pitch = 1 + radius = 3 + leadInOut = False + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - 'G1 Y3.000000', - 'G3 J-3.000000 Y-3.000000 Z0.500000', - 'G3 J3.000000 Y3.000000 Z1.000000', - 'G3 J-3.000000 Y-3.000000 Z1.500000', - #'(------- finish-thread -------)', - 'G3 J3.000000 X3.000000 Y0.000000 Z1.750000', - #'(------- finish-thread -------)', - 'G1 X2.000000 Y0.000000', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + "G1 Y3.000000", + "G3 J-3.000000 Y-3.000000 Z0.500000", + "G3 J3.000000 Y3.000000 Z1.000000", + "G3 J-3.000000 Y-3.000000 Z1.500000", + #'(------- finish-thread -------)', + "G3 J3.000000 X3.000000 Y0.000000 Z1.750000", + #'(------- finish-thread -------)', + "G1 X2.000000 Y0.000000", + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(2, 0, zFinal)) def test50(self): - '''Verify lead in/out commands for a single thread''' + """Verify lead in/out commands for a single thread""" - center = FreeCAD.Vector() - cmd = 'G2' - zStart = 0 - zFinal = 1 - pitch = 1 - radius = 3 - leadInOut = True - elevator = 2 + center = FreeCAD.Vector() + cmd = "G2" + zStart = 0 + zFinal = 1 + pitch = 1 + radius = 3 + leadInOut = True + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - #'(------- lead-in -------)', - 'G2 J0.500000 Y3.000000', - #'(------- lead-in -------)', - 'G2 J-3.000000 Y-3.000000 Z0.500000', - 'G2 J3.000000 Y3.000000 Z1.000000', - #'(------- lead-out -------)', - 'G2 I0.000000 J-0.500000 X0.000000 Y2.000000', - #'(------- lead-out -------)', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + #'(------- lead-in -------)', + "G2 J0.500000 Y3.000000", + #'(------- lead-in -------)', + "G2 J-3.000000 Y-3.000000 Z0.500000", + "G2 J3.000000 Y3.000000 Z1.000000", + #'(------- lead-out -------)', + "G2 I0.000000 J-0.500000 X0.000000 Y2.000000", + #'(------- lead-out -------)', + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(0, 2, zFinal)) def test51(self): - '''Verify lead in/out commands for one and a half threads''' + """Verify lead in/out commands for one and a half threads""" - center = FreeCAD.Vector() - cmd = 'G2' - zStart = 0 - zFinal = 1.5 - pitch = 1 - radius = 3 - leadInOut = True - elevator = 2 + center = FreeCAD.Vector() + cmd = "G2" + zStart = 0 + zFinal = 1.5 + pitch = 1 + radius = 3 + leadInOut = True + elevator = 2 - path, start = PathThreadMilling.threadCommands(center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None) + path, start = PathThreadMilling.threadCommands( + center, cmd, zStart, zFinal, pitch, radius, leadInOut, elevator, None + ) gcode = [ - 'G0 X0.000000 Y2.000000', - 'G0 Z0.000000', - #'(------- lead-in -------)', - 'G2 J0.500000 Y3.000000', - #'(------- lead-in -------)', - 'G2 J-3.000000 Y-3.000000 Z0.500000', - 'G2 J3.000000 Y3.000000 Z1.000000', - 'G2 J-3.000000 Y-3.000000 Z1.500000', - #'(------- lead-out -------)', - 'G2 I0.000000 J0.500000 X0.000000 Y-2.000000', - #'(------- lead-out -------)', - ] + "G0 X0.000000 Y2.000000", + "G0 Z0.000000", + #'(------- lead-in -------)', + "G2 J0.500000 Y3.000000", + #'(------- lead-in -------)', + "G2 J-3.000000 Y-3.000000 Z0.500000", + "G2 J3.000000 Y3.000000 Z1.000000", + "G2 J-3.000000 Y-3.000000 Z1.500000", + #'(------- lead-out -------)', + "G2 I0.000000 J0.500000 X0.000000 Y-2.000000", + #'(------- lead-out -------)', + ] self.assertEqual([p.toGCode() for p in path], gcode) self.assertCoincide(start, FreeCAD.Vector(0, -2, zFinal))