black format
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user