forked from MoonsideGames/MoonTools.Bonk
				
			polygon with immutable array
							parent
							
								
									b1a3e37a9d
								
							
						
					
					
						commit
						1430047327
					
				| 
						 | 
				
			
			@ -17,6 +17,6 @@
 | 
			
		|||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="MoonTools.Core.Structs" Version="2.0.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>
 | 
			
		||||
</Project>
 | 
			
		||||
| 
						 | 
				
			
			@ -4,9 +4,10 @@
 | 
			
		|||
 * https://blog.hamaluik.ca/posts/building-a-collision-engine-part-2-2d-penetration-vectors/
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
using Collections.Pooled;
 | 
			
		||||
using MoonTools.Core.Structs;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Immutable;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
 | 
			
		||||
namespace MoonTools.Core.Bonk
 | 
			
		||||
| 
						 | 
				
			
			@ -26,12 +27,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
        /// <returns></returns>
 | 
			
		||||
        public static Vector2 Intersect(IShape2D shapeA, Transform2D Transform2DA, IShape2D shapeB, Transform2D Transform2DB, Simplex2D simplex)
 | 
			
		||||
        {
 | 
			
		||||
            var simplexVertices = new PooledList<Vector2>(36, ClearMode.Always);
 | 
			
		||||
 | 
			
		||||
            foreach (var vertex in simplex.Vertices)
 | 
			
		||||
            {
 | 
			
		||||
                simplexVertices.Add(vertex);
 | 
			
		||||
            }
 | 
			
		||||
            var simplexVertices = simplex.Vertices.Select(vertex => vertex.ToVector2()).ToImmutableArray();
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
| 
						 | 
				
			
			@ -55,25 +51,23 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    simplexVertices.Insert(edge.index, support);
 | 
			
		||||
                    simplexVertices = simplexVertices.Insert(edge.index, support);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            simplexVertices.Dispose();
 | 
			
		||||
 | 
			
		||||
            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 closestNormal = Vector2.Zero;
 | 
			
		||||
            var closestIndex = 0;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < simplexVertices.Count; i++)
 | 
			
		||||
            for (int i = 0; i < simplexVertices.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var j = i + 1;
 | 
			
		||||
                if (j >= simplexVertices.Count) { j = 0; }
 | 
			
		||||
                if (j >= simplexVertices.Length) { j = 0; }
 | 
			
		||||
                Vector2 edge = simplexVertices[j] - simplexVertices[i];
 | 
			
		||||
 | 
			
		||||
                Vector2 norm;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
        private Position2D v0;
 | 
			
		||||
        private Position2D v1;
 | 
			
		||||
 | 
			
		||||
        private IEnumerable<Position2D> vertices
 | 
			
		||||
        private IEnumerable<Position2D> Vertices
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
 | 
			
		||||
        public AABB AABB(Transform2D Transform2D)
 | 
			
		||||
        {
 | 
			
		||||
            return Bonk.AABB.FromTransformedVertices(vertices, Transform2D);
 | 
			
		||||
            return Bonk.AABB.FromTransformedVertices(Vertices, Transform2D);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool Equals(object obj)
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
            var hashCode = -851829407;
 | 
			
		||||
            hashCode = hashCode * -1521134295 + EqualityComparer<Position2D>.Default.GetHashCode(v0);
 | 
			
		||||
            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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,26 +1,32 @@
 | 
			
		|||
using System.Linq;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.Immutable;
 | 
			
		||||
using System.Numerics;
 | 
			
		||||
using Collections.Pooled;
 | 
			
		||||
using MoonTools.Core.Structs;
 | 
			
		||||
using MoreLinq;
 | 
			
		||||
 | 
			
		||||
namespace MoonTools.Core.Bonk
 | 
			
		||||
{
 | 
			
		||||
    /// <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>
 | 
			
		||||
    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; } }
 | 
			
		||||
 | 
			
		||||
        // vertices are local to the origin
 | 
			
		||||
        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)
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +53,19 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
        {
 | 
			
		||||
            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;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,10 +73,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
 | 
			
		||||
        public override int GetHashCode()
 | 
			
		||||
        {
 | 
			
		||||
            var hashCode = -1404792980;
 | 
			
		||||
            hashCode = hashCode * -1521134295 + EqualityComparer<PooledSet<Position2D>>.Default.GetHashCode(vertices);
 | 
			
		||||
            hashCode = hashCode * -1521134295 + EqualityComparer<IEnumerable<Position2D>>.Default.GetHashCode(Vertices);
 | 
			
		||||
            return hashCode;
 | 
			
		||||
            return HashCode.Combine(vertices, Vertices);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator ==(Polygon a, Polygon b)
 | 
			
		||||
| 
						 | 
				
			
			@ -70,5 +85,15 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
        {
 | 
			
		||||
            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 MaxY { get; }
 | 
			
		||||
 | 
			
		||||
        private IEnumerable<Position2D> vertices
 | 
			
		||||
        public IEnumerable<Position2D> Vertices
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -38,12 +38,12 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
 | 
			
		||||
        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)
 | 
			
		||||
        {
 | 
			
		||||
            return Bonk.AABB.FromTransformedVertices(vertices, Transform2D);
 | 
			
		||||
            return Bonk.AABB.FromTransformedVertices(Vertices, Transform2D);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool Equals(object obj)
 | 
			
		||||
| 
						 | 
				
			
			@ -76,7 +76,7 @@ namespace MoonTools.Core.Bonk
 | 
			
		|||
            hashCode = hashCode * -1521134295 + MinY.GetHashCode();
 | 
			
		||||
            hashCode = hashCode * -1521134295 + MaxX.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;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -253,6 +253,66 @@ namespace Tests
 | 
			
		|||
 | 
			
		||||
                (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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue