namespace OpenNest.Data; /// /// A machine's fixed edge-clamp rail, stored on its in the machine's /// units. New nests assigned the machine copy it as their own rail; editing it never changes an /// existing nest. validates the stored values field by field. /// public sealed class MachineClamps { /// Whether new nests assigned this machine receive the rail. Default off. public bool Enabled { get; set; } /// Clamp extent along its edge. public double Width { get; set; } = ClampSettings.DefaultWidth; /// Clamp intrusion into the sheet from its edge. public double Depth { get; set; } = ClampSettings.DefaultDepth; /// Minutes to remove one clamp and put it back after cutting; never scaled. public double RemovalMinutes { get; set; } = ClampRail.DefaultRemovalMinutes; /// Origin-side clamp centers along X, measured from the plate origin. public List Centers { get; set; } = new(); /// Far-side clamp centers along X, measured from the plate origin. public List FarSideCenters { get; set; } = new(); /// Origin-end clamp centers along Y, measured from the plate origin. public List OriginEndCenters { get; set; } = new(); /// Far-end clamp centers along Y, measured from the plate origin. public List FarEndCenters { get; set; } = new(); /// The matching a machine's . public static Units UnitsOf(UnitSystem units) => units == UnitSystem.Millimeters ? Units.Millimeters : Units.Inches; /// /// converted to a machine in , e.g. for /// "Save as Machine Defaults" from a nest in other units or the clamps.json migration. /// public static MachineClamps FromSettings(ClampSettings settings, UnitSystem units) { ArgumentNullException.ThrowIfNull(settings); var converted = settings.ConvertedTo(UnitsOf(units)); return new MachineClamps { Enabled = converted.Enabled, Width = converted.Width, Depth = converted.Depth, RemovalMinutes = converted.RemovalMinutes, Centers = converted.Centers.ToList(), FarSideCenters = converted.FarSideCenters.ToList(), OriginEndCenters = converted.OriginEndCenters.ToList(), FarEndCenters = converted.FarEndCenters.ToList(), }; } /// /// The rail as clamp settings in the machine's . An invalid size or /// removal time falls back to the default, and an invalid center is dropped, as when /// reads a file. /// public ClampSettings ToSettings(UnitSystem units) { var defaults = ClampSettings.FromRail(null, UnitsOf(units), Enabled); if (IsLength(Width) && Width > 0) defaults.Width = Width; if (IsLength(Depth) && Depth > 0) defaults.Depth = Depth; if (IsLength(RemovalMinutes) && RemovalMinutes >= 0) defaults.RemovalMinutes = RemovalMinutes; defaults.Centers = Valid(Centers); defaults.FarSideCenters = Valid(FarSideCenters); defaults.OriginEndCenters = Valid(OriginEndCenters); defaults.FarEndCenters = Valid(FarEndCenters); return defaults; } private static double[] Valid(IEnumerable? centers) => (centers ?? Enumerable.Empty()).Where(c => IsLength(c) && c >= 0).Distinct().Order().ToArray(); // Finite in either unit, so converting to an inch or millimeter nest cannot overflow. private static bool IsLength(double value) => double.IsFinite(value) && double.IsFinite(value * 25.4); }