diff --git a/Bonk/Shapes/Point.cs b/Bonk/Shapes/Point.cs new file mode 100644 index 0000000..83290e1 --- /dev/null +++ b/Bonk/Shapes/Point.cs @@ -0,0 +1,67 @@ +using System; +using System.Linq; +using System.Numerics; +using MoonTools.Core.Structs; + +namespace MoonTools.Core.Bonk +{ + public struct Point : IShape2D, IEquatable + { + private Position2D position; + + public Point(Position2D position) + { + this.position = position; + } + + public Point(int x, int y) + { + this.position = new Position2D(x, y); + } + + public AABB AABB(Transform2D transform) + { + return Bonk.AABB.FromTransformedVertices(Enumerable.Repeat(position, 1), transform); + } + + public Vector2 Support(Vector2 direction, Transform2D transform) + { + return position; + } + + public override bool Equals(object obj) + { + if (obj is IShape2D other) + { + return Equals(other); + } + + return false; + } + + public bool Equals(IShape2D other) + { + if (other is Point otherPoint) + { + return position == otherPoint.position; + } + + return false; + } + + public override int GetHashCode() + { + return HashCode.Combine(position); + } + + public static bool operator ==(Point a, Point b) + { + return a.Equals(b); + } + + public static bool operator !=(Point a, Point b) + { + return !(a == b); + } + } +} \ No newline at end of file diff --git a/Bonk/Shapes/Polygon.cs b/Bonk/Shapes/Polygon.cs index 0e10f48..1198960 100644 --- a/Bonk/Shapes/Polygon.cs +++ b/Bonk/Shapes/Polygon.cs @@ -10,7 +10,7 @@ namespace MoonTools.Core.Bonk { /// /// A Shape defined by an arbitrary collection of vertices. - /// NOTE: A Polygon must have more than 2 vertices and should not have duplicate vertices. + /// NOTE: A Polygon must have more than 2 vertices, be convex, and should not have duplicate vertices. /// public struct Polygon : IShape2D, IEquatable { diff --git a/Test/Equality.cs b/Test/Equality.cs index e5921fd..07979a0 100644 --- a/Test/Equality.cs +++ b/Test/Equality.cs @@ -9,6 +9,44 @@ namespace Tests { public class EqualityTests { + public class PointTests + { + [Test] + public void PointEqual() + { + var a = new Point(1, 1); + var b = new Point(1, 1); + + a.Should().BeEquivalentTo(b); + } + + [Test] + public void PointNotEqual() + { + var a = new Point(1, 1); + var b = new Point(-1, 1); + + a.Should().NotBeEquivalentTo(b); + } + + [Test] + public void PointEqualOperator() + { + var a = new Point(1, 1); + var b = new Point(1, 1); + (a == b).Should().BeTrue(); + } + + [Test] + public void PointNotEqualOperator() + { + var a = new Point(1, 1); + var b = new Point(-1, 1); + + (a != b).Should().BeTrue(); + } + } + public class CircleTests { [Test] diff --git a/Test/GJK2DTest.cs b/Test/GJK2DTest.cs index 6d15f4b..1cab165 100644 --- a/Test/GJK2DTest.cs +++ b/Test/GJK2DTest.cs @@ -8,6 +8,91 @@ namespace Tests { public class GJK2DTest { + [Test] + public void PointLineOverlapping() + { + var point = new Point(1, 1); + var line = new Line(new Position2D(-2, -2), new Position2D(2, 2)); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, line, Transform2D.DefaultTransform).Should().BeTrue(); + } + + [Test] + public void PointLineNotOverlapping() + { + var point = new Point(1, 1); + var line = new Line(new Position2D(-3, -2), new Position2D(-9, -5)); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, line, Transform2D.DefaultTransform).Should().BeFalse(); + } + + [Test] + public void PointCircleOverlapping() + { + var point = new Point(); + var circle = new Circle(3); + + var pointTransform = new Transform2D(new Position2D(1, 1)); + var circleTransform = new Transform2D(new Position2D(-1, 0)); + + GJK2D.TestCollision(point, pointTransform, circle, circleTransform).Should().BeTrue(); + } + + [Test] + public void PointCircleNotOverlapping() + { + var point = new Point(3, 0); + var circle = new Circle(1); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, circle, Transform2D.DefaultTransform).Should().BeFalse(); + } + + [Test] + public void PointRectangleOverlapping() + { + var point = new Point(1, 1); + var rectangle = new Rectangle(-2, -2, 2, 2); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeTrue(); + } + + [Test] + public void PointRectangleNotOverlapping() + { + var point = new Point(5, 5); + var rectangle = new Rectangle(-2, -2, 2, 2); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, rectangle, Transform2D.DefaultTransform).Should().BeFalse(); + } + + [Test] + public void PointPolygonOverlapping() + { + var point = new Point(1, 1); + var polygon = new Polygon( + new Position2D(-2, -2), + new Position2D(-3, 2), + new Position2D(3, 2), + new Position2D(3, -2) + ); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, polygon, Transform2D.DefaultTransform).Should().BeTrue(); + } + + [Test] + public void PointPolygonNotOverlapping() + { + var point = new Point(5, 5); + var polygon = new Polygon( + new Position2D(-2, -2), + new Position2D(-3, 2), + new Position2D(3, 2), + new Position2D(3, -2) + ); + + GJK2D.TestCollision(point, Transform2D.DefaultTransform, polygon, Transform2D.DefaultTransform).Should().BeFalse(); + } + [Test] public void LineLineOverlapping() { diff --git a/Test/SpatialHashTest.cs b/Test/SpatialHashTest.cs index a608dc6..85bb512 100644 --- a/Test/SpatialHashTest.cs +++ b/Test/SpatialHashTest.cs @@ -34,6 +34,9 @@ namespace Tests var line = new MoonTools.Core.Bonk.Line(new Position2D(20, -4), new Position2D(22, -12)); var lineTransform = new Transform2D(new Vector2(0, 0)); + var point = new MoonTools.Core.Bonk.Point(8, 8); + var pointTransform = Transform2D.DefaultTransform; + spatialHash.Insert(0, rectA, rectATransform); spatialHash.Insert(1, rectB, rectBTransform); spatialHash.Insert(2, rectC, rectCTransform); @@ -41,9 +44,11 @@ namespace Tests spatialHash.Insert(4, circleA, circleATransform); spatialHash.Insert(1, circleB, circleBTransform); spatialHash.Insert(6, line, lineTransform); + spatialHash.Insert(7, point, pointTransform); spatialHash.Retrieve(0, rectA, rectATransform).Should().BeEmpty(); spatialHash.Retrieve(1, rectB, rectBTransform).Should().NotContain((1, circleB, circleBTransform)); + spatialHash.Retrieve(1, rectB, rectBTransform).Should().Contain((7, point, pointTransform)); spatialHash.Retrieve(2, rectC, rectCTransform).Should().Contain((6, line, lineTransform)).And.Contain((4, circleA, circleATransform)); spatialHash.Retrieve(3, rectD, rectDTransform).Should().Contain((1, circleB, circleBTransform));