From 203bd4eeea2e3b2a2d69a6f9caddfe849c56f585 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Fri, 27 Mar 2026 17:34:15 -0400 Subject: [PATCH] feat: add BomImportForm nest creation logic Task 9: CreateNests_Click validates plate dimensions, then for each MaterialGroup creates a Nest with name '{job} - {thickness} {material}', sets PlateDefaults (size, thickness, material, quadrant=1, spacing), imports each matched DXF via DxfImporter, converts entities to Program with leading RapidMove offset handling (same pattern as CadConverterForm), sets Quantity.Required from BOM qty, then opens an EditNestForm for each nest that has drawings. Summary MessageBox reports count and import errors. Co-Authored-By: Claude Sonnet 4.6 --- OpenNest/Forms/BomImportForm.cs | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/OpenNest/Forms/BomImportForm.cs b/OpenNest/Forms/BomImportForm.cs index d8705b5..a9e042a 100644 --- a/OpenNest/Forms/BomImportForm.cs +++ b/OpenNest/Forms/BomImportForm.cs @@ -126,6 +126,95 @@ namespace OpenNest.Forms private void CreateNests_Click(object sender, EventArgs e) { + if (!double.TryParse(txtPlateWidth.Text, out var plateWidth) || plateWidth <= 0) + { + MessageBox.Show("Plate width must be a positive number.", "Validation Error", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + if (!double.TryParse(txtPlateLength.Text, out var plateLength) || plateLength <= 0) + { + MessageBox.Show("Plate length must be a positive number.", "Validation Error", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + var jobName = txtJobName.Text.Trim(); + var nestsCreated = 0; + var importErrors = new List(); + + foreach (var group in _analysis.Groups) + { + var nestName = $"{jobName} - {group.Thickness:0.###} {group.Material}"; + var nest = new Nest(nestName); + nest.DateCreated = DateTime.Now; + nest.DateLastModified = DateTime.Now; + nest.PlateDefaults.Size = new Size(plateWidth, plateLength); + nest.PlateDefaults.Thickness = group.Thickness; + nest.PlateDefaults.Material = new Material(group.Material); + nest.PlateDefaults.Quadrant = 1; + nest.PlateDefaults.PartSpacing = 1; + nest.PlateDefaults.EdgeSpacing = new Spacing(1, 1, 1, 1); + + foreach (var matched in group.Parts) + { + if (string.IsNullOrWhiteSpace(matched.DxfPath) || !File.Exists(matched.DxfPath)) + { + importErrors.Add($"{matched.Item.FileName}: DXF file not found"); + continue; + } + + try + { + var importer = new DxfImporter(); + var result = importer.Import(matched.DxfPath); + + var drawingName = Path.GetFileNameWithoutExtension(matched.DxfPath); + var drawing = new Drawing(drawingName); + drawing.Source.Path = matched.DxfPath; + drawing.Quantity.Required = matched.Item.Qty ?? 1; + + var pgm = ConvertGeometry.ToProgram(result.Entities); + + if (pgm.Codes.Count > 0 && pgm[0].Type == CodeType.RapidMove) + { + var rapid = (RapidMove)pgm[0]; + drawing.Source.Offset = rapid.EndPoint; + pgm.Offset(-rapid.EndPoint); + pgm.Codes.RemoveAt(0); + } + + drawing.Program = pgm; + nest.Drawings.Add(drawing); + } + catch (Exception ex) + { + importErrors.Add($"{matched.Item.FileName}: {ex.Message}"); + } + } + + if (nest.Drawings.Count == 0) + continue; + + nest.CreatePlate(); + + var editForm = new EditNestForm(nest); + editForm.MdiParent = MdiParentForm; + editForm.Show(); + editForm.PlateView.ZoomToFit(); + + nestsCreated++; + } + + var summary = $"{nestsCreated} nest{(nestsCreated != 1 ? "s" : "")} created."; + if (importErrors.Count > 0) + summary += $"\n\n{importErrors.Count} import error(s):\n" + string.Join("\n", importErrors); + + MessageBox.Show(summary, "Import Complete", MessageBoxButtons.OK, + importErrors.Count > 0 ? MessageBoxIcon.Warning : MessageBoxIcon.Information); + + Close(); } private void BtnClose_Click(object sender, EventArgs e)