FreeCAD / src /Mod /PartDesign /InvoluteGearFeature.py
AbdulElahGwaith's picture
Upload folder using huggingface_hub
985c397 verified
# ***************************************************************************
# * Copyright (c) 2014 Juergen Riegel <FreeCAD@juergen-riegel.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 *
# * *
# ***************************************************************************
import pathlib
import FreeCAD, Part
from PySide import QtCore
from fcgear import involute
from fcgear import fcgear
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtGui
__title__ = "PartDesign InvoluteGearObject management"
__author__ = "Juergen Riegel"
__url__ = "https://www.freecad.org"
def makeInvoluteGear(name):
"""makeInvoluteGear(name): makes an InvoluteGear"""
obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython", name)
_InvoluteGear(obj)
if FreeCAD.GuiUp:
_ViewProviderInvoluteGear(obj.ViewObject)
# FreeCAD.ActiveDocument.recompute()
if FreeCAD.GuiUp:
body = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("pdbody")
part = FreeCADGui.ActiveDocument.ActiveView.getActiveObject("part")
if body:
body.Group = body.Group + [obj]
elif part:
part.Group = part.Group + [obj]
return obj
class CommandInvoluteGear:
"GUI command to create an InvoluteGear"
def GetResources(self):
return {
"Pixmap": "PartDesign_InternalExternalGear",
"MenuText": QtCore.QT_TRANSLATE_NOOP("PartDesign_InvoluteGear", "Involute Gear"),
"Accel": "",
"ToolTip": QtCore.QT_TRANSLATE_NOOP(
"PartDesign_InvoluteGear", "Creates or edits the involute gear definition"
),
}
def Activated(self):
FreeCAD.ActiveDocument.openTransaction("Create involute gear")
FreeCADGui.addModule("InvoluteGearFeature")
FreeCADGui.doCommand("InvoluteGearFeature.makeInvoluteGear('InvoluteGear')")
FreeCADGui.doCommand("Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name,0)")
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
class _InvoluteGear:
"The InvoluteGear object"
def __init__(self, obj):
self.Type = "InvoluteGear"
self._ensure_properties(obj, is_restore=False)
obj.Proxy = self
def onDocumentRestored(self, obj):
"""hook used to migrate older versions of this object"""
self._ensure_properties(obj, is_restore=True)
def _ensure_properties(self, obj, is_restore):
def ensure_property(type_, name, doc, default):
if not hasattr(obj, name):
obj.addProperty(type_, name, "Gear", doc, locked=True)
if callable(default):
setattr(obj, name, default())
else:
setattr(obj, name, default)
# for details about the property's docstring translation,
# see https://tracker.freecad.org/view.php?id=2524
ensure_property(
"App::PropertyInteger",
"NumberOfTeeth",
doc=QtCore.QT_TRANSLATE_NOOP("App::Property", "Number of gear teeth"),
default=26,
)
ensure_property(
"App::PropertyLength",
"Modules",
doc=QtCore.QT_TRANSLATE_NOOP("App::Property", "Module of the gear"),
default="2.5 mm",
)
ensure_property(
"App::PropertyAngle",
"PressureAngle",
doc=QtCore.QT_TRANSLATE_NOOP("App::Property", "Pressure angle of gear teeth"),
default="20 deg",
)
ensure_property(
"App::PropertyBool",
"HighPrecision",
doc=QtCore.QT_TRANSLATE_NOOP(
"App::Property",
"True=2 curves with each 3 control points, False=1 curve with 4 control points.",
),
default=True,
)
ensure_property(
"App::PropertyBool",
"ExternalGear",
doc=QtCore.QT_TRANSLATE_NOOP(
"App::Property", "True=external Gear, False=internal Gear"
),
default=True,
)
ensure_property(
"App::PropertyFloat",
"AddendumCoefficient",
doc=QtCore.QT_TRANSLATE_NOOP(
"App::Property",
"The height of the tooth from the pitch circle up to its tip, normalized by the module.",
),
default=lambda: 1.0 if obj.ExternalGear else 0.6,
)
ensure_property(
"App::PropertyFloat",
"DedendumCoefficient",
doc=QtCore.QT_TRANSLATE_NOOP(
"App::Property",
"The height of the tooth from the pitch circle down to its root, normalized by the module.",
),
default=1.25,
)
ensure_property(
"App::PropertyFloat",
"RootFilletCoefficient",
doc=QtCore.QT_TRANSLATE_NOOP(
"App::Property",
"The radius of the fillet at the root of the tooth, normalized by the module.",
),
default=lambda: 0.375 if is_restore else 0.38,
)
ensure_property(
"App::PropertyFloat",
"ProfileShiftCoefficient",
doc=QtCore.QT_TRANSLATE_NOOP(
"App::Property",
"The distance by which the reference profile is shifted outwards, normalized by the module.",
),
default=0.0,
)
def execute(self, obj):
w = fcgear.FCWireBuilder()
generator_func = (
involute.CreateExternalGear if obj.ExternalGear else involute.CreateInternalGear
)
generator_func(
w,
obj.Modules.Value,
obj.NumberOfTeeth,
obj.PressureAngle.Value,
split=obj.HighPrecision,
addCoeff=obj.AddendumCoefficient,
dedCoeff=obj.DedendumCoefficient,
filletCoeff=obj.RootFilletCoefficient,
shiftCoeff=obj.ProfileShiftCoefficient,
)
gearw = Part.Wire([o.toShape() for o in w.wire])
obj.Shape = gearw
obj.positionBySupport()
return
class _ViewProviderInvoluteGear:
"A View Provider for the InvoluteGear object"
def __init__(self, vobj):
vobj.Proxy = self
def getIcon(self):
return ":/icons/PartDesign_InternalExternalGear.svg"
def attach(self, vobj):
self.ViewObject = vobj
self.Object = vobj.Object
def setEdit(self, vobj, mode):
taskd = _InvoluteGearTaskPanel(self.Object, mode)
taskd.obj = vobj.Object
taskd.update()
FreeCADGui.Control.showDialog(taskd)
return True
def unsetEdit(self, vobj, mode):
FreeCADGui.Control.closeDialog()
return
def dumps(self):
return None
def loads(self, state):
return None
class _InvoluteGearTaskPanel:
"""The editmode TaskPanel for InvoluteGear objects"""
def __init__(self, obj, mode):
self.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(str(pathlib.Path(__file__).with_suffix(".ui")))
self.form.setWindowIcon(QtGui.QIcon(":/icons/PartDesign_InternalExternalGear.svg"))
self.assignToolTipsFromPropertyDocs()
def assignValue(property_name, fitView=False):
"""Returns a function that takes a single value and assigns it to the given property"""
def assigner(value):
setattr(self.obj, property_name, value)
self.obj.Proxy.execute(self.obj)
if fitView:
FreeCAD.Gui.SendMsgToActiveView("ViewFit")
return assigner
def assignIndexAsBool(property_name):
"""Variant of assignValue that transforms the index of a Yes/No Combobox to a bool."""
assigner = assignValue(property_name)
def transformingAssigner(value):
assigner(True if value == 0 else False)
return transformingAssigner
self.form.Quantity_Modules.valueChanged.connect(assignValue("Modules", fitView=True))
self.form.Quantity_PressureAngle.valueChanged.connect(assignValue("PressureAngle"))
self.form.spinBox_NumberOfTeeth.valueChanged.connect(
assignValue("NumberOfTeeth", fitView=True)
)
self.form.comboBox_HighPrecision.currentIndexChanged.connect(
assignIndexAsBool("HighPrecision")
)
self.form.comboBox_ExternalGear.currentIndexChanged.connect(
assignIndexAsBool("ExternalGear")
)
self.form.doubleSpinBox_Addendum.valueChanged.connect(assignValue("AddendumCoefficient"))
self.form.doubleSpinBox_Dedendum.valueChanged.connect(assignValue("DedendumCoefficient"))
self.form.doubleSpinBox_RootFillet.valueChanged.connect(
assignValue("RootFilletCoefficient")
)
self.form.doubleSpinBox_ProfileShift.valueChanged.connect(
assignValue("ProfileShiftCoefficient")
)
self.update()
if mode == 0: # fresh created
self.obj.Proxy.execute(self.obj) # calculate once
FreeCAD.Gui.SendMsgToActiveView("ViewFit")
def assignToolTipsFromPropertyDocs(self):
def assign(property_name, *widgets):
doc = self.obj.getDocumentationOfProperty(property_name)
translated_doc = QtGui.QApplication.translate("App::Property", doc)
for w in widgets:
w.setToolTip(translated_doc)
# we assign the tool tip to both, the label and the input field, for user convenience
assign("Modules", self.form.Quantity_Modules, self.form.label_Modules)
assign("PressureAngle", self.form.Quantity_PressureAngle, self.form.label_PressureAngle)
assign("NumberOfTeeth", self.form.spinBox_NumberOfTeeth, self.form.label_NumberOfTeeth)
assign("HighPrecision", self.form.comboBox_HighPrecision, self.form.label_HighPrecision)
assign("ExternalGear", self.form.comboBox_ExternalGear, self.form.label_ExternalGear)
assign("AddendumCoefficient", self.form.doubleSpinBox_Addendum, self.form.label_Addendum)
assign("DedendumCoefficient", self.form.doubleSpinBox_Dedendum, self.form.label_Dedendum)
assign(
"RootFilletCoefficient", self.form.doubleSpinBox_RootFillet, self.form.label_RootFillet
)
assign(
"ProfileShiftCoefficient",
self.form.doubleSpinBox_ProfileShift,
self.form.label_ProfileShift,
)
def changeEvent(self, event):
if event == QtCore.QEvent.LanguageChange:
self.assignToolTipsFromPropertyDocs()
def transferTo(self):
"Transfer from the dialog to the object"
self.obj.NumberOfTeeth = self.form.spinBox_NumberOfTeeth.value()
self.obj.Modules = self.form.Quantity_Modules.text()
self.obj.PressureAngle = self.form.Quantity_PressureAngle.text()
self.obj.HighPrecision = (
True if self.form.comboBox_HighPrecision.currentIndex() == 0 else False
)
self.obj.ExternalGear = (
True if self.form.comboBox_ExternalGear.currentIndex() == 0 else False
)
self.obj.AddendumCoefficient = self.form.doubleSpinBox_Addendum.value()
self.obj.DedendumCoefficient = self.form.doubleSpinBox_Dedendum.value()
self.obj.RootFilletCoefficient = self.form.doubleSpinBox_RootFillet.value()
self.obj.ProfileShiftCoefficient = self.form.doubleSpinBox_ProfileShift.value()
def transferFrom(self):
"Transfer from the object to the dialog"
self.form.spinBox_NumberOfTeeth.setValue(self.obj.NumberOfTeeth)
self.form.Quantity_Modules.setText(self.obj.Modules.UserString)
self.form.Quantity_PressureAngle.setText(self.obj.PressureAngle.UserString)
self.form.comboBox_HighPrecision.setCurrentIndex(0 if self.obj.HighPrecision else 1)
self.form.comboBox_ExternalGear.setCurrentIndex(0 if self.obj.ExternalGear else 1)
self.form.doubleSpinBox_Addendum.setValue(self.obj.AddendumCoefficient)
self.form.doubleSpinBox_Dedendum.setValue(self.obj.DedendumCoefficient)
self.form.doubleSpinBox_RootFillet.setValue(self.obj.RootFilletCoefficient)
self.form.doubleSpinBox_ProfileShift.setValue(self.obj.ProfileShiftCoefficient)
def getStandardButtons(self):
return (
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Apply
)
def clicked(self, button):
if button == QtGui.QDialogButtonBox.Apply:
self.transferTo()
self.obj.Proxy.execute(self.obj)
def update(self):
"fills the widgets"
self.transferFrom()
def accept(self):
self.transferTo()
FreeCAD.ActiveDocument.recompute()
FreeCADGui.ActiveDocument.resetEdit()
def reject(self):
FreeCADGui.ActiveDocument.resetEdit()
FreeCAD.ActiveDocument.abortTransaction()