diff --git a/PepApi.Core/Configuration/PepSettings.cs b/PepApi.Core/Configuration/PepSettings.cs index c110328..8ea31bb 100644 --- a/PepApi.Core/Configuration/PepSettings.cs +++ b/PepApi.Core/Configuration/PepSettings.cs @@ -4,4 +4,5 @@ public class PepSettings { public string NestDirectory { get; set; } = string.Empty; public string MaterialsFile { get; set; } = string.Empty; + public string DrawingsDirectory { get; set; } = string.Empty; } diff --git a/PepApi.Core/Models/NestFilterData.cs b/PepApi.Core/Models/NestFilterData.cs index 7960c39..d613d8d 100644 --- a/PepApi.Core/Models/NestFilterData.cs +++ b/PepApi.Core/Models/NestFilterData.cs @@ -77,7 +77,7 @@ namespace PepApi.Core.Models nests = nests.Where(n => n.DateCreated <= this.EndDate); } - if (this.Status != null) + if (this.Status != null && !this.Status.Equals("All", StringComparison.OrdinalIgnoreCase)) { var x = this.Status.ToUpper(); nests = nests.Where(n => n.Status.ToUpper() == x); diff --git a/PepLib.Core/IO/DrawingDxfExporter.cs b/PepLib.Core/IO/DrawingDxfExporter.cs index 917bc8b..461d1c7 100644 --- a/PepLib.Core/IO/DrawingDxfExporter.cs +++ b/PepLib.Core/IO/DrawingDxfExporter.cs @@ -1,4 +1,4 @@ -using ACadSharp; +using ACadSharp; using ACadSharp.IO; using ACadSharp.Tables; using CSMath; @@ -17,76 +17,29 @@ public static class DrawingDxfExporter public static Stream Export(Drawing drawing) { var doc = new CadDocument(); + doc.Header.Version = ACadVersion.AC1018; + + // Collect loop IDs that are called as subprograms so we skip drawing them as top-level + var subprogramIds = new HashSet(); + foreach (var loop in drawing.Loops) + { + foreach (var code in loop) + { + if (code.CodeType() == CodeType.SubProgramCall) + subprogramIds.Add(((SubProgramCall)code).LoopId); + } + } foreach (var loop in drawing.Loops) { + var loopNumber = GetLoopNumber(loop.Name); + if (subprogramIds.Contains(loopNumber)) + continue; // drawn inline at SubProgramCall positions + var layer = new Layer(loop.Name); doc.Layers.Add(layer); - var pos = new Vector(); - - foreach (var code in loop) - { - switch (code.CodeType()) - { - case CodeType.RapidMove: - pos = Advance(pos, ((RapidMove)code).EndPoint, loop.Mode); - break; - - case CodeType.LinearMove: - var lm = (LinearMove)code; - var lineEnd = Advance(pos, lm.EndPoint, loop.Mode); - doc.Entities.Add(new AcadLine - { - StartPoint = ToXYZ(pos), - EndPoint = ToXYZ(lineEnd), - Layer = layer - }); - pos = lineEnd; - break; - - case CodeType.CircularMove: - var cm = (CircularMove)code; - var arcEnd = Advance(pos, cm.EndPoint, loop.Mode); - var arcCenter = Advance(pos, cm.CenterPoint, loop.Mode); - - var dx = pos.X - arcCenter.X; - var dy = pos.Y - arcCenter.Y; - var radius = Math.Sqrt(dx * dx + dy * dy); - - var startAngle = Math.Atan2(pos.Y - arcCenter.Y, pos.X - arcCenter.X); - var endAngle = Math.Atan2(arcEnd.Y - arcCenter.Y, arcEnd.X - arcCenter.X); - - if (cm.Rotation == RotationType.CW) - { - (startAngle, endAngle) = (endAngle, startAngle); - } - - if (Math.Abs(startAngle - endAngle) < 1e-10) // full circle - { - doc.Entities.Add(new AcadCircle - { - Center = ToXYZ(arcCenter), - Radius = radius, - Layer = layer - }); - } - else - { - doc.Entities.Add(new AcadArc - { - Center = ToXYZ(arcCenter), - Radius = radius, - StartAngle = startAngle * (180.0 / Math.PI), - EndAngle = endAngle * (180.0 / Math.PI), - Layer = layer - }); - } - - pos = arcEnd; - break; - } - } + DrawLoop(doc, drawing, loop, layer, new Vector()); } var buffer = new MemoryStream(); @@ -95,8 +48,97 @@ public static class DrawingDxfExporter writer.Write(); } - var stream = new MemoryStream(buffer.ToArray()); - return stream; + return new MemoryStream(buffer.ToArray()); + } + + private static Vector DrawLoop(CadDocument doc, Drawing drawing, Loop loop, Layer layer, Vector startPos) + { + var pos = startPos; + + foreach (var code in loop) + { + switch (code.CodeType()) + { + case CodeType.RapidMove: + pos = Advance(pos, ((RapidMove)code).EndPoint, loop.Mode); + break; + + case CodeType.LinearMove: + var lm = (LinearMove)code; + if (lm.Type == EntityType.Cut) + { + var lineEnd = Advance(pos, lm.EndPoint, loop.Mode); + doc.Entities.Add(new AcadLine + { + StartPoint = ToXYZ(pos), + EndPoint = ToXYZ(lineEnd), + Layer = layer + }); + pos = lineEnd; + } + else + { + pos = Advance(pos, lm.EndPoint, loop.Mode); + } + break; + + case CodeType.CircularMove: + var cm = (CircularMove)code; + var arcEnd = Advance(pos, cm.EndPoint, loop.Mode); + var arcCenter = Advance(pos, cm.CenterPoint, loop.Mode); + + var dx = pos.X - arcCenter.X; + var dy = pos.Y - arcCenter.Y; + var radius = Math.Sqrt(dx * dx + dy * dy); + + var startAngle = Math.Atan2(pos.Y - arcCenter.Y, pos.X - arcCenter.X); + var endAngle = Math.Atan2(arcEnd.Y - arcCenter.Y, arcEnd.X - arcCenter.X); + + if (cm.Rotation == RotationType.CW) + (startAngle, endAngle) = (endAngle, startAngle); + + if (Math.Abs(startAngle - endAngle) < 1e-10) + { + doc.Entities.Add(new AcadCircle + { + Center = ToXYZ(arcCenter), + Radius = radius, + Layer = layer + }); + } + else + { + doc.Entities.Add(new AcadArc + { + Center = ToXYZ(arcCenter), + Radius = radius, + StartAngle = startAngle, + EndAngle = endAngle, + Layer = layer + }); + } + + pos = arcEnd; + break; + + case CodeType.SubProgramCall: + var call = (SubProgramCall)code; + var subLoop = drawing.Loops.FirstOrDefault(l => l.Name == drawing.GetLoopName(call.LoopId)); + if (subLoop != null) + DrawLoop(doc, drawing, subLoop, layer, pos); + // pos unchanged — subprograms are closed shapes that return to start + break; + } + } + + return pos; + } + + private static int GetLoopNumber(string loopName) + { + var idx = loopName.LastIndexOf(".loop-", StringComparison.OrdinalIgnoreCase); + if (idx < 0) return -1; + return int.TryParse(loopName.Substring(idx + 6), out var n) ? n : -1; } private static Vector Advance(Vector current, Vector offset, ProgrammingMode mode) => @@ -104,4 +146,3 @@ public static class DrawingDxfExporter private static XYZ ToXYZ(Vector v) => new XYZ(v.X, v.Y, 0); } - diff --git a/PepLib.Core/IO/DrawingInfoReader.cs b/PepLib.Core/IO/DrawingInfoReader.cs index 7009f89..e3394a2 100644 --- a/PepLib.Core/IO/DrawingInfoReader.cs +++ b/PepLib.Core/IO/DrawingInfoReader.cs @@ -34,7 +34,8 @@ namespace PepLib.IO stream.Seek(0x9, SeekOrigin.Current); - Info.MaterialNumber = int.Parse(ReadString(0x40, ref stream)); + int.TryParse(ReadString(0x40, ref stream), out var materialNumber); + Info.MaterialNumber = materialNumber; Info.MaterialGrade = ReadString(0x10, ref stream); Info.ProgrammedBy = ReadString(0x40, ref stream); Info.CreatedBy = ReadString(0x40, ref stream); diff --git a/PepLib.Core/IO/DrawingReader.cs b/PepLib.Core/IO/DrawingReader.cs index 189bde8..be8aa98 100644 --- a/PepLib.Core/IO/DrawingReader.cs +++ b/PepLib.Core/IO/DrawingReader.cs @@ -1,5 +1,4 @@ using PepLib.Models; -using System.Diagnostics; using System.IO.Compression; using System.Text.RegularExpressions; @@ -38,6 +37,11 @@ namespace PepLib.IO LoadInfo(memstream); memstream.Close(); continue; + + case ".loop-info": + case ".cadsnapshot": + memstream.Close(); + continue; } if (Regex.IsMatch(extension, "loop-\\d\\d\\d")) @@ -47,6 +51,9 @@ namespace PepLib.IO } } + if (Drawing.Info == null) + Drawing.Info = DeriveInfoFromLoops(); + Drawing.ResolveLoops(); } @@ -62,7 +69,7 @@ namespace PepLib.IO try { - stream = new FileStream(nestFile, FileMode.Open); + stream = new FileStream(nestFile, FileMode.Open, FileAccess.Read, FileShare.Read); Read(stream); } finally @@ -74,15 +81,22 @@ namespace PepLib.IO private void LoadInfo(Stream stream) { - try + Drawing.Info = DrawingInfo.Load(stream); + } + + private DrawingInfo DeriveInfoFromLoops() + { + var info = new DrawingInfo(); + + if (Drawing.Loops.Count > 0) { - Drawing.Info = DrawingInfo.Load(stream); - } - catch (Exception exception) - { - Debug.WriteLine(exception.Message); - Debug.WriteLine(exception.StackTrace); + // Loop names follow the pattern "{DrawingName}.loop-XXX" + var loopName = Drawing.Loops[0].Name; + var suffix = loopName.LastIndexOf(".loop-", StringComparison.OrdinalIgnoreCase); + info.Name = suffix >= 0 ? loopName.Substring(0, suffix) : loopName; } + + return info; } private Loop ReadLoop(string name, Stream stream) diff --git a/PepLib.Core/Models/Drawing.cs b/PepLib.Core/Models/Drawing.cs index 705c426..92908ea 100644 --- a/PepLib.Core/Models/Drawing.cs +++ b/PepLib.Core/Models/Drawing.cs @@ -76,7 +76,7 @@ namespace PepLib.Models return null; } - private string GetLoopName(int loopId) + public string GetLoopName(int loopId) { return string.Format("{0}.loop-{1}", Info.Name, loopId.ToString().PadLeft(3, '0')); } diff --git a/PepLib.Core/Utilities/ZipHelper.cs b/PepLib.Core/Utilities/ZipHelper.cs index 2362486..16aaf05 100644 --- a/PepLib.Core/Utilities/ZipHelper.cs +++ b/PepLib.Core/Utilities/ZipHelper.cs @@ -18,7 +18,7 @@ namespace PepLib.Utilities var nameList = new List(); var streamList = new List(); - using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) + using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var zip = new ZipArchive(fileStream, ZipArchiveMode.Read)) { foreach (var entry in zip.Entries) @@ -52,7 +52,7 @@ namespace PepLib.Utilities /// public static bool ExtractByExtension(string file, string extension, out string name, out Stream stream) { - using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) + using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var zip = new ZipArchive(fileStream, ZipArchiveMode.Read)) { foreach (var entry in zip.Entries)