Files
OpenNest/Posts/OpenNest.Posts.Cincinnati/CincinnatiHeadRaise.cs
T
ajandClaude Opus 5.5 abfc1a714a feat(posts): trigger the Cincinnati safety head raise by rapid length
The safety raise (M47 P<SafetyHeadraiseDistance>) used to fire only when
the next part had a different drawing name, which has nothing to do with
crash risk: a long rapid between copies of the same part got a plain M47,
while a short hop between neighbouring different drawings got the full
raise. Sheets are rarely flat (5/8" plate can be ~1.5" out of flat within
supplier tolerance), and longer rapids cross more of that bow.

Add SafetyHeadraiseRapidDistance (program units, default 12"): any rapid to
the next pierce longer than it takes the safety raise, regardless of
drawing. Unknown travel never does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 07:08:10 -04:00

45 lines
1.8 KiB
C#

namespace OpenNest.Posts.Cincinnati;
/// <summary>
/// Chooses the M47 head raise (§3.47) written before the rapid that leaves a feature.
/// </summary>
internal static class CincinnatiHeadRaise
{
/// <param name="isExterior">True when the feature just cut is a part exterior.</param>
/// <param name="rapidDistance">Travel to the next pierce; null when unknown.</param>
/// <returns>The block to write, or null for no head raise.</returns>
internal static string Line(CincinnatiPostConfig config, bool isExterior, double? rapidDistance)
{
if (IsSafetyRapid(config, rapidDistance))
return SafetyLine(config);
var mode = isExterior ? config.ExteriorM47 : config.InteriorM47;
return mode switch
{
M47Mode.Always => "M47",
M47Mode.BlockDelete => "/M47",
M47Mode.Auto => IsLongRapid(config, rapidDistance) ? "M47" : "/M47",
_ => null,
};
}
/// <summary>
/// True when the rapid is long enough to cross warped plate, so it takes the
/// safety head raise. Unknown travel never does.
/// </summary>
internal static bool IsSafetyRapid(CincinnatiPostConfig config, double? rapidDistance) =>
config.SafetyHeadraiseDistance.HasValue
&& config.SafetyHeadraiseRapidDistance is { } threshold
&& rapidDistance is { } distance
&& distance > threshold;
internal static string SafetyLine(CincinnatiPostConfig config) =>
$"M47 P{config.SafetyHeadraiseDistance.Value} (Safety Headraise)";
// Unknown travel, or no threshold configured, always gets the full raise.
private static bool IsLongRapid(CincinnatiPostConfig config, double? rapidDistance) =>
config.M47OverrideDistanceThreshold is not { } threshold
|| rapidDistance is not { } distance
|| distance > threshold;
}