diff --git a/X10D.Tests/src/Drawing/PolygonFTests.cs b/X10D.Tests/src/Drawing/PolygonFTests.cs index b822c49..cecffd2 100644 --- a/X10D.Tests/src/Drawing/PolygonFTests.cs +++ b/X10D.Tests/src/Drawing/PolygonFTests.cs @@ -12,25 +12,25 @@ public class PolygonFTests public void AddPoints_ShouldAddPoints() { var polygon = PolygonF.Empty; - polygon.AddPoints(new[] {new PointF(1, 2), new PointF(3, 4)}); - Assert.AreEqual(2, polygon.PointCount); + polygon.AddVertices(new[] {new PointF(1, 2), new PointF(3, 4)}); + Assert.AreEqual(2, polygon.VertexCount); // assert that the empty polygon was not modified - Assert.AreEqual(0, PolygonF.Empty.PointCount); + Assert.AreEqual(0, PolygonF.Empty.VertexCount); } [TestMethod] public void ClearPoints_ShouldClearPoints() { var polygon = PolygonF.Empty; - polygon.AddPoints(new[] {new Vector2(1, 2), new Vector2(3, 4)}); - Assert.AreEqual(2, polygon.PointCount); + polygon.AddVertices(new[] {new Vector2(1, 2), new Vector2(3, 4)}); + Assert.AreEqual(2, polygon.VertexCount); // assert that the empty polygon was not modified - Assert.AreEqual(0, PolygonF.Empty.PointCount); + Assert.AreEqual(0, PolygonF.Empty.VertexCount); - polygon.ClearPoints(); - Assert.AreEqual(0, polygon.PointCount); + polygon.ClearVertices(); + Assert.AreEqual(0, polygon.VertexCount); } [TestMethod] @@ -39,26 +39,26 @@ public class PolygonFTests var pointPolygon = new PolygonF(new[] {new PointF(1, 2), new PointF(3, 4)}); var vectorPolygon = new PolygonF(new[] {new Vector2(1, 2), new Vector2(3, 4)}); - Assert.AreEqual(2, pointPolygon.PointCount); - Assert.AreEqual(2, vectorPolygon.PointCount); + Assert.AreEqual(2, pointPolygon.VertexCount); + Assert.AreEqual(2, vectorPolygon.VertexCount); } [TestMethod] public void CopyConstructor_ShouldCopyPoints_GivenPolygon() { var first = PolygonF.Empty; - first.AddPoints(new[] {new PointF(1, 2), new PointF(3, 4)}); + first.AddVertices(new[] {new PointF(1, 2), new PointF(3, 4)}); var second = new PolygonF(first); - Assert.AreEqual(2, first.PointCount); - Assert.AreEqual(2, second.PointCount); + Assert.AreEqual(2, first.VertexCount); + Assert.AreEqual(2, second.VertexCount); // we cannot use CollectionAssert here for reasons I am not entirely sure of. // it seems to dislike casting from IReadOnlyList to ICollection. but okay. - Assert.IsTrue(first.Points.SequenceEqual(second.Points)); + Assert.IsTrue(first.Vertices.SequenceEqual(second.Vertices)); // assert that the empty polygon was not modified - Assert.AreEqual(0, PolygonF.Empty.PointCount); + Assert.AreEqual(0, PolygonF.Empty.VertexCount); } [TestMethod] @@ -135,9 +135,9 @@ public class PolygonFTests Assert.AreEqual(polygon, converted); Assert.AreEqual(polygon.IsConvex, converted.IsConvex); - Assert.AreEqual(polygon.PointCount, converted.PointCount); + Assert.AreEqual(polygon.VertexCount, converted.VertexCount); - Assert.IsTrue(polygon.Points.SequenceEqual(converted.Points.Select(p => (PointF)p))); + Assert.IsTrue(polygon.Vertices.SequenceEqual(converted.Vertices.Select(p => (PointF)p))); } [TestMethod] @@ -148,27 +148,27 @@ public class PolygonFTests Assert.AreEqual(polygon, converted); Assert.AreEqual(polygon.IsConvex, converted.IsConvex); - Assert.AreEqual(polygon.PointCount, converted.PointCount); + Assert.AreEqual(polygon.VertexCount, converted.VertexCount); - Assert.IsTrue(converted.Points.SequenceEqual(polygon.Points.Select(p => (PointF)p))); + Assert.IsTrue(converted.Vertices.SequenceEqual(polygon.Vertices.Select(p => (PointF)p))); } [TestMethod] public void PointCount_ShouldBe1_GivenPolygonFWith1Point() { var polygon = new PolygonF(); - polygon.AddPoint(new Point(1, 1)); + polygon.AddVertex(new Point(1, 1)); - Assert.AreEqual(1, polygon.PointCount); + Assert.AreEqual(1, polygon.VertexCount); // assert that the empty polygon was not modified - Assert.AreEqual(0, PolygonF.Empty.PointCount); + Assert.AreEqual(0, PolygonF.Empty.VertexCount); } [TestMethod] public void PointCount_ShouldBe0_GivenEmptyPolygon() { - Assert.AreEqual(0, PolygonF.Empty.PointCount); + Assert.AreEqual(0, PolygonF.Empty.VertexCount); } [TestMethod] @@ -182,23 +182,23 @@ public class PolygonFTests internal static PolygonF CreateHexagon() { var hexagon = new PolygonF(); - hexagon.AddPoint(new Vector2(0, 0)); - hexagon.AddPoint(new Vector2(1, 0)); - hexagon.AddPoint(new Vector2(1, 1)); - hexagon.AddPoint(new Vector2(0, 1)); - hexagon.AddPoint(new Vector2(-1, 1)); - hexagon.AddPoint(new Vector2(-1, 0)); + hexagon.AddVertex(new Vector2(0, 0)); + hexagon.AddVertex(new Vector2(1, 0)); + hexagon.AddVertex(new Vector2(1, 1)); + hexagon.AddVertex(new Vector2(0, 1)); + hexagon.AddVertex(new Vector2(-1, 1)); + hexagon.AddVertex(new Vector2(-1, 0)); return hexagon; } internal static PolygonF CreateConcavePolygon() { var hexagon = new PolygonF(); - hexagon.AddPoint(new Vector2(0, 0)); - hexagon.AddPoint(new Vector2(2, 0)); - hexagon.AddPoint(new Vector2(1, 1)); - hexagon.AddPoint(new Vector2(2, 1)); - hexagon.AddPoint(new Vector2(0, 1)); + hexagon.AddVertex(new Vector2(0, 0)); + hexagon.AddVertex(new Vector2(2, 0)); + hexagon.AddVertex(new Vector2(1, 1)); + hexagon.AddVertex(new Vector2(2, 1)); + hexagon.AddVertex(new Vector2(0, 1)); return hexagon; } } diff --git a/X10D.Tests/src/Drawing/PolygonTests.cs b/X10D.Tests/src/Drawing/PolygonTests.cs index bf91600..c56f283 100644 --- a/X10D.Tests/src/Drawing/PolygonTests.cs +++ b/X10D.Tests/src/Drawing/PolygonTests.cs @@ -11,44 +11,44 @@ public class PolygonTests public void AddPoints_ShouldAddPoints() { var polygon = Polygon.Empty; - polygon.AddPoints(new[] {new Point(1, 2), new Point(3, 4)}); - Assert.AreEqual(2, polygon.PointCount); + polygon.AddVertices(new[] {new Point(1, 2), new Point(3, 4)}); + Assert.AreEqual(2, polygon.VertexCount); // assert that the empty polygon was not modified - Assert.AreEqual(0, Polygon.Empty.PointCount); + Assert.AreEqual(0, Polygon.Empty.VertexCount); } [TestMethod] public void ClearPoints_ShouldClearPoints() { var polygon = Polygon.Empty; - polygon.AddPoints(new[] {new Point(1, 2), new Point(3, 4)}); - Assert.AreEqual(2, polygon.PointCount); + polygon.AddVertices(new[] {new Point(1, 2), new Point(3, 4)}); + Assert.AreEqual(2, polygon.VertexCount); // assert that the empty polygon was not modified - Assert.AreEqual(0, PolygonF.Empty.PointCount); + Assert.AreEqual(0, PolygonF.Empty.VertexCount); - polygon.ClearPoints(); - Assert.AreEqual(0, polygon.PointCount); + polygon.ClearVertices(); + Assert.AreEqual(0, polygon.VertexCount); } [TestMethod] public void CopyConstructor_ShouldCopyPoints_GivenPolygon() { var first = Polygon.Empty; - first.AddPoints(new[] {new Point(1, 2), new Point(3, 4)}); + first.AddVertices(new[] {new Point(1, 2), new Point(3, 4)}); var second = new Polygon(first); - Assert.AreEqual(2, first.PointCount); - Assert.AreEqual(2, second.PointCount); + Assert.AreEqual(2, first.VertexCount); + Assert.AreEqual(2, second.VertexCount); // we cannot use CollectionAssert here for reasons I am not entirely sure of. // it seems to dislike casting from IReadOnlyList to ICollection. but okay. - Assert.IsTrue(first.Points.SequenceEqual(second.Points)); + Assert.IsTrue(first.Vertices.SequenceEqual(second.Vertices)); // assert that the empty polygon was not modified - Assert.AreEqual(0, Polygon.Empty.PointCount); + Assert.AreEqual(0, Polygon.Empty.VertexCount); } [TestMethod] @@ -121,18 +121,18 @@ public class PolygonTests public void PointCount_ShouldBe1_GivenPolygonWith1Point() { var polygon = Polygon.Empty; - polygon.AddPoint(new Point(1, 1)); + polygon.AddVertex(new Point(1, 1)); - Assert.AreEqual(1, polygon.PointCount); + Assert.AreEqual(1, polygon.VertexCount); // assert that the empty polygon was not modified - Assert.AreEqual(0, Polygon.Empty.PointCount); + Assert.AreEqual(0, Polygon.Empty.VertexCount); } [TestMethod] public void PointCount_ShouldBe0_GivenEmptyPolygon() { - Assert.AreEqual(0, Polygon.Empty.PointCount); + Assert.AreEqual(0, Polygon.Empty.VertexCount); } [TestMethod] @@ -146,23 +146,23 @@ public class PolygonTests internal static Polygon CreateHexagon() { var hexagon = new Polygon(); - hexagon.AddPoint(new Point(0, 0)); - hexagon.AddPoint(new Point(1, 0)); - hexagon.AddPoint(new Point(1, 1)); - hexagon.AddPoint(new Point(0, 1)); - hexagon.AddPoint(new Point(-1, 1)); - hexagon.AddPoint(new Point(-1, 0)); + hexagon.AddVertex(new Point(0, 0)); + hexagon.AddVertex(new Point(1, 0)); + hexagon.AddVertex(new Point(1, 1)); + hexagon.AddVertex(new Point(0, 1)); + hexagon.AddVertex(new Point(-1, 1)); + hexagon.AddVertex(new Point(-1, 0)); return hexagon; } internal static Polygon CreateConcavePolygon() { var hexagon = new Polygon(); - hexagon.AddPoint(new Point(0, 0)); - hexagon.AddPoint(new Point(2, 0)); - hexagon.AddPoint(new Point(1, 1)); - hexagon.AddPoint(new Point(2, 1)); - hexagon.AddPoint(new Point(0, 1)); + hexagon.AddVertex(new Point(0, 0)); + hexagon.AddVertex(new Point(2, 0)); + hexagon.AddVertex(new Point(1, 1)); + hexagon.AddVertex(new Point(2, 1)); + hexagon.AddVertex(new Point(0, 1)); return hexagon; } } diff --git a/X10D/src/Drawing/Polygon.cs b/X10D/src/Drawing/Polygon.cs index 61098ee..9d4e4b3 100644 --- a/X10D/src/Drawing/Polygon.cs +++ b/X10D/src/Drawing/Polygon.cs @@ -3,32 +3,39 @@ namespace X10D.Drawing; /// -/// Represents a 2D polygon composed of 32-bit signed integer points. +/// Represents a 2D polygon composed of 32-bit signed integer vertices. /// -public struct Polygon : IEquatable +public class Polygon : IEquatable { /// - /// The empty polygon. That is, a polygon with no points. + /// The empty polygon. That is, a polygon with no vertices. /// public static readonly Polygon Empty = new(); - private Point[]? _points; + private readonly List _vertices = new(); + + /// + /// Initializes a new instance of the class. + /// + public Polygon() + { + } /// /// Initializes a new instance of the struct by copying the specified polygon. /// public Polygon(Polygon polygon) - : this(polygon._points ?? ArraySegment.Empty) + : this(polygon._vertices) { } /// - /// Initializes a new instance of the struct by constructing it from the specified points. + /// Initializes a new instance of the struct by constructing it from the specified vertices. /// - /// An enumerable collection of points from which the polygon should be constructed. - public Polygon(IEnumerable points) + /// An enumerable collection of vertices from which the polygon should be constructed. + public Polygon(IEnumerable vertices) { - _points = points.ToArray(); + _vertices = new List(vertices); } /// @@ -39,18 +46,18 @@ public struct Polygon : IEquatable { get { - if (_points is null || _points.Length < 3) + if (_vertices.Count < 3) { return false; } var positive = false; var negative = false; - Point p0 = _points[0]; + Point p0 = _vertices[0]; - for (var index = 1; index < _points.Length; index++) + for (var index = 1; index < _vertices.Count; index++) { - Point p1 = _points[index]; + Point p1 = _vertices[index]; int d = (p1.X - p0.X) * (p1.Y + p0.Y); if (d > 0) @@ -75,21 +82,23 @@ public struct Polygon : IEquatable } /// - /// Gets the number of points in this polygon. + /// Gets the number of vertices in this polygon. /// - /// An value, representing the number of points in this polygon. - public int PointCount + /// An value, representing the number of vertices in this polygon. + public int VertexCount { - get => _points?.Length ?? 0; + get => _vertices.Count; } /// - /// Gets a read-only view of the points in this polygon. + /// Gets a read-only view of the vertices in this polygon. /// - /// A of values, representing the points of this polygon. - public IReadOnlyList Points + /// + /// A of values, representing the vertices of this polygon. + /// + public IReadOnlyList Vertices { - get => _points?.ToArray() ?? ArraySegment.Empty; + get => _vertices.AsReadOnly(); } /// @@ -121,46 +130,42 @@ public struct Polygon : IEquatable } /// - /// Adds a point to this polygon. + /// Adds a vertex to this polygon. /// - /// The point to add. - public void AddPoint(Point point) + /// The vertex to add. + public void AddVertex(Point vertex) { - _points ??= Array.Empty(); - Span span = stackalloc Point[_points.Length + 1]; - _points.CopyTo(span); - span[^1] = point; - _points = span.ToArray(); + _vertices.Add(vertex); } /// - /// Adds a collection of points to this polygon. + /// Adds a collection of vertices to this polygon. /// - /// An enumerable collection of points to add. - /// is . - public void AddPoints(IEnumerable points) + /// An enumerable collection of vertices to add. + /// is . + public void AddVertices(IEnumerable vertices) { #if NET6_0_OR_GREATER - ArgumentNullException.ThrowIfNull(points); + ArgumentNullException.ThrowIfNull(vertices); #else - if (points is null) + if (vertices is null) { - throw new ArgumentNullException(nameof(points)); + throw new ArgumentNullException(nameof(vertices)); } #endif - foreach (Point point in points) + foreach (Point vertex in vertices) { - AddPoint(point); + AddVertex(vertex); } } /// - /// Clears all points from this polygon. + /// Clears all vertices from this polygon. /// - public void ClearPoints() + public void ClearVertices() { - _points = Array.Empty(); + _vertices.Clear(); } /// @@ -179,19 +184,12 @@ public struct Polygon : IEquatable /// public bool Equals(Polygon other) { - return _points switch - { - null when other._points is null => true, - null => false, - not null when other._points is null => false, - _ => _points.SequenceEqual(other._points) - }; + return _vertices.SequenceEqual(other._vertices); } /// public override int GetHashCode() { - Point[] points = _points ?? Array.Empty(); - return points.Aggregate(0, HashCode.Combine); + return _vertices.Aggregate(0, HashCode.Combine); } } diff --git a/X10D/src/Drawing/PolygonF.cs b/X10D/src/Drawing/PolygonF.cs index cd8f2ad..99863fb 100644 --- a/X10D/src/Drawing/PolygonF.cs +++ b/X10D/src/Drawing/PolygonF.cs @@ -5,59 +5,66 @@ using X10D.Numerics; namespace X10D.Drawing; /// -/// Represents a 2D polygon composed of single-precision floating-point points. +/// Represents a 2D polygon composed of single-precision floating-vertex vertices. /// -public struct PolygonF +public class PolygonF { /// - /// The empty polygon. That is, a polygon with no points. + /// The empty polygon. That is, a polygon with no vertices. /// public static readonly PolygonF Empty = new(); - private PointF[]? _points; + private readonly List _vertices = new(); /// - /// Initializes a new instance of the struct by copying the specified polygon. + /// Initializes a new instance of the class. + /// + public PolygonF() + { + } + + /// + /// Initializes a new instance of the class by copying the specified polygon. /// public PolygonF(PolygonF polygon) - : this(polygon._points ?? Array.Empty()) + : this(polygon._vertices) { } /// - /// Initializes a new instance of the struct by constructing it from the specified points. + /// Initializes a new instance of the class by constructing it from the specified vertices. /// - /// An enumerable collection of points from which the polygon should be constructed. - public PolygonF(IEnumerable points) - : this(points.Select(p => p.ToPointF())) + /// An enumerable collection of vertices from which the polygon should be constructed. + public PolygonF(IEnumerable vertices) + : this(vertices.Select(p => p.ToPointF())) { #if NET6_0_OR_GREATER - ArgumentNullException.ThrowIfNull(points); + ArgumentNullException.ThrowIfNull(vertices); #else - if (points is null) + if (vertices is null) { - throw new ArgumentNullException(nameof(points)); + throw new ArgumentNullException(nameof(vertices)); } #endif } /// - /// Initializes a new instance of the struct by constructing it from the specified points. + /// Initializes a new instance of the class by constructing it from the specified vertices. /// - /// An enumerable collection of points from which the polygon should be constructed. - /// is . - public PolygonF(IEnumerable points) + /// An enumerable collection of vertices from which the polygon should be constructed. + /// is . + public PolygonF(IEnumerable vertices) { #if NET6_0_OR_GREATER - ArgumentNullException.ThrowIfNull(points); + ArgumentNullException.ThrowIfNull(vertices); #else - if (points is null) + if (vertices is null) { - throw new ArgumentNullException(nameof(points)); + throw new ArgumentNullException(nameof(vertices)); } #endif - _points = points.ToArray(); + _vertices = new List(vertices); } /// @@ -68,18 +75,18 @@ public struct PolygonF { get { - if (_points is null || _points.Length < 3) + if (_vertices.Count < 3) { return false; } var positive = false; var negative = false; - PointF p0 = _points[0]; + PointF p0 = _vertices[0]; - for (var index = 1; index < _points.Length; index++) + for (var index = 1; index < _vertices.Count; index++) { - PointF p1 = _points[index]; + PointF p1 = _vertices[index]; float d = (p1.X - p0.X) * (p1.Y + p0.Y); if (d > 0) @@ -104,21 +111,23 @@ public struct PolygonF } /// - /// Gets the number of points in this polygon. + /// Gets the number of vertices in this polygon. /// - /// An value, representing the number of points in this polygon. - public int PointCount + /// An value, representing the number of vertices in this polygon. + public int VertexCount { - get => _points?.Length ?? 0; + get => _vertices.Count; } /// - /// Gets a read-only view of the points in this polygon. + /// Gets a read-only view of the vertices in this polygon. /// - /// A of values, representing the points of this polygon. - public IReadOnlyList Points + /// + /// A of values, representing the vertices of this polygon. + /// + public IReadOnlyList Vertices { - get => _points?.ToArray() ?? ArraySegment.Empty; + get => _vertices.AsReadOnly(); } /// @@ -156,14 +165,14 @@ public struct PolygonF /// The converted polygon. public static explicit operator Polygon(PolygonF polygon) { - var points = new List(); + var vertices = new List(); - foreach (PointF point in polygon.Points) + foreach (PointF vertex in polygon.Vertices) { - points.Add(new Point((int)point.X, (int)point.Y)); + vertices.Add(new Point((int)vertex.X, (int)vertex.Y)); } - return new Polygon(points); + return new Polygon(vertices); } /// @@ -173,88 +182,84 @@ public struct PolygonF /// The converted polygon. public static implicit operator PolygonF(Polygon polygon) { - var points = new List(); + var vertices = new List(); - foreach (Point point in polygon.Points) + foreach (Point vertex in polygon.Vertices) { - points.Add(point); + vertices.Add(vertex); } - return new PolygonF(points); + return new PolygonF(vertices); } /// - /// Adds a point to this polygon. + /// Adds a vertex to this polygon. /// - /// The point to add. - public void AddPoint(PointF point) + /// The vertex to add. + public void AddVertex(PointF vertex) { - _points ??= Array.Empty(); - Span span = stackalloc PointF[_points.Length + 1]; - _points.CopyTo(span); - span[^1] = point; - _points = span.ToArray(); + _vertices.Add(vertex); } /// - /// Adds a point to this polygon. + /// Adds a vertex to this polygon. /// - /// The point to add. - public void AddPoint(Vector2 point) + /// The vertex to add. + public void AddVertex(Vector2 vertex) { - AddPoint(point.ToPointF()); + AddVertex(vertex.ToPointF()); } /// - /// Adds a collection of points to this polygon. + /// Adds a collection of vertices to this polygon. /// - /// An enumerable collection of points to add. - /// is . - public void AddPoints(IEnumerable points) + /// An enumerable collection of vertices to add. + /// is . + public void AddVertices(IEnumerable vertices) { #if NET6_0_OR_GREATER - ArgumentNullException.ThrowIfNull(points); + ArgumentNullException.ThrowIfNull(vertices); #else - if (points is null) + if (vertices is null) { - throw new ArgumentNullException(nameof(points)); + throw new ArgumentNullException(nameof(vertices)); } #endif - foreach (PointF point in points) + foreach (PointF vertex in vertices) { - AddPoint(point); + AddVertex(vertex); } } /// - /// Adds a collection of points to this polygon. + /// Adds a collection of vertices to this polygon. /// - /// An enumerable collection of points to add. - /// is . - public void AddPoints(IEnumerable points) + /// An enumerable collection of vertices to add. + /// is . + public void AddVertices(IEnumerable vertices) { #if NET6_0_OR_GREATER - ArgumentNullException.ThrowIfNull(points); + ArgumentNullException.ThrowIfNull(vertices); #else - if (points is null) + if (vertices is null) { - throw new ArgumentNullException(nameof(points)); + throw new ArgumentNullException(nameof(vertices)); } #endif - foreach (Vector2 point in points) + foreach (Vector2 vertex in vertices) { - AddPoint(point); + AddVertex(vertex); } } /// - /// Clears all points from this polygon. + /// Clears all vertices from this polygon. /// - public void ClearPoints() + public void ClearVertices() { - _points = Array.Empty(); + _vertices.Clear(); } /// @@ -273,19 +278,12 @@ public struct PolygonF /// public bool Equals(PolygonF other) { - return _points switch - { - null when other._points is null => true, - null => false, - not null when other._points is null => false, - _ => _points.SequenceEqual(other._points) - }; + return _vertices.SequenceEqual(other._vertices); } /// public override int GetHashCode() { - PointF[] points = _points ?? Array.Empty(); - return points.Aggregate(0, HashCode.Combine); + return _vertices.Aggregate(0, HashCode.Combine); } }