polygon with immutable array
							parent
							
								
									b1a3e37a9d
								
							
						
					
					
						commit
						1430047327
					
				|  | @ -17,6 +17,6 @@ | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <PackageReference Include="MoonTools.Core.Structs" Version="2.0.0"/> |     <PackageReference Include="MoonTools.Core.Structs" Version="2.0.0"/> | ||||||
|     <PackageReference Include="morelinq" Version="3.2.0"/> |     <PackageReference Include="morelinq" Version="3.2.0"/> | ||||||
|     <PackageReference Include="Collections.Pooled" Version="1.0.82"/> |     <PackageReference Include="System.Collections.Immutable" Version="1.6.0"/> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -4,9 +4,10 @@ | ||||||
|  * https://blog.hamaluik.ca/posts/building-a-collision-engine-part-2-2d-penetration-vectors/ |  * https://blog.hamaluik.ca/posts/building-a-collision-engine-part-2-2d-penetration-vectors/ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| using Collections.Pooled; |  | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using System; | using System; | ||||||
|  | using System.Collections.Immutable; | ||||||
|  | using System.Linq; | ||||||
| using System.Numerics; | using System.Numerics; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.Core.Bonk | namespace MoonTools.Core.Bonk | ||||||
|  | @ -26,12 +27,7 @@ namespace MoonTools.Core.Bonk | ||||||
|         /// <returns></returns> |         /// <returns></returns> | ||||||
|         public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex2D simplex) |         public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex2D simplex) | ||||||
|         { |         { | ||||||
|             var simplexVertices = new PooledList<Vector2>(36, ClearMode.Always); |             var simplexVertices = simplex.Vertices.Select(vertex => vertex.ToVector2()).ToImmutableArray(); | ||||||
| 
 |  | ||||||
|             foreach (var vertex in simplex.Vertices) |  | ||||||
|             { |  | ||||||
|                 simplexVertices.Add(vertex); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|             var e0 = (simplexVertices[1].X - simplexVertices[0].X) * (simplexVertices[1].Y + simplexVertices[0].Y); |             var e0 = (simplexVertices[1].X - simplexVertices[0].X) * (simplexVertices[1].Y + simplexVertices[0].Y); | ||||||
|             var e1 = (simplexVertices[2].X - simplexVertices[1].X) * (simplexVertices[2].Y + simplexVertices[1].Y); |             var e1 = (simplexVertices[2].X - simplexVertices[1].X) * (simplexVertices[2].Y + simplexVertices[1].Y); | ||||||
|  | @ -55,25 +51,23 @@ namespace MoonTools.Core.Bonk | ||||||
|                 } |                 } | ||||||
|                 else |                 else | ||||||
|                 { |                 { | ||||||
|                     simplexVertices.Insert(edge.index, support); |                     simplexVertices = simplexVertices.Insert(edge.index, support); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             simplexVertices.Dispose(); |  | ||||||
| 
 |  | ||||||
|             return intersection; |             return intersection; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private static Edge FindClosestEdge(PolygonWinding winding, PooledList<Vector2> simplexVertices) |         private static Edge FindClosestEdge(PolygonWinding winding, ImmutableArray<Vector2> simplexVertices) | ||||||
|         { |         { | ||||||
|             var closestDistance = float.PositiveInfinity; |             var closestDistance = float.PositiveInfinity; | ||||||
|             var closestNormal = Vector2.Zero; |             var closestNormal = Vector2.Zero; | ||||||
|             var closestIndex = 0; |             var closestIndex = 0; | ||||||
| 
 | 
 | ||||||
|             for (int i = 0; i < simplexVertices.Count; i++) |             for (int i = 0; i < simplexVertices.Length; i++) | ||||||
|             { |             { | ||||||
|                 var j = i + 1; |                 var j = i + 1; | ||||||
|                 if (j >= simplexVertices.Count) { j = 0; } |                 if (j >= simplexVertices.Length) { j = 0; } | ||||||
|                 Vector2 edge = simplexVertices[j] - simplexVertices[i]; |                 Vector2 edge = simplexVertices[j] - simplexVertices[i]; | ||||||
| 
 | 
 | ||||||
|                 Vector2 norm; |                 Vector2 norm; | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ namespace MoonTools.Core.Bonk | ||||||
|         private Position2D v0; |         private Position2D v0; | ||||||
|         private Position2D v1; |         private Position2D v1; | ||||||
| 
 | 
 | ||||||
|         private IEnumerable<Position2D> vertices |         private IEnumerable<Position2D> Vertices | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
|             { |             { | ||||||
|  | @ -39,7 +39,7 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public AABB AABB(Transform2D Transform2D) |         public AABB AABB(Transform2D Transform2D) | ||||||
|         { |         { | ||||||
|             return Bonk.AABB.FromTransformedVertices(vertices, Transform2D); |             return Bonk.AABB.FromTransformedVertices(Vertices, Transform2D); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override bool Equals(object obj) |         public override bool Equals(object obj) | ||||||
|  | @ -67,7 +67,7 @@ namespace MoonTools.Core.Bonk | ||||||
|             var hashCode = -851829407; |             var hashCode = -851829407; | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Position2D>.Default.GetHashCode(v0); |             hashCode = hashCode * -1521134295 + EqualityComparer<Position2D>.Default.GetHashCode(v0); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<Position2D>.Default.GetHashCode(v1); |             hashCode = hashCode * -1521134295 + EqualityComparer<Position2D>.Default.GetHashCode(v1); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(vertices); |             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices); | ||||||
|             return hashCode; |             return hashCode; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,26 +1,32 @@ | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.Collections.Immutable; | ||||||
| using System.Numerics; | using System.Numerics; | ||||||
| using Collections.Pooled; |  | ||||||
| using MoonTools.Core.Structs; | using MoonTools.Core.Structs; | ||||||
| using MoreLinq; | using MoreLinq; | ||||||
| 
 | 
 | ||||||
| namespace MoonTools.Core.Bonk | namespace MoonTools.Core.Bonk | ||||||
| { | { | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// A Shape defined by an arbitrary collection of vertices. WARNING: Polygon must use an Array internally and therefore will create GC pressure. |     /// A Shape defined by an arbitrary collection of vertices. | ||||||
|  |     /// NOTE: A Polygon must have more than 2 vertices and should not have duplicate vertices. | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     public struct Polygon : IShape2D, IEquatable<IShape2D> |     public struct Polygon : IShape2D, IEquatable<IShape2D> | ||||||
|     { |     { | ||||||
|         private PooledSet<Position2D> vertices; |         private ImmutableArray<Position2D> vertices; | ||||||
| 
 | 
 | ||||||
|         public IEnumerable<Position2D> Vertices { get { return vertices == null ? Enumerable.Empty<Position2D>() : vertices; } } |         public IEnumerable<Position2D> Vertices { get { return vertices == null ? Enumerable.Empty<Position2D>() : vertices; } } | ||||||
| 
 | 
 | ||||||
|         // vertices are local to the origin |         // vertices are local to the origin | ||||||
|         public Polygon(params Position2D[] vertices) |         public Polygon(params Position2D[] vertices) | ||||||
|         { |         { | ||||||
|             this.vertices = new PooledSet<Position2D>(vertices, ClearMode.Always); |             this.vertices = ImmutableArray.Create<Position2D>(vertices); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public Polygon(ImmutableArray<Position2D> vertices) | ||||||
|  |         { | ||||||
|  |             this.vertices = vertices; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction, Transform2D transform) |         public Vector2 Support(Vector2 direction, Transform2D transform) | ||||||
|  | @ -47,7 +53,19 @@ namespace MoonTools.Core.Bonk | ||||||
|         { |         { | ||||||
|             if (other is Polygon otherPolygon) |             if (other is Polygon otherPolygon) | ||||||
|             { |             { | ||||||
|                 return vertices.SetEquals(otherPolygon.vertices); |                 var q = from a in vertices | ||||||
|  |                         join b in otherPolygon.vertices on a equals b | ||||||
|  |                         select a; | ||||||
|  | 
 | ||||||
|  |                 return vertices.Length == otherPolygon.vertices.Length && q.Count() == vertices.Length; | ||||||
|  |             } | ||||||
|  |             else if (other is Rectangle rectangle) | ||||||
|  |             { | ||||||
|  |                 var q = from a in vertices | ||||||
|  |                         join b in rectangle.Vertices on a equals b | ||||||
|  |                         select a; | ||||||
|  | 
 | ||||||
|  |                 return vertices.Length == 4 && q.Count() == vertices.Length; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return false; |             return false; | ||||||
|  | @ -55,10 +73,7 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public override int GetHashCode() |         public override int GetHashCode() | ||||||
|         { |         { | ||||||
|             var hashCode = -1404792980; |             return HashCode.Combine(vertices, Vertices); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<PooledSet<Position2D>>.Default.GetHashCode(vertices); |  | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices); |  | ||||||
|             return hashCode; |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static bool operator ==(Polygon a, Polygon b) |         public static bool operator ==(Polygon a, Polygon b) | ||||||
|  | @ -70,5 +85,15 @@ namespace MoonTools.Core.Bonk | ||||||
|         { |         { | ||||||
|             return !(a == b); |             return !(a == b); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         public static bool operator ==(Polygon a, Rectangle b) | ||||||
|  |         { | ||||||
|  |             return a.Equals(b); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public static bool operator !=(Polygon a, Rectangle b) | ||||||
|  |         { | ||||||
|  |             return !(a == b); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ namespace MoonTools.Core.Bonk | ||||||
|         public int MaxX { get; } |         public int MaxX { get; } | ||||||
|         public int MaxY { get; } |         public int MaxY { get; } | ||||||
| 
 | 
 | ||||||
|         private IEnumerable<Position2D> vertices |         public IEnumerable<Position2D> Vertices | ||||||
|         { |         { | ||||||
|             get |             get | ||||||
|             { |             { | ||||||
|  | @ -38,12 +38,12 @@ namespace MoonTools.Core.Bonk | ||||||
| 
 | 
 | ||||||
|         public Vector2 Support(Vector2 direction, Transform2D transform) |         public Vector2 Support(Vector2 direction, Transform2D transform) | ||||||
|         { |         { | ||||||
|             return vertices.Select(vertex => Vector2.Transform(vertex, transform.TransformMatrix)).MaxBy(transformed => Vector2.Dot(transformed, direction)).First(); |             return Vertices.Select(vertex => Vector2.Transform(vertex, transform.TransformMatrix)).MaxBy(transformed => Vector2.Dot(transformed, direction)).First(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public AABB AABB(Transform2D Transform2D) |         public AABB AABB(Transform2D Transform2D) | ||||||
|         { |         { | ||||||
|             return Bonk.AABB.FromTransformedVertices(vertices, Transform2D); |             return Bonk.AABB.FromTransformedVertices(Vertices, Transform2D); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public override bool Equals(object obj) |         public override bool Equals(object obj) | ||||||
|  | @ -76,7 +76,7 @@ namespace MoonTools.Core.Bonk | ||||||
|             hashCode = hashCode * -1521134295 + MinY.GetHashCode(); |             hashCode = hashCode * -1521134295 + MinY.GetHashCode(); | ||||||
|             hashCode = hashCode * -1521134295 + MaxX.GetHashCode(); |             hashCode = hashCode * -1521134295 + MaxX.GetHashCode(); | ||||||
|             hashCode = hashCode * -1521134295 + MaxY.GetHashCode(); |             hashCode = hashCode * -1521134295 + MaxY.GetHashCode(); | ||||||
|             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(vertices); |             hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices); | ||||||
|             return hashCode; |             return hashCode; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -253,6 +253,66 @@ namespace Tests | ||||||
| 
 | 
 | ||||||
|                 (a != b).Should().BeTrue(); |                 (a != b).Should().BeTrue(); | ||||||
|             } |             } | ||||||
|  | 
 | ||||||
|  |             [Test] | ||||||
|  |             public void PolygonRectangleEqual() | ||||||
|  |             { | ||||||
|  |                 var a = new Polygon( | ||||||
|  |                     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.Should().BeEquivalentTo(b); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Test] | ||||||
|  |             public void PolygonRectangleNotEqual() | ||||||
|  |             { | ||||||
|  |                 var a = new Polygon( | ||||||
|  |                     new Position2D(2, 1), | ||||||
|  |                     new Position2D(1, -1), | ||||||
|  |                     new Position2D(-1, -1), | ||||||
|  |                     new Position2D(-2, 1) | ||||||
|  |                 ); | ||||||
|  | 
 | ||||||
|  |                 var b = new Rectangle(-1, -1, 1, 1); | ||||||
|  | 
 | ||||||
|  |                 a.Should().NotBeEquivalentTo(b); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Test] | ||||||
|  |             public void PolygonRectangleEqualOperator() | ||||||
|  |             { | ||||||
|  |                 var a = new Polygon( | ||||||
|  |                     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(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             [Test] | ||||||
|  |             public void PolygonRectangleNotEqualOperator() | ||||||
|  |             { | ||||||
|  |                 var a = new Polygon( | ||||||
|  |                     new Position2D(2, 1), | ||||||
|  |                     new Position2D(1, -1), | ||||||
|  |                     new Position2D(-1, -1), | ||||||
|  |                     new Position2D(-2, 1) | ||||||
|  |                 ); | ||||||
|  | 
 | ||||||
|  |                 var b = new Rectangle(-1, -1, 1, 1); | ||||||
|  | 
 | ||||||
|  |                 (a != b).Should().BeTrue(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public class SimplexTests |         public class SimplexTests | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue