feat: add SplitDxfWriter for split DXF output with bend data
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
177
OpenNest.IO/SplitDxfWriter.cs
Normal file
177
OpenNest.IO/SplitDxfWriter.cs
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
using ACadSharp;
|
||||||
|
using ACadSharp.Entities;
|
||||||
|
using ACadSharp.IO;
|
||||||
|
using ACadSharp.Tables;
|
||||||
|
using CSMath;
|
||||||
|
using OpenNest.Bending;
|
||||||
|
using OpenNest.Converters;
|
||||||
|
using OpenNest.Geometry;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
// Disambiguate Entity — both ACadSharp.Entities and OpenNest.Geometry define it
|
||||||
|
using GeoEntity = OpenNest.Geometry.Entity;
|
||||||
|
|
||||||
|
namespace OpenNest.IO
|
||||||
|
{
|
||||||
|
public class SplitDxfWriter
|
||||||
|
{
|
||||||
|
private const double DefaultEtchLength = 1.0;
|
||||||
|
|
||||||
|
public double EtchLength { get; set; } = DefaultEtchLength;
|
||||||
|
|
||||||
|
public void Write(string path, Drawing drawing)
|
||||||
|
{
|
||||||
|
var doc = new CadDocument();
|
||||||
|
|
||||||
|
var cutLayer = new ACadSharp.Tables.Layer("CUT") { Color = new Color(7) };
|
||||||
|
var bendLayer = new ACadSharp.Tables.Layer("BEND") { Color = new Color(2) };
|
||||||
|
var etchLayer = new ACadSharp.Tables.Layer("ETCH") { Color = new Color(3) };
|
||||||
|
doc.Layers.Add(cutLayer);
|
||||||
|
doc.Layers.Add(bendLayer);
|
||||||
|
doc.Layers.Add(etchLayer);
|
||||||
|
|
||||||
|
var centerLineType = new LineType("CENTERX2");
|
||||||
|
doc.LineTypes.Add(centerLineType);
|
||||||
|
|
||||||
|
WriteProgramEntities(doc, drawing.Program, cutLayer);
|
||||||
|
|
||||||
|
if (drawing.Bends != null)
|
||||||
|
{
|
||||||
|
foreach (var bend in drawing.Bends)
|
||||||
|
{
|
||||||
|
WriteBendLine(doc, bend, bendLayer, centerLineType);
|
||||||
|
WriteEtchLines(doc, bend, etchLayer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using var stream = File.Create(path);
|
||||||
|
using var writer = new DxfWriter(stream, doc, false);
|
||||||
|
writer.Write();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteProgramEntities(CadDocument doc, CNC.Program program, ACadSharp.Tables.Layer layer)
|
||||||
|
{
|
||||||
|
var geometry = ConvertProgram.ToGeometry(program);
|
||||||
|
WriteGeometryEntities(doc, geometry, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteGeometryEntities(CadDocument doc, List<GeoEntity> geometry, ACadSharp.Tables.Layer layer)
|
||||||
|
{
|
||||||
|
foreach (var entity in geometry)
|
||||||
|
{
|
||||||
|
// Skip rapid moves
|
||||||
|
if (entity.Layer == SpecialLayers.Rapid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (entity)
|
||||||
|
{
|
||||||
|
case OpenNest.Geometry.Line line:
|
||||||
|
doc.Entities.Add(new ACadSharp.Entities.Line
|
||||||
|
{
|
||||||
|
StartPoint = new XYZ(line.StartPoint.X, line.StartPoint.Y, 0),
|
||||||
|
EndPoint = new XYZ(line.EndPoint.X, line.EndPoint.Y, 0),
|
||||||
|
Layer = layer
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OpenNest.Geometry.Arc arc:
|
||||||
|
var startAngle = arc.StartAngle;
|
||||||
|
var endAngle = arc.EndAngle;
|
||||||
|
if (arc.IsReversed)
|
||||||
|
OpenNest.Math.Generic.Swap(ref startAngle, ref endAngle);
|
||||||
|
|
||||||
|
doc.Entities.Add(new ACadSharp.Entities.Arc
|
||||||
|
{
|
||||||
|
Center = new XYZ(arc.Center.X, arc.Center.Y, 0),
|
||||||
|
Radius = arc.Radius,
|
||||||
|
StartAngle = startAngle,
|
||||||
|
EndAngle = endAngle,
|
||||||
|
Layer = layer
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OpenNest.Geometry.Circle circle:
|
||||||
|
doc.Entities.Add(new ACadSharp.Entities.Circle
|
||||||
|
{
|
||||||
|
Center = new XYZ(circle.Center.X, circle.Center.Y, 0),
|
||||||
|
Radius = circle.Radius,
|
||||||
|
Layer = layer
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OpenNest.Geometry.Shape shape:
|
||||||
|
WriteGeometryEntities(doc, shape.Entities, layer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteBendLine(CadDocument doc, Bend bend, ACadSharp.Tables.Layer layer, LineType lineType)
|
||||||
|
{
|
||||||
|
var line = new ACadSharp.Entities.Line
|
||||||
|
{
|
||||||
|
StartPoint = new XYZ(bend.StartPoint.X, bend.StartPoint.Y, 0),
|
||||||
|
EndPoint = new XYZ(bend.EndPoint.X, bend.EndPoint.Y, 0),
|
||||||
|
Layer = layer,
|
||||||
|
LineType = lineType
|
||||||
|
};
|
||||||
|
doc.Entities.Add(line);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(bend.NoteText))
|
||||||
|
{
|
||||||
|
var midX = (bend.StartPoint.X + bend.EndPoint.X) / 2;
|
||||||
|
var midY = (bend.StartPoint.Y + bend.EndPoint.Y) / 2;
|
||||||
|
|
||||||
|
var mtext = new MText
|
||||||
|
{
|
||||||
|
InsertPoint = new XYZ(midX, midY + 0.5, 0),
|
||||||
|
Value = bend.NoteText,
|
||||||
|
Height = 0.1,
|
||||||
|
Layer = layer
|
||||||
|
};
|
||||||
|
doc.Entities.Add(mtext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteEtchLines(CadDocument doc, Bend bend, ACadSharp.Tables.Layer layer)
|
||||||
|
{
|
||||||
|
if (bend.Direction != BendDirection.Up)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var start = bend.StartPoint;
|
||||||
|
var end = bend.EndPoint;
|
||||||
|
var length = bend.Length;
|
||||||
|
|
||||||
|
if (length < EtchLength * 3.0)
|
||||||
|
{
|
||||||
|
doc.Entities.Add(new ACadSharp.Entities.Line
|
||||||
|
{
|
||||||
|
StartPoint = new XYZ(start.X, start.Y, 0),
|
||||||
|
EndPoint = new XYZ(end.X, end.Y, 0),
|
||||||
|
Layer = layer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var angle = start.AngleTo(end);
|
||||||
|
var dx = System.Math.Cos(angle) * EtchLength;
|
||||||
|
var dy = System.Math.Sin(angle) * EtchLength;
|
||||||
|
|
||||||
|
doc.Entities.Add(new ACadSharp.Entities.Line
|
||||||
|
{
|
||||||
|
StartPoint = new XYZ(start.X, start.Y, 0),
|
||||||
|
EndPoint = new XYZ(start.X + dx, start.Y + dy, 0),
|
||||||
|
Layer = layer
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.Entities.Add(new ACadSharp.Entities.Line
|
||||||
|
{
|
||||||
|
StartPoint = new XYZ(end.X, end.Y, 0),
|
||||||
|
EndPoint = new XYZ(end.X - dx, end.Y - dy, 0),
|
||||||
|
Layer = layer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -249,17 +249,19 @@ namespace OpenNest.Forms
|
|||||||
var index = fileList.SelectedIndex;
|
var index = fileList.SelectedIndex;
|
||||||
var newItems = new List<string>();
|
var newItems = new List<string>();
|
||||||
|
|
||||||
|
var splitWriter = new SplitDxfWriter();
|
||||||
|
|
||||||
for (var i = 0; i < form.ResultDrawings.Count; i++)
|
for (var i = 0; i < form.ResultDrawings.Count; i++)
|
||||||
{
|
{
|
||||||
|
var splitDrawing = form.ResultDrawings[i];
|
||||||
|
|
||||||
|
// Assign bends from the source item — spatial filtering is a future enhancement
|
||||||
|
splitDrawing.Bends.AddRange(item.Bends);
|
||||||
|
|
||||||
var splitName = $"{baseName}_split{i + 1}.dxf";
|
var splitName = $"{baseName}_split{i + 1}.dxf";
|
||||||
var splitPath = GetUniquePath(Path.Combine(writableDir, splitName));
|
var splitPath = GetUniquePath(Path.Combine(writableDir, splitName));
|
||||||
|
|
||||||
// TODO: Use SplitDxfWriter when implemented
|
splitWriter.Write(splitPath, splitDrawing);
|
||||||
// For now, export via DxfExporter
|
|
||||||
var exporter = new DxfExporter();
|
|
||||||
using var stream = new FileStream(splitPath, FileMode.Create);
|
|
||||||
exporter.ExportProgram(form.ResultDrawings[i].Program, stream);
|
|
||||||
|
|
||||||
newItems.Add(splitPath);
|
newItems.Add(splitPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user