Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 58 additions & 2 deletions src/ACadSharp.Tests/IO/DXF/DxfWriterSingleObjectTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using ACadSharp.IO;
using ACadSharp.Entities;
using ACadSharp.IO;
using CSMath;
using System.IO;
using System.Linq;
using Xunit;
using Xunit.Abstractions;

Expand Down Expand Up @@ -51,6 +54,59 @@ public void WriteCasesAC1032(SingleCaseGenerator data)
this.writeDxfFile(data, ACadVersion.AC1032);
}

[Theory]
[InlineData(-90, 270, -90, 270)]
[InlineData(180, 540, -180, 180)]
[InlineData(-540, -180, -180, 180)]
[InlineData(540, 180, 180, -180)]
[InlineData(-180, -540, 180, -180)]
[InlineData(0, 360, 0, 360)]
[InlineData(0, -360, 0, -360)]
[InlineData(360, 720, 0, 360)]
[InlineData(90, 90, 90, 90)]
[InlineData(0, 90, 0, 90)]
[InlineData(450, 540, 90, 180)]
[InlineData(-540, -450, -180, -90)]
public void WriteHatchNormalizesBoundaryAngles(double startDegrees, double endDegrees, double expectedStartDegrees, double expectedEndDegrees)
{
double startAngle = MathHelper.DegToRad(startDegrees);
double endAngle = MathHelper.DegToRad(endDegrees);
double expectedStartAngle = MathHelper.DegToRad(expectedStartDegrees);
double expectedEndAngle = MathHelper.DegToRad(expectedEndDegrees);

SingleCaseGenerator data = new SingleCaseGenerator();
data.CreateHatchFullSweeps();

Hatch hatch = Assert.Single(data.Document.Entities.OfType<Hatch>());
Hatch.BoundaryPath.Arc arc = Assert.Single(
hatch.Paths.SelectMany(p => p.Edges).OfType<Hatch.BoundaryPath.Arc>());
Hatch.BoundaryPath.Ellipse ellipse = Assert.Single(
hatch.Paths.SelectMany(p => p.Edges).OfType<Hatch.BoundaryPath.Ellipse>());
arc.StartAngle = ellipse.StartAngle = startAngle;
arc.EndAngle = ellipse.EndAngle = endAngle;
ellipse.CounterClockWise = false;

using MemoryStream output = new MemoryStream();
DxfWriter.Write(output, data.Document);

using MemoryStream input = new MemoryStream(output.ToArray());
CadDocument result = DxfReader.Read(input);
Hatch writtenHatch = Assert.Single(result.Entities.OfType<Hatch>());
arc = Assert.Single(writtenHatch.Paths.SelectMany(p => p.Edges).OfType<Hatch.BoundaryPath.Arc>());
ellipse = Assert.Single(writtenHatch.Paths.SelectMany(p => p.Edges).OfType<Hatch.BoundaryPath.Ellipse>());

Assert.Equal(expectedStartAngle, arc.StartAngle, 12);
Assert.Equal(expectedEndAngle, arc.EndAngle, 12);
Assert.Equal(expectedStartAngle, ellipse.StartAngle, 12);
Assert.Equal(expectedEndAngle, ellipse.EndAngle, 12);
Assert.InRange(arc.StartAngle, -MathHelper.TwoPI, MathHelper.TwoPI);
Assert.InRange(arc.EndAngle, -MathHelper.TwoPI, MathHelper.TwoPI);
Assert.InRange(ellipse.StartAngle, -MathHelper.TwoPI, MathHelper.TwoPI);
Assert.InRange(ellipse.EndAngle, -MathHelper.TwoPI, MathHelper.TwoPI);
Assert.True(arc.CounterClockWise);
Assert.False(ellipse.CounterClockWise);
}

protected void writeDxfFile(SingleCaseGenerator data, ACadVersion version)
{
Assert.True(data.HasExecuted, $"The writer has failed during it's execution.");
Expand Down Expand Up @@ -84,4 +140,4 @@ protected void writeDxfFile(SingleCaseGenerator data, ACadVersion version)
}
}
}
}
}
34 changes: 33 additions & 1 deletion src/ACadSharp.Tests/IO/WriterSingleObjectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static WriterSingleObjectTests()
Data.Add(new(nameof(SingleCaseGenerator.CreateHatchPolyline)));
Data.Add(new(nameof(SingleCaseGenerator.CreateHatch)));
Data.Add(new(nameof(SingleCaseGenerator.CreateCircleHatch)));
Data.Add(new(nameof(SingleCaseGenerator.CreateHatchFullSweeps)));
Data.Add(new(nameof(SingleCaseGenerator.HatchWithEntities)));
Data.Add(new(nameof(SingleCaseGenerator.ChangedEncoding)));
Data.Add(new(nameof(SingleCaseGenerator.AddBlockWithAttributes)));
Expand Down Expand Up @@ -739,6 +740,37 @@ public void CreateHatch()
this.Document.Entities.Add(hatch);
}

public void CreateHatchFullSweeps()
{
Hatch hatch = new Hatch { IsSolid = true };
hatch.SeedPoints.Add(XY.Zero);

Hatch.BoundaryPath arcPath = new Hatch.BoundaryPath();
arcPath.Edges.Add(new Hatch.BoundaryPath.Arc
{
Center = XY.Zero,
Radius = 2,
StartAngle = -MathHelper.HalfPI,
EndAngle = MathHelper.ThreeHalfPI,
CounterClockWise = true,
});
hatch.Paths.Add(arcPath);

Hatch.BoundaryPath ellipsePath = new Hatch.BoundaryPath();
ellipsePath.Edges.Add(new Hatch.BoundaryPath.Ellipse
{
Center = new XY(5, 0),
MajorAxisEndPoint = new XY(2, 0),
RadiusRatio = 0.5,
StartAngle = Math.PI,
EndAngle = 3 * Math.PI,
CounterClockWise = true,
});
hatch.Paths.Add(ellipsePath);

this.Document.Entities.Add(hatch);
}

public void CreateHatchPolyline()
{
Hatch hatch = new Hatch();
Expand Down Expand Up @@ -2014,4 +2046,4 @@ public void XRef()
this.Document.Entities.Add(new Insert(record));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,26 @@ private void writeHatch(Hatch hatch)
//TODO: Implement HatchGradientPattern
}

private void writeHatchBoundaryAngles(double startAngle, double endAngle)
{
double start = MathHelper.RadToDeg(startAngle, normalize: true, absolute: false);
double end = MathHelper.RadToDeg(endAngle, normalize: true, absolute: false);

if (MathHelper.IsEqual(Math.Abs(endAngle - startAngle), MathHelper.TwoPI))
{
// Keep a full sweep distinct without writing angles outside -360 to 360.
double sweep = endAngle > startAngle ? 360.0 : -360.0;
if (Math.Abs(start + sweep) > 360.0)
{
start -= sweep;
}
end = start + sweep;
}

this._writer.Write(50, start);
this._writer.Write(51, end);
}

private void writeHatchBoundaryPathEdge(Hatch.BoundaryPath.Edge edge)
{
if (edge is not Hatch.BoundaryPath.Polyline)
Expand All @@ -528,16 +548,14 @@ private void writeHatchBoundaryPathEdge(Hatch.BoundaryPath.Edge edge)
case Hatch.BoundaryPath.Arc arc:
this._writer.Write(10, arc.Center);
this._writer.Write(40, arc.Radius);
this._writer.Write(50, MathHelper.RadToDeg(arc.StartAngle));
this._writer.Write(51, MathHelper.RadToDeg(arc.EndAngle));
this.writeHatchBoundaryAngles(arc.StartAngle, arc.EndAngle);
this._writer.Write(73, arc.CounterClockWise ? (short)1 : (short)0);
break;
case Hatch.BoundaryPath.Ellipse ellipse:
this._writer.Write(10, ellipse.Center);
this._writer.Write(11, ellipse.MajorAxisEndPoint);
this._writer.Write(40, ellipse.RadiusRatio);
this._writer.Write(50, MathHelper.RadToDeg(ellipse.StartAngle));
this._writer.Write(51, MathHelper.RadToDeg(ellipse.EndAngle));
this.writeHatchBoundaryAngles(ellipse.StartAngle, ellipse.EndAngle);
this._writer.Write(73, ellipse.CounterClockWise ? (short)1 : (short)0);
break;
case Hatch.BoundaryPath.Line line:
Expand Down
Loading