Files
create/src/Mod/TechDraw/TechDrawTools/TaskHoleShaftFit.py
Marco Patzer 1cfa0426fb Add leading plus (+) in hole/shaft fit limit
ISO 286/14405-1 calls for a plus sign if the limit is positive and a
minus sign if the limit is negative. A zero limit should have neither
a plus nor a minus sign. This commit adds the plus sign.
2024-03-23 08:52:06 -04:00

198 lines
10 KiB
Python

# ***************************************************************************
# * Copyright (c) 2023 edi <edi271@a1.net> *
# * *
# * 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 *
# * *
# ***************************************************************************
"""Provides the TechDraw HoleShaftFit Task Dialog."""
__title__ = "TechDrawTools.TaskHoleShaftFit"
__author__ = "edi"
__url__ = "https://www.freecad.org"
__version__ = "00.01"
__date__ = "2023/02/07"
import FreeCAD as App
import FreeCADGui as Gui
from functools import partial
import os
translate = App.Qt.translate
class TaskHoleShaftFit:
def __init__(self,sel):
loose = translate("TechDraw_HoleShaftFit", "loose fit")
snug = translate("TechDraw_HoleShaftFit", "snug fit")
press = translate("TechDraw_HoleShaftFit", "press fit")
self.isHole = True
self.sel = sel
self.holeValues = [["h9","D10",loose],["h9","E9",loose],["h9","F8",loose],["h6","G7",loose],
["c11","H11",loose],["f7","H8",loose],["h6","H7",loose],["h7","H8",loose],
["k6","H7",snug],["n6","H7",snug],["r6","H7",press],["s6","H7",press],
["h6","K7",snug],["h6","N7",snug],["h6","R7",press],["h6","S7",press]]
self.shaftValues = [["H11","c11",loose],["H8","f7",loose],["H7","h6",loose],["H8","h7",loose],
["D10","h9",loose],["E9","h9",loose],["F8","h9",loose],["G7","h6",loose],
["K7","h6",snug],["N7","h6",snug],["R7","h6",press],["S7","h6",press],
["H7","k6",snug],["H7","n6",snug],["H7","r6",press],["H7","s6",press]]
self._uiPath = App.getHomePath()
self._uiPath = os.path.join(self._uiPath, "Mod/TechDraw/TechDrawTools/Gui/TaskHoleShaftFit.ui")
self.form = Gui.PySideUic.loadUi(self._uiPath)
self.form.setWindowTitle(translate("TechDraw_HoleShaftFit", "Hole / Shaft Fit ISO 286"))
self.form.rbHoleBase.clicked.connect(partial(self.on_HoleShaftChanged,True))
self.form.rbShaftBase.clicked.connect(partial(self.on_HoleShaftChanged,False))
self.form.cbField.currentIndexChanged.connect(self.on_FieldChanged)
def setHoleFields(self):
'''set hole fields in the combo box'''
for i in range(self.form.cbField.count()):
self.form.cbField.removeItem(0)
for value in self.holeValues:
self.form.cbField.addItem(value[1])
self.form.lbBaseField.setText(' '+self.holeValues[0][0]+" /")
self.form.lbFitType.setText(self.holeValues[0][2])
def setShaftFields(self):
'''set shaft fields in the combo box'''
for i in range(self.form.cbField.count()):
self.form.cbField.removeItem(0)
for value in self.shaftValues:
self.form.cbField.addItem(value[1])
self.form.lbBaseField.setText(' '+self.shaftValues[0][0]+" /")
self.form.lbFitType.setText(self.shaftValues[0][2])
def on_HoleShaftChanged(self,isHole):
'''slot: change the used base fit hole/shaft'''
if isHole:
self.isHole = isHole
self.setShaftFields()
else:
self.isHole = isHole
self.setHoleFields()
def on_FieldChanged(self):
'''slot: change of the desired field'''
currentIndex = self.form.cbField.currentIndex()
if self.isHole:
self.form.lbBaseField.setText(' '+self.shaftValues[currentIndex][0]+" /")
self.form.lbFitType.setText(self.shaftValues[currentIndex][2])
else:
self.form.lbBaseField.setText(' '+self.holeValues[currentIndex][0]+" /")
self.form.lbFitType.setText(self.holeValues[currentIndex][2])
def accept(self):
'''slot: OK pressed'''
currentIndex = self.form.cbField.currentIndex()
if self.isHole:
selectedField = self.shaftValues[currentIndex][1]
else:
selectedField = self.holeValues[currentIndex][1]
fieldChar = selectedField[0]
quality = int(selectedField[1:])
dim = self.sel[0].Object
value = dim.getRawValue()
iso = ISO286()
iso.calculate(value,fieldChar,quality)
rangeValues = iso.getValues()
mainFormat = dim.FormatSpec
dim.FormatSpec = mainFormat+' '+selectedField
dim.EqualTolerance = False
dim.OverTolerance = rangeValues[0]
dim.UnderTolerance = rangeValues[1]
if dim.OverTolerance < 0:
dim.FormatSpecOverTolerance = '(%-0.6w)'
elif dim.OverTolerance > 0:
dim.FormatSpecOverTolerance = '(+%-0.6w)'
else:
dim.FormatSpecOverTolerance = '( %-0.6w)'
if dim.UnderTolerance < 0:
dim.FormatSpecUnderTolerance = '(%-0.6w)'
elif dim.UnderTolerance > 0:
dim.FormatSpecUnderTolerance = '(+%-0.6w)'
else:
dim.FormatSpecUnderTolerance = '( %-0.6w)'
Gui.Control.closeDialog()
def reject(self):
return True
class ISO286:
'''This class represents a subset of the ISO 286 standard'''
def getNominalRange(self,measureValue):
'''return index of selected nominal range field, 0 < measureValue < 500 mm'''
measureRanges = [0,3,6,10,14,18,24,30,40,50,65,80,100,120,140,160,180,200,225,250,280,315,355,400,450,500]
index = 1
while measureValue > measureRanges[index]:
index = index+1
return index-1
def getITValue(self,valueQuality,valueNominalRange):
'''return IT-value (value of quality in micrometers)'''
'''tables IT6 to IT11 from 0 to 500 mm'''
IT6 = [6,8,9,11,11,13,13,16,16,19,19,22,22,25,25,25,29,29,29,32,32,36,36,40,40]
IT7 = [10,12,15,18,18,21,21,25,25,30,30,35,35,40,40,40,46,46,46,52,52,57,57,63,63]
IT8 = [14,18,22,27,27,33,33,39,39,46,46,54,54,63,63,63,72,72,72,81,81,89,89,97,97]
IT9 = [25,30,36,43,43,52,52,62,62,74,74,87,87,100,100,100,115,115,115,130,130,140,140,155,155]
IT10 = [40,48,58,70,70,84,84,100,100,120,120,140,140,160,160,160,185,185,185,210,210,230,230,250,250]
IT11 = [60,75,90,110,110,130,130,160,160,190,190,220,220,250,250,250,290,290,290,320,320,360,360,400,400]
qualityTable = [IT6,IT7,IT8,IT9,IT10,IT11]
return qualityTable[valueQuality-6][valueNominalRange]
def getFieldValue(self,fieldCharacter,valueNominalRange):
'''return es or ES value of the field in micrometers'''
cField = [-60,-70,-80,-95,-95,-110,-110,-120,-130,-140,-150,-170,-180,-200,-210,-230,-240,-260,-280,-300,-330,-360,-400,-440,-480]
fField = [-6,-10,-13,-16,-16,-20,-20,-25,-25,-30,-30,-36,-36,-43,-43,-43,-50,-50,-50,-56,-56,-62,-62,-68,-68]
gField = [-2,-4,-5,-6,-6,-7,-7,-9,-9,-10,-10,-12,-12,-14,-14,-14,-15,-15,-15,-17,-17,-18,-18,-20,-20]
hField = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
kField = [6,9,10,12,12,15,15,18,18,21,21,25,25,28,28,28,33,33,33,36,36,40,40,45,45]
nField = [10,16,19,23,23,28,28,33,33,39,39,45,45,52,52,60,60,66,66,73,73,80,80]
rField = [16,23,28,34,34,41,41,50,50,60,62,73,76,88,90,93,106,109,113,126,130,144,150,166,172]
sField = [20,27,32,39,39,48,48,59,59,72,78,93,101,117,125,133,151,159,169,190,202,226,244,272,292]
DField = [60,78,98,120,120,149,149,180,180,220,220,260,260,305,305,305,355,355,355,400,400,440,440,480,480]
EField = [39,50,61,75,75,92,92,112,112,134,134,159,159,185,185,185,215,215,215,240,240,265,265,290,290]
FField = [20,28,35,43,43,53,53,64,64,76,76,90,90,106,106,106,122,122,122,137,137,151,151,165,165]
GField = [12,16,20,24,24,28,28,34,34,40,40,47,47,54,54,54,61,61,61,69,69,75,75,83,83]
HField = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
KField = [0,3,5,6,6,6,6,7,7,9,9,10,10,12,12,12,13,13,13,16,16,17,17,18,18]
NField = [-4,-4,-4,-5,-5,-7,-7,-8,-8,-9,-9,-10,-10,-12,-12,-12,-14,-14,-14,-14,-14,-16,-16,-17,-17]
RField = [-10,-11,-13,-16,-16,-20,-20,-25,-25,-30,-32,-38,-41,-48,-50,-53,-60,-63,-67,-74,-78,-87,-93,-103,-109]
SField = [-14,-15,-17,-21,-21,-27,-27,-34,-34,-42,-48,-58,-66,-77,-85,-93,-105,-113,-123,-138,-150,-169,-187,-209,-229]
fieldDict = {'c':cField,'f':fField,'g':gField,'h':hField,'k':kField,'n':nField,'r':rField,'s':sField,
'D':DField,'E':EField,'F':FField,'G':GField,'H':HField,'K':KField,'N':NField,'R':RField,'S':SField}
return fieldDict[fieldCharacter][valueNominalRange]
def calculate(self,value,fieldChar,quality):
'''calculate upper and lower field values'''
self.nominalRange = self. getNominalRange(value)
self.upperValue = self.getFieldValue(fieldChar,self.nominalRange)
self.lowerValue = self.upperValue-self.getITValue(quality,self.nominalRange)
if fieldChar == 'H':
self.upperValue = -self.lowerValue
self.lowerValue = 0
def getValues(self):
'''return range values in mm'''
return (self.upperValue/1000,self.lowerValue/1000)