diff --git a/src/Mod/Path/PathScripts/PathDressupDragknife.py b/src/Mod/Path/PathScripts/PathDressupDragknife.py index 8b0fea27c7..1f5e25e344 100644 --- a/src/Mod/Path/PathScripts/PathDressupDragknife.py +++ b/src/Mod/Path/PathScripts/PathDressupDragknife.py @@ -30,7 +30,8 @@ import PathScripts.PathGui as PathGui # lazily loaded modules from lazy_loader.lazy_loader import LazyLoader -D = LazyLoader('DraftVecUtils', globals(), 'DraftVecUtils') + +D = LazyLoader("DraftVecUtils", globals(), "DraftVecUtils") __doc__ = """Dragknife Dressup object and FreeCAD command""" @@ -43,20 +44,46 @@ def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) -movecommands = ['G1', 'G01', 'G2', 'G02', 'G3', 'G03'] -rapidcommands = ['G0', 'G00'] -arccommands = ['G2', 'G3', 'G02', 'G03'] +movecommands = ["G1", "G01", "G2", "G02", "G3", "G03"] +rapidcommands = ["G0", "G00"] +arccommands = ["G2", "G3", "G02", "G03"] currLocation = {} class ObjectDressup: - def __init__(self, obj): - obj.addProperty("App::PropertyLink", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The base path to modify")) - obj.addProperty("App::PropertyAngle", "filterAngle", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Angles less than filter angle will not receive corner actions")) - obj.addProperty("App::PropertyFloat", "offset", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Distance the point trails behind the spindle")) - obj.addProperty("App::PropertyFloat", "pivotheight", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Height to raise during corner action")) + obj.addProperty( + "App::PropertyLink", + "Base", + "Path", + QtCore.QT_TRANSLATE_NOOP("App::Property", "The base path to modify"), + ) + obj.addProperty( + "App::PropertyAngle", + "filterAngle", + "Path", + QtCore.QT_TRANSLATE_NOOP( + "App::Property", + "Angles less than filter angle will not receive corner actions", + ), + ) + obj.addProperty( + "App::PropertyFloat", + "offset", + "Path", + QtCore.QT_TRANSLATE_NOOP( + "App::Property", "Distance the point trails behind the spindle" + ), + ) + obj.addProperty( + "App::PropertyFloat", + "pivotheight", + "Path", + QtCore.QT_TRANSLATE_NOOP( + "App::Property", "Height to raise during corner action" + ), + ) obj.Proxy = self @@ -67,13 +94,17 @@ class ObjectDressup: return None def shortcut(self, queue): - '''Determines whether its shorter to twist CW or CCW to align with - the next move''' + """Determines whether its shorter to twist CW or CCW to align with + the next move""" # get the vector of the last move if queue[1].Name in arccommands: - arcLoc = FreeCAD.Vector(queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation['Z']) - radvector = arcLoc.sub(queue[1].Placement.Base) # .sub(arcLoc) # vector of chord from center to point + arcLoc = FreeCAD.Vector( + queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation["Z"] + ) + radvector = arcLoc.sub( + queue[1].Placement.Base + ) # .sub(arcLoc) # vector of chord from center to point # vector of line perp to chord. v1 = radvector.cross(FreeCAD.Vector(0, 0, 1)) else: @@ -81,7 +112,9 @@ class ObjectDressup: # get the vector of the current move if queue[0].Name in arccommands: - arcLoc = FreeCAD.Vector((queue[1].x + queue[0].I), (queue[1].y + queue[0].J), currLocation['Z']) + arcLoc = FreeCAD.Vector( + (queue[1].x + queue[0].I), (queue[1].y + queue[0].J), currLocation["Z"] + ) radvector = queue[1].Placement.Base.sub(arcLoc) # calculate arcangle v2 = radvector.cross(FreeCAD.Vector(0, 0, 1)) else: @@ -93,24 +126,36 @@ class ObjectDressup: return "CCW" def segmentAngleXY(self, prevCommand, currCommand, endpos=False, currentZ=0): - '''returns in the starting angle in radians for a Path command. + """returns in the starting angle in radians for a Path command. requires the previous command in order to calculate arcs correctly - if endpos = True, return the angle at the end of the segment.''' + if endpos = True, return the angle at the end of the segment.""" if currCommand.Name in arccommands: - arcLoc = FreeCAD.Vector((prevCommand.x + currCommand.I), (prevCommand.y + currCommand.J), currentZ) + arcLoc = FreeCAD.Vector( + (prevCommand.x + currCommand.I), + (prevCommand.y + currCommand.J), + currentZ, + ) if endpos is True: - radvector = arcLoc.sub(currCommand.Placement.Base) # Calculate vector at start of arc + radvector = arcLoc.sub( + currCommand.Placement.Base + ) # Calculate vector at start of arc else: - radvector = arcLoc.sub(prevCommand.Placement.Base) # Calculate vector at end of arc + radvector = arcLoc.sub( + prevCommand.Placement.Base + ) # Calculate vector at end of arc v1 = radvector.cross(FreeCAD.Vector(0, 0, 1)) if currCommand.Name in ["G2", "G02"]: v1 = D.rotate2D(v1, math.radians(180)) else: - v1 = currCommand.Placement.Base.sub(prevCommand.Placement.Base) # Straight segments are easy + v1 = currCommand.Placement.Base.sub( + prevCommand.Placement.Base + ) # Straight segments are easy - myAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) + myAngle = D.angle( + v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) + ) return myAngle def getIncidentAngle(self, queue): @@ -123,18 +168,20 @@ class ObjectDressup: if angleatstart < 0: angleatstart = 360 + angleatstart - incident_angle = angleatend-angleatstart + incident_angle = angleatend - angleatstart return incident_angle def arcExtension(self, obj, queue): - '''returns gcode for arc extension''' + """returns gcode for arc extension""" global currLocation # pylint: disable=global-statement results = [] offset = obj.offset # Find the center of the old arc - C = FreeCAD.Base.Vector(queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation['Z']) + C = FreeCAD.Base.Vector( + queue[2].x + queue[1].I, queue[2].y + queue[1].J, currLocation["Z"] + ) # Find radius of old arc R = math.hypot(queue[1].I, queue[1].J) @@ -165,8 +212,8 @@ class ObjectDressup: return (results, replace) def arcTwist(self, obj, queue, lastXY, twistCW=False): - '''returns gcode to do an arc move toward an arc to perform - a corner action twist. Includes lifting and plungeing the knife''' + """returns gcode to do an arc move toward an arc to perform + a corner action twist. Includes lifting and plungeing the knife""" global currLocation # pylint: disable=global-statement pivotheight = obj.pivotheight @@ -186,7 +233,9 @@ class ObjectDressup: currLocation.update(retract.Parameters) # get the center of the destination arc - arccenter = FreeCAD.Base.Vector(queue[1].x + queue[0].I, queue[1].y + queue[0].J, currLocation["Z"]) + arccenter = FreeCAD.Base.Vector( + queue[1].x + queue[0].I, queue[1].y + queue[0].J, currLocation["Z"] + ) # The center of the twist arc is the old line end point. C = queue[1].Placement.Base @@ -196,7 +245,9 @@ class ObjectDressup: # find angle of original center to startpoint v1 = queue[1].Placement.Base.sub(arccenter) - segAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) + segAngle = D.angle( + v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) + ) # Find angle subtended by the offset theta = offset / R @@ -210,14 +261,21 @@ class ObjectDressup: # calculate endpoints Bx = arccenter.x + R * math.cos(newangle) By = arccenter.y + R * math.sin(newangle) - endpointvector = FreeCAD.Base.Vector(Bx, By, currLocation['Z']) + endpointvector = FreeCAD.Base.Vector(Bx, By, currLocation["Z"]) # calculate IJ offsets of twist arc from current position. offsetvector = C.sub(lastXY) # add G2/G3 move arcmove = Path.Command( - arcdir, {"X": endpointvector.x, "Y": endpointvector.y, "I": offsetvector.x, "J": offsetvector.y}) + arcdir, + { + "X": endpointvector.x, + "Y": endpointvector.y, + "I": offsetvector.x, + "J": offsetvector.y, + }, + ) results.append(arcmove) currLocation.update(arcmove.Parameters) @@ -230,11 +288,13 @@ class ObjectDressup: offsetv = arccenter.sub(endpointvector) replace = Path.Command( - queue[0].Name, {"X": queue[0].X, "Y": queue[0].Y, "I": offsetv.x, "J": offsetv.y}) + queue[0].Name, + {"X": queue[0].X, "Y": queue[0].Y, "I": offsetv.x, "J": offsetv.y}, + ) return (results, replace) def lineExtension(self, obj, queue): - '''returns gcode for line extension''' + """returns gcode for line extension""" global currLocation # pylint: disable=global-statement offset = float(obj.offset) @@ -243,14 +303,16 @@ class ObjectDressup: v1 = queue[1].Placement.Base.sub(queue[2].Placement.Base) # extend the current segment to comp for offset - segAngle = D.angle(v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) + segAngle = D.angle( + v1, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) + ) xoffset = math.cos(segAngle) * offset yoffset = math.sin(segAngle) * offset newX = currLocation["X"] + xoffset newY = currLocation["Y"] + yoffset - extendcommand = Path.Command('G1', {"X": newX, "Y": newY}) + extendcommand = Path.Command("G1", {"X": newX, "Y": newY}) results.append(extendcommand) currLocation.update(extendcommand.Parameters) @@ -259,8 +321,8 @@ class ObjectDressup: return (results, replace) def lineTwist(self, obj, queue, lastXY, twistCW=False): - '''returns gcode to do an arc move toward a line to perform - a corner action twist. Includes lifting and plungeing the knife''' + """returns gcode to do an arc move toward a line to perform + a corner action twist. Includes lifting and plungeing the knife""" global currLocation # pylint: disable=global-statement pivotheight = obj.pivotheight offset = obj.offset @@ -285,7 +347,9 @@ class ObjectDressup: v2 = queue[0].Placement.Base.sub(queue[1].Placement.Base) # calc arc endpoints to twist to - segAngle = D.angle(v2, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1)) + segAngle = D.angle( + v2, FreeCAD.Base.Vector(1, 0, 0), FreeCAD.Base.Vector(0, 0, -1) + ) xoffset = math.cos(segAngle) * offset yoffset = math.sin(segAngle) * offset newX = queue[1].x + xoffset @@ -297,7 +361,8 @@ class ObjectDressup: # add the arc move arcmove = Path.Command( - arcdir, {"X": newX, "Y": newY, "I": I, "J": J}) # add G2/G3 move + arcdir, {"X": newX, "Y": newY, "I": I, "J": J} + ) # add G2/G3 move results.append(arcmove) currLocation.update(arcmove.Parameters) @@ -335,11 +400,11 @@ class ObjectDressup: continue if curCommand.x is None: - curCommand.x = currLocation['X'] + curCommand.x = currLocation["X"] if curCommand.y is None: - curCommand.y = currLocation['Y'] + curCommand.y = currLocation["Y"] if curCommand.z is None: - curCommand.z = currLocation['Z'] + curCommand.z = currLocation["Z"] # rapid retract triggers exit move, else just add to output if curCommand.Name in rapidcommands: @@ -348,7 +413,7 @@ class ObjectDressup: tempqueue = queue tempqueue.insert(0, curCommand) - if queue[1].Name in ['G01', 'G1']: + if queue[1].Name in ["G01", "G1"]: temp = self.lineExtension(obj, tempqueue) newpath.extend(temp[0]) lastxy = temp[0][-1].Placement.Base @@ -395,7 +460,7 @@ class ObjectDressup: # # DO THE EXTENSION # - if queue[1].Name in ['G01', 'G1']: + if queue[1].Name in ["G01", "G1"]: temp = self.lineExtension(obj, queue) newpath.extend(temp[0]) replace = temp[1] @@ -410,7 +475,7 @@ class ObjectDressup: # # DO THE TWIST # - if queue[0].Name in ['G01', 'G1']: + if queue[0].Name in ["G01", "G1"]: temp = self.lineTwist(obj, queue, lastxy, twistCW) replace = temp[1] newpath.extend(temp[0]) @@ -433,15 +498,22 @@ class ObjectDressup: class TaskPanel: - def __init__(self, obj): self.obj = obj self.form = FreeCADGui.PySideUic.loadUi(":/panels/DragKnifeEdit.ui") - self.filterAngle = PathGui.QuantitySpinBox(self.form.filterAngle, obj, 'filterAngle') - self.offsetDistance = PathGui.QuantitySpinBox(self.form.offsetDistance, obj, 'offset') - self.pivotHeight = PathGui.QuantitySpinBox(self.form.pivotHeight, obj, 'pivotheight') + self.filterAngle = PathGui.QuantitySpinBox( + self.form.filterAngle, obj, "filterAngle" + ) + self.offsetDistance = PathGui.QuantitySpinBox( + self.form.offsetDistance, obj, "offset" + ) + self.pivotHeight = PathGui.QuantitySpinBox( + self.form.pivotHeight, obj, "pivotheight" + ) - FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupDragKnife", "Edit Dragknife Dress-up")) + FreeCAD.ActiveDocument.openTransaction( + translate("Path_DressupDragKnife", "Edit Dragknife Dress-up") + ) def reject(self): FreeCAD.ActiveDocument.abortTransaction() @@ -483,7 +555,6 @@ class TaskPanel: class ViewProviderDressup: - def __init__(self, vobj): self.Object = vobj.Object @@ -537,9 +608,16 @@ class CommandDressupDragknife: # pylint: disable=no-init def GetResources(self): - return {'Pixmap': 'Path_Dressup', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_DressupDragKnife", "DragKnife Dress-up"), - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_DressupDragKnife", "Modifies a path to add dragknife corner actions")} + return { + "Pixmap": "Path_Dressup", + "MenuText": QtCore.QT_TRANSLATE_NOOP( + "Path_DressupDragKnife", "DragKnife Dress-up" + ), + "ToolTip": QtCore.QT_TRANSLATE_NOOP( + "Path_DressupDragKnife", + "Modifies a path to add dragknife corner actions", + ), + } def IsActive(self): if FreeCAD.ActiveDocument is not None: @@ -554,33 +632,46 @@ class CommandDressupDragknife: selection = FreeCADGui.Selection.getSelection() if len(selection) != 1: FreeCAD.Console.PrintError( - translate("Path_DressupDragKnife", "Please select one path object")+"\n") + translate("Path_DressupDragKnife", "Please select one path object") + + "\n" + ) return if not selection[0].isDerivedFrom("Path::Feature"): FreeCAD.Console.PrintError( - translate("Path_DressupDragKnife", "The selected object is not a path")+"\n") + translate("Path_DressupDragKnife", "The selected object is not a path") + + "\n" + ) return if selection[0].isDerivedFrom("Path::FeatureCompoundPython"): FreeCAD.Console.PrintError( - translate("Path_DressupDragKnife", "Please select a Path object")) + translate("Path_DressupDragKnife", "Please select a Path object") + ) return # everything ok! - FreeCAD.ActiveDocument.openTransaction(translate("Path_DressupDragKnife", "Create Dress-up")) + FreeCAD.ActiveDocument.openTransaction( + translate("Path_DressupDragKnife", "Create Dress-up") + ) FreeCADGui.addModule("PathScripts.PathDressupDragknife") FreeCADGui.addModule("PathScripts.PathUtils") - FreeCADGui.doCommand('obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","DragknifeDressup")') - FreeCADGui.doCommand('PathScripts.PathDressupDragknife.ObjectDressup(obj)') - FreeCADGui.doCommand('base = FreeCAD.ActiveDocument.' + selection[0].Name) - FreeCADGui.doCommand('job = PathScripts.PathUtils.findParentJob(base)') - FreeCADGui.doCommand('obj.Base = base') - FreeCADGui.doCommand('job.Proxy.addOperation(obj, base)') - FreeCADGui.doCommand('obj.ViewObject.Proxy = PathScripts.PathDressupDragknife.ViewProviderDressup(obj.ViewObject)') - FreeCADGui.doCommand('Gui.ActiveDocument.getObject(base.Name).Visibility = False') - FreeCADGui.doCommand('obj.filterAngle = 20') - FreeCADGui.doCommand('obj.offset = 2') - FreeCADGui.doCommand('obj.pivotheight = 4') - FreeCADGui.doCommand('obj.ViewObject.Document.setEdit(obj.ViewObject, 0)') + FreeCADGui.doCommand( + 'obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","DragknifeDressup")' + ) + FreeCADGui.doCommand("PathScripts.PathDressupDragknife.ObjectDressup(obj)") + FreeCADGui.doCommand("base = FreeCAD.ActiveDocument." + selection[0].Name) + FreeCADGui.doCommand("job = PathScripts.PathUtils.findParentJob(base)") + FreeCADGui.doCommand("obj.Base = base") + FreeCADGui.doCommand("job.Proxy.addOperation(obj, base)") + FreeCADGui.doCommand( + "obj.ViewObject.Proxy = PathScripts.PathDressupDragknife.ViewProviderDressup(obj.ViewObject)" + ) + FreeCADGui.doCommand( + "Gui.ActiveDocument.getObject(base.Name).Visibility = False" + ) + FreeCADGui.doCommand("obj.filterAngle = 20") + FreeCADGui.doCommand("obj.offset = 2") + FreeCADGui.doCommand("obj.pivotheight = 4") + FreeCADGui.doCommand("obj.ViewObject.Document.setEdit(obj.ViewObject, 0)") FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() @@ -588,6 +679,6 @@ class CommandDressupDragknife: if FreeCAD.GuiUp: # register the FreeCAD command - FreeCADGui.addCommand('Path_DressupDragKnife', CommandDressupDragknife()) + FreeCADGui.addCommand("Path_DressupDragKnife", CommandDressupDragknife()) FreeCAD.Console.PrintLog("Loading Path_DressupDragKnife... done\n")