mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 19:41:08 -04:00
Clamps are physical fixtures that differ between machines, but one global clamps.json served every machine, so a plasma table and a fiber laser could not have different rails. - MachineConfig.Clamps holds each machine's rail in the machine's units, edited on a new Clamps tab in Tools > Machine Configuration. - New and BOM import give a nest the rail of the machine they assign; Nest > Clamps loads and saves the nest's machine's clamps. Each nest keeps its own copy, so machine edits never move existing nests' clamps. - At startup, while no machine has clamps, the legacy clamps.json (or the server's shared copy) is copied once into the default or only machine; with several machines and no default the user picks one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
86 lines
3.9 KiB
C#
86 lines
3.9 KiB
C#
namespace OpenNest.Data;
|
|
|
|
/// <summary>
|
|
/// A machine's fixed edge-clamp rail, stored on its <see cref="MachineConfig"/> in the machine's
|
|
/// units. New nests assigned the machine copy it as their own rail; editing it never changes an
|
|
/// existing nest. <see cref="ToSettings"/> validates the stored values field by field.
|
|
/// </summary>
|
|
public sealed class MachineClamps
|
|
{
|
|
/// <summary>Whether new nests assigned this machine receive the rail. Default off.</summary>
|
|
public bool Enabled { get; set; }
|
|
|
|
/// <summary>Clamp extent along its edge.</summary>
|
|
public double Width { get; set; } = ClampSettings.DefaultWidth;
|
|
|
|
/// <summary>Clamp intrusion into the sheet from its edge.</summary>
|
|
public double Depth { get; set; } = ClampSettings.DefaultDepth;
|
|
|
|
/// <summary>Minutes to remove one clamp and put it back after cutting; never scaled.</summary>
|
|
public double RemovalMinutes { get; set; } = ClampRail.DefaultRemovalMinutes;
|
|
|
|
/// <summary>Origin-side clamp centers along X, measured from the plate origin.</summary>
|
|
public List<double> Centers { get; set; } = new();
|
|
|
|
/// <summary>Far-side clamp centers along X, measured from the plate origin.</summary>
|
|
public List<double> FarSideCenters { get; set; } = new();
|
|
|
|
/// <summary>Origin-end clamp centers along Y, measured from the plate origin.</summary>
|
|
public List<double> OriginEndCenters { get; set; } = new();
|
|
|
|
/// <summary>Far-end clamp centers along Y, measured from the plate origin.</summary>
|
|
public List<double> FarEndCenters { get; set; } = new();
|
|
|
|
/// <summary>The <see cref="Units"/> matching a machine's <see cref="UnitSystem"/>.</summary>
|
|
public static Units UnitsOf(UnitSystem units) =>
|
|
units == UnitSystem.Millimeters ? Units.Millimeters : Units.Inches;
|
|
|
|
/// <summary>
|
|
/// <paramref name="settings"/> converted to a machine in <paramref name="units"/>, e.g. for
|
|
/// "Save as Machine Defaults" from a nest in other units or the clamps.json migration.
|
|
/// </summary>
|
|
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(),
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// The rail as clamp settings in the machine's <paramref name="units"/>. An invalid size or
|
|
/// removal time falls back to the default, and an invalid center is dropped, as when
|
|
/// <see cref="ClampSettings.Parse"/> reads a file.
|
|
/// </summary>
|
|
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<double>? centers) =>
|
|
(centers ?? Enumerable.Empty<double>()).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);
|
|
}
|