diff --git a/OpenNest.IO/Extensions.cs b/OpenNest.IO/Extensions.cs
index 34fab3b..5128b1b 100644
--- a/OpenNest.IO/Extensions.cs
+++ b/OpenNest.IO/Extensions.cs
@@ -181,13 +181,22 @@ namespace OpenNest.IO
{
var center = new Vector(ellipse.Center.X, ellipse.Center.Y);
var majorAxis = new Vector(ellipse.MajorAxisEndPoint.X, ellipse.MajorAxisEndPoint.Y);
- var semiMajor = System.Math.Sqrt(majorAxis.X * majorAxis.X + majorAxis.Y * majorAxis.Y);
- var semiMinor = semiMajor * ellipse.RadiusRatio;
- var rotation = System.Math.Atan2(majorAxis.Y, majorAxis.X);
var startParam = ellipse.StartParameter;
var endParam = ellipse.EndParameter;
+ if (ellipse.Normal.Z < 0)
+ {
+ var newStart = OpenNest.Math.Angle.TwoPI - endParam;
+ var newEnd = OpenNest.Math.Angle.TwoPI - startParam;
+ startParam = newStart;
+ endParam = newEnd;
+ }
+
+ var semiMajor = System.Math.Sqrt(majorAxis.X * majorAxis.X + majorAxis.Y * majorAxis.Y);
+ var semiMinor = semiMajor * ellipse.RadiusRatio;
+ var rotation = System.Math.Atan2(majorAxis.Y, majorAxis.X);
+
var layer = ellipse.Layer.ToOpenNest();
var color = ellipse.ResolveColor();
var lineTypeName = ellipse.ResolveLineTypeName();
diff --git a/OpenNest.IO/OpenNest.IO.csproj b/OpenNest.IO/OpenNest.IO.csproj
index 1d048f7..436b75f 100644
--- a/OpenNest.IO/OpenNest.IO.csproj
+++ b/OpenNest.IO/OpenNest.IO.csproj
@@ -4,6 +4,9 @@
OpenNest.IO
OpenNest.IO
+
+
+
diff --git a/OpenNest.Tests/Geometry/EllipseConverterTests.cs b/OpenNest.Tests/Geometry/EllipseConverterTests.cs
index b068bac..7115260 100644
--- a/OpenNest.Tests/Geometry/EllipseConverterTests.cs
+++ b/OpenNest.Tests/Geometry/EllipseConverterTests.cs
@@ -1,4 +1,5 @@
using OpenNest.Geometry;
+using OpenNest.IO;
using OpenNest.Math;
using Xunit;
using System.Linq;
@@ -244,6 +245,81 @@ public class EllipseConverterTests
}
}
+ [Fact]
+ public void ToOpenNest_FlippedNormalZ_ProducesCorrectArcs()
+ {
+ var normal = new ACadSharp.Entities.Ellipse
+ {
+ Center = new CSMath.XYZ(-0.275, -0.245, 0),
+ MajorAxisEndPoint = new CSMath.XYZ(0.0001, 1.245, 0),
+ RadiusRatio = 0.28,
+ StartParameter = 0.017,
+ EndParameter = 1.571,
+ Normal = new CSMath.XYZ(0, 0, 1)
+ };
+
+ var flipped = new ACadSharp.Entities.Ellipse
+ {
+ Center = new CSMath.XYZ(0.275, -0.245, 0),
+ MajorAxisEndPoint = new CSMath.XYZ(-0.0001, 1.245, 0),
+ RadiusRatio = 0.28,
+ StartParameter = 0.017,
+ EndParameter = 1.571,
+ Normal = new CSMath.XYZ(0, 0, -1)
+ };
+
+ var normalArcs = normal.ToOpenNest();
+ var flippedArcs = flipped.ToOpenNest();
+
+ Assert.True(normalArcs.Count > 0);
+ Assert.True(flippedArcs.Count > 0);
+ Assert.True(normalArcs.All(e => e is Arc));
+ Assert.True(flippedArcs.All(e => e is Arc));
+
+ var normalFirst = (Arc)normalArcs.First();
+ var flippedFirst = (Arc)flippedArcs.First();
+ var normalStart = GetArcStart(normalFirst);
+ var flippedStart = GetArcStart(flippedFirst);
+
+ Assert.True(normalStart.X < 0, $"Normal ellipse start X should be negative, got {normalStart.X}");
+ Assert.True(flippedStart.X > 0, $"Flipped ellipse should bulge right, got {flippedStart.X}");
+
+ var normalBbox = GetBoundingBox(normalArcs.Cast());
+ var flippedBbox = GetBoundingBox(flippedArcs.Cast());
+ Assert.True(flippedBbox.minX > 0, $"Flipped ellipse should stay on positive X side, minX={flippedBbox.minX}");
+ Assert.True(normalBbox.maxX < 0, $"Normal ellipse should stay on negative X side, maxX={normalBbox.maxX}");
+ }
+
+ private static (double minX, double maxX) GetBoundingBox(IEnumerable arcs)
+ {
+ var minX = double.MaxValue;
+ var maxX = double.MinValue;
+ foreach (var arc in arcs)
+ {
+ var s = GetArcStart(arc);
+ var e = GetArcEnd(arc);
+ minX = System.Math.Min(minX, System.Math.Min(s.X, e.X));
+ maxX = System.Math.Max(maxX, System.Math.Max(s.X, e.X));
+ }
+ return (minX, maxX);
+ }
+
+ private static Vector GetArcStart(Arc arc)
+ {
+ var angle = arc.IsReversed ? arc.EndAngle : arc.StartAngle;
+ return new Vector(
+ arc.Center.X + arc.Radius * System.Math.Cos(angle),
+ arc.Center.Y + arc.Radius * System.Math.Sin(angle));
+ }
+
+ private static Vector GetArcEnd(Arc arc)
+ {
+ var angle = arc.IsReversed ? arc.StartAngle : arc.EndAngle;
+ return new Vector(
+ arc.Center.X + arc.Radius * System.Math.Cos(angle),
+ arc.Center.Y + arc.Radius * System.Math.Sin(angle));
+ }
+
private static double MaxDeviationFromEllipse(Arc arc, Vector ellipseCenter,
double semiMajor, double semiMinor, double rotation, int samples)
{