Files
ajandClaude Opus 5.5 b026bd19d2 feat(common-line): place parts on common lines automatically at a chosen level
Slice 3 of common-line cutting. On costly plate (N26-295: 3/16 RA310S at about
$2,500 a sheet) pairing parts one kerf apart fits the part the spacing cannot:
the last plate's 38 parts fit on one 48x120 with Auto Nest only with pairs.

- Drawing Properties gains "Allow common line" (Drawing.AllowCommonLine, off by
  default because customer edge-quality needs vary). The nest's CommonLineUsage
  (Off / When it adds parts / Whenever available) is set in Auto Nest and seeded
  from Tools > Nest Defaults; both persist (nest.json, defaults.json).
- NestPipeline runs the ordinary solve, then, with a level on, trials where
  eligible parts are offered as kerf-gap pair compounds. Placed pairs expand into
  parts plus explicit NestJobCommonLine groups, are validated again, and
  CommonLineRanking keeps a trial only by the level: count first, then sheets;
  "when it adds parts" keeps the plain layout on a tie, "whenever" also takes a
  shorter cut or less material, never at the cost of a part. Engines, FillScore
  and their comparers are unchanged; Off asks the engine exactly what it did.
- NestLayoutCheck exempts members only through a sheet's explicit group list and
  only when the job allows common lines; materializing and committing create
  Plate.CommonLines.
- Server nesting writes common-line jobs as version 3 and replays the recorded
  trial answers, so the desktop binds the same groups.
- Fill Area honors the level through a PlateFillService overload.
- The benchmark gains --common-lines <level> --kerf <k>.

Benchmark (synthetic nests + N26-295, --parallel 1): with no flag and with
--common-lines off every engine matches the base commit; with a level on no
layout becomes invalid and three runs save a sheet at equal nested area.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 19:38:00 -05:00

47 lines
1.6 KiB
C#

using System.Windows.Forms;
using OpenNest.CNC;
using OpenNest.Forms;
namespace OpenNest.WinForms.Tests.Forms;
public class CommonLineUsageFormTests
{
[Theory]
[InlineData(false)]
[InlineData(true)]
public void DrawingProperties_LoadsAndSavesAllowCommonLine(bool allow) => RunSta(() =>
{
var drawing = new Drawing("pair", new Program()) { AllowCommonLine = allow };
using var form = new EditDrawingForm();
form.LoadDrawing(drawing);
var box = Assert.IsType<CheckBox>(form.Controls.Find("allowCommonLineBox", true).Single());
Assert.Equal(allow, box.Checked);
box.Checked = !allow;
form.SaveDrawing(drawing);
Assert.Equal(!allow, drawing.AllowCommonLine);
});
[Theory]
[InlineData(CommonLineUsage.Off, 0)]
[InlineData(CommonLineUsage.WhenItAddsParts, 1)]
[InlineData(CommonLineUsage.Whenever, 2)]
public void AutoNest_StartsAtTheNestsUsage_AndReadsTheChoice(CommonLineUsage usage, int index) =>
RunSta(() =>
{
var nest = new Nest { CommonLineUsage = usage };
using var form = new AutoNestForm(nest);
var combo = Assert.IsType<ComboBox>(form.Controls.Find("commonLineComboBox", true).Single());
Assert.Equal(index, combo.SelectedIndex);
Assert.Equal(usage, form.CommonLineUsage);
combo.SelectedIndex = (index + 1) % 3;
Assert.Equal((CommonLineUsage)((index + 1) % 3), form.CommonLineUsage);
});
private static void RunSta(Action action) =>
StaTestThread.Run(action, TimeSpan.FromSeconds(15), "The STA test did not complete.");
}