Merge pull request #21193 from davidgilkaufman/adaptive_helix_fixes

[CAM] Adaptive helix fixes
This commit is contained in:
sliptonic
2025-05-12 11:09:16 -05:00
committed by GitHub

View File

@@ -117,14 +117,6 @@ def discretize(edge, flipDirection=False):
return pts
def CalcHelixConePoint(height, cur_z, radius, angle):
x = ((height - cur_z) / height) * radius * math.cos(math.radians(angle) * cur_z)
y = ((height - cur_z) / height) * radius * math.sin(math.radians(angle) * cur_z)
z = cur_z
return {"X": x, "Y": y, "Z": z}
def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
if not adaptiveResults or not adaptiveResults[0]["AdaptivePaths"]:
return
@@ -140,7 +132,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
length = 2 * math.pi * helixRadius
obj.HelixAngle = min(89, max(obj.HelixAngle.Value, 1))
obj.HelixAngle = min(89.99, max(obj.HelixAngle.Value, 0.01))
obj.HelixConeAngle = max(obj.HelixConeAngle, 0)
helixAngleRad = math.radians(obj.HelixAngle)
@@ -173,7 +165,7 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
)
for passEndDepth in depthParams.data:
startAngle = math.atan2(
pass_start_angle = math.atan2(
region["StartPoint"][1] - region["HelixCenterPoint"][1],
region["StartPoint"][0] - region["HelixCenterPoint"][0],
)
@@ -187,19 +179,28 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
# Helix ramp
if helixRadius > 0.01:
r = helixRadius - 0.01
maxfi = passDepth / depthPerOneCircle * 2 * math.pi
fi = 0
offsetFi = -maxfi + startAngle - math.pi / 16
helixStart = [
region["HelixCenterPoint"][0] + r * math.cos(offsetFi),
region["HelixCenterPoint"][1] + r * math.sin(offsetFi),
]
op.commandlist.append(Path.Command("(Helix to depth: %f)" % passEndDepth))
if obj.UseHelixArcs is False:
helix_down_angle = passDepth / depthPerOneCircle * 2 * math.pi
r_bottom = r - (passStartDepth - passEndDepth) * math.tan(
math.radians(obj.HelixConeAngle.Value)
)
r_bottom = max(
r_bottom, r * 0.5
) # put a limit on how small the cone tip can be
step_over = obj.StepOver * 0.01 * op.tool.Diameter.Value
spiral_out_angle = (r - r_bottom) / step_over * 2 * math.pi
helix_base_angle = pass_start_angle - helix_down_angle - spiral_out_angle
helix_angular_progress = 0
helixStart = [
region["HelixCenterPoint"][0] + r * math.cos(helix_base_angle),
region["HelixCenterPoint"][1] + r * math.sin(helix_base_angle),
]
# rapid move to start point
op.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
op.commandlist.append(
@@ -238,117 +239,47 @@ def GenerateGCode(op, obj, adaptiveResults, helixDiameter):
)
)
if obj.HelixConeAngle == 0:
while fi < maxfi:
x = region["HelixCenterPoint"][0] + r * math.cos(fi + offsetFi)
y = region["HelixCenterPoint"][1] + r * math.sin(fi + offsetFi)
z = passStartDepth - fi / maxfi * (passStartDepth - passEndDepth)
op.commandlist.append(
Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.vertFeed})
)
fi = fi + math.pi / 16
# one more circle at target depth to make sure center is cleared
maxfi = maxfi + 2 * math.pi
while fi < maxfi:
x = region["HelixCenterPoint"][0] + r * math.cos(fi + offsetFi)
y = region["HelixCenterPoint"][1] + r * math.sin(fi + offsetFi)
z = passEndDepth
op.commandlist.append(
Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.horizFeed})
)
fi = fi + math.pi / 16
else:
# Cone
_HelixAngle = 360 - (obj.HelixAngle.Value * 4)
if obj.HelixConeAngle > 6:
obj.HelixConeAngle = 6
helixRadius *= 0.9
# Calculate everything
helix_height = passStartDepth - passEndDepth
r_extra = helix_height * math.tan(math.radians(obj.HelixConeAngle))
HelixTopRadius = helixRadius + r_extra
helix_full_height = HelixTopRadius * (
math.cos(math.radians(obj.HelixConeAngle))
/ math.sin(math.radians(obj.HelixConeAngle))
# helix down
while helix_angular_progress < helix_down_angle:
progress = helix_angular_progress / helix_down_angle
r_current = r * (1 - progress) + r_bottom * progress
x = region["HelixCenterPoint"][0] + r_current * math.cos(
helix_angular_progress + helix_base_angle
)
# Start height
z = passStartDepth
i = 0
# Default step down
z_step = 0.05
# Bigger angle, smaller step down
if _HelixAngle > 120:
z_step = 0.025
if _HelixAngle > 240:
z_step = 0.015
p = None
# Calculate conical helix
while z >= passEndDepth:
if z < passEndDepth:
z = passEndDepth
p = CalcHelixConePoint(
helix_full_height, i, HelixTopRadius, _HelixAngle
)
op.commandlist.append(
Path.Command(
"G1",
{
"X": p["X"] + region["HelixCenterPoint"][0],
"Y": p["Y"] + region["HelixCenterPoint"][1],
"Z": z,
"F": op.vertFeed,
},
)
)
z = z - z_step
i = i + z_step
# Calculate some stuff for arcs at bottom
p["X"] = p["X"] + region["HelixCenterPoint"][0]
p["Y"] = p["Y"] + region["HelixCenterPoint"][1]
x_m = region["HelixCenterPoint"][0] - p["X"] + region["HelixCenterPoint"][0]
y_m = region["HelixCenterPoint"][1] - p["Y"] + region["HelixCenterPoint"][1]
i_off = (x_m - p["X"]) / 2
j_off = (y_m - p["Y"]) / 2
# One more circle at target depth to make sure center is cleared
y = region["HelixCenterPoint"][1] + r_current * math.sin(
helix_angular_progress + helix_base_angle
)
z = passStartDepth - progress * (passStartDepth - passEndDepth)
op.commandlist.append(
Path.Command(
"G3",
{
"X": x_m,
"Y": y_m,
"Z": passEndDepth,
"I": i_off,
"J": j_off,
"F": op.horizFeed,
},
)
Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.vertFeed})
)
op.commandlist.append(
Path.Command(
"G3",
{
"X": p["X"],
"Y": p["Y"],
"Z": passEndDepth,
"I": -i_off,
"J": -j_off,
"F": op.horizFeed,
},
)
helix_angular_progress = min(
helix_angular_progress + math.pi / 16, helix_down_angle
)
# spiral out, plus a full extra circle
max_angle = helix_down_angle + spiral_out_angle + 2 * math.pi
while helix_angular_progress < max_angle:
if spiral_out_angle == 0:
progress = 1
else:
progress = min(
1, (helix_angular_progress - helix_down_angle) / spiral_out_angle
)
r_current = r_bottom * (1 - progress) + r * progress
x = region["HelixCenterPoint"][0] + r_current * math.cos(
helix_angular_progress + helix_base_angle
)
y = region["HelixCenterPoint"][1] + r_current * math.sin(
helix_angular_progress + helix_base_angle
)
z = passEndDepth
op.commandlist.append(
Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.horizFeed})
)
helix_angular_progress = min(
helix_angular_progress + math.pi / 16, max_angle
)
else:
# Use arcs for helix - no conical shape support
helixStart = [