using System; using System.Collections.Generic; using OpenNest.Geometry; namespace OpenNest; /// /// Maps a plate's , stored in the sheet's lower-left frame /// (), into the signed placement frame of its parts, /// cut-offs and motions. The translation matches the sheet itself and the engine stock: /// -Length on X in quadrants 2 and 3, -Width on Y in quadrants 3 and 4. Whole footprints are /// kept, never clipped. Every plate uses the sheet frame, including plates the engine builds /// from a NestPlateStock, so this is the only translation any consumer applies. /// public static class ClampZoneFrame { /// /// Detached placement-frame copies in the plate's zone order; empty when there are none. /// Throws for a missing or malformed zone: zone bounds stay /// publicly mutable, so construction-time validation is not proof of current geometry. /// public static IReadOnlyList ToPlacement(Plate plate) { ArgumentNullException.ThrowIfNull(plate); var zones = plate.ClampZones; if (zones == null || zones.Count == 0) return Array.Empty(); if (plate.Quadrant is < 1 or > 4) throw new ArgumentException("Quadrant must be 1 through 4.", nameof(plate)); var left = plate.Quadrant is 2 or 3 ? -plate.Size.Length : 0; var bottom = plate.Quadrant is 3 or 4 ? -plate.Size.Width : 0; if (!double.IsFinite(left) || !double.IsFinite(bottom)) throw new ArgumentException("Sheet size must be finite.", nameof(plate)); var mapped = new ClampZone[zones.Count]; for (var i = 0; i < mapped.Length; i++) { var zone = zones[i]; if (zone?.Bounds == null) throw new ArgumentException($"Clamp zone {i + 1} is missing.", nameof(plate)); var box = zone.Bounds; var x = box.X + left; var y = box.Y + bottom; if (!(box.Length > 0) || !(box.Width > 0) || !double.IsFinite(box.Length) || !double.IsFinite(box.Width) || !double.IsFinite(box.X) || !double.IsFinite(box.Y) || !double.IsFinite(x) || !double.IsFinite(y) || !double.IsFinite(x + box.Length) || !double.IsFinite(y + box.Width)) throw new ArgumentException( $"Clamp zone '{zone.Id}' must have finite bounds and a positive size.", nameof(plate)); mapped[i] = new ClampZone(zone.Id, new Box(x, y, box.Length, box.Width)); } return mapped; } }