diff --git a/src/UglyToad.PdfPig.Core/TransformationMatrix.cs b/src/UglyToad.PdfPig.Core/TransformationMatrix.cs index af08dc8d..a33df15b 100644 --- a/src/UglyToad.PdfPig.Core/TransformationMatrix.cs +++ b/src/UglyToad.PdfPig.Core/TransformationMatrix.cs @@ -22,6 +22,51 @@ public static TransformationMatrix GetTranslationMatrix(double x, double y) => new TransformationMatrix(1, 0, 0, 0, 1, 0, x, y, 1); + + /// + /// Create a new with the X and Y scaling values set. + /// + public static TransformationMatrix GetScaleMatrix(double scaleX, double scaleY) => new TransformationMatrix(scaleX, 0, 0, + 0, scaleY, 0, + 0, 0, 1); + + /// + /// Create a new with the X and Y scaling values set. + /// + public static TransformationMatrix GetRotationMatrix(double degreesCounterclockwise) + { + double cos; + double sin; + + switch (degreesCounterclockwise) + { + case 0: + case 360: + cos = 1; + sin = 0; + break; + case 90: + cos = 0; + sin = 1; + break; + case 180: + cos = -1; + sin = 0; + break; + case 270: + cos = 0; + sin = -1; + break; + default: + cos = Math.Cos(degreesCounterclockwise * (Math.PI / 180)); + sin = Math.Sin(degreesCounterclockwise * (Math.PI / 180)); + break; + } + + return new TransformationMatrix(cos, sin, 0, + -sin, cos, 0, + 0, 0, 1); + } private readonly double row1; private readonly double row2; diff --git a/src/UglyToad.PdfPig.Tests/Geometry/PdfRectangleTests.cs b/src/UglyToad.PdfPig.Tests/Geometry/PdfRectangleTests.cs index 070a0e49..3df83b34 100644 --- a/src/UglyToad.PdfPig.Tests/Geometry/PdfRectangleTests.cs +++ b/src/UglyToad.PdfPig.Tests/Geometry/PdfRectangleTests.cs @@ -6,24 +6,32 @@ public class PdfRectangleTests { + private static readonly DoubleComparer DoubleComparer = new DoubleComparer(3); + private static readonly PointComparer PointComparer = new PointComparer(DoubleComparer); + private static readonly PdfRectangle UnitRectangle = new PdfRectangle(new PdfPoint(0, 0), new PdfPoint(1, 1)); + + [Fact] public void Area() { PdfRectangle rectangle = new PdfRectangle(10, 10, 20, 20); Assert.Equal(100d, rectangle.Area); PdfRectangle rectangle1 = new PdfRectangle(149.95376d, 687.13456d, 451.73539d, 1478.4997d); - Assert.Equal(238819.4618743782d, rectangle1.Area); + Assert.Equal(238819.4618743782d, rectangle1.Area, DoubleComparer); } + [Fact] public void Centroid() { PdfRectangle rectangle = new PdfRectangle(10, 10, 20, 20); Assert.Equal(new PdfPoint(15, 15), rectangle.Centroid); PdfRectangle rectangle1 = new PdfRectangle(149.95376d, 687.13456d, 451.73539d, 1478.4997d); - Assert.Equal(new PdfPoint(300.844575d, 1082.81713d), rectangle1.Centroid); + Assert.Equal(new PdfPoint(300.844575d, 1082.81713d), rectangle1.Centroid, + PointComparer); } + [Fact] public void Intersect() { PdfRectangle rectangle = new PdfRectangle(10, 10, 20, 20); @@ -38,6 +46,7 @@ Assert.Equal(rectangle3, rectangle1.Intersect(rectangle3)); } + [Fact] public void IntersectsWith() { PdfRectangle rectangle = new PdfRectangle(10, 10, 20, 20); @@ -55,6 +64,7 @@ Assert.False(rectangle1.IntersectsWith(rectangle4)); // special case where they share one border } + [Fact] public void Contains() { PdfRectangle rectangle = new PdfRectangle(10, 10, 20, 20); @@ -63,5 +73,85 @@ Assert.True(rectangle.Contains(new PdfPoint(10, 15), true)); Assert.False(rectangle.Contains(new PdfPoint(100, 100), true)); } + + [Fact] + public void Translate() + { + var tm = TransformationMatrix.GetTranslationMatrix(5, 7); + + var translated = tm.Transform(UnitRectangle); + + Assert.Equal(new PdfPoint(5, 7), translated.BottomLeft); + Assert.Equal(new PdfPoint(6, 7), translated.BottomRight); + Assert.Equal(new PdfPoint(5, 8), translated.TopLeft); + Assert.Equal(new PdfPoint(6, 8), translated.TopRight); + + Assert.Equal(1, translated.Width); + Assert.Equal(1, translated.Height); + } + + [Fact] + public void Scale() + { + var tm = TransformationMatrix.GetScaleMatrix(3, 5); + + var scaled = tm.Transform(UnitRectangle); + + Assert.Equal(new PdfPoint(0, 0), scaled.BottomLeft); + Assert.Equal(new PdfPoint(3, 0), scaled.BottomRight); + Assert.Equal(new PdfPoint(0, 5), scaled.TopLeft); + Assert.Equal(new PdfPoint(3, 5), scaled.TopRight); + + Assert.Equal(3, scaled.Width); + Assert.Equal(5, scaled.Height); + } + + [Fact] + public void Rotate360() + { + var tm = TransformationMatrix.GetRotationMatrix(360); + + var rotated = tm.Transform(UnitRectangle); + + Assert.Equal(new PdfPoint(0, 0), rotated.BottomLeft); + Assert.Equal(new PdfPoint(1, 0), rotated.BottomRight); + Assert.Equal(new PdfPoint(0, 1), rotated.TopLeft); + Assert.Equal(new PdfPoint(1, 1), rotated.TopRight); + + Assert.Equal(1, rotated.Width); + Assert.Equal(1, rotated.Height); + } + + [Fact] + public void Rotate90() + { + var tm = TransformationMatrix.GetRotationMatrix(90); + + var rotated = tm.Transform(UnitRectangle); + + Assert.Equal(new PdfPoint(0, 0), rotated.BottomLeft); + Assert.Equal(new PdfPoint(0, 1), rotated.BottomRight); + Assert.Equal(new PdfPoint(-1, 0), rotated.TopLeft); + Assert.Equal(new PdfPoint(-1, 1), rotated.TopRight); + + Assert.Equal(1, rotated.Width); + Assert.Equal(-1, rotated.Height); + } + + [Fact] + public void Rotate180() + { + var tm = TransformationMatrix.GetRotationMatrix(180); + + var rotated = tm.Transform(UnitRectangle); + + Assert.Equal(new PdfPoint(0, 0), rotated.BottomLeft); + Assert.Equal(new PdfPoint(-1, 0), rotated.BottomRight); + Assert.Equal(new PdfPoint(0, -1), rotated.TopLeft); + Assert.Equal(new PdfPoint(-1, -1), rotated.TopRight); + + Assert.Equal(-1, rotated.Width); + Assert.Equal(-1, rotated.Height); + } } }