diff --git a/Bonk/Shapes/Polygon.cs b/Bonk/Shapes/Polygon.cs
index e68663b..90dc44c 100644
--- a/Bonk/Shapes/Polygon.cs
+++ b/Bonk/Shapes/Polygon.cs
@@ -1,5 +1,4 @@
-using System.Linq;
-using System;
+using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Numerics;
@@ -9,34 +8,32 @@ namespace MoonTools.Core.Bonk
{
///
/// A Shape defined by an arbitrary collection of vertices.
- /// NOTE: A Polygon must have more than 2 vertices, be convex, and should not have duplicate vertices.
+ /// NOTE: A Polygon must be defined in clockwise order, have more than 2 vertices, be convex, and have no duplicate vertices.
///
public struct Polygon : IShape2D, IEquatable
{
- private ImmutableArray _vertices;
+ public ImmutableArray Vertices { get; private set; }
public AABB AABB { get; }
- public IEnumerable Vertices { get { return _vertices; } }
-
- public int VertexCount { get { return _vertices.Length; } }
+ public int VertexCount { get { return Vertices.Length; } }
// vertices are local to the origin
public Polygon(IEnumerable vertices)
{
- _vertices = vertices.ToImmutableArray();
+ Vertices = vertices.ToImmutableArray();
AABB = AABB.FromVertices(vertices);
}
public Polygon(ImmutableArray vertices)
{
- _vertices = vertices;
+ Vertices = vertices;
AABB = AABB.FromVertices(vertices);
}
public Vector2 Support(Vector2 direction, Transform2D transform)
{
var maxDotProduct = float.NegativeInfinity;
- var maxVertex = _vertices[0].ToVector2();
+ var maxVertex = Vertices[0].ToVector2();
foreach (var vertex in Vertices)
{
var transformed = Vector2.Transform(vertex, transform.TransformMatrix);
@@ -67,11 +64,22 @@ namespace MoonTools.Core.Bonk
public bool Equals(Polygon other)
{
- var q = from a in _vertices
- join b in other.Vertices on a equals b
- select a;
+ if (VertexCount != other.VertexCount) { return false; }
- return _vertices.Length == other.VertexCount && q.Count() == _vertices.Length;
+ int? offset = null;
+ for (var i = 0; i < VertexCount; i++)
+ {
+ if (Vertices[0] == other.Vertices[i]) { offset = i; break; }
+ }
+
+ if (!offset.HasValue) { return false; }
+
+ for (var i = 0; i < VertexCount; i++)
+ {
+ if (Vertices[i] != other.Vertices[(i + offset.Value) % VertexCount]) { return false; }
+ }
+
+ return true;
}
public bool Equals(Rectangle rectangle)
diff --git a/Bonk/Shapes/Rectangle.cs b/Bonk/Shapes/Rectangle.cs
index 5433ecc..cd0da32 100644
--- a/Bonk/Shapes/Rectangle.cs
+++ b/Bonk/Shapes/Rectangle.cs
@@ -10,51 +10,66 @@ namespace MoonTools.Core.Bonk
///
public struct Rectangle : IShape2D, IEquatable
{
- public int MinX { get; }
- public int MinY { get; }
- public int MaxX { get; }
- public int MaxY { get; }
-
+ ///
+ /// The minimum position of the rectangle. Note that we assume y-down coordinates.
+ ///
+ ///
+ public Position2D Min { get; }
+ ///
+ /// The maximum position of the rectangle. Note that we assume y-down coordinates.
+ ///
+ ///
+ public Position2D Max { get; }
public AABB AABB { get; }
+ public int Left { get { return Min.X; } }
+ public int Right { get { return Max.X; } }
+ public int Top { get { return Min.Y; } }
+ public int Bottom { get { return Max.Y; } }
+
+ public int Width { get; }
+ public int Height { get; }
+
+ public Position2D TopRight { get { return new Position2D(Right, Top); } }
+ public Position2D BottomLeft { get { return new Position2D(Left, Bottom); } }
+
public IEnumerable Vertices
{
get
{
- yield return new Position2D(MinX, MinY);
- yield return new Position2D(MinX, MaxY);
- yield return new Position2D(MaxX, MinY);
- yield return new Position2D(MaxX, MaxY);
+ yield return new Position2D(Min.X, Min.Y);
+ yield return new Position2D(Min.X, Max.Y);
+ yield return new Position2D(Max.X, Min.Y);
+ yield return new Position2D(Max.X, Max.Y);
}
}
public Rectangle(int minX, int minY, int maxX, int maxY)
{
- MinX = minX;
- MinY = minY;
- MaxX = maxX;
- MaxY = maxY;
-
+ Min = new Position2D(minX, minY);
+ Max = new Position2D(maxX, maxY);
AABB = new AABB(minX, minY, maxX, maxY);
+ Width = Max.X - Min.X;
+ Height = Max.Y - Min.Y;
}
private Vector2 Support(Vector2 direction)
{
if (direction.X >= 0 && direction.Y >= 0)
{
- return new Vector2(MaxX, MaxY);
+ return Max;
}
else if (direction.X >= 0 && direction.Y < 0)
{
- return new Vector2(MaxX, MinY);
+ return new Vector2(Max.X, Min.Y);
}
else if (direction.X < 0 && direction.Y >= 0)
{
- return new Vector2(MinX, MaxY);
+ return new Vector2(Min.X, Max.Y);
}
else if (direction.X < 0 && direction.Y < 0)
{
- return new Vector2(MinX, MinY);
+ return new Vector2(Min.X, Min.Y);
}
else
{
@@ -87,10 +102,7 @@ namespace MoonTools.Core.Bonk
public bool Equals(Rectangle other)
{
- return MinX == other.MinX &&
- MinY == other.MinY &&
- MaxX == other.MaxX &&
- MaxY == other.MaxY;
+ return Min == other.Min && Max == other.Max;
}
public bool Equals(Polygon other)
@@ -100,7 +112,7 @@ namespace MoonTools.Core.Bonk
public override int GetHashCode()
{
- return HashCode.Combine(MinX, MinY, MaxX, MaxY);
+ return HashCode.Combine(Min, Max);
}
public static bool operator ==(Rectangle a, Rectangle b)
@@ -112,5 +124,15 @@ namespace MoonTools.Core.Bonk
{
return !(a == b);
}
+
+ public static bool operator ==(Rectangle a, Polygon b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(Rectangle a, Polygon b)
+ {
+ return !(a == b);
+ }
}
}
diff --git a/Bonk/Shapes/RectanglePolygonComparison.cs b/Bonk/Shapes/RectanglePolygonComparison.cs
index 34c7ef3..36821d7 100644
--- a/Bonk/Shapes/RectanglePolygonComparison.cs
+++ b/Bonk/Shapes/RectanglePolygonComparison.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using MoonTools.Core.Structs;
namespace MoonTools.Core.Bonk
{
@@ -6,11 +6,20 @@ namespace MoonTools.Core.Bonk
{
public static bool Equals(Polygon polygon, Rectangle rectangle)
{
- var q = from a in polygon.Vertices
- join b in rectangle.Vertices on a equals b
- select a;
+ if (polygon.VertexCount != 4) { return false; }
- return polygon.VertexCount == 4 && q.Count() == 4;
+ int? minIndex = null;
+ for (var i = 0; i < 4; i++)
+ {
+ if (polygon.Vertices[i] == rectangle.Min) { minIndex = i; break; }
+ }
+
+ if (!minIndex.HasValue) { return false; }
+
+ return
+ polygon.Vertices[(minIndex.Value + 1) % 4] == rectangle.TopRight &&
+ polygon.Vertices[(minIndex.Value + 2) % 4] == rectangle.Max &&
+ polygon.Vertices[(minIndex.Value + 3) % 4] == rectangle.BottomLeft;
}
}
}
diff --git a/Test/Equality.cs b/Test/Equality.cs
index bf303dd..e69c9e5 100644
--- a/Test/Equality.cs
+++ b/Test/Equality.cs
@@ -288,45 +288,48 @@ namespace Tests
public void PolygonRectangleEqual()
{
var a = new Polygon(ImmutableArray.Create(
- new Position2D(1, 1),
- new Position2D(1, -1),
new Position2D(-1, -1),
+ new Position2D(1, -1),
+ new Position2D(1, 1),
new Position2D(-1, 1)
));
var b = new Rectangle(-1, -1, 1, 1);
a.Equals(b).Should().BeTrue();
+ b.Equals(a).Should().BeTrue();
}
[Test]
public void PolygonRectangleNotEqual()
{
var a = new Polygon(ImmutableArray.Create(
- new Position2D(2, 1),
+ new Position2D(-2, -1),
new Position2D(1, -1),
- new Position2D(-1, -1),
+ new Position2D(1, 1),
new Position2D(-2, 1)
));
var b = new Rectangle(-1, -1, 1, 1);
a.Equals(b).Should().BeFalse();
+ b.Equals(a).Should().BeFalse();
}
[Test]
public void PolygonRectangleEqualOperator()
{
var a = new Polygon(ImmutableArray.Create(
- new Position2D(1, 1),
- new Position2D(1, -1),
new Position2D(-1, -1),
+ new Position2D(1, -1),
+ new Position2D(1, 1),
new Position2D(-1, 1)
));
var b = new Rectangle(-1, -1, 1, 1);
(a == b).Should().BeTrue();
+ (b == a).Should().BeTrue();
}
[Test]
@@ -342,6 +345,7 @@ namespace Tests
var b = new Rectangle(-1, -1, 1, 1);
(a != b).Should().BeTrue();
+ (b != a).Should().BeTrue();
}
}