Added new Feature to force-set Tolerance on a part
This commit is contained in:
210
src/Mod/Part/BOPTools/ToleranceFeatures.py
Normal file
210
src/Mod/Part/BOPTools/ToleranceFeatures.py
Normal file
@@ -0,0 +1,210 @@
|
||||
#/***************************************************************************
|
||||
# * Copyright (c) 2024 Eric Price (CorvusCorax) *
|
||||
# * <eric.price[at]tuebingen.mpg.de> *
|
||||
# * *
|
||||
# * This file is part of FreeCAD. *
|
||||
# * *
|
||||
# * FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
# * under the terms of the GNU Lesser General Public License as *
|
||||
# * published by the Free Software Foundation, either version 2.1 of the *
|
||||
# * License, or (at your option) any later version. *
|
||||
# * *
|
||||
# * FreeCAD 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 *
|
||||
# * Lesser General Public License for more details. *
|
||||
# * *
|
||||
# * You should have received a copy of the GNU Lesser General Public *
|
||||
# * License along with FreeCAD. If not, see *
|
||||
# * <https://www.gnu.org/licenses/>. *
|
||||
# ***************************************************************************/
|
||||
|
||||
__title__ = "BOPTools.ToleranceFeatures module"
|
||||
__author__ = "CorvusCorax"
|
||||
__url__ = "https://www.freecad.org"
|
||||
__doc__ = "Implementation of document objects (features) to adjust/manipulate tolerances."
|
||||
|
||||
import FreeCAD
|
||||
import Part
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
import FreeCADGui
|
||||
from PySide import QtCore, QtGui
|
||||
# -------------------------- common stuff -------------------------------------
|
||||
|
||||
# -------------------------- translation-related code -------------------------
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except Exception:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
translate = FreeCAD.Qt.translate
|
||||
# --------------------------/translation-related code -------------------------
|
||||
|
||||
|
||||
def getParamRefine():
|
||||
return FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Part/Boolean").GetBool("RefineModel")
|
||||
|
||||
|
||||
def cmdCreateToleranceSetFeature(name, minTolerance=1e-7):
|
||||
"""cmdCreateToleranceSetFeature(name, minTolerance): generalized implementation of GUI commands."""
|
||||
sel = FreeCADGui.Selection.getSelectionEx()
|
||||
|
||||
FreeCAD.ActiveDocument.openTransaction("Create ToleranceSet")
|
||||
FreeCADGui.addModule("BOPTools.ToleranceFeatures")
|
||||
FreeCADGui.doCommand("j = BOPTools.ToleranceFeatures.makeToleranceSet(name='{name}')".format(name=name))
|
||||
FreeCADGui.doCommand("j.minTolerance = {minTolerance}".format(minTolerance=minTolerance))
|
||||
FreeCADGui.doCommand("j.Objects = {sel}".format(
|
||||
sel= "[" + ", ".join(["App.ActiveDocument."+so.Object.Name for so in sel]) + "]"
|
||||
))
|
||||
|
||||
try:
|
||||
FreeCADGui.doCommand("j.Proxy.execute(j)")
|
||||
FreeCADGui.doCommand("j.purgeTouched()")
|
||||
except Exception as err:
|
||||
mb = QtGui.QMessageBox()
|
||||
mb.setIcon(mb.Icon.Warning)
|
||||
error_text1 = translate("Part_ToleranceFeatures", "Computing the result failed with an error:")
|
||||
error_text2 = translate("Part_ToleranceFeatures", "Click 'Continue' to create the feature anyway, or 'Abort' to cancel.")
|
||||
mb.setText(error_text1 + "\n\n" + str(err) + "\n\n" + error_text2)
|
||||
mb.setWindowTitle(translate("Part_ToleranceFeatures","Bad selection", None))
|
||||
btnAbort = mb.addButton(QtGui.QMessageBox.StandardButton.Abort)
|
||||
btnOK = mb.addButton(translate("Part_ToleranceFeatures","Continue",None),
|
||||
QtGui.QMessageBox.ButtonRole.ActionRole)
|
||||
mb.setDefaultButton(btnOK)
|
||||
mb.exec_()
|
||||
|
||||
if mb.clickedButton() is btnAbort:
|
||||
FreeCAD.ActiveDocument.abortTransaction()
|
||||
return
|
||||
|
||||
FreeCADGui.doCommand("for obj in j.ViewObject.Proxy.claimChildren():\n"
|
||||
" obj.ViewObject.hide()")
|
||||
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
|
||||
|
||||
def getIconPath(icon_dot_svg):
|
||||
return icon_dot_svg
|
||||
|
||||
# -------------------------- /common stuff ------------------------------------
|
||||
|
||||
# -------------------------- Connect ------------------------------------------
|
||||
|
||||
def makeToleranceSet(name):
|
||||
'''makeToleranceSet(name): makes an ToleranceSet object.'''
|
||||
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
|
||||
FeatureToleranceSet(obj)
|
||||
if FreeCAD.GuiUp:
|
||||
ViewProviderToleranceSet(obj.ViewObject)
|
||||
return obj
|
||||
|
||||
|
||||
class FeatureToleranceSet:
|
||||
"""The PartToleranceSetFeature object."""
|
||||
|
||||
def __init__(self,obj):
|
||||
obj.addProperty("App::PropertyLinkList","Objects","ToleranceSet","Objects to have tolerance adjusted.")
|
||||
obj.addProperty("App::PropertyBool","Refine","ToleranceSet",
|
||||
"True = refine resulting shape. False = output as is.")
|
||||
obj.addProperty("App::PropertyFloat","minTolerance","ToleranceSet", "1e-7")
|
||||
obj.Refine = getParamRefine()
|
||||
|
||||
obj.Proxy = self
|
||||
self.Type = "FeatureToleranceSet"
|
||||
|
||||
def execute(self,selfobj):
|
||||
shapes = []
|
||||
for obj in selfobj.Objects:
|
||||
sh = obj.Shape.copy(True,False)
|
||||
sh.limitTolerance(selfobj.minTolerance)
|
||||
if selfobj.Refine:
|
||||
sh = sh.removeSplitter()
|
||||
shapes.append(sh)
|
||||
|
||||
if len(shapes)>1:
|
||||
rst = Part.makeCompound(shapes)
|
||||
else:
|
||||
rst = shapes[0]
|
||||
selfobj.Shape = rst
|
||||
|
||||
|
||||
class ViewProviderToleranceSet:
|
||||
"""A View Provider for the Part ToleranceSet feature."""
|
||||
|
||||
def __init__(self,vobj):
|
||||
vobj.Proxy = self
|
||||
|
||||
def getIcon(self):
|
||||
return getIconPath("preferences-part_design.svg")
|
||||
|
||||
def attach(self, vobj):
|
||||
self.ViewObject = vobj
|
||||
self.Object = vobj.Object
|
||||
|
||||
def dumps(self):
|
||||
return None
|
||||
|
||||
def loads(self,state):
|
||||
return None
|
||||
|
||||
def claimChildren(self):
|
||||
return self.Object.Objects
|
||||
|
||||
def onDelete(self, feature, subelements):
|
||||
try:
|
||||
for obj in self.claimChildren():
|
||||
obj.ViewObject.show()
|
||||
except Exception as err:
|
||||
FreeCAD.Console.PrintError("Error in onDelete: " + str(err))
|
||||
return True
|
||||
|
||||
def canDragObjects(self):
|
||||
return True
|
||||
def canDropObjects(self):
|
||||
return True
|
||||
def canDragObject(self, dragged_object):
|
||||
return True
|
||||
def canDropObject(self, incoming_object):
|
||||
return hasattr(incoming_object, 'Shape')
|
||||
def dragObject(self, selfvp, dragged_object):
|
||||
objs = self.Object.Objects
|
||||
objs.remove(dragged_object)
|
||||
self.Object.Objects = objs
|
||||
def dropObject(self, selfvp, incoming_object):
|
||||
self.Object.Objects = self.Object.Objects + [incoming_object]
|
||||
|
||||
|
||||
class CommandToleranceSet:
|
||||
"""Command to create ToleranceSet feature."""
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap': getIconPath("preferences-part_design.svg"),
|
||||
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_ToleranceSet","Set Tolerance"),
|
||||
'Accel': "",
|
||||
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_ToleranceSet",
|
||||
"Set Tolerance for selected objects.")}
|
||||
|
||||
def Activated(self):
|
||||
if len(FreeCADGui.Selection.getSelectionEx()) >= 1:
|
||||
cmdCreateToleranceSetFeature(name="Tolerance")
|
||||
else:
|
||||
mb = QtGui.QMessageBox()
|
||||
mb.setIcon(mb.Icon.Warning)
|
||||
mb.setText(translate("Part_ToleranceSet",
|
||||
"Select at least one object or compounds", None))
|
||||
mb.setWindowTitle(translate("Part_ToleranceSet","Bad selection", None))
|
||||
mb.exec_()
|
||||
|
||||
def IsActive(self):
|
||||
if FreeCAD.ActiveDocument:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# -------------------------- /Connect -----------------------------------------
|
||||
|
||||
|
||||
def addCommands():
|
||||
FreeCADGui.addCommand('Part_ToleranceSet', CommandToleranceSet())
|
||||
@@ -50,6 +50,7 @@ def importAll():
|
||||
from . import Utils
|
||||
from . import SplitAPI
|
||||
from . import SplitFeatures
|
||||
from . import ToleranceFeatures
|
||||
|
||||
def reloadAll():
|
||||
"reloadAll(): reloads all modules of BOPTools package. Useful for debugging."
|
||||
@@ -63,4 +64,5 @@ def addCommands():
|
||||
"addCommands(): add all GUI commands of BOPTools package to FreeCAD command manager."
|
||||
JoinFeatures.addCommands()
|
||||
SplitFeatures.addCommands()
|
||||
ToleranceFeatures.addCommands()
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ set(BOPTools_Scripts
|
||||
BOPTools/ShapeMerge.py
|
||||
BOPTools/SplitAPI.py
|
||||
BOPTools/SplitFeatures.py
|
||||
BOPTools/ToleranceFeatures.py
|
||||
BOPTools/Utils.py
|
||||
)
|
||||
|
||||
|
||||
@@ -115,7 +115,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
compound->setCommand("Compound");
|
||||
*compound << "Part_Compound"
|
||||
<< "Part_ExplodeCompound"
|
||||
<< "Part_CompoundFilter";
|
||||
<< "Part_CompoundFilter"
|
||||
<< "Part_ToleranceSet";
|
||||
|
||||
Gui::MenuItem* part = new Gui::MenuItem;
|
||||
root->insertItem(item, part);
|
||||
|
||||
Reference in New Issue
Block a user