Merge pull request #23980 from davidgilkaufman/adaptive_auto_helix
[CAM] Adaptive automatically pick diameter of helix entrance
This commit is contained in:
@@ -115,7 +115,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -149,7 +148,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -177,7 +175,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = True
|
||||
@@ -218,7 +215,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -261,7 +257,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -304,7 +299,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -347,7 +341,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
# setDepthsAndHeights(adaptive)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -408,7 +401,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
setDepthsAndHeights(adaptive, 15, 0)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -478,7 +470,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
setDepthsAndHeights(adaptive, 15, 10)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -540,7 +531,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
setDepthsAndHeights(adaptive, 15, 0)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
@@ -622,7 +612,6 @@ class TestPathAdaptive(PathTestBase):
|
||||
setDepthsAndHeights(adaptive, 15, 5)
|
||||
adaptive.FinishingProfile = False
|
||||
adaptive.HelixAngle = 75.0
|
||||
adaptive.HelixDiameterLimit.Value = 1.0
|
||||
adaptive.LiftDistance.Value = 1.0
|
||||
adaptive.StepOver = 75
|
||||
adaptive.UseOutline = False
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="threadFitLabel">
|
||||
<widget class="QLabel" name="accuracyPerformanceLabel">
|
||||
<property name="text">
|
||||
<string>Accuracy vs performance</string>
|
||||
</property>
|
||||
@@ -164,29 +164,15 @@ Larger values (further to the right) will calculate faster; smaller values (furt
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Step over percent</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="Gui::InputField" name="HelixConeAngle">
|
||||
<property name="toolTip">
|
||||
<string>Angle of the helix entry cone</string>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Helix ramp angle</string>
|
||||
<string>Step over</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -221,33 +207,6 @@ Larger values (further to the right) will calculate faster; smaller values (furt
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="HelixDiameterLimit" native="true">
|
||||
<property name="toolTip">
|
||||
<string>If greater than zero it limits the helix ramp diameter, otherwise 75 percent of tool diameter is used</string>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Helix cone angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="Gui::InputField" name="HelixAngle">
|
||||
<property name="toolTip">
|
||||
<string>Angle of the helix ramp entry</string>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
@@ -272,10 +231,131 @@ Larger values (further to the right) will calculate faster; smaller values (furt
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="helixFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="helixLayout">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="helix_header">
|
||||
<property name="text">
|
||||
<string><b>Helix Parameters</b></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_max_stepdown">
|
||||
<property name="text">
|
||||
<string>Max stepdown</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="Gui::InputField" name="HelixMaxStepdown">
|
||||
<property name="toolTip">
|
||||
<string>The maximum allowable descent in a single revolution of the helix.</string>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Ramp angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="Gui::InputField" name="HelixAngle">
|
||||
<property name="toolTip">
|
||||
<string>Angle of the helix ramp entry</string>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Cone angle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="Gui::InputField" name="HelixConeAngle">
|
||||
<property name="toolTip">
|
||||
<string>Angle of the helix entry cone</string>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Helix max diameter</string>
|
||||
<string>Max diameter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QSpinBox" name="HelixMaxDiameterPercent">
|
||||
<property name="toolTip">
|
||||
<string>Maximum (and nominal) helix entry diameter, as a percentage of the tool diameter.</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Min diameter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QSpinBox" name="HelixMinDiameterPercent">
|
||||
<property name="toolTip">
|
||||
<string>Minimum acceptable entry diameter, as a percentage of the tool diameter.</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>%</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -118,7 +118,7 @@ def discretize(edge, flipDirection=False):
|
||||
return pts
|
||||
|
||||
|
||||
def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
|
||||
def GenerateGCode(op, obj, adaptiveResults):
|
||||
if not adaptiveResults or not adaptiveResults[0]["AdaptivePaths"]:
|
||||
return
|
||||
|
||||
@@ -138,6 +138,8 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
|
||||
|
||||
helixAngleRad = math.radians(obj.HelixAngle)
|
||||
depthPerOneCircle = length * math.tan(helixAngleRad)
|
||||
if obj.HelixMaxStepdown.Value != 0 and obj.HelixMaxStepdown.Value < depthPerOneCircle:
|
||||
depthPerOneCircle = obj.HelixMaxStepdown.Value
|
||||
|
||||
stepUp = max(obj.LiftDistance.Value, 0)
|
||||
|
||||
@@ -538,7 +540,11 @@ def Execute(op, obj):
|
||||
FreeCADGui.updateGui()
|
||||
|
||||
try:
|
||||
helixDiameter = obj.HelixDiameterLimit.Value
|
||||
obj.HelixMinDiameterPercent = max(obj.HelixMinDiameterPercent, 10)
|
||||
obj.HelixMaxDiameterPercent = max(obj.HelixMaxDiameterPercent, obj.HelixMinDiameterPercent)
|
||||
|
||||
helixDiameter = obj.HelixMaxDiameterPercent / 100 * op.tool.Diameter.Value
|
||||
helixMinDiameter = obj.HelixMinDiameterPercent / 100 * op.tool.Diameter.Value
|
||||
topZ = op.stock.Shape.BoundBox.ZMax
|
||||
obj.Stopped = False
|
||||
obj.StopProcessing = False
|
||||
@@ -592,6 +598,7 @@ def Execute(op, obj):
|
||||
"stockGeometry": stockPath2d,
|
||||
"stepover": float(obj.StepOver),
|
||||
"effectiveHelixDiameter": float(helixDiameter),
|
||||
"helixMinDiameter": float(helixMinDiameter),
|
||||
"operationType": obj.OperationType,
|
||||
"side": obj.Side,
|
||||
"forceInsideOut": obj.ForceInsideOut,
|
||||
@@ -633,7 +640,8 @@ def Execute(op, obj):
|
||||
a2d = area.Adaptive2d()
|
||||
a2d.stepOverFactor = 0.01 * obj.StepOver
|
||||
a2d.toolDiameter = float(op.tool.Diameter)
|
||||
a2d.helixRampDiameter = helixDiameter
|
||||
a2d.helixRampTargetDiameter = helixDiameter
|
||||
a2d.helixRampMinDiameter = helixMinDiameter
|
||||
a2d.keepToolDownDistRatio = keepToolDownRatio
|
||||
a2d.stockToLeave = float(obj.StockToLeave)
|
||||
a2d.tolerance = float(obj.Tolerance)
|
||||
@@ -657,7 +665,7 @@ def Execute(op, obj):
|
||||
)
|
||||
|
||||
# GENERATE
|
||||
GenerateGCode(op, obj, adaptiveResults, helixDiameter)
|
||||
GenerateGCode(op, obj, adaptiveResults)
|
||||
|
||||
if not obj.StopProcessing:
|
||||
Path.Log.info("*** Done. Elapsed time: %f sec\n\n" % (time.time() - start))
|
||||
@@ -699,7 +707,12 @@ def ExecuteModelAware(op, obj):
|
||||
FreeCADGui.updateGui()
|
||||
|
||||
try:
|
||||
helixDiameter = obj.HelixDiameterLimit.Value
|
||||
obj.HelixMinDiameterPercent = max(obj.HelixMinDiameterPercent, 10)
|
||||
obj.HelixMaxDiameterPercent = max(obj.HelixMaxDiameterPercent, obj.HelixMinDiameterPercent)
|
||||
obj.StepOver = max(obj.StepOver, 1)
|
||||
|
||||
helixDiameter = obj.HelixMaxDiameterPercent / 100 * op.tool.Diameter.Value
|
||||
helixMinDiameter = obj.HelixMinDiameterPercent / 100 * op.tool.Diameter.Value
|
||||
topZ = op.stock.Shape.BoundBox.ZMax
|
||||
obj.Stopped = False
|
||||
obj.StopProcessing = False
|
||||
@@ -774,6 +787,7 @@ def ExecuteModelAware(op, obj):
|
||||
"stockGeometry": stockPaths,
|
||||
"stepover": obj.StepOver,
|
||||
"effectiveHelixDiameter": helixDiameter,
|
||||
"helixMinDiameter": helixMinDiameter,
|
||||
"operationType": "Clearing",
|
||||
"side": "Outside",
|
||||
"forceInsideOut": obj.ForceInsideOut,
|
||||
@@ -793,6 +807,7 @@ def ExecuteModelAware(op, obj):
|
||||
"stockGeometry": stockPaths,
|
||||
"stepover": obj.StepOver,
|
||||
"effectiveHelixDiameter": helixDiameter,
|
||||
"helixMinDiameter": helixMinDiameter,
|
||||
"operationType": "Clearing",
|
||||
"side": "Inside",
|
||||
"forceInsideOut": obj.ForceInsideOut,
|
||||
@@ -857,7 +872,8 @@ def ExecuteModelAware(op, obj):
|
||||
a2d = area.Adaptive2d()
|
||||
a2d.stepOverFactor = 0.01 * obj.StepOver
|
||||
a2d.toolDiameter = op.tool.Diameter.Value
|
||||
a2d.helixRampDiameter = helixDiameter
|
||||
a2d.helixRampTargetDiameter = helixDiameter
|
||||
a2d.helixRampMinDiameter = helixMinDiameter
|
||||
a2d.keepToolDownDistRatio = keepToolDownRatio
|
||||
# NOTE: Z stock is handled in our stepdowns
|
||||
a2d.stockToLeave = obj.StockToLeave.Value
|
||||
@@ -946,7 +962,7 @@ def ExecuteModelAware(op, obj):
|
||||
)
|
||||
|
||||
# GENERATE
|
||||
GenerateGCode(op, obj, adaptiveResults, helixDiameter)
|
||||
GenerateGCode(op, obj, adaptiveResults)
|
||||
|
||||
if not obj.StopProcessing:
|
||||
Path.Log.info("*** Done. Elapsed time: %f sec\n\n" % (time.time() - start))
|
||||
@@ -1800,6 +1816,15 @@ class PathAdaptive(PathOp.ObjectOp):
|
||||
"Helix ramp entry angle (degrees)",
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyLength",
|
||||
"HelixMaxStepdown",
|
||||
"Adaptive",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"The maximum allowable descent in a single revolution of the helix.",
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyAngle",
|
||||
"HelixConeAngle",
|
||||
@@ -1810,12 +1835,21 @@ class PathAdaptive(PathOp.ObjectOp):
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyLength",
|
||||
"HelixDiameterLimit",
|
||||
"App::PropertyPercent",
|
||||
"HelixMaxDiameterPercent",
|
||||
"Adaptive",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Limit helix entry diameter, if limit larger than tool diameter or 0, tool diameter is used",
|
||||
"Maximum (and nominal) helix entry diameter, as a percentage of the tool diameter",
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyPercent",
|
||||
"HelixMinDiameterPercent",
|
||||
"Adaptive",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Minimum acceptable helix entry diameter, as a percentage of the tool diameter",
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
@@ -1874,7 +1908,8 @@ class PathAdaptive(PathOp.ObjectOp):
|
||||
obj.StopProcessing = False
|
||||
obj.HelixAngle = 5
|
||||
obj.HelixConeAngle = 0
|
||||
obj.HelixDiameterLimit = 0.0
|
||||
obj.HelixMaxDiameterPercent = 100
|
||||
obj.HelixMinDiameterPercent = 10
|
||||
obj.AdaptiveInputState = ""
|
||||
obj.AdaptiveOutputState = ""
|
||||
obj.StockToLeave = 0
|
||||
@@ -1964,6 +1999,44 @@ class PathAdaptive(PathOp.ObjectOp):
|
||||
obj.addProperty("Part::PropertyPartShape", "removalshape", "Path", "")
|
||||
obj.setEditorMode("removalshape", 2) # hide
|
||||
|
||||
if hasattr(obj, "HelixDiameterLimit"):
|
||||
oldD = obj.HelixDiameterLimit.Value
|
||||
obj.removeProperty("HelixDiameterLimit")
|
||||
obj.addProperty(
|
||||
"App::PropertyPercent",
|
||||
"HelixMaxDiameterPercent",
|
||||
"Adaptive",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Maximum (and nominal) helix entry diameter, as a percentage of the tool diameter",
|
||||
),
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyPercent",
|
||||
"HelixMinDiameterPercent",
|
||||
"Adaptive",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Minimum acceptable helix entry diameter, as a percentage of the tool diameter",
|
||||
),
|
||||
)
|
||||
obj.HelixMinDiameterPercent = 10
|
||||
if hasattr(obj, "ToolController"):
|
||||
obj.HelixMaxDiameterPercent = int(
|
||||
75 if oldD == 0 else 100 * oldD / obj.ToolController.Tool.Diameter.Value
|
||||
)
|
||||
|
||||
if not hasattr(obj, "HelixMaxStepdown"):
|
||||
obj.addProperty(
|
||||
"App::PropertyLength",
|
||||
"HelixMaxStepdown",
|
||||
"Adaptive",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"The maximum allowable descent in a single revolution of the helix.",
|
||||
),
|
||||
)
|
||||
|
||||
FeatureExtensions.initialize_properties(obj)
|
||||
|
||||
|
||||
@@ -1986,7 +2059,8 @@ def SetupProperties():
|
||||
"AdaptiveOutputState",
|
||||
"HelixAngle",
|
||||
"HelixConeAngle",
|
||||
"HelixDiameterLimit",
|
||||
"HelixMaxDiameterPercent",
|
||||
"HelixMinDiameterPercent",
|
||||
"UseOutline",
|
||||
"OrderCutsByRegion",
|
||||
]
|
||||
|
||||
@@ -45,10 +45,9 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
return form
|
||||
|
||||
def initPage(self, obj):
|
||||
self.form.HelixMaxStepdown.setProperty("unit", obj.HelixMaxStepdown.getUserPreferred()[2])
|
||||
|
||||
self.form.LiftDistance.setProperty("unit", obj.LiftDistance.getUserPreferred()[2])
|
||||
self.form.HelixDiameterLimit.setProperty(
|
||||
"unit", obj.HelixDiameterLimit.getUserPreferred()[2]
|
||||
)
|
||||
self.form.KeepToolDownRatio.setProperty("unit", obj.KeepToolDownRatio.getUserPreferred()[2])
|
||||
self.form.StockToLeave.setProperty("unit", obj.StockToLeave.getUserPreferred()[2])
|
||||
|
||||
@@ -61,8 +60,10 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
signals.append(self.form.stepOverPercent.valueChanged)
|
||||
signals.append(self.form.Tolerance.valueChanged)
|
||||
signals.append(self.form.HelixAngle.valueChanged)
|
||||
signals.append(self.form.HelixMaxStepdown.valueChanged)
|
||||
signals.append(self.form.HelixConeAngle.valueChanged)
|
||||
signals.append(self.form.HelixDiameterLimit.valueChanged)
|
||||
signals.append(self.form.HelixMaxDiameterPercent.valueChanged)
|
||||
signals.append(self.form.HelixMinDiameterPercent.valueChanged)
|
||||
signals.append(self.form.LiftDistance.valueChanged)
|
||||
signals.append(self.form.KeepToolDownRatio.valueChanged)
|
||||
signals.append(self.form.StockToLeave.valueChanged)
|
||||
@@ -88,11 +89,14 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
FreeCAD.Units.Quantity(obj.HelixAngle, FreeCAD.Units.Angle).UserString
|
||||
)
|
||||
|
||||
self.form.HelixMaxStepdown.setProperty("rawValue", obj.HelixMaxStepdown.Value)
|
||||
|
||||
self.form.HelixConeAngle.setText(
|
||||
FreeCAD.Units.Quantity(obj.HelixConeAngle, FreeCAD.Units.Angle).UserString
|
||||
)
|
||||
|
||||
self.form.HelixDiameterLimit.setProperty("rawValue", obj.HelixDiameterLimit.Value)
|
||||
self.form.HelixMaxDiameterPercent.setValue(obj.HelixMaxDiameterPercent)
|
||||
self.form.HelixMinDiameterPercent.setValue(obj.HelixMinDiameterPercent)
|
||||
|
||||
self.form.LiftDistance.setProperty("rawValue", obj.LiftDistance.Value)
|
||||
|
||||
@@ -124,10 +128,16 @@ class TaskPanelOpPage(PathOpGui.TaskPanelPage):
|
||||
if obj.StepOver != self.form.stepOverPercent.value():
|
||||
obj.StepOver = self.form.stepOverPercent.value()
|
||||
|
||||
if obj.HelixMaxDiameterPercent != self.form.HelixMaxDiameterPercent.value():
|
||||
obj.HelixMaxDiameterPercent = self.form.HelixMaxDiameterPercent.value()
|
||||
|
||||
if obj.HelixMinDiameterPercent != self.form.HelixMinDiameterPercent.value():
|
||||
obj.HelixMinDiameterPercent = self.form.HelixMinDiameterPercent.value()
|
||||
|
||||
obj.Tolerance = 1.0 * self.form.Tolerance.value() / 100.0
|
||||
PathGuiUtil.updateInputField(obj, "HelixAngle", self.form.HelixAngle)
|
||||
PathGuiUtil.updateInputField(obj, "HelixMaxStepdown", self.form.HelixMaxStepdown)
|
||||
PathGuiUtil.updateInputField(obj, "HelixConeAngle", self.form.HelixConeAngle)
|
||||
PathGuiUtil.updateInputField(obj, "HelixDiameterLimit", self.form.HelixDiameterLimit)
|
||||
PathGuiUtil.updateInputField(obj, "LiftDistance", self.form.LiftDistance)
|
||||
|
||||
if hasattr(obj, "KeepToolDownRatio"):
|
||||
|
||||
@@ -1773,17 +1773,15 @@ std::list<AdaptiveOutput> Adaptive2d::Execute(
|
||||
lastProgressTime = clock();
|
||||
stopProcessing = false;
|
||||
|
||||
if (helixRampDiameter < NTOL) {
|
||||
helixRampDiameter = 0.75 * toolDiameter;
|
||||
}
|
||||
if (helixRampDiameter > toolDiameter) {
|
||||
helixRampDiameter = toolDiameter;
|
||||
}
|
||||
if (helixRampDiameter < toolDiameter / 8) {
|
||||
helixRampDiameter = toolDiameter / 8;
|
||||
if (helixRampTargetDiameter < NTOL) {
|
||||
helixRampTargetDiameter = toolDiameter;
|
||||
}
|
||||
helixRampTargetDiameter = min(helixRampTargetDiameter, toolDiameter);
|
||||
helixRampMinDiameter = max(helixRampMinDiameter, toolDiameter / 8);
|
||||
helixRampTargetDiameter = max(helixRampTargetDiameter, helixRampMinDiameter);
|
||||
|
||||
helixRampRadiusScaled = long(helixRampDiameter * scaleFactor / 2);
|
||||
helixRampMaxRadiusScaled = long(helixRampTargetDiameter * scaleFactor / 2);
|
||||
helixRampMinRadiusScaled = long(helixRampMinDiameter * scaleFactor / 2);
|
||||
if (finishingProfile) {
|
||||
finishPassOffsetScaled = long(stepOverScaled / 10);
|
||||
}
|
||||
@@ -1812,7 +1810,7 @@ std::list<AdaptiveOutput> Adaptive2d::Execute(
|
||||
#ifdef DEV_MODE
|
||||
cout << "optimalCutAreaPD:" << optimalCutAreaPD << " scaleFactor:" << scaleFactor
|
||||
<< " toolRadiusScaled:" << toolRadiusScaled
|
||||
<< " helixRampRadiusScaled:" << helixRampRadiusScaled << endl;
|
||||
<< " helixRampMaxRadiusScaled:" << helixRampMaxRadiusScaled << endl;
|
||||
#endif
|
||||
//******************************
|
||||
// Convert input paths to clipper
|
||||
@@ -1912,8 +1910,8 @@ std::list<AdaptiveOutput> Adaptive2d::Execute(
|
||||
|
||||
if (opType == OperationType::otProfilingInside || opType == OperationType::otProfilingOutside) {
|
||||
double offset = opType == OperationType::otProfilingInside
|
||||
? -2 * (helixRampRadiusScaled + toolRadiusScaled) - MIN_STEP_CLIPPER
|
||||
: 2 * (helixRampRadiusScaled + toolRadiusScaled) + MIN_STEP_CLIPPER;
|
||||
? -2 * (helixRampMaxRadiusScaled + toolRadiusScaled) - MIN_STEP_CLIPPER
|
||||
: 2 * (helixRampMaxRadiusScaled + toolRadiusScaled) + MIN_STEP_CLIPPER;
|
||||
for (const auto& current : inputPaths) {
|
||||
int nesting = getPathNestingLevel(current, inputPaths);
|
||||
if (nesting % 2 != 0 && (polyTreeNestingLimit == 0 || nesting <= polyTreeNestingLimit)) {
|
||||
@@ -1977,7 +1975,8 @@ bool Adaptive2d::FindEntryPoint(
|
||||
ClearedArea& clearedArea /*output-initial cleared area by helix*/,
|
||||
IntPoint& entryPoint /*output*/,
|
||||
IntPoint& toolPos,
|
||||
DoublePoint& toolDir
|
||||
DoublePoint& toolDir,
|
||||
long& helixRadiusScaled
|
||||
)
|
||||
{
|
||||
Paths incOffset;
|
||||
@@ -2018,13 +2017,12 @@ bool Adaptive2d::FindEntryPoint(
|
||||
}
|
||||
}
|
||||
// check if helix fits
|
||||
if (found) {
|
||||
// make initial polygon cleared by helix ramp
|
||||
const auto checkHelixFit = [&](long testHelixRadiusScaled) {
|
||||
clipof.Clear();
|
||||
Path p1;
|
||||
p1.push_back(entryPoint);
|
||||
clipof.AddPath(p1, JoinType::jtRound, EndType::etOpenRound);
|
||||
clipof.Execute(clearedPaths, helixRampRadiusScaled + toolRadiusScaled);
|
||||
clipof.Execute(clearedPaths, (double)(testHelixRadiusScaled + toolRadiusScaled));
|
||||
CleanPolygons(clearedPaths);
|
||||
// we got first cleared area - check if it is crossing boundary
|
||||
clip.Clear();
|
||||
@@ -2032,11 +2030,32 @@ bool Adaptive2d::FindEntryPoint(
|
||||
clip.AddPaths(boundPaths, PolyType::ptClip, true);
|
||||
Paths crossing;
|
||||
clip.Execute(ClipType::ctDifference, crossing);
|
||||
if (!crossing.empty()) {
|
||||
// helix does not fit to the cutting area
|
||||
|
||||
return crossing.empty();
|
||||
};
|
||||
|
||||
if (found) {
|
||||
// check that helix fits, and make initial polygon cleared by helix ramp
|
||||
if (!checkHelixFit(helixRampMinRadiusScaled)) {
|
||||
// min-size helix does not fit
|
||||
found = false;
|
||||
}
|
||||
else {
|
||||
// find the largest helix that fits
|
||||
// minSize = largest known fit; maxSize = largest possible fit
|
||||
long minSize = helixRampMinRadiusScaled;
|
||||
long maxSize = helixRampMaxRadiusScaled;
|
||||
while (minSize < maxSize) {
|
||||
long testSize = (minSize + maxSize + 1) / 2; // always testSize > minSize
|
||||
if (checkHelixFit(testSize)) {
|
||||
minSize = testSize;
|
||||
}
|
||||
else {
|
||||
maxSize = testSize - 1; // always maxSize >= minSize
|
||||
}
|
||||
}
|
||||
helixRadiusScaled = minSize;
|
||||
checkHelixFit(helixRadiusScaled); // set clearedPaths for final size
|
||||
clearedArea.SetClearedPaths(clearedPaths);
|
||||
}
|
||||
}
|
||||
@@ -2070,14 +2089,15 @@ bool Adaptive2d::FindEntryPoint(
|
||||
hp << entryPoint;
|
||||
clipof.AddPath(hp, JoinType::jtRound, EndType::etOpenRound);
|
||||
Paths hps;
|
||||
clipof.Execute(hps, helixRampRadiusScaled);
|
||||
clipof.Execute(hps, helixRadiusScaled);
|
||||
AddPathsToProgress(progressPaths, hps);
|
||||
|
||||
toolPos = IntPoint(entryPoint.X, entryPoint.Y - helixRampRadiusScaled);
|
||||
toolPos = IntPoint(entryPoint.X, entryPoint.Y - helixRadiusScaled);
|
||||
toolDir = DoublePoint(1.0, 0.0);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
bool Adaptive2d::FindEntryPointOutside(
|
||||
TPaths& progressPaths,
|
||||
const Paths& toolBoundPaths,
|
||||
@@ -2780,6 +2800,7 @@ void Adaptive2d::ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths)
|
||||
ClipperOffset clipof;
|
||||
|
||||
IntPoint entryPoint;
|
||||
long helixRadiusScaled;
|
||||
TPaths progressPaths;
|
||||
progressPaths.reserve(10000);
|
||||
|
||||
@@ -2824,7 +2845,16 @@ void Adaptive2d::ProcessPolyNode(Paths boundPaths, Paths toolBoundPaths)
|
||||
outsideEntry = true;
|
||||
}
|
||||
else {
|
||||
if (!FindEntryPoint(progressPaths, toolBoundPaths, boundPaths, cleared, entryPoint, toolPos, toolDir)) {
|
||||
if (!FindEntryPoint(
|
||||
progressPaths,
|
||||
toolBoundPaths,
|
||||
boundPaths,
|
||||
cleared,
|
||||
entryPoint,
|
||||
toolPos,
|
||||
toolDir,
|
||||
helixRadiusScaled
|
||||
)) {
|
||||
Perf_ProcessPolyNode.Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,8 @@ class Adaptive2d
|
||||
public:
|
||||
Adaptive2d();
|
||||
double toolDiameter = 5;
|
||||
double helixRampDiameter = 0;
|
||||
double helixRampTargetDiameter = 0;
|
||||
double helixRampMinDiameter = 0;
|
||||
double stepOverFactor = 0.2;
|
||||
double tolerance = 0.1;
|
||||
double stockToLeave = 0;
|
||||
@@ -118,7 +119,8 @@ private:
|
||||
double stepOverScaled = 1;
|
||||
long toolRadiusScaled = 10;
|
||||
long finishPassOffsetScaled = 0;
|
||||
long helixRampRadiusScaled = 0;
|
||||
long helixRampMaxRadiusScaled = 0;
|
||||
long helixRampMinRadiusScaled = 0;
|
||||
double referenceCutArea = 0;
|
||||
double optimalCutAreaPD = 0;
|
||||
bool stopProcessing = false;
|
||||
@@ -136,7 +138,8 @@ private:
|
||||
ClearedArea& cleared /*output*/,
|
||||
IntPoint& entryPoint /*output*/,
|
||||
IntPoint& toolPos,
|
||||
DoublePoint& toolDir
|
||||
DoublePoint& toolDir,
|
||||
long& helixRadiusScaled
|
||||
);
|
||||
bool FindEntryPointOutside(
|
||||
TPaths& progressPaths,
|
||||
|
||||
@@ -426,7 +426,8 @@ void init_pyarea(py::module& m)
|
||||
.def_readwrite("stepOverFactor", &Adaptive2d::stepOverFactor)
|
||||
.def_readwrite("toolDiameter", &Adaptive2d::toolDiameter)
|
||||
.def_readwrite("stockToLeave", &Adaptive2d::stockToLeave)
|
||||
.def_readwrite("helixRampDiameter", &Adaptive2d::helixRampDiameter)
|
||||
.def_readwrite("helixRampTargetDiameter", &Adaptive2d::helixRampTargetDiameter)
|
||||
.def_readwrite("helixRampMinDiameter", &Adaptive2d::helixRampMinDiameter)
|
||||
.def_readwrite("forceInsideOut", &Adaptive2d::forceInsideOut)
|
||||
.def_readwrite("finishingProfile", &Adaptive2d::finishingProfile)
|
||||
//.def_readwrite("polyTreeNestingLimit", &Adaptive2d::polyTreeNestingLimit)
|
||||
|
||||
Reference in New Issue
Block a user