feat(cutting): let a tab alone hold parts up to 6 in new settings

Small parts on a coarse support grid (the help tutorial's 5 x 5 gussets
on a 2 inch grid) rest on one or two points, so no single tab could
steady them and every plan came back unverified. New cutting settings
now start "Tab alone holds parts up to" at 6; settings saved without the
field still read as 0, so existing settings keep their meaning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ajandClaude Opus 5.5 committed 2026-11-02 16:54:59 -05:00
1 parent bfc36d166c
commit 8a282d53cf
3 files changed
+37 -3

No files matched your search

@@ -81,9 +81,9 @@ namespace OpenNest.CNC.CuttingStrategy
/// With <see cref="SupportTabs"/> on a plate with a support bed, the longest part (the
/// long side of its outline's minimum-area bounding rectangle) its tab alone holds: such a
/// part the bed cannot hold level is tabbed, and any tab clear of inside corners steadies
/// it. 0 turns the rule off.
/// it. 0 turns the rule off. New settings start at 6; settings saved without it read as 0.
/// </summary>
public double TabHeldMaxLength { get; set; }
public double TabHeldMaxLength { get; set; } = 6;
/// <summary>Whether a part <paramref name="length"/> long is held by its tab alone (see <see cref="TabHeldMaxLength"/>).</summary>
public bool TabHoldsAt(double length) =>
@@ -60,6 +60,35 @@ public class TabHeldSupportTabTests
Assert.Equal(holdsALengthOfOneAndAHalf, new CuttingParameters { TabHeldMaxLength = max }.TabHoldsAt(1.5));
}
[Theory]
[InlineData(0)]
[InlineData(45)]
[InlineData(90)]
[InlineData(135)]
[InlineData(180)]
[InlineData(270)]
[InlineData(315)]
public void LengthOfATriangleWithTwoLeastBoxes_DoesNotDependOnItsRotation(double degrees)
{
// A 5 x 5 right triangle fits its legs' square and its hypotenuse's 7.07 x 3.54 box, both
// of area 25: the squarer box is the one measured, whatever way the part is turned.
var triangle = new Program();
triangle.MoveTo(0, 0); triangle.LineTo(5, 0); triangle.LineTo(0, 5); triangle.LineTo(0, 0);
var part = new Part(new Drawing("gusset", triangle), new Vector(10, 10));
part.Rotate(degrees * System.Math.PI / 180);
var material = SupportMaterial.FromPart(part);
Assert.Equal(5, SupportAnalyzer.Length(material), 6);
Assert.Equal(5, SupportAnalyzer.Width(material), 6);
}
[Fact]
public void NewSettingsHoldPartsUpToSixLong()
{
Assert.Equal(6, new CuttingParameters().TabHeldMaxLength);
Assert.True(new CuttingParameters().TabHoldsAt(5));
}
[Fact]
public void Analyze_HoldsAShortPartTheBedCannotByAnyClearTab()
{
+6 -1
View File
@@ -102,7 +102,12 @@ hold level whose length (the long side of its outline's minimum-area bounding re
`SupportAnalyzer.Length`) is at most that, bound included, is still tabbed, but
`SupportAnalyzer.HeldByTab` marks its analysis `IsHeldByTab`: it keeps its contacts and margin,
every tab clear of inside corners steadies it, and its best tab point is chosen as on a plate
with no bed (below). A part the bed holds is not tabbed. 0 turns the rule off.
with no bed (below). A part the bed holds is not tabbed. 0 turns the rule off; new settings
start at 6, while settings saved without the field read as 0, so saved settings keep their
meaning. Some outlines have two minimum-area rectangles (a right isosceles triangle fits both
its legs' square and its hypotenuse's 2:1 box), and which one rounding finds depends on how the
part is turned; of rectangles tied for area, `SupportAnalyzer` measures the one with the shorter
long side, so a drawing's length and width are the same at every rotation.
`SupportTabSettings.Analyze` applies it for Plan Cutting, hand-placed lead-ins and the pre-post
review alike, so such a part warns only when it is cut with no tab at all. View > Draw Support
does not read cutting settings and still shows it red, since it would tip without its tab.