Black pathdressupdragknife

This commit is contained in:
sliptonic
2021-12-22 16:08:25 -06:00
parent 1a9374ec59
commit a3674181ae

View File

@@ -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")