Added support for imperial threads to thread milling
This commit is contained in:
@@ -31,6 +31,7 @@ import PathScripts.PathGeom as PathGeom
|
||||
import PathScripts.PathLog as PathLog
|
||||
import PathScripts.PathOp as PathOp
|
||||
import PathScripts.PathUtils as PathUtils
|
||||
import math
|
||||
|
||||
from PySide import QtCore
|
||||
|
||||
@@ -47,14 +48,20 @@ def translate(context, text, disambig=None):
|
||||
return QtCore.QCoreApplication.translate(context, text, disambig)
|
||||
|
||||
|
||||
def radiiMetricInternal(majorDia, minorDia, toolDia, toolCrest = None):
|
||||
def radiiInternal(majorDia, minorDia, toolDia, toolCrest = None):
|
||||
'''internlThreadRadius(majorDia, minorDia, toolDia, toolCrest) ... returns the maximum radius for thread.'''
|
||||
PathLog.track(majorDia, minorDia, toolDia, toolCrest)
|
||||
if toolCrest is None:
|
||||
toolCrest = 0.0
|
||||
# see https://www.amesweb.info/Screws/Internal-Metric-Thread-Dimensions-Chart.aspx
|
||||
# As it turns out metric and imperial standard threads follow the same rules.
|
||||
# The determining factor is the height of the full 60 degree triangle H.
|
||||
# - The minor diameter is 1/4 * H smaller than the pitch diameter.
|
||||
# - The major diameter is 3/8 * H bigger than the pitch diameter
|
||||
# Since we already have the outer diameter it's simpler to just add 1/8 * H
|
||||
# to get the outer tip of the thread.
|
||||
H = ((majorDia - minorDia) / 2.0 ) * 1.6 # (D - d)/2 = 5/8 * H
|
||||
outerTip = majorDia / 2.0 + H / 8.0
|
||||
# Compensate for the crest of the tool
|
||||
toolTip = outerTip - toolCrest * 0.8660254037844386 # math.sqrt(3)/2 ... 60deg triangle height
|
||||
return ((minorDia - toolDia) / 2, toolTip - toolDia / 2)
|
||||
|
||||
@@ -161,11 +168,12 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
RightHand = 'RightHand'
|
||||
ThreadTypeCustom = 'Custom'
|
||||
ThreadTypeMetricInternal = 'Metric - internal'
|
||||
ThreadTypeImperialInternal = 'Imperial - internal'
|
||||
DirectionClimb = 'Climb'
|
||||
DirectionConventional = 'Conventional'
|
||||
|
||||
ThreadOrientations = [LeftHand, RightHand]
|
||||
ThreadTypes = [ThreadTypeCustom, ThreadTypeMetricInternal]
|
||||
ThreadTypes = [ThreadTypeCustom, ThreadTypeMetricInternal, ThreadTypeImperialInternal]
|
||||
Directions = [DirectionClimb, DirectionConventional]
|
||||
|
||||
def circularHoleFeatures(self, obj):
|
||||
@@ -179,7 +187,8 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
obj.addProperty("App::PropertyString", "ThreadName", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Devfines which standard thread was chosen"))
|
||||
obj.addProperty("App::PropertyLength", "MajorDiameter", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set thread's major diameter"))
|
||||
obj.addProperty("App::PropertyLength", "MinorDiameter", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set thread's minor diameter"))
|
||||
obj.addProperty("App::PropertyLength", "Pitch", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set thread's pitch"))
|
||||
obj.addProperty("App::PropertyLength", "Pitch", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set thread's pitch - used for metric threads"))
|
||||
obj.addProperty("App::PropertyInteger", "TPI", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set thread's tpi - used for imperial threads"))
|
||||
obj.addProperty("App::PropertyInteger", "ThreadFit", "Thread", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set how many passes are used to cut the thread"))
|
||||
obj.addProperty("App::PropertyInteger", "Passes", "Operation", QtCore.QT_TRANSLATE_NOOP("App::Property", "Set how many passes are used to cut the thread"))
|
||||
obj.addProperty("App::PropertyEnumeration", "Direction", "Operation", QtCore.QT_TRANSLATE_NOOP("App::Property", "Direction of thread cutting operation"))
|
||||
@@ -254,7 +263,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
|
||||
self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid}))
|
||||
|
||||
for radius in threadPasses(obj.Passes, radiiMetricInternal, obj.MajorDiameter.Value, obj.MinorDiameter.Value, self.tool.Diameter, 0):
|
||||
for radius in threadPasses(obj.Passes, radiiInternal, obj.MajorDiameter.Value, obj.MinorDiameter.Value, self.tool.Diameter, 0):
|
||||
commands = internalThreadCommands(loc, gcode, zStart, zFinal, pitch, radius, obj.LeadInOut)
|
||||
for cmd in commands:
|
||||
p = cmd.Parameters
|
||||
@@ -274,6 +283,8 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
|
||||
(cmd, zStart, zFinal) = self.threadSetup(obj)
|
||||
pitch = obj.Pitch.Value
|
||||
if obj.TPI > 0:
|
||||
pitch = 25.4 / obj.TPI
|
||||
if pitch <= 0:
|
||||
PathLog.error("Cannot create thread with pitch {}".format(pitch))
|
||||
return
|
||||
@@ -288,6 +299,7 @@ class ObjectThreadMilling(PathCircularHoleBase.ObjectOp):
|
||||
obj.ThreadType = self.ThreadTypeMetricInternal
|
||||
obj.ThreadFit = 50
|
||||
obj.Pitch = 1
|
||||
obj.TPI = 0
|
||||
obj.Passes = 1
|
||||
obj.Direction = self.DirectionClimb
|
||||
obj.LeadInOut = True
|
||||
@@ -302,6 +314,7 @@ def SetupProperties():
|
||||
setup.append("MajorDiameter")
|
||||
setup.append("MinorDiameter")
|
||||
setup.append("Pitch")
|
||||
setup.append("TPI")
|
||||
setup.append("Passes")
|
||||
setup.append("Direction")
|
||||
setup.append("LeadInOut")
|
||||
|
||||
@@ -86,6 +86,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
obj.Direction = self.form.opDirection.currentText()
|
||||
obj.Passes = self.form.opPasses.value()
|
||||
obj.LeadInOut = self.form.leadInOut.checkState() == QtCore.Qt.Checked
|
||||
obj.TPI = self.form.threadTPI.value()
|
||||
|
||||
self.updateToolController(obj, self.form.toolController)
|
||||
|
||||
@@ -102,6 +103,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
self.form.threadName.setCurrentText(obj.ThreadName)
|
||||
self.form.threadType.blockSignals(False)
|
||||
self.form.threadName.blockSignals(False)
|
||||
self.form.threadTPI.setValue(obj.TPI)
|
||||
|
||||
self.form.opPasses.setValue(obj.Passes)
|
||||
self.form.opDirection.setCurrentText(obj.Direction)
|
||||
@@ -114,30 +116,65 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
|
||||
|
||||
def _isThreadMetric(self):
|
||||
return self.form.threadType.currentText() == PathThreadMilling.ObjectThreadMilling.ThreadTypeMetricInternal
|
||||
|
||||
def _isThreadImperial(self):
|
||||
return self.form.threadType.currentText() == PathThreadMilling.ObjectThreadMilling.ThreadTypeImperialInternal
|
||||
|
||||
def _updateFromThreadType(self):
|
||||
if self.form.threadType.currentIndex() == 0:
|
||||
PathLog.track(self.form.threadType.currentIndex())
|
||||
|
||||
if self.form.threadType.currentText() == PathThreadMilling.ObjectThreadMilling.ThreadTypeCustom:
|
||||
self.form.threadName.setEnabled(False)
|
||||
self.form.threadFit.setEnabled(False)
|
||||
self.form.threadFitLabel.setEnabled(False)
|
||||
else:
|
||||
PathLog.track(self.form.threadType.currentIndex())
|
||||
self.form.threadPitch.setEnabled(True)
|
||||
self.form.threadPitchLabel.setEnabled(True)
|
||||
self.form.threadTPI.setEnabled(True)
|
||||
self.form.threadTPILabel.setEnabled(True)
|
||||
|
||||
if self._isThreadMetric():
|
||||
self.form.threadFit.setEnabled(True)
|
||||
self.form.threadFitLabel.setEnabled(True)
|
||||
self.form.threadPitch.setEnabled(True)
|
||||
self.form.threadPitchLabel.setEnabled(True)
|
||||
self.form.threadTPI.setEnabled(False)
|
||||
self.form.threadTPILabel.setEnabled(False)
|
||||
self.form.threadTPI.setValue(0)
|
||||
fillThreads(self.form.threadName, 'metric-internal')
|
||||
|
||||
if self._isThreadImperial():
|
||||
self.form.threadFit.setEnabled(True)
|
||||
self.form.threadFitLabel.setEnabled(True)
|
||||
self.form.threadPitch.setEnabled(False)
|
||||
self.form.threadPitchLabel.setEnabled(False)
|
||||
self.form.threadTPI.setEnabled(True)
|
||||
self.form.threadTPILabel.setEnabled(True)
|
||||
self.pitch.updateSpinBox(0)
|
||||
fillThreads(self.form.threadName, 'imperial-internal')
|
||||
|
||||
def _updateFromThreadName(self):
|
||||
thread = self.form.threadName.currentData()
|
||||
fit = float(self.form.threadFit.value()) / 100
|
||||
mamin = float(thread['dMajorMin'])
|
||||
mamax = float(thread['dMajorMax'])
|
||||
major = mamin + (mamax - mamin) * fit
|
||||
mimin = float(thread['dMinorMin'])
|
||||
mimax = float(thread['dMinorMax'])
|
||||
pitch = float(thread['pitch'])
|
||||
minor = mimin + (mimax - mimin) * fit
|
||||
|
||||
self.pitch.updateSpinBox(pitch)
|
||||
self.majorDia.updateSpinBox((mamin + mamax) / 2)
|
||||
self.minorDia.updateSpinBox((mimin + mimax) / 2)
|
||||
if self._isThreadMetric():
|
||||
pitch = float(thread['pitch'])
|
||||
self.pitch.updateSpinBox(pitch)
|
||||
|
||||
if self._isThreadImperial():
|
||||
tpi = int(thread['tpi'])
|
||||
self.form.threadTPI.setValue(tpi)
|
||||
minor = minor * 25.4
|
||||
major = major * 25.4
|
||||
|
||||
self.majorDia.updateSpinBox(major)
|
||||
self.minorDia.updateSpinBox(minor)
|
||||
|
||||
self.setDirty()
|
||||
|
||||
@@ -149,6 +186,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
signals.append(self.form.threadMinor.editingFinished)
|
||||
signals.append(self.form.threadPitch.editingFinished)
|
||||
signals.append(self.form.threadOrientation.currentIndexChanged)
|
||||
signals.append(self.form.threadTPI.editingFinished)
|
||||
signals.append(self.form.opDirection.currentIndexChanged)
|
||||
signals.append(self.form.opPasses.editingFinished)
|
||||
signals.append(self.form.leadInOut.stateChanged)
|
||||
@@ -160,6 +198,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
def registerSignalHandlers(self, obj):
|
||||
self.form.threadType.currentIndexChanged.connect(self._updateFromThreadType)
|
||||
self.form.threadName.currentIndexChanged.connect(self._updateFromThreadName)
|
||||
self.form.threadFit.valueChanged.connect(self._updateFromThreadName)
|
||||
|
||||
|
||||
Command = PathOpGui.SetupOperation('Thread Milling',
|
||||
|
||||
Reference in New Issue
Block a user