using System; using System.Collections.Generic; using OpenNest.CNC.CuttingStrategy; using OpenNest.Geometry; using static OpenNest.IO.CuttingParametersDto; using static OpenNest.IO.NestFormat; namespace OpenNest.IO; /// /// Maps drawing cut pins to and from the nest file. Reading is strict per pin: unlike desktop /// settings, an unknown lead or tab type is not replaced by a default, because a pin that cut /// differently from what was saved would be worse than no pin. /// internal static class CutPinFormat { private static readonly HashSet LeadInTypes = new(StringComparer.Ordinal) { "None", "Line", "Arc", "LineArc", "CleanHole", "LineLine" }; private static readonly HashSet LeadOutTypes = new(StringComparer.Ordinal) { "None", "Line", "Arc" }; private static readonly HashSet TabTypes = new(StringComparer.Ordinal) { "Normal", "Machine", "Breaker" }; internal static CutPinDto ToDto(ContourCutPin pin) => new() { X = pin.Point.X, Y = pin.Point.Y, LeadIn = CuttingParametersSerializer.ToLeadInDto(pin.LeadIn), LeadOut = CuttingParametersSerializer.ToLeadOutDto(pin.LeadOut), Tab = pin.HasTab ? CuttingParametersSerializer.ToTabDto(pin.Tab) : null, }; /// Builds the pin, or returns null with the reason it cannot be trusted. internal static ContourCutPin Read(CutPinDto dto, out string problem) { problem = null; if (dto == null || dto.Malformed) return Fail("it is not a readable pin", out problem); if (!IsLeadIn(dto.LeadIn)) return Fail("its lead-in is missing or of an unknown type", out problem); if (!IsLeadOut(dto.LeadOut)) return Fail("its lead-out is missing or of an unknown type", out problem); if (dto.Tab != null && (!TabTypes.Contains(dto.Tab.Type ?? "") || dto.Tab.TabLeadIn != null && !IsLeadIn(dto.Tab.TabLeadIn) || dto.Tab.TabLeadOut != null && !IsLeadOut(dto.Tab.TabLeadOut))) return Fail("its tab is of an unknown type", out problem); try { return new ContourCutPin( new Vector(dto.X, dto.Y), CuttingParametersSerializer.FromLeadInDto(dto.LeadIn), CuttingParametersSerializer.FromLeadOutDto(dto.LeadOut), dto.Tab == null ? null : CuttingParametersSerializer.FromTabDto(dto.Tab)); } catch (Exception ex) when (ex is ArgumentException || ex is NotSupportedException) { return Fail(ex.Message, out problem); } } private static bool IsLeadIn(LeadInDto dto) => dto != null && LeadInTypes.Contains(dto.Type ?? ""); private static bool IsLeadOut(LeadOutDto dto) => dto != null && LeadOutTypes.Contains(dto.Type ?? ""); private static ContourCutPin Fail(string reason, out string problem) { problem = reason; return null; } }