diff --git a/src/Mod/CAM/CAMTests/TestPathAdaptive.py b/src/Mod/CAM/CAMTests/TestPathAdaptive.py
index ab3b498e34..bbef17870a 100644
--- a/src/Mod/CAM/CAMTests/TestPathAdaptive.py
+++ b/src/Mod/CAM/CAMTests/TestPathAdaptive.py
@@ -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
diff --git a/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui b/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui
index d2b1d43549..fa6b76ab74 100644
--- a/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui
+++ b/src/Mod/CAM/Gui/Resources/panels/PageOpAdaptiveEdit.ui
@@ -66,7 +66,7 @@
-
-
+
Accuracy vs performance
@@ -164,29 +164,15 @@ Larger values (further to the right) will calculate faster; smaller values (furt
100
+
+ %
+
-
- Step over percent
-
-
-
- -
-
-
- Angle of the helix entry cone
-
-
-
-
-
-
- -
-
-
- Helix ramp angle
+ Step over
@@ -221,33 +207,6 @@ Larger values (further to the right) will calculate faster; smaller values (furt
- -
-
-
- If greater than zero it limits the helix ramp diameter, otherwise 75 percent of tool diameter is used
-
-
-
-
-
-
- -
-
-
- Helix cone angle
-
-
-
- -
-
-
- Angle of the helix ramp entry
-
-
-
-
-
-
-
@@ -272,10 +231,131 @@ Larger values (further to the right) will calculate faster; smaller values (furt
+
+
+
+ -
+
+
+ QFrame::Shape::StyledPanel
+
+
+ QFrame::Shadow::Raised
+
+
+
-
+
+
+ <b>Helix Parameters</b>
+
+
+
+ -
+
+
+ Max stepdown
+
+
+
+ -
+
+
+ The maximum allowable descent in a single revolution of the helix.
+
+
+
+
+
+
+ -
+
+
+ Ramp angle
+
+
+
+ -
+
+
+ Angle of the helix ramp entry
+
+
+
+
+
+
+ -
+
+
+ Cone angle
+
+
+
+ -
+
+
+ Angle of the helix entry cone
+
+
+
+
+
+
-
- Helix max diameter
+ Max diameter
+
+
+
+ -
+
+
+ Maximum (and nominal) helix entry diameter, as a percentage of the tool diameter.
+
+
+ 10
+
+
+ 100
+
+
+ 5
+
+
+ %
+
+
+ 1
+
+
+
+ -
+
+
+ Min diameter
+
+
+
+ -
+
+
+ Minimum acceptable entry diameter, as a percentage of the tool diameter.
+
+
+ 10
+
+
+ 100
+
+
+ 5
+
+
+ %
+
+
+ 1
diff --git a/src/Mod/CAM/Path/Op/Adaptive.py b/src/Mod/CAM/Path/Op/Adaptive.py
index 4d8fb39dce..b6a69f7fd8 100644
--- a/src/Mod/CAM/Path/Op/Adaptive.py
+++ b/src/Mod/CAM/Path/Op/Adaptive.py
@@ -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",
]
diff --git a/src/Mod/CAM/Path/Op/Gui/Adaptive.py b/src/Mod/CAM/Path/Op/Gui/Adaptive.py
index 3e94602ca0..70c98b3ef4 100644
--- a/src/Mod/CAM/Path/Op/Gui/Adaptive.py
+++ b/src/Mod/CAM/Path/Op/Gui/Adaptive.py
@@ -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"):
diff --git a/src/Mod/CAM/libarea/Adaptive.cpp b/src/Mod/CAM/libarea/Adaptive.cpp
index 5a3015a190..d0a52c477d 100644
--- a/src/Mod/CAM/libarea/Adaptive.cpp
+++ b/src/Mod/CAM/libarea/Adaptive.cpp
@@ -1773,17 +1773,15 @@ std::list 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 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 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;
}
diff --git a/src/Mod/CAM/libarea/Adaptive.hpp b/src/Mod/CAM/libarea/Adaptive.hpp
index 03b63ad270..4c0690eab8 100644
--- a/src/Mod/CAM/libarea/Adaptive.hpp
+++ b/src/Mod/CAM/libarea/Adaptive.hpp
@@ -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,
diff --git a/src/Mod/CAM/libarea/pyarea.cpp b/src/Mod/CAM/libarea/pyarea.cpp
index ee3cfd483b..5cecf5c1b3 100644
--- a/src/Mod/CAM/libarea/pyarea.cpp
+++ b/src/Mod/CAM/libarea/pyarea.cpp
@@ -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)