CAM: LeadInOut - Fix overtravel
This commit is contained in:
@@ -162,6 +162,7 @@ class ObjectDressup:
|
||||
"Path Lead-out",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Move end point"),
|
||||
)
|
||||
|
||||
obj.Proxy = self
|
||||
|
||||
def dumps(self):
|
||||
@@ -201,7 +202,7 @@ class ObjectDressup:
|
||||
return None
|
||||
if isinstance(obj.Base, list) and obj.Base and obj.Base[0].isDerivedFrom("Path::Feature"):
|
||||
return self.getBaseWithTC(obj.Base[0])
|
||||
elif not isinstance(obj.Base, list) and obj.Base.isDerivedFrom("Path::Feature"):
|
||||
if not isinstance(obj.Base, list) and obj.Base.isDerivedFrom("Path::Feature"):
|
||||
return self.getBaseWithTC(obj.Base)
|
||||
return None
|
||||
|
||||
@@ -251,8 +252,18 @@ class ObjectDressup:
|
||||
)
|
||||
return
|
||||
|
||||
self.invertAlt = False
|
||||
self.job = PathUtils.findParentJob(obj)
|
||||
self.horizFeed = self.toolController.HorizFeed.Value
|
||||
self.vertFeed = self.toolController.VertFeed.Value
|
||||
self.clearanceHeight = self.baseOp.ClearanceHeight.Value
|
||||
self.safeHeight = self.baseOp.SafeHeight.Value
|
||||
self.startDepth = self.baseOp.StartDepth.Value
|
||||
self.side = self.baseOp.Side if hasattr(self.baseOp, "Side") else "Inside"
|
||||
if hasattr(self.baseOp, "Direction") and self.baseOp.Direction in ("CW", "CCW"):
|
||||
self.direction = self.baseOp.Direction
|
||||
else:
|
||||
self.direction = "CCW"
|
||||
self.entranceFeed = self.toolController.LeadInFeed.Value
|
||||
self.exitFeed = self.toolController.LeadOutFeed.Value
|
||||
|
||||
@@ -424,23 +435,30 @@ class ObjectDressup:
|
||||
# Get direction for lead-in/lead-out in XY plane
|
||||
def getLeadDir(self, obj, invert=False):
|
||||
output = math.pi / 2
|
||||
side = self.baseOp.Side if hasattr(self.baseOp, "Side") else "Inside"
|
||||
direction = self.baseOp.Direction if hasattr(self.baseOp, "Direction") else "CCW"
|
||||
side = self.side
|
||||
direction = self.direction
|
||||
if (side == "Inside" and direction == "CW") or (side == "Outside" and direction == "CCW"):
|
||||
output = -output
|
||||
if invert:
|
||||
output = -output
|
||||
if self.invertAlt:
|
||||
output = -output
|
||||
|
||||
return output
|
||||
|
||||
# Get direction of original path
|
||||
def getPathDir(self, obj):
|
||||
# only CW or CCW is matter
|
||||
direction = self.baseOp.Direction if hasattr(self.baseOp, "Direction") else "CCW"
|
||||
def getArcPathDir(self, obj, cmdName):
|
||||
# only CW/CCW and G2/G3 matters
|
||||
direction = self.direction
|
||||
output = math.pi / 2
|
||||
if direction == "CW":
|
||||
output = -output
|
||||
|
||||
if cmdName == "G2" and direction == "CCW":
|
||||
output = -output
|
||||
elif cmdName == "G3" and direction == "CW":
|
||||
output = -output
|
||||
|
||||
return output
|
||||
|
||||
# Create safety movements to start point
|
||||
@@ -453,9 +471,7 @@ class ObjectDressup:
|
||||
|
||||
if first or (distance > obj.RetractThreshold):
|
||||
# move to clearance height
|
||||
commands.append(
|
||||
PathLanguage.MoveStraight(None, "G00", {"Z": self.baseOp.ClearanceHeight.Value})
|
||||
)
|
||||
commands.append(PathLanguage.MoveStraight(None, "G00", {"Z": self.clearanceHeight}))
|
||||
|
||||
# move to mill position at clearance height
|
||||
commands.append(PathLanguage.MoveStraight(None, "G00", {"X": pos.x, "Y": pos.y}))
|
||||
@@ -466,9 +482,7 @@ class ObjectDressup:
|
||||
commands.append(PathLanguage.MoveStraight(None, "G00", {"Z": pos.z}))
|
||||
else:
|
||||
# move to mill position in two steps
|
||||
commands.append(
|
||||
PathLanguage.MoveStraight(None, "G00", {"Z": self.baseOp.SafeHeight.Value})
|
||||
)
|
||||
commands.append(PathLanguage.MoveStraight(None, "G00", {"Z": self.safeHeight}))
|
||||
commands.append(
|
||||
PathLanguage.MoveStraight(None, "G01", {"Z": pos.z, "F": self.vertFeed})
|
||||
)
|
||||
@@ -491,7 +505,7 @@ class ObjectDressup:
|
||||
# Create commands with movements to clearance height
|
||||
def getTravelEnd(self, obj):
|
||||
commands = []
|
||||
z = self.baseOp.ClearanceHeight.Value
|
||||
z = self.clearanceHeight
|
||||
commands.append(PathLanguage.MoveStraight(None, "G00", {"Z": z}))
|
||||
|
||||
return commands
|
||||
@@ -535,10 +549,9 @@ class ObjectDressup:
|
||||
return command
|
||||
|
||||
# Get optimal step angle for iteration ArcZ
|
||||
def getStepAngleArcZ(self, obj, radius):
|
||||
job = PathUtils.findParentJob(obj)
|
||||
minArcLength = job.GeometryTolerance.Value * 2
|
||||
maxArcLength = 1
|
||||
def getStepAngleArcZ(self, obj, radius, segm=1):
|
||||
minArcLength = self.job.GeometryTolerance.Value * 2
|
||||
maxArcLength = segm
|
||||
stepAngle = math.pi / 60
|
||||
stepArcLength = stepAngle * radius
|
||||
if stepArcLength > maxArcLength:
|
||||
@@ -681,7 +694,7 @@ class ObjectDressup:
|
||||
elif styleIn == "LineZ":
|
||||
# tangent vector in XY plane
|
||||
# normal vector is vertical
|
||||
normalLengthMax = self.baseOp.SafeHeight.Value - begin.z
|
||||
normalLengthMax = self.safeHeight - begin.z
|
||||
normalLength = math.sin(angleIn) * length
|
||||
# do not exceed Normal vector max length
|
||||
normalLength = min(normalLength, normalLengthMax)
|
||||
@@ -692,12 +705,12 @@ class ObjectDressup:
|
||||
lead.append(self.createStraightMove(obj, lineBegin, begin, self.entranceFeed))
|
||||
|
||||
# prepend "ArcZ" style lead-in - vertical Arc
|
||||
# Should be applied only on straight Path segment
|
||||
# Should be applied only on straight Path segment or open profile
|
||||
elif styleIn == "ArcZ":
|
||||
# tangent vector in XY plane
|
||||
# normal vector is vertical
|
||||
arcRadius = length
|
||||
normalLengthMax = self.baseOp.SafeHeight.Value - begin.z
|
||||
normalLengthMax = self.safeHeight - begin.z
|
||||
normalLength = arcRadius * (1 - math.cos(angleIn))
|
||||
if normalLength > normalLengthMax:
|
||||
# do not exceed Normal vector max length
|
||||
@@ -720,7 +733,7 @@ class ObjectDressup:
|
||||
if inInstrPrev and inInstrPrev.z() > begin.z:
|
||||
begin.z = inInstrPrev.z()
|
||||
else:
|
||||
begin.z = self.baseOp.StartDepth.Value
|
||||
begin.z = self.startDepth
|
||||
lead[0].setPositionBegin(begin)
|
||||
|
||||
elif styleIn == "Helix":
|
||||
@@ -732,7 +745,7 @@ class ObjectDressup:
|
||||
halfStepZ = (posPrevZ - beginZ) / 2
|
||||
begin.z += halfStepZ
|
||||
else:
|
||||
begin.z = self.baseOp.StartDepth.Value
|
||||
begin.z = self.startDepth
|
||||
|
||||
if obj.StyleOut == "Helix" and outInstrPrev:
|
||||
"""change Z for previous helix lead-out
|
||||
@@ -821,7 +834,7 @@ class ObjectDressup:
|
||||
elif obj.StyleOut == "LineZ":
|
||||
# tangent vector in XY plane
|
||||
# normal vector is vertical
|
||||
normalLengthMax = self.baseOp.StartDepth.Value - end.z
|
||||
normalLengthMax = self.startDepth - end.z
|
||||
normalLength = math.sin(angleOut) * length
|
||||
# do not exceed Normal vector max length
|
||||
normalLength = min(normalLength, normalLengthMax)
|
||||
@@ -837,7 +850,7 @@ class ObjectDressup:
|
||||
# tangent vector in XY plane
|
||||
# normal vector is vertical
|
||||
arcRadius = length
|
||||
normalLengthMax = self.baseOp.SafeHeight.Value - end.z
|
||||
normalLengthMax = self.safeHeight - end.z
|
||||
normalLength = arcRadius * (1 - math.cos(angleOut))
|
||||
if normalLength > normalLengthMax:
|
||||
# do not exceed Normal vector max length
|
||||
@@ -855,7 +868,7 @@ class ObjectDressup:
|
||||
if outInstrPrev and outInstrPrev.positionBegin().z > end.z:
|
||||
lead[-1].param["Z"] = outInstrPrev.positionBegin().z
|
||||
else:
|
||||
lead[-1].param["Z"] = self.baseOp.StartDepth.Value
|
||||
lead[-1].param["Z"] = self.startDepth
|
||||
|
||||
# append travel moves to clearance height after finishing all profiles
|
||||
if last and obj.StyleOut != "No Retract":
|
||||
@@ -881,43 +894,55 @@ class ObjectDressup:
|
||||
return None
|
||||
|
||||
# Get last index of mill command in whole Path
|
||||
def findLastCuttingMoveIndex(self, source):
|
||||
for i in range(len(source) - 1, -1, -1):
|
||||
if self.isCuttingMove(source[i]):
|
||||
def findLastCuttingMoveIndex(self):
|
||||
for i in range(len(self.source) - 1, -1, -1):
|
||||
if self.isCuttingMove(self.source[i]):
|
||||
return i
|
||||
|
||||
return None
|
||||
|
||||
# Get finish index of mill command for one profile
|
||||
def findLastCutMultiProfileIndex(self, source, startIndex):
|
||||
if startIndex >= len(source):
|
||||
return len(source) - 1
|
||||
for i in range(startIndex, len(source), +1):
|
||||
if not self.isCuttingMove(source[i]):
|
||||
def findLastCutMultiProfileIndex(self):
|
||||
startIndex = self.firstMillIndex
|
||||
if startIndex >= len(self.source):
|
||||
return len(self.source) - 1
|
||||
for i in range(startIndex, len(self.source), +1):
|
||||
if not self.isCuttingMove(self.source[i]):
|
||||
return i - 1
|
||||
|
||||
return i
|
||||
|
||||
# Increase travel length from 'begin'
|
||||
def getOvertravelIn(self, obj, source, length, start, end):
|
||||
startPoint = source[start].positionBegin()
|
||||
endPoint = source[end].positionEnd()
|
||||
def isProfileClosed(self):
|
||||
start = self.firstMillIndex
|
||||
end = self.lastMillIndex
|
||||
startPoint = self.source[start].positionBegin()
|
||||
endPoint = self.source[end].positionEnd()
|
||||
|
||||
if Path.Geom.pointsCoincide(startPoint, endPoint):
|
||||
self.closedProfile = True
|
||||
else:
|
||||
self.closedProfile = False
|
||||
|
||||
# Increase travel length from 'begin', take commands from profile 'end'
|
||||
def getOvertravelIn(self, obj, length):
|
||||
start = self.firstMillIndex
|
||||
end = self.lastMillIndex
|
||||
|
||||
if self.closedProfile:
|
||||
# closed profile
|
||||
# get extra commands from end of the closed profile
|
||||
measuredLength = 0
|
||||
for i, instr in enumerate(reversed(source[start : end + 1])):
|
||||
for i, instr in enumerate(reversed(self.source[start : end + 1])):
|
||||
instrLength = instr.pathLength()
|
||||
|
||||
if Path.Geom.isRoughly(measuredLength + instrLength, length, 1):
|
||||
if Path.Geom.isRoughly(measuredLength + instrLength, length):
|
||||
# get needed length without needing to cut last command
|
||||
commands = source[end - i : end + 1]
|
||||
commands = self.source[end - i : end + 1]
|
||||
return commands
|
||||
|
||||
elif measuredLength + instrLength > length:
|
||||
# measured length exceeds needed length and needs cut command
|
||||
commands = source[end - i + 1 : end + 1]
|
||||
commands = self.source[end - i + 1 : end + 1]
|
||||
newLength = length - measuredLength
|
||||
newInstr = self.cutInstrBegin(obj, instr, newLength)
|
||||
commands.insert(0, newInstr)
|
||||
@@ -928,33 +953,32 @@ class ObjectDressup:
|
||||
else:
|
||||
# open profile
|
||||
# extend first move
|
||||
instr = source[start]
|
||||
instr = self.source[start]
|
||||
newLength = length + instr.pathLength()
|
||||
newInstr = self.cutInstrBegin(obj, instr, newLength)
|
||||
return [newInstr]
|
||||
|
||||
return None
|
||||
|
||||
# Increase travel length from end
|
||||
def getOvertravelOut(self, obj, source, length, start, end):
|
||||
startPoint = source[start].positionBegin()
|
||||
endPoint = source[end].positionEnd()
|
||||
|
||||
if Path.Geom.pointsCoincide(startPoint, endPoint):
|
||||
# Increase travel length from end, take commands from profile start
|
||||
def getOvertravelOut(self, obj, length):
|
||||
start = self.firstMillIndex
|
||||
end = self.lastMillIndex
|
||||
if self.closedProfile:
|
||||
# closed profile
|
||||
# get extra commands from begin of the closed profile
|
||||
measuredLength = 0
|
||||
for i, instr in enumerate(source[start:end]):
|
||||
for i, instr in enumerate(self.source[start : end + 1]):
|
||||
instrLength = instr.pathLength()
|
||||
|
||||
if Path.Geom.isRoughly(measuredLength + instrLength, length, 1):
|
||||
if Path.Geom.isRoughly(measuredLength + instrLength, length):
|
||||
# get needed length without needing to cut last command
|
||||
commands = source[start : start + i + 1]
|
||||
commands = self.source[start : start + i + 1]
|
||||
return commands
|
||||
|
||||
elif measuredLength + instrLength > length:
|
||||
# measured length exceeds needed length and needs cut command
|
||||
commands = source[start : start + i]
|
||||
commands = self.source[start : start + i]
|
||||
newLength = length - measuredLength
|
||||
newInstr = self.cutInstrEnd(obj, instr, newLength)
|
||||
commands.append(newInstr)
|
||||
@@ -965,7 +989,7 @@ class ObjectDressup:
|
||||
else:
|
||||
# open profile
|
||||
# extend last move
|
||||
instr = source[end]
|
||||
instr = self.source[end]
|
||||
newLength = length + instr.pathLength()
|
||||
newInstr = self.cutInstrEnd(obj, instr, newLength)
|
||||
return [newInstr]
|
||||
@@ -973,25 +997,29 @@ class ObjectDressup:
|
||||
return None
|
||||
|
||||
# Cut travel end by distance (negative overtravel out)
|
||||
def cutTravelEnd(self, obj, source, cutLength):
|
||||
def cutTravelEnd(self, obj, commands, cutLength):
|
||||
measuredLength = 0
|
||||
for i, instr in enumerate(reversed(commands)):
|
||||
if instr.positionBegin() is None:
|
||||
# workaround if cut whole profile by negative offset
|
||||
cmds = commands[:-i]
|
||||
newInstr = self.cutInstrEnd(obj, commands[-i], 0.1)
|
||||
cmds.append(newInstr)
|
||||
return cmds
|
||||
|
||||
for i, instr in enumerate(reversed(source)):
|
||||
instrLength = instr.pathLength()
|
||||
measuredLength += instrLength
|
||||
|
||||
if Path.Geom.isRoughly(measuredLength, cutLength):
|
||||
# get needed length and not need to cut any command
|
||||
commands = source[: -i - 1]
|
||||
return commands
|
||||
return commands[: -i - 1]
|
||||
|
||||
elif measuredLength > cutLength:
|
||||
# measured length exceed needed cut length and need cut command
|
||||
commands = source[: -i - 1]
|
||||
cmds = commands[: -i - 1]
|
||||
newLength = measuredLength - cutLength
|
||||
newInstr = self.cutInstrEnd(obj, instr, newLength)
|
||||
commands.append(newInstr)
|
||||
return commands
|
||||
cmds.append(newInstr)
|
||||
return cmds
|
||||
|
||||
return None
|
||||
|
||||
@@ -1010,6 +1038,7 @@ class ObjectDressup:
|
||||
|
||||
# Cut arc move from begin
|
||||
elif instr.isArc():
|
||||
cmdName = instr.cmd
|
||||
angleTangent = instr.anglesOfTangents()[0]
|
||||
arcBegin = instr.positionBegin()
|
||||
arcOffset = App.Vector(instr.i(), instr.j(), instr.k())
|
||||
@@ -1018,9 +1047,10 @@ class ObjectDressup:
|
||||
tangentLength = math.sin(arcAngle) * arcRadius
|
||||
normalLength = arcRadius * (1 - math.cos(arcAngle))
|
||||
tangent = self.angleToVector(angleTangent) * tangentLength
|
||||
normal = self.angleToVector(angleTangent + self.getPathDir(obj)) * normalLength
|
||||
normal = (
|
||||
self.angleToVector(angleTangent + self.getArcPathDir(obj, cmdName)) * normalLength
|
||||
)
|
||||
arcEnd = arcBegin + tangent + normal
|
||||
cmdName = "G2" if instr.isCW() else "G3"
|
||||
command = self.createArcMoveN(obj, arcBegin, arcEnd, arcOffset, cmdName, self.horizFeed)
|
||||
|
||||
return command
|
||||
@@ -1040,6 +1070,7 @@ class ObjectDressup:
|
||||
|
||||
# Cut arc move from begin
|
||||
elif instr.isArc():
|
||||
cmdName = instr.cmd
|
||||
angleTangent = instr.anglesOfTangents()[1]
|
||||
arcEnd = instr.positionEnd()
|
||||
arcCenter = instr.xyCenter()
|
||||
@@ -1048,10 +1079,11 @@ class ObjectDressup:
|
||||
tangentLength = math.sin(arcAngle) * arcRadius
|
||||
normalLength = arcRadius * (1 - math.cos(arcAngle))
|
||||
tangent = -self.angleToVector(angleTangent) * tangentLength
|
||||
normal = self.angleToVector(angleTangent + self.getPathDir(obj)) * normalLength
|
||||
normal = (
|
||||
self.angleToVector(angleTangent + self.getArcPathDir(obj, cmdName)) * normalLength
|
||||
)
|
||||
arcBegin = arcEnd + tangent + normal
|
||||
arcOffset = arcCenter - arcBegin
|
||||
cmdName = "G2" if instr.isCW() else "G3"
|
||||
command = self.createArcMoveN(obj, arcBegin, arcEnd, arcOffset, cmdName, self.horizFeed)
|
||||
return command
|
||||
|
||||
@@ -1059,20 +1091,22 @@ class ObjectDressup:
|
||||
|
||||
def generateLeadInOutCurve(self, obj):
|
||||
source = PathLanguage.Maneuver.FromPath(PathUtils.getPathWithPlacement(obj.Base)).instr
|
||||
self.source = source
|
||||
maneuver = PathLanguage.Maneuver()
|
||||
|
||||
# Knowing whether a given instruction is the first cutting move is easy,
|
||||
# we just use a flag and set it to false afterwards. To find the last
|
||||
# cutting move we need to search the list in reverse order.
|
||||
|
||||
commands = []
|
||||
first = True # prepare first move at clearance height
|
||||
firstMillIndex = None # Index start mill instruction for one profile
|
||||
lastCuttingMoveIndex = self.findLastCuttingMoveIndex(source)
|
||||
inInstrPrev = None
|
||||
outInstrPrev = None
|
||||
self.firstMillIndex = None # Index start mill instruction for one profile
|
||||
self.lastMillIndex = None # Index end mill instruction for one profile
|
||||
self.lastCuttingMoveIndex = self.findLastCuttingMoveIndex()
|
||||
inInstrPrev = None # for RetractThreshold
|
||||
outInstrPrev = None # for RetractThreshold
|
||||
measuredLength = 0 # for negative OffsetIn
|
||||
skipCounter = 0 # for negative OffsetIn
|
||||
commands = []
|
||||
moveDir = None
|
||||
|
||||
# Process all instructions
|
||||
@@ -1105,8 +1139,17 @@ class ObjectDressup:
|
||||
if obj.LeadIn or obj.LeadOut:
|
||||
# can not skip leadin if leadout
|
||||
|
||||
# Process negative Offset Lead-In (cut travel from begin)
|
||||
self.firstMillIndex = i if self.firstMillIndex is None else self.firstMillIndex
|
||||
self.lastMillIndex = (
|
||||
self.findLastCutMultiProfileIndex()
|
||||
if self.lastMillIndex is None
|
||||
else self.lastMillIndex
|
||||
)
|
||||
self.isProfileClosed()
|
||||
|
||||
overtravelIn = None
|
||||
if obj.OffsetIn.Value < 0 and obj.StyleIn != "No Retract":
|
||||
# Process negative Offset Lead-In (cut travel from begin)
|
||||
if measuredLength <= abs(obj.OffsetIn.Value):
|
||||
# skip mill instruction
|
||||
skipCounter += 1 # count skipped instructions
|
||||
@@ -1117,18 +1160,9 @@ class ObjectDressup:
|
||||
newLength = measuredLength - abs(obj.OffsetIn.Value)
|
||||
instr = self.cutInstrBegin(obj, instr, newLength)
|
||||
|
||||
# Process positive offset Lead-In (overtravel)
|
||||
firstMillIndex = i
|
||||
lastMillIndex = self.findLastCutMultiProfileIndex(source, i + 1)
|
||||
overtravelIn = None
|
||||
if obj.OffsetIn.Value > 0 and obj.StyleIn != "No Retract":
|
||||
overtravelIn = self.getOvertravelIn(
|
||||
obj,
|
||||
source,
|
||||
obj.OffsetIn.Value,
|
||||
firstMillIndex,
|
||||
lastMillIndex,
|
||||
)
|
||||
elif obj.OffsetIn.Value > 0 and obj.StyleIn != "No Retract":
|
||||
# Process positive offset Lead-In (overtravel)
|
||||
overtravelIn = self.getOvertravelIn(obj, obj.OffsetIn.Value)
|
||||
if overtravelIn:
|
||||
commands.extend(
|
||||
self.getLeadStart(
|
||||
@@ -1140,7 +1174,6 @@ class ObjectDressup:
|
||||
commands.extend(
|
||||
self.getLeadStart(obj, instr, first, inInstrPrev, outInstrPrev)
|
||||
)
|
||||
firstMillIndex = i if not firstMillIndex else firstMillIndex
|
||||
inInstrPrev = commands[-1]
|
||||
first = False
|
||||
|
||||
@@ -1148,10 +1181,9 @@ class ObjectDressup:
|
||||
commands.append(instr)
|
||||
|
||||
# Process Lead-Out
|
||||
last = bool(i == lastCuttingMoveIndex)
|
||||
last = bool(i == self.lastCuttingMoveIndex)
|
||||
if (last or not self.isCuttingMove(source[i + 1])) and obj.LeadOut:
|
||||
measuredLength = 0 # reset measured length for last profile
|
||||
lastMillIndex = i # index last mill instruction for last profile
|
||||
|
||||
# Process negative Offset Lead-Out (cut travel from end)
|
||||
if obj.OffsetOut.Value < 0 and obj.StyleOut != "No Retract":
|
||||
@@ -1159,14 +1191,7 @@ class ObjectDressup:
|
||||
|
||||
# Process positive Offset Lead-Out (overtravel)
|
||||
if obj.OffsetOut.Value > 0 and obj.StyleOut != "No Retract":
|
||||
overtravelOut = self.getOvertravelOut(
|
||||
obj,
|
||||
source,
|
||||
obj.OffsetOut.Value,
|
||||
firstMillIndex,
|
||||
lastMillIndex,
|
||||
)
|
||||
firstMillIndex = None
|
||||
overtravelOut = self.getOvertravelOut(obj, obj.OffsetOut.Value)
|
||||
if overtravelOut:
|
||||
commands.extend(overtravelOut)
|
||||
|
||||
@@ -1180,6 +1205,10 @@ class ObjectDressup:
|
||||
else:
|
||||
outInstrPrev = instr
|
||||
|
||||
self.firstMillIndex = None
|
||||
self.lastMillIndex = None
|
||||
self.invertAlt = not self.invertAlt if getattr(obj, "InvertAlt", None) else False
|
||||
|
||||
maneuver.addInstructions(commands)
|
||||
return maneuver.toPath()
|
||||
|
||||
@@ -1198,8 +1227,6 @@ class TaskDressupLeadInOut(SimpleEditPanel):
|
||||
def setupSpinBoxes(self):
|
||||
self.connectWidget("InvertIn", self.form.chkInvertDirectionIn)
|
||||
self.connectWidget("InvertOut", self.form.chkInvertDirectionOut)
|
||||
self.connectWidget("PercentageRadiusIn", self.form.dspPercentageRadiusIn)
|
||||
self.connectWidget("PercentageRadiusOut", self.form.dspPercentageRadiusOut)
|
||||
self.connectWidget("StyleIn", self.form.cboStyleIn)
|
||||
self.connectWidget("StyleOut", self.form.cboStyleOut)
|
||||
self.radiusIn = PathGuiUtil.QuantitySpinBox(self.form.dspRadiusIn, self.obj, "RadiusIn")
|
||||
@@ -1384,7 +1411,12 @@ class CommandPathDressupLeadInOut:
|
||||
return False
|
||||
if not selection[0].isDerivedFrom("Path::Feature"):
|
||||
return False
|
||||
if selection[0].Name.startswith("Job"):
|
||||
baseOp = PathDressup.baseOp(selection[0])
|
||||
if not hasattr(baseOp, "ClearanceHeight"):
|
||||
return False
|
||||
if not hasattr(baseOp, "SafeHeight"):
|
||||
return False
|
||||
if not hasattr(baseOp, "StartDepth"):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user