Merge pull request #23285 from davidgilkaufman/feed_rate_percentage
[CAM] Feed rate percentage for ramp and lead in/out moves
This commit is contained in:
@@ -117,14 +117,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<widget class="QLabel" name="label_leadin_feed">
|
||||
<property name="text">
|
||||
<string>Horizontal rapid</string>
|
||||
<string>Lead-in feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="horizRapid">
|
||||
<widget class="Gui::QuantitySpinBox" name="leadInFeed">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -146,13 +146,100 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_leadOutFeed">
|
||||
<property name="text">
|
||||
<string>Lead-out feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="leadOutFeed">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm/s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_rampFeed">
|
||||
<property name="text">
|
||||
<string>Ramp feed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="rampFeed">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm/s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Horizontal rapid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="horizRapid">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>9999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm/s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Vertical rapid</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="vertRapid">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
|
||||
@@ -253,6 +253,8 @@ class ObjectDressup:
|
||||
|
||||
self.horizFeed = self.toolController.HorizFeed.Value
|
||||
self.vertFeed = self.toolController.VertFeed.Value
|
||||
self.entranceFeed = self.toolController.LeadInFeed.Value
|
||||
self.exitFeed = self.toolController.LeadOutFeed.Value
|
||||
|
||||
obj.Path = self.generateLeadInOutCurve(obj)
|
||||
|
||||
@@ -499,14 +501,14 @@ class ObjectDressup:
|
||||
return App.Vector(math.cos(angle), math.sin(angle), 0)
|
||||
|
||||
# Create arc in XY plane with automatic detection G2|G3
|
||||
def createArcMove(self, obj, begin, end, offset, invert=False):
|
||||
def createArcMove(self, obj, begin, end, offset, invert, feedRate):
|
||||
param = {
|
||||
"X": end.x,
|
||||
"Y": end.y,
|
||||
"Z": end.z,
|
||||
"I": offset.x,
|
||||
"J": offset.y,
|
||||
"F": self.horizFeed,
|
||||
"F": feedRate,
|
||||
}
|
||||
if self.getLeadDir(obj, invert) > 0:
|
||||
command = PathLanguage.MoveArcCCW(begin, "G3", param)
|
||||
@@ -516,8 +518,8 @@ class ObjectDressup:
|
||||
return command
|
||||
|
||||
# Create arc in XY plane with manually set G2|G3
|
||||
def createArcMoveN(self, obj, begin, end, offset, cmdName):
|
||||
param = {"X": end.x, "Y": end.y, "I": offset.x, "J": offset.y, "F": self.horizFeed}
|
||||
def createArcMoveN(self, obj, begin, end, offset, cmdName, feedRate):
|
||||
param = {"X": end.x, "Y": end.y, "I": offset.x, "J": offset.y, "F": feedRate}
|
||||
if cmdName == "G2":
|
||||
command = PathLanguage.MoveArcCW(begin, cmdName, param)
|
||||
else:
|
||||
@@ -526,8 +528,8 @@ class ObjectDressup:
|
||||
return command
|
||||
|
||||
# Create line movement G1
|
||||
def createStraightMove(self, obj, begin, end):
|
||||
param = {"X": end.x, "Y": end.y, "Z": end.z, "F": self.horizFeed}
|
||||
def createStraightMove(self, obj, begin, end, feedRate):
|
||||
param = {"X": end.x, "Y": end.y, "Z": end.z, "F": feedRate}
|
||||
command = PathLanguage.MoveStraight(begin, "G1", param)
|
||||
|
||||
return command
|
||||
@@ -549,7 +551,7 @@ class ObjectDressup:
|
||||
return stepAngle
|
||||
|
||||
# Create vertical arc with move Down by line segments
|
||||
def createArcZMoveDown(self, obj, begin, end, radius):
|
||||
def createArcZMoveDown(self, obj, begin, end, radius, feedRate):
|
||||
commands = []
|
||||
angle = math.acos((radius - begin.z + end.z) / radius) # start angle
|
||||
stepAngle = self.getStepAngleArcZ(obj, radius)
|
||||
@@ -568,7 +570,7 @@ class ObjectDressup:
|
||||
else:
|
||||
# exclude error of calculations for the last iteration
|
||||
iterEnd = copy.copy(end)
|
||||
param = {"X": iterEnd.x, "Y": iterEnd.y, "Z": iterEnd.z, "F": self.horizFeed}
|
||||
param = {"X": iterEnd.x, "Y": iterEnd.y, "Z": iterEnd.z, "F": feedRate}
|
||||
commands.append(PathLanguage.MoveStraight(iterBegin, "G1", param))
|
||||
iterBegin = copy.copy(iterEnd)
|
||||
iter += 1
|
||||
@@ -576,7 +578,7 @@ class ObjectDressup:
|
||||
return commands
|
||||
|
||||
# Create vertical arc with move Up by line segments
|
||||
def createArcZMoveUp(self, obj, begin, end, radius):
|
||||
def createArcZMoveUp(self, obj, begin, end, radius, feedRate):
|
||||
commands = []
|
||||
angleMax = math.acos((radius - end.z + begin.z) / radius) # finish angle
|
||||
stepAngle = self.getStepAngleArcZ(obj, radius)
|
||||
@@ -596,7 +598,7 @@ class ObjectDressup:
|
||||
else:
|
||||
# exclude the error of calculations of the last point
|
||||
iterEnd = copy.copy(end)
|
||||
param = {"X": iterEnd.x, "Y": iterEnd.y, "Z": iterEnd.z, "F": self.horizFeed}
|
||||
param = {"X": iterEnd.x, "Y": iterEnd.y, "Z": iterEnd.z, "F": feedRate}
|
||||
commands.append(PathLanguage.MoveStraight(iterBegin, "G1", param))
|
||||
iterBegin = copy.copy(iterEnd)
|
||||
iter += 1
|
||||
@@ -654,7 +656,11 @@ class ObjectDressup:
|
||||
arcBegin = begin + tangent + normal
|
||||
arcCenter = begin + normalMax
|
||||
arcOffset = arcCenter - arcBegin
|
||||
lead.append(self.createArcMove(obj, arcBegin, begin, arcOffset, obj.InvertIn))
|
||||
lead.append(
|
||||
self.createArcMove(
|
||||
obj, arcBegin, begin, arcOffset, obj.InvertIn, self.entranceFeed
|
||||
)
|
||||
)
|
||||
|
||||
# prepend "Line" style lead-in - line in XY
|
||||
# Line3d the same as Line, but increased Z start point
|
||||
@@ -668,7 +674,7 @@ class ObjectDressup:
|
||||
* normalLength
|
||||
)
|
||||
lineBegin = begin + tangent + normal
|
||||
lead.append(self.createStraightMove(obj, lineBegin, begin))
|
||||
lead.append(self.createStraightMove(obj, lineBegin, begin, self.entranceFeed))
|
||||
|
||||
# prepend "LineZ" style lead-in - vertical inclined line
|
||||
# Should be applied only on straight Path segment
|
||||
@@ -683,7 +689,7 @@ class ObjectDressup:
|
||||
tangent = -self.angleToVector(angleTangent) * tangentLength
|
||||
normal = App.Vector(0, 0, normalLength)
|
||||
lineBegin = begin + tangent + normal
|
||||
lead.append(self.createStraightMove(obj, lineBegin, begin))
|
||||
lead.append(self.createStraightMove(obj, lineBegin, begin, self.entranceFeed))
|
||||
|
||||
# prepend "ArcZ" style lead-in - vertical Arc
|
||||
# Should be applied only on straight Path segment
|
||||
@@ -702,7 +708,9 @@ class ObjectDressup:
|
||||
tangent = -self.angleToVector(angleTangent) * tangentLength
|
||||
normal = App.Vector(0, 0, normalLength)
|
||||
arcBegin = begin + tangent + normal
|
||||
lead.extend(self.createArcZMoveDown(obj, arcBegin, begin, arcRadius))
|
||||
lead.extend(
|
||||
self.createArcZMoveDown(obj, arcBegin, begin, arcRadius, self.entranceFeed)
|
||||
)
|
||||
|
||||
# replace 'begin' position with first lead-in command
|
||||
begin = lead[0].positionBegin()
|
||||
@@ -742,7 +750,7 @@ class ObjectDressup:
|
||||
travelToStart = self.getTravelStart(obj, begin, first, outInstrPrev)
|
||||
else:
|
||||
# exclude any lead-in commands
|
||||
param = {"X": begin.x, "Y": begin.y, "Z": begin.z, "F": self.horizFeed}
|
||||
param = {"X": begin.x, "Y": begin.y, "Z": begin.z, "F": self.entranceFeed}
|
||||
travelToStart = [PathLanguage.MoveStraight(None, "G01", param)]
|
||||
|
||||
lead = travelToStart + lead
|
||||
@@ -790,7 +798,9 @@ class ObjectDressup:
|
||||
* normalLength
|
||||
)
|
||||
arcEnd = end + tangent + normal
|
||||
lead.append(self.createArcMove(obj, end, arcEnd, normalMax, obj.InvertOut))
|
||||
lead.append(
|
||||
self.createArcMove(obj, end, arcEnd, normalMax, obj.InvertOut, self.exitFeed)
|
||||
)
|
||||
|
||||
# append "Line" style lead-out
|
||||
# Line3d the same as Line, but increased Z start point
|
||||
@@ -804,7 +814,7 @@ class ObjectDressup:
|
||||
* normalLength
|
||||
)
|
||||
lineEnd = end + tangent + normal
|
||||
lead.append(self.createStraightMove(obj, end, lineEnd))
|
||||
lead.append(self.createStraightMove(obj, end, lineEnd, self.exitFeed))
|
||||
|
||||
# append "LineZ" style lead-out - vertical inclined line
|
||||
# Should be apply only on straight Path segment
|
||||
@@ -819,7 +829,7 @@ class ObjectDressup:
|
||||
tangent = self.angleToVector(angleTangent) * tangentLength
|
||||
normal = App.Vector(0, 0, normalLength)
|
||||
lineEnd = end + tangent + normal
|
||||
lead.append(self.createStraightMove(obj, end, lineEnd))
|
||||
lead.append(self.createStraightMove(obj, end, lineEnd, self.exitFeed))
|
||||
|
||||
# prepend "ArcZ" style lead-out - vertical Arc
|
||||
# Should be apply only on straight Path segment
|
||||
@@ -838,7 +848,7 @@ class ObjectDressup:
|
||||
tangent = self.angleToVector(angleTangent) * tangentLength
|
||||
normal = App.Vector(0, 0, normalLength)
|
||||
arcEnd = end + tangent + normal
|
||||
lead.extend(self.createArcZMoveUp(obj, end, arcEnd, arcRadius))
|
||||
lead.extend(self.createArcZMoveUp(obj, end, arcEnd, arcRadius, self.exitFeed))
|
||||
|
||||
if obj.StyleOut in ("Arc3d", "Line3d"):
|
||||
# Up Z end point for Arc3d and Line3d
|
||||
@@ -996,7 +1006,7 @@ class ObjectDressup:
|
||||
n = math.hypot(v.x, v.y)
|
||||
u = v / n
|
||||
cutEnd = begin + u * newLength
|
||||
command = self.createStraightMove(obj, begin, cutEnd)
|
||||
command = self.createStraightMove(obj, begin, cutEnd, self.horizFeed)
|
||||
|
||||
# Cut arc move from begin
|
||||
elif instr.isArc():
|
||||
@@ -1011,7 +1021,7 @@ class ObjectDressup:
|
||||
normal = self.angleToVector(angleTangent + self.getPathDir(obj)) * normalLength
|
||||
arcEnd = arcBegin + tangent + normal
|
||||
cmdName = "G2" if instr.isCW() else "G3"
|
||||
command = self.createArcMoveN(obj, arcBegin, arcEnd, arcOffset, cmdName)
|
||||
command = self.createArcMoveN(obj, arcBegin, arcEnd, arcOffset, cmdName, self.horizFeed)
|
||||
|
||||
return command
|
||||
|
||||
@@ -1025,7 +1035,7 @@ class ObjectDressup:
|
||||
n = math.hypot(v.x, v.y)
|
||||
u = v / n
|
||||
newBegin = end - u * newLength
|
||||
command = self.createStraightMove(obj, newBegin, end)
|
||||
command = self.createStraightMove(obj, newBegin, end, self.horizFeed)
|
||||
return command
|
||||
|
||||
# Cut arc move from begin
|
||||
@@ -1042,7 +1052,7 @@ class ObjectDressup:
|
||||
arcBegin = arcEnd + tangent + normal
|
||||
arcOffset = arcCenter - arcBegin
|
||||
cmdName = "G2" if instr.isCW() else "G3"
|
||||
command = self.createArcMoveN(obj, arcBegin, arcEnd, arcOffset, cmdName)
|
||||
command = self.createArcMoveN(obj, arcBegin, arcEnd, arcOffset, cmdName, self.horizFeed)
|
||||
return command
|
||||
|
||||
return None
|
||||
@@ -1188,6 +1198,8 @@ 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")
|
||||
|
||||
@@ -181,18 +181,6 @@ class ObjectDressup:
|
||||
"Path",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Ramping Method"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyEnumeration",
|
||||
"RampFeedRate",
|
||||
"FeedRate",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Which feed rate to use for ramping"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"CustomFeedRate",
|
||||
"FeedRate",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Custom feed rate"),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyBool",
|
||||
"UseStartDepth",
|
||||
@@ -246,21 +234,6 @@ class ObjectDressup:
|
||||
(translate("CAM_DressupRampEntry", "RampMethod3"), "RampMethod3"),
|
||||
(translate("CAM_DressupRampEntry", "Helix"), "Helix"),
|
||||
],
|
||||
"RampFeedRate": [
|
||||
(
|
||||
translate("CAM_DressupRampEntry", "Horizontal Feed Rate"),
|
||||
"Horizontal Feed Rate",
|
||||
),
|
||||
(
|
||||
translate("CAM_DressupRampEntry", "Vertical Feed Rate"),
|
||||
"Vertical Feed Rate",
|
||||
),
|
||||
(
|
||||
translate("CAM_DressupRampEntry", "Ramp Feed Rate"),
|
||||
"Ramp Feed Rate",
|
||||
),
|
||||
(translate("CAM_DressupRampEntry", "Custom"), "Custom"),
|
||||
],
|
||||
}
|
||||
|
||||
if dataType == "raw":
|
||||
@@ -284,7 +257,7 @@ class ObjectDressup:
|
||||
return None
|
||||
|
||||
def onChanged(self, obj, prop):
|
||||
if prop in ["RampFeedRate", "UseStartDepth"]:
|
||||
if prop in ["UseStartDepth"]:
|
||||
self.setEditorProperties(obj)
|
||||
if prop == "Path" and obj.ViewObject:
|
||||
obj.ViewObject.signalChangeIcon()
|
||||
@@ -296,14 +269,24 @@ class ObjectDressup:
|
||||
else:
|
||||
obj.setEditorMode("DressupStartDepth", 2)
|
||||
|
||||
if obj.RampFeedRate == "Custom":
|
||||
obj.setEditorMode("CustomFeedRate", 0)
|
||||
else:
|
||||
obj.setEditorMode("CustomFeedRate", 2)
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
self.setEditorProperties(obj)
|
||||
|
||||
# Remove RampFeedRate + CustomFeedRate properties, but keep the values around temporarily
|
||||
# This is required for tool controller migration: if a TC migrates with onDocumentRestored
|
||||
# called after this, the prior ramp feed rate still needs to be accessible.
|
||||
if hasattr(obj, "RampFeedRate"):
|
||||
obj.Proxy.RampFeedRate = obj.RampFeedRate
|
||||
obj.removeProperty("RampFeedRate")
|
||||
|
||||
if hasattr(obj, "CustomFeedRate"):
|
||||
tmp = obj.CustomFeedRate.Value
|
||||
for prop, exp in obj.ExpressionEngine:
|
||||
if prop == "CustomFeedRate":
|
||||
tmp = exp
|
||||
obj.Proxy.CustomFeedRate = tmp
|
||||
obj.removeProperty("CustomFeedRate")
|
||||
|
||||
def setup(self, obj):
|
||||
obj.Angle = 60
|
||||
obj.Method = 2
|
||||
@@ -683,15 +666,7 @@ class ObjectDressup:
|
||||
vertFeed = tc.VertFeed.Value
|
||||
horizRapid = tc.HorizRapid.Value
|
||||
vertRapid = tc.VertRapid.Value
|
||||
|
||||
if obj.RampFeedRate == "Horizontal Feed Rate":
|
||||
rampFeed = horizFeed
|
||||
elif obj.RampFeedRate == "Vertical Feed Rate":
|
||||
rampFeed = vertFeed
|
||||
elif obj.RampFeedRate == "Ramp Feed Rate":
|
||||
rampFeed = math.sqrt(pow(vertFeed, 2) + pow(horizFeed, 2))
|
||||
else:
|
||||
rampFeed = obj.CustomFeedRate.Value
|
||||
rampFeed = tc.RampFeed.Value
|
||||
|
||||
lastX = lastY = lastZ = 0
|
||||
for cmd in commands:
|
||||
|
||||
@@ -705,7 +705,7 @@ class ObjectJob:
|
||||
"VertRapid",
|
||||
"%s.%s"
|
||||
% (
|
||||
self.setupSheet.expressionReference(),
|
||||
self.obj.SetupSheet.Proxy.expressionReference(),
|
||||
PathSetupSheet.Template.VertRapid,
|
||||
),
|
||||
)
|
||||
@@ -713,7 +713,7 @@ class ObjectJob:
|
||||
"HorizRapid",
|
||||
"%s.%s"
|
||||
% (
|
||||
self.setupSheet.expressionReference(),
|
||||
self.obj.SetupSheet.Proxy.expressionReference(),
|
||||
PathSetupSheet.Template.HorizRapid,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -429,22 +429,8 @@ class TaskPanelPage(object):
|
||||
def copyToolController(self):
|
||||
oldTc = self.tcEditor.obj
|
||||
self.tcEditor.updateToolController()
|
||||
tc = PathToolController.Create(
|
||||
name=oldTc.Label, tool=oldTc.Tool, toolNumber=oldTc.ToolNumber
|
||||
)
|
||||
job = self.obj.Proxy.getJob(self.obj)
|
||||
job.Proxy.addToolController(tc)
|
||||
|
||||
tc.HorizFeed = oldTc.HorizFeed
|
||||
tc.VertFeed = oldTc.VertFeed
|
||||
tc.HorizRapid = oldTc.HorizRapid
|
||||
tc.VertRapid = oldTc.VertRapid
|
||||
tc.SpindleSpeed = oldTc.SpindleSpeed
|
||||
tc.SpindleDir = oldTc.SpindleDir
|
||||
for attr, expr in oldTc.ExpressionEngine:
|
||||
tc.setExpression(attr, expr)
|
||||
|
||||
self.obj.ToolController = tc
|
||||
self.obj.ToolController = PathToolController.copyTC(oldTc, job)
|
||||
self.setupToolController()
|
||||
|
||||
def tcEditorChanged(self):
|
||||
|
||||
@@ -313,9 +313,6 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
def areaOpOnDocumentRestored(self, obj):
|
||||
self.propertiesReady = False
|
||||
|
||||
self.initAreaOpProperties(obj, warn=True)
|
||||
self.areaOpSetDefaultValues(obj, PathUtils.findParentJob(obj))
|
||||
self.setOpEditorProperties(obj)
|
||||
if not hasattr(obj, "NumPasses"):
|
||||
obj.addProperty(
|
||||
"App::PropertyInteger",
|
||||
@@ -326,6 +323,7 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
"The number of passes to do. Requires a non-zero value for Stepover",
|
||||
),
|
||||
)
|
||||
|
||||
if not hasattr(obj, "Stepover"):
|
||||
obj.addProperty(
|
||||
"App::PropertyDistance",
|
||||
@@ -337,6 +335,10 @@ class ObjectProfile(PathAreaOp.ObjectOp):
|
||||
),
|
||||
)
|
||||
|
||||
self.initAreaOpProperties(obj, warn=True)
|
||||
self.areaOpSetDefaultValues(obj, PathUtils.findParentJob(obj))
|
||||
self.setOpEditorProperties(obj)
|
||||
|
||||
def areaOpOnChanged(self, obj, prop):
|
||||
"""areaOpOnChanged(obj, prop) ... updates certain property visibilities depending on changed properties."""
|
||||
if prop in ["UseComp", "JoinType", "Base"]:
|
||||
|
||||
@@ -49,7 +49,10 @@ class ToolControllerTemplate:
|
||||
HorizFeed = "hfeed"
|
||||
HorizRapid = "hrapid"
|
||||
Label = "label"
|
||||
LeadInFeed = "leadinfeed"
|
||||
LeadOutFeed = "leadoutfeed"
|
||||
Name = "name"
|
||||
RampFeed = "rampfeed"
|
||||
SpindleDir = "dir"
|
||||
SpindleSpeed = "speed"
|
||||
ToolNumber = "nr"
|
||||
@@ -59,6 +62,77 @@ class ToolControllerTemplate:
|
||||
VertRapid = "vrapid"
|
||||
|
||||
|
||||
def _migrateRampDressups(tc):
|
||||
# Enumerate ramp dressups using this TC and their feed rates
|
||||
ramps = set()
|
||||
job_ramp_feeds = []
|
||||
for job in tc.Document.Objects:
|
||||
if hasattr(job, "Operations") and hasattr(job.Operations, "Group"):
|
||||
for op in job.Operations.Group:
|
||||
for ramp in [op] + op.OutListRecursive:
|
||||
if ramp not in ramps and (
|
||||
hasattr(ramp, "RampFeedRate")
|
||||
or (hasattr(ramp, "Proxy") and hasattr(ramp.Proxy, "RampFeedRate"))
|
||||
):
|
||||
rampFeedRate = (
|
||||
ramp.RampFeedRate
|
||||
if hasattr(ramp, "RampFeedRate")
|
||||
else ramp.Proxy.RampFeedRate
|
||||
)
|
||||
if hasattr(ramp, "CustomFeedRate"):
|
||||
customFeedRate = ramp.CustomFeedRate.Value
|
||||
for prop, exp in ramp.ExpressionEngine:
|
||||
if prop == "CustomFeedRate":
|
||||
customFeedRate = exp
|
||||
else:
|
||||
customFeedRate = (
|
||||
ramp.Proxy.CustomFeedRate
|
||||
if hasattr(ramp.Proxy, "CustomFeedRate")
|
||||
else "HorizFeed"
|
||||
)
|
||||
|
||||
if op.Base.ToolController == tc:
|
||||
ramps.add(ramp)
|
||||
if rampFeedRate == "Horizontal Feed Rate":
|
||||
feed = "HorizFeed"
|
||||
elif rampFeedRate == "Vertical Feed Rate":
|
||||
feed = "VertFeed"
|
||||
elif rampFeedRate == "Ramp Feed Rate":
|
||||
feed = "sqrt(HorizFeed * HorizFeed + VertFeed * VertFeed)"
|
||||
else:
|
||||
feed = customFeedRate
|
||||
job_ramp_feeds.append((job, ramp, feed))
|
||||
|
||||
# Ensure there is a TC for each required feed, starting with this one
|
||||
feed_to_tc = {}
|
||||
for i, (job, ramp, feed) in enumerate(job_ramp_feeds):
|
||||
if feed in feed_to_tc:
|
||||
continue
|
||||
|
||||
if len(feed_to_tc) == 0:
|
||||
opTc = tc
|
||||
else:
|
||||
opTc = copyTC(tc, job)
|
||||
# Note: C++ doesn't try to deduplicate the Labels of objects created
|
||||
# during document restore, so here we will reuse the (deduplicated)
|
||||
# name as the label
|
||||
opTc.Label = opTc.Name
|
||||
|
||||
feed_to_tc[feed] = opTc
|
||||
|
||||
if isinstance(feed, str):
|
||||
opTc.setExpression("RampFeed", feed)
|
||||
else:
|
||||
opTc.setExpression("RampFeed", None)
|
||||
opTc.RampFeed = feed
|
||||
if opTc is not tc:
|
||||
opTc.recompute()
|
||||
|
||||
# Loop over ramps and assign each one the appropriate TC
|
||||
for _, ramp, feed in job_ramp_feeds:
|
||||
ramp.Base.ToolController = feed_to_tc[feed]
|
||||
|
||||
|
||||
class ToolController:
|
||||
def __init__(self, obj, createTool=True):
|
||||
Path.Log.track("tool: ")
|
||||
@@ -106,6 +180,31 @@ class ToolController:
|
||||
"Rapid",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Rapid rate for horizontal moves"),
|
||||
)
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"RampFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for ramp moves"),
|
||||
)
|
||||
obj.setExpression("RampFeed", "HorizFeed")
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadInFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-in moves"),
|
||||
)
|
||||
obj.setExpression("LeadInFeed", "HorizFeed")
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadOutFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-out moves"),
|
||||
)
|
||||
obj.setExpression("LeadOutFeed", "HorizFeed")
|
||||
|
||||
obj.setEditorMode("Placement", 2)
|
||||
|
||||
for n in self.propertyEnumerations():
|
||||
@@ -166,6 +265,40 @@ class ToolController:
|
||||
|
||||
obj.setEditorMode("Placement", 2)
|
||||
|
||||
needsRecompute = False
|
||||
if not hasattr(obj, "RampFeed"):
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"RampFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for ramp moves"),
|
||||
)
|
||||
_migrateRampDressups(obj)
|
||||
needsRecompute = True
|
||||
|
||||
if not hasattr(obj, "LeadInFeed"):
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadInFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-in moves"),
|
||||
)
|
||||
obj.setExpression("LeadInFeed", "HorizFeed")
|
||||
needsRecompute = True
|
||||
|
||||
if not hasattr(obj, "LeadOutFeed"):
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadOutFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-out moves"),
|
||||
)
|
||||
obj.setExpression("LeadOutFeed", "HorizFeed")
|
||||
needsRecompute = True
|
||||
|
||||
if needsRecompute:
|
||||
obj.recompute()
|
||||
|
||||
def onDelete(self, obj, arg2=None):
|
||||
if hasattr(obj.Tool, "InList") and len(obj.Tool.InList) == 1:
|
||||
if hasattr(obj.Tool.Proxy, "onDelete"):
|
||||
@@ -181,12 +314,22 @@ class ToolController:
|
||||
if template.get(ToolControllerTemplate.Version):
|
||||
version = int(template.get(ToolControllerTemplate.Version))
|
||||
if version == 1 or version == 2:
|
||||
# TODO figure out the meaning of this, and how to handle ramp/leadin/leadout feed rates
|
||||
# or what else must be added to templates
|
||||
if template.get(ToolControllerTemplate.Label):
|
||||
obj.Label = template.get(ToolControllerTemplate.Label)
|
||||
if template.get(ToolControllerTemplate.VertFeed):
|
||||
obj.VertFeed = template.get(ToolControllerTemplate.VertFeed)
|
||||
if template.get(ToolControllerTemplate.HorizFeed):
|
||||
obj.HorizFeed = template.get(ToolControllerTemplate.HorizFeed)
|
||||
if template.get(ToolControllerTemplate.LeadInFeed):
|
||||
obj.LeadInFeed = template.get(ToolControllerTemplate.LeadInFeed, obj.LeadInFeed)
|
||||
if template.get(ToolControllerTemplate.LeadOutFeed):
|
||||
obj.LeadOutFeed = template.get(
|
||||
ToolControllerTemplate.LeadOutFeed, obj.LeadOutFeed
|
||||
)
|
||||
if template.get(ToolControllerTemplate.RampFeed):
|
||||
obj.RampFeed = template.get(ToolControllerTemplate.RampFeed, obj.RampFeed)
|
||||
if template.get(ToolControllerTemplate.VertRapid):
|
||||
obj.VertRapid = template.get(ToolControllerTemplate.VertRapid)
|
||||
if template.get(ToolControllerTemplate.HorizRapid):
|
||||
@@ -241,6 +384,9 @@ class ToolController:
|
||||
attrs[ToolControllerTemplate.ToolNumber] = obj.ToolNumber
|
||||
attrs[ToolControllerTemplate.VertFeed] = "%s" % (obj.VertFeed)
|
||||
attrs[ToolControllerTemplate.HorizFeed] = "%s" % (obj.HorizFeed)
|
||||
attrs[ToolControllerTemplate.LeadInFeed] = "%s" % (obj.LeadInFeed)
|
||||
attrs[ToolControllerTemplate.LeadOutFeed] = "%s" % (obj.LeadOutFeed)
|
||||
attrs[ToolControllerTemplate.RampFeed] = "%s" % (obj.RampFeed)
|
||||
attrs[ToolControllerTemplate.VertRapid] = "%s" % (obj.VertRapid)
|
||||
attrs[ToolControllerTemplate.HorizRapid] = "%s" % (obj.HorizRapid)
|
||||
attrs[ToolControllerTemplate.SpindleSpeed] = obj.SpindleSpeed
|
||||
@@ -327,6 +473,23 @@ def Create(
|
||||
return obj
|
||||
|
||||
|
||||
def copyTC(tc, job):
|
||||
newtc = Create(name=tc.Label, tool=tc.Tool, toolNumber=tc.ToolNumber)
|
||||
job.Proxy.addToolController(newtc)
|
||||
|
||||
for prop in tc.PropertiesList:
|
||||
try:
|
||||
if prop not in ["Label", "Label2"]:
|
||||
setattr(newtc, prop, getattr(tc, prop))
|
||||
except RuntimeError:
|
||||
# Ignore errors for read-only properties
|
||||
pass
|
||||
for attr, expr in tc.ExpressionEngine:
|
||||
newtc.setExpression(attr, expr)
|
||||
|
||||
return newtc
|
||||
|
||||
|
||||
def FromTemplate(template, assignViewProvider=True):
|
||||
Path.Log.track()
|
||||
|
||||
|
||||
@@ -218,6 +218,11 @@ class ToolControllerEditor(object):
|
||||
PathGuiUtil.populateCombobox(self.controller, enumTups, comboToPropertyMap)
|
||||
self.vertFeed = PathGuiUtil.QuantitySpinBox(self.controller.vertFeed, obj, "VertFeed")
|
||||
self.horizFeed = PathGuiUtil.QuantitySpinBox(self.controller.horizFeed, obj, "HorizFeed")
|
||||
self.leadInFeed = PathGuiUtil.QuantitySpinBox(self.controller.leadInFeed, obj, "LeadInFeed")
|
||||
self.leadOutFeed = PathGuiUtil.QuantitySpinBox(
|
||||
self.controller.leadOutFeed, obj, "LeadOutFeed"
|
||||
)
|
||||
self.rampFeed = PathGuiUtil.QuantitySpinBox(self.controller.rampFeed, obj, "RampFeed")
|
||||
self.vertRapid = PathGuiUtil.QuantitySpinBox(self.controller.vertRapid, obj, "VertRapid")
|
||||
self.horizRapid = PathGuiUtil.QuantitySpinBox(self.controller.horizRapid, obj, "HorizRapid")
|
||||
|
||||
@@ -260,6 +265,9 @@ class ToolControllerEditor(object):
|
||||
self.controller.tcNumber,
|
||||
self.horizFeed.widget,
|
||||
self.horizRapid.widget,
|
||||
self.leadInFeed.widget,
|
||||
self.leadOutFeed.widget,
|
||||
self.rampFeed.widget,
|
||||
self.vertFeed.widget,
|
||||
self.vertRapid.widget,
|
||||
self.controller.spindleSpeed,
|
||||
@@ -273,6 +281,9 @@ class ToolControllerEditor(object):
|
||||
self.controller.tcNumber.setValue(tc.ToolNumber)
|
||||
self.horizFeed.updateWidget()
|
||||
self.horizRapid.updateWidget()
|
||||
self.leadInFeed.updateWidget()
|
||||
self.leadOutFeed.updateWidget()
|
||||
self.rampFeed.updateWidget()
|
||||
self.vertFeed.updateWidget()
|
||||
self.vertRapid.updateWidget()
|
||||
self.controller.spindleSpeed.setValue(tc.SpindleSpeed)
|
||||
@@ -292,6 +303,9 @@ class ToolControllerEditor(object):
|
||||
tc.ToolNumber = self.controller.tcNumber.value()
|
||||
self.horizFeed.updateProperty()
|
||||
self.vertFeed.updateProperty()
|
||||
self.leadInFeed.updateProperty()
|
||||
self.leadOutFeed.updateProperty()
|
||||
self.rampFeed.updateProperty()
|
||||
self.horizRapid.updateProperty()
|
||||
self.vertRapid.updateProperty()
|
||||
tc.SpindleSpeed = self.controller.spindleSpeed.value()
|
||||
@@ -323,6 +337,9 @@ class ToolControllerEditor(object):
|
||||
self.controller.tcNumber.editingFinished.connect(self.changed)
|
||||
self.vertFeed.widget.textChanged.connect(self.changed)
|
||||
self.horizFeed.widget.textChanged.connect(self.changed)
|
||||
self.leadInFeed.widget.textChanged.connect(self.changed)
|
||||
self.leadOutFeed.widget.textChanged.connect(self.changed)
|
||||
self.rampFeed.widget.textChanged.connect(self.changed)
|
||||
self.vertRapid.widget.textChanged.connect(self.changed)
|
||||
self.horizRapid.widget.textChanged.connect(self.changed)
|
||||
self.controller.spindleSpeed.editingFinished.connect(self.changed)
|
||||
|
||||
Reference in New Issue
Block a user