Part: clean up spacing of lines in BOP JoinFeatures

This commit is contained in:
vocx-fc
2020-10-10 23:40:16 -05:00
committed by wwmayer
parent d603136821
commit 5d1d8d800b
3 changed files with 112 additions and 67 deletions

View File

@@ -40,18 +40,27 @@ def myCustomFusionRoutine(list_of_shapes):
... (use attributes and methods of ao) ..."""
def __define_attributes(self):
self.gfa_return = None #stores the data returned by generalFuse, supplied to class constructor
# stores the data returned by generalFuse, supplied to class constructor
self.gfa_return = None
self.pieces = None #pieces that resulted from intersetion routine. List of shapes (non-decorated).
self._piece_to_index = {} # key = decorated shape. Value = index (int) into self.pieces
# pieces that resulted from intersetion routine. List of shapes (non-decorated).
self.pieces = None
# key = decorated shape. Value = index (int) into self.pieces
self._piece_to_index = {}
self.source_shapes = [] # list of shapes that was supplied to generalFuse (plus the self-shape). List of shapes (non-decorated)
self._source_to_index = {} # key = decorated shape. Value = index (int) into self.source_shapes
# list of shapes that was supplied to generalFuse (plus the self-shape). List of shapes (non-decorated)
self.source_shapes = []
# key = decorated shape. Value = index (int) into self.source_shapes
self._source_to_index = {}
self._pieces_of_source = [] #list of pieces (indexes) generated from a source shape, by index of source shape. List of lists of ints.
self._sources_of_piece = [] #list of source shapes (indexes) the piece came from, by index of piece. List of lists of ints.
#list of pieces (indexes) generated from a source shape, by index of source shape. List of lists of ints.
self._pieces_of_source = []
#list of source shapes (indexes) the piece came from, by index of piece. List of lists of ints.
self._sources_of_piece = []
self._element_to_source = {} #dictionary for finding, which source shapes did an element of pieces come from. key = HashableShape (element). Value = set of ints
# dictionary for finding, which source shapes did an element of pieces come from.
# key = HashableShape (element). Value = set of ints
self._element_to_source = {}
self._freeze()
@@ -138,7 +147,8 @@ def myCustomFusionRoutine(list_of_shapes):
for iSource in range(len(map)):
if len(map[iSource]) == 0:
import FreeCAD as App
App.Console.PrintWarning("Map entry {num} is empty. Source-to-piece correspondence information is probably incomplete.".format(num= iSource))
App.Console.PrintWarning("Map entry {num} is empty. "
"Source-to-piece correspondence information is probably incomplete.".format(num=iSource))
self._pieces_of_source = [[] for i in range(len(self.source_shapes))]
self._sources_of_piece = [[] for i in range(len(self.pieces))]
@@ -311,7 +321,8 @@ def myCustomFusionRoutine(list_of_shapes):
#can't split the shape
return [shape]
# for each joint, test if all bits it's connected to are from same number of sources. If not, this is a joint for splitting
# for each joint, test if all bits it's connected to are from same number of sources.
# If not, this is a joint for splitting
# FIXME: this is slow, and maybe can be optimized
splits = []
for joint in joint_extractor(shape):
@@ -372,7 +383,9 @@ class GeneralFuseReturnBuilder(FrozenClass):
"GeneralFuseReturnBuilder: utility class used by splitAggregates to build fake return of generalFuse, for re-parsing."
def __define_attributes(self):
self.pieces = []
self._piece_to_index = {} # key = hasher_class(shape). Value = (index_into_self_dot_pieces, shape). Note that GeneralFuseResult uses this item directly.
# key = hasher_class(shape). Value = (index_into_self_dot_pieces, shape).
# Note that GeneralFuseResult uses this item directly.
self._piece_to_index = {}
self._pieces_from_source = [] #list of list of ints
self.source_shapes = []

View File

@@ -32,7 +32,8 @@ from .GeneralFuseResult import GeneralFuseResult
from .Utils import compoundLeaves
def shapeOfMaxSize(list_of_shapes):
"""shapeOfMaxSize(list_of_shapes): finds the shape that has the largest mass in the list and returns it. The shapes in the list must be of same dimension."""
"""shapeOfMaxSize(list_of_shapes): finds the shape that has the largest "
"mass in the list and returns it. The shapes in the list must be of same dimension."""
#first, check if shapes can be compared by size
ShapeMerge.dimensionOfShapes(list_of_shapes)

View File

@@ -20,7 +20,7 @@
# * *
# ***************************************************************************/
__title__="BOPTools.JoinFeatures module"
__title__ = "BOPTools.JoinFeatures module"
__author__ = "DeepSOIC"
__url__ = "http://www.freecadweb.org"
__doc__ = "Implementation of document objects (features) for connect, ebmed and cutout operations."
@@ -32,11 +32,11 @@ import Part
if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
# -------------------------- common stuff --------------------------------------------------
#-------------------------- translation-related code ----------------------------------------
#Thanks, yorik! (see forum thread "A new Part tool is being born... JoinFeatures!"
#http://forum.freecadweb.org/viewtopic.php?f=22&t=11112&start=30#p90239 )
# -------------------------- common stuff -------------------------------------
# -------------------------- translation-related code -------------------------
# Thanks, yorik! (see forum thread "A new Part tool is being born... JoinFeatures!"
# http://forum.freecadweb.org/viewtopic.php?f=22&t=11112&start=30#p90239 )
try:
_fromUtf8 = QtCore.QString.fromUtf8
@@ -53,18 +53,20 @@ if FreeCAD.GuiUp:
else:
def _translate(context, text, disambig):
return text
#--------------------------/translation-related code ----------------------------------------
# --------------------------/translation-related code -------------------------
def getParamRefine():
return FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Part/Boolean").GetBool("RefineModel")
def cmdCreateJoinFeature(name, mode):
"cmdCreateJoinFeature(name, mode): generalized implementation of GUI commands."
"""cmdCreateJoinFeature(name, mode): generalized implementation of GUI commands."""
sel = FreeCADGui.Selection.getSelectionEx()
FreeCAD.ActiveDocument.openTransaction("Create "+mode)
FreeCADGui.addModule("BOPTools.JoinFeatures")
FreeCADGui.doCommand("j = BOPTools.JoinFeatures.make{mode}(name = '{name}')".format(mode= mode, name= name))
FreeCADGui.doCommand("j = BOPTools.JoinFeatures.make{mode}(name='{name}')".format(mode=mode, name=name))
if mode == "Embed" or mode == "Cutout":
FreeCADGui.doCommand("j.Base = App.ActiveDocument."+sel[0].Object.Name)
FreeCADGui.doCommand("j.Tool = App.ActiveDocument."+sel[1].Object.Name)
@@ -73,7 +75,7 @@ def cmdCreateJoinFeature(name, mode):
sel= "[" + ", ".join(["App.ActiveDocument."+so.Object.Name for so in sel]) + "]"
))
else:
raise ValueError("cmdCreateJoinFeature: Unexpected mode {mode}".format(mode= repr(mode)))
raise ValueError("cmdCreateJoinFeature: Unexpected mode {mode}".format(mode=repr(mode)))
try:
FreeCADGui.doCommand("j.Proxy.execute(j)")
@@ -81,13 +83,16 @@ def cmdCreateJoinFeature(name, mode):
except Exception as err:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures","Computing the result failed with an error: \n\n{err}\n\n Click 'Continue' to create the feature anyway, or 'Abort' to cancel.", None)
.format(err= str(err)))
mb.setText(_translate("Part_JoinFeatures",
"Computing the result failed with an error:\n\n"
"{err}\n\n"
"Click 'Continue' to create the feature anyway, or 'Abort' to cancel.", None)
.format(err=str(err)))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
btnAbort = mb.addButton(QtGui.QMessageBox.StandardButton.Abort)
btnOK = mb.addButton(_translate("Part_JoinFeatures","Continue",None), QtGui.QMessageBox.ButtonRole.ActionRole)
btnOK = mb.addButton(_translate("Part_JoinFeatures","Continue",None),
QtGui.QMessageBox.ButtonRole.ActionRole)
mb.setDefaultButton(btnOK)
mb.exec_()
if mb.clickedButton() is btnAbort:
@@ -99,12 +104,13 @@ def cmdCreateJoinFeature(name, mode):
FreeCAD.ActiveDocument.commitTransaction()
def getIconPath(icon_dot_svg):
return icon_dot_svg
# -------------------------- /common stuff --------------------------------------------------
# -------------------------- /common stuff ------------------------------------
# -------------------------- Connect --------------------------------------------------
# -------------------------- Connect ------------------------------------------
def makeConnect(name):
'''makeConnect(name): makes an Connect object.'''
@@ -114,13 +120,18 @@ def makeConnect(name):
ViewProviderConnect(obj.ViewObject)
return obj
class FeatureConnect:
"The PartJoinFeature object"
"""The PartJoinFeature object."""
def __init__(self,obj):
obj.addProperty("App::PropertyLinkList","Objects","Connect","Object to be connectded.")
obj.addProperty("App::PropertyBool","Refine","Connect","True = refine resulting shape. False = output as is.")
obj.addProperty("App::PropertyBool","Refine","Connect",
"True = refine resulting shape. False = output as is.")
obj.Refine = getParamRefine()
obj.addProperty("App::PropertyLength","Tolerance","Connect","Tolerance when intersecting (fuzzy value). In addition to tolerances of the shapes.")
obj.addProperty("App::PropertyLength","Tolerance","Connect",
"Tolerance when intersecting (fuzzy value). "
"In addition to tolerances of the shapes.")
obj.Proxy = self
self.Type = "FeatureConnect"
@@ -133,7 +144,7 @@ class FeatureConnect:
class ViewProviderConnect:
"A View Provider for the Part Connect feature"
"""A View Provider for the Part Connect feature."""
def __init__(self,vobj):
vobj.Proxy = self
@@ -179,20 +190,23 @@ class ViewProviderConnect:
class CommandConnect:
"Command to create Connect feature"
"""Command to create Connect feature."""
def GetResources(self):
return {'Pixmap' : getIconPath("Part_JoinConnect.svg"),
return {'Pixmap': getIconPath("Part_JoinConnect.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_JoinConnect","Connect objects"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_JoinConnect","Fuses objects, taking care to preserve voids.")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_JoinConnect",
"Fuses objects, taking care to preserve voids.")}
def Activated(self):
if len(FreeCADGui.Selection.getSelectionEx()) >= 1 :
cmdCreateJoinFeature(name = "Connect", mode = "Connect")
if len(FreeCADGui.Selection.getSelectionEx()) >= 1:
cmdCreateJoinFeature(name="Connect", mode="Connect")
else:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures", "Select at least two objects, or one or more compounds, first!", None))
mb.setText(_translate("Part_JoinFeatures",
"Select at least two objects, or one or more compounds", None))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
mb.exec_()
@@ -202,10 +216,10 @@ class CommandConnect:
else:
return False
# -------------------------- /Connect --------------------------------------------------
# -------------------------- /Connect -----------------------------------------
# -------------------------- Embed --------------------------------------------------
# -------------------------- Embed --------------------------------------------
def makeEmbed(name):
@@ -216,14 +230,19 @@ def makeEmbed(name):
ViewProviderEmbed(obj.ViewObject)
return obj
class FeatureEmbed:
"The Part Embed object"
"""The Part Embed object."""
def __init__(self,obj):
obj.addProperty("App::PropertyLink","Base","Embed","Object to embed into.")
obj.addProperty("App::PropertyLink","Tool","Embed","Object to be embedded.")
obj.addProperty("App::PropertyBool","Refine","Embed","True = refine resulting shape. False = output as is.")
obj.addProperty("App::PropertyBool","Refine","Embed",
"True = refine resulting shape. False = output as is.")
obj.Refine = getParamRefine()
obj.addProperty("App::PropertyLength","Tolerance","Embed","Tolerance when intersecting (fuzzy value). In addition to tolerances of the shapes.")
obj.addProperty("App::PropertyLength","Tolerance","Embed",
"Tolerance when intersecting (fuzzy value). "
"In addition to tolerances of the shapes.")
obj.Proxy = self
self.Type = "FeatureEmbed"
@@ -236,7 +255,7 @@ class FeatureEmbed:
class ViewProviderEmbed:
"A View Provider for the Part Embed feature"
"""A View Provider for the Part Embed feature."""
def __init__(self,vobj):
vobj.Proxy = self
@@ -265,36 +284,39 @@ class ViewProviderEmbed:
FreeCAD.Console.PrintError("Error in onDelete: " + str(err))
return True
class CommandEmbed:
"Command to create Part Embed feature"
"""Command to create Part Embed feature."""
def GetResources(self):
return {'Pixmap' : getIconPath("Part_JoinEmbed.svg"),
return {'Pixmap': getIconPath("Part_JoinEmbed.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_JoinEmbed","Embed object"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_JoinEmbed","Fuses one object into another, taking care to preserve voids.")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_JoinEmbed",
"Fuses one object into another, taking care to preserve voids.")}
def Activated(self):
if len(FreeCADGui.Selection.getSelectionEx()) == 2 :
if len(FreeCADGui.Selection.getSelectionEx()) == 2:
cmdCreateJoinFeature(name = "Embed", mode = "Embed")
else:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures","Select base object, then the object to embed, and invoke this tool.", None))
mb.setText(_translate("Part_JoinFeatures",
"Select base object, then the object to embed, "
"and then invoke this tool.", None))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
mb.exec_()
def IsActive(self):
if FreeCAD.ActiveDocument:
return True
else:
return False
# -------------------------- /Embed --------------------------------------------------
# -------------------------- /Embed -------------------------------------------
# -------------------------- Cutout --------------------------------------------------
# -------------------------- Cutout -------------------------------------------
def makeCutout(name):
'''makeCutout(name): makes an Cutout object.'''
@@ -304,14 +326,18 @@ def makeCutout(name):
ViewProviderCutout(obj.ViewObject)
return obj
class FeatureCutout:
"The Part Cutout object"
"""The Part Cutout object."""
def __init__(self,obj):
obj.addProperty("App::PropertyLink","Base","Cutout","Object to be cut.")
obj.addProperty("App::PropertyLink","Tool","Cutout","Object to make cutout for.")
obj.addProperty("App::PropertyBool","Refine","Cutout","True = refine resulting shape. False = output as is.")
obj.addProperty("App::PropertyBool","Refine","Cutout",
"True = refine resulting shape. False = output as is.")
obj.Refine = getParamRefine()
obj.addProperty("App::PropertyLength","Tolerance","Cutout","Tolerance when intersecting (fuzzy value). In addition to tolerances of the shapes.")
obj.addProperty("App::PropertyLength","Tolerance","Cutout",
"Tolerance when intersecting (fuzzy value). In addition to tolerances of the shapes.")
obj.Proxy = self
self.Type = "FeatureCutout"
@@ -324,7 +350,7 @@ class FeatureCutout:
class ViewProviderCutout:
"A View Provider for the Part Cutout feature"
"""A View Provider for the Part Cutout feature."""
def __init__(self,vobj):
vobj.Proxy = self
@@ -355,20 +381,25 @@ class ViewProviderCutout:
class CommandCutout:
"Command to create PartJoinFeature in Cutout mode"
"""Command to create PartJoinFeature in Cutout mode."""
def GetResources(self):
return {'Pixmap' : getIconPath("Part_JoinCutout.svg"),
return {'Pixmap': getIconPath("Part_JoinCutout.svg"),
'MenuText': QtCore.QT_TRANSLATE_NOOP("Part_JoinCutout","Cutout for object"),
'Accel': "",
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_JoinCutout","Makes a cutout in one object to fit another object.")}
'ToolTip': QtCore.QT_TRANSLATE_NOOP("Part_JoinCutout",
"Makes a cutout in one object to fit another object.")}
def Activated(self):
if len(FreeCADGui.Selection.getSelectionEx()) == 2 :
cmdCreateJoinFeature(name = "Cutout", mode = "Cutout")
if len(FreeCADGui.Selection.getSelectionEx()) == 2:
cmdCreateJoinFeature(name="Cutout", mode="Cutout")
else:
mb = QtGui.QMessageBox()
mb.setIcon(mb.Icon.Warning)
mb.setText(_translate("Part_JoinFeatures","Select the object to make a cutout in, then the object that should fit into the cutout, and invoke this tool.", None))
mb.setText(_translate("Part_JoinFeatures",
"Select the object to make a cutout in, "
"then the object that should fit into the cutout, "
"and then invoke this tool.", None))
mb.setWindowTitle(_translate("Part_JoinFeatures","Bad selection", None))
mb.exec_()
@@ -378,9 +409,9 @@ class CommandCutout:
else:
return False
# -------------------------- /Cutout --------------------------------------------------
# -------------------------- /Cutout ------------------------------------------
def addCommands():
FreeCADGui.addCommand('Part_JoinCutout',CommandCutout())
FreeCADGui.addCommand('Part_JoinEmbed',CommandEmbed())
FreeCADGui.addCommand('Part_JoinConnect',CommandConnect())
FreeCADGui.addCommand('Part_JoinCutout', CommandCutout())
FreeCADGui.addCommand('Part_JoinEmbed', CommandEmbed())
FreeCADGui.addCommand('Part_JoinConnect', CommandConnect())