Files
PepApi.Core/PepLib.Core/IO/DrawingDxfExporter.cs
T
ajandClaude Sonnet 4.6 7a4a35da55 fix: convert arc angles from radians to degrees in DrawingDxfExporter
ACadSharp Arc.StartAngle/EndAngle store values in degrees (DXF spec groups
50/51). The previous code passed Math.Atan2 results (radians) directly,
causing silent geometry corruption. Also hardened the arc export test to
assert angles are in degree range (0..360).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 06:53:17 -04:00

108 lines
3.6 KiB
C#

using ACadSharp;
using ACadSharp.IO;
using ACadSharp.Tables;
using CSMath;
using PepLib.Codes;
using PepLib.Enums;
using PepLib.Geometry;
using PepLib.Models;
using AcadArc = ACadSharp.Entities.Arc;
using AcadCircle = ACadSharp.Entities.Circle;
using AcadLine = ACadSharp.Entities.Line;
namespace PepLib.IO;
public static class DrawingDxfExporter
{
public static Stream Export(Drawing drawing)
{
var doc = new CadDocument();
foreach (var loop in drawing.Loops)
{
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;
}
}
}
var buffer = new MemoryStream();
using (var writer = new DxfWriter(buffer, doc, false))
{
writer.Write();
}
var stream = new MemoryStream(buffer.ToArray());
return stream;
}
private static Vector Advance(Vector current, Vector offset, ProgrammingMode mode) =>
mode == ProgrammingMode.Incremental ? current + offset : offset;
private static XYZ ToXYZ(Vector v) => new XYZ(v.X, v.Y, 0);
}