using System; using System.Collections.Generic; using System.Linq; using System.Text; using Annulus.SweptCollisionDetection; using Annulus; using Azimuth; using Azimuth.RootFinding; namespace Annulus.UnitTests.SweptCollisionDetection { public class PolygonvsPolygonTests : UnitTestSharp.TestFixture { public class EdgeEdge_SolidHit : UnitTestSharp.TestFixture { public class EdgesAlign : UnitTestSharp.TestFixture { public void EdgeEdgeFlush_NullUserData() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void EdgeEdgeFlush_VV() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void EdgeEdgeFlush_VV_BothReverseOrder() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, payload = 25, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void EdgeEdgeFlush_VV_BothReverseWinding() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void EdgeEdgeFlush_VV_FirstReverseWinding() { var polygonReverse = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var polygonForward = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonReverse, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonForward, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonReverse.GetEdge(1), EdgeB = polygonForward.GetEdge(0), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonReverse.GetEdge(0), EdgeB = polygonForward.GetEdge(3), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonReverse.GetEdge(1), EdgeB = polygonForward.GetEdge(2), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonReverse.GetEdge(2), EdgeB = polygonForward.GetEdge(1), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonReverse.GetEdge(3), EdgeB = polygonForward.GetEdge(0), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonReverse.GetEdge(3), EdgeB = polygonForward.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void EdgeEdgeFlush_VV_SecondReverseWinding() { var polygonReverse = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var polygonForward = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonForward, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonReverse, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonForward.GetEdge(2), EdgeB = polygonReverse.GetEdge(3), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonForward.GetEdge(0), EdgeB = polygonReverse.GetEdge(3), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonForward.GetEdge(1), EdgeB = polygonReverse.GetEdge(2), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonForward.GetEdge(2), EdgeB = polygonReverse.GetEdge(1), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonForward.GetEdge(3), EdgeB = polygonReverse.GetEdge(0), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonForward.GetEdge(0), EdgeB = polygonReverse.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void Trapezoid() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var trapezoid = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 2,-1), new Vector(-2,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 10), LinearAcceleration = new Vector(0, -1), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = trapezoid, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = trapezoid.GetEdge(0), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = trapezoid.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = trapezoid.GetEdge(2), LeadingHitFraction = new Tuple(1, 0.75), TrailingHitFraction = new Tuple(0, 0.25), TOI = Math.Sqrt(20), Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = trapezoid.GetEdge(2), LeadingHitFraction = new Tuple(1, 0.25), TrailingHitFraction = new Tuple(0, 0.75), TOI = Math.Sqrt(24), Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void TODONameThisTest() { var polygon = new SimplePolygon(new Vector[] { new Vector(-10, -10), new Vector( 10, -10), new Vector( 10, 10), new Vector(-10, 10), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 259.81751884), LinearAcceleration = new Vector(0, -500), LinearVelocity = new Vector(0, -624.6458846122), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 221.00902846), LinearAcceleration = new Vector(0, -500), LinearVelocity = new Vector(0, 590.75457809), }, payload = 25, }, impactWindow = new Interval(0, 0.0166666667), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(2), PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, TOI = 0.0154751384, Transition = PolygonvsPolygon.TransitionState.Entering, LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), }, }; CheckEqual(expected, output); } } public class EdgeEdge_OneSmaller : UnitTestSharp.TestFixture { public void SmallerFalling() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_SmallerReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_LargerReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_BothReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.25), LeadingHitFraction = new Tuple(1, 0.75), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.75), LeadingHitFraction = new Tuple(1, 0.25), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void LargerFalling() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(2), EdgeB = smallerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(2), EdgeB = smallerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(0), EdgeB = smallerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(0), EdgeB = smallerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void LargerFalling_SmallerReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(2), EdgeB = smallerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(2), EdgeB = smallerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(0), EdgeB = smallerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(0), EdgeB = smallerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void LargerFalling_LargerReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(1), EdgeB = smallerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(1), EdgeB = smallerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(3), EdgeB = smallerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(3), EdgeB = smallerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void LargerFalling_BothReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 17, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(1), EdgeB = smallerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(1), EdgeB = smallerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(3), EdgeB = smallerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0.25, 0), LeadingHitFraction = new Tuple(0.75, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = largerPolygon.GetEdge(3), EdgeB = smallerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0.25, 1), LeadingHitFraction = new Tuple(0.75, 0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } } public class EdgeEdge_UnevenOnVertex : UnitTestSharp.TestFixture { public void SmallerFalling_AlignedLeft() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(-1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedRight() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedLeft_ReverseSmaller() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(-1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedRight_ReverseSmaller() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedLeft_ReverseLarger() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(-1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedRight_ReverseLarger() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedLeft_ReverseBoth() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(-1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SmallerFalling_AlignedRight_ReverseBoth() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector(-2,-2), new Vector( 2,-2), new Vector( 2, 2), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(1, 7), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } } public class EdgeEdge_Overlap : UnitTestSharp.TestFixture { // [-----------------> // <--------------] public void Basic() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0.25, 6), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(0), TrailingHitFraction = new Tuple(0.125, 1), LeadingHitFraction = new Tuple(1, 0.125), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.125), LeadingHitFraction = new Tuple(0.875, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), TrailingHitFraction = new Tuple(0.125, 0), LeadingHitFraction = new Tuple(1, 0.875), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.875), LeadingHitFraction = new Tuple(0.875, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void Basic_BothReversed() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0.25, 6), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.875), LeadingHitFraction = new Tuple(0.875, 0), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.125), LeadingHitFraction = new Tuple(0.875, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), TrailingHitFraction = new Tuple(0.125, 0), LeadingHitFraction = new Tuple(1, 0.875), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(1), TrailingHitFraction = new Tuple(0.125, 1), LeadingHitFraction = new Tuple(1, 0.125), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void Basic_TopReversed() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var reversedPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = reversedPolygon, motion = new Motion { InitialPosition = new Vector(0.25, 6), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(1), EdgeB = polygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.125), LeadingHitFraction = new Tuple(0.875, 1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(1), EdgeB = polygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.875), LeadingHitFraction = new Tuple(0.875, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(3), EdgeB = polygon.GetEdge(0), TrailingHitFraction = new Tuple(0.125, 1), LeadingHitFraction = new Tuple(1, 0.125), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(3), EdgeB = polygon.GetEdge(2), TrailingHitFraction = new Tuple(0.125, 0), LeadingHitFraction = new Tuple(1, 0.875), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void Basic_BottomReversed() { var polygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var reversedPolygon = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector(-1,-1), new Vector( 1,-1), new Vector( 1, 1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0.25, 6), LinearVelocity = new Vector(0, -1), }, payload = 25, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = reversedPolygon, motion = new Motion { }, payload = 17, }, impactWindow = new Interval(0, 20), }; var output = PolygonvsPolygon.FindIntersectionsInWindow(input); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = reversedPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0.125, 0), LeadingHitFraction = new Tuple(1, 0.875), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = reversedPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.875), LeadingHitFraction = new Tuple(0.875, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = reversedPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0.125, 1), LeadingHitFraction = new Tuple(1, 0.125), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = reversedPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.125), LeadingHitFraction = new Tuple(0.875, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } } } public class VertexVertex_SolidHit : UnitTestSharp.TestFixture { public void DiamondDiamond_SameSize() { var polygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = polygon.GetVertex(0), VertexB = polygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygon.GetVertex(2), VertexB = polygon.GetVertex(0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_SameSize_TopReversed() { var polygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var reversedPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector(-1, 0), new Vector( 0, 1), new Vector( 1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = reversedPolygon, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = reversedPolygon.GetVertex(0), VertexB = polygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(0), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(1), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(2), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = reversedPolygon.GetEdge(3), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = reversedPolygon.GetVertex(2), VertexB = polygon.GetVertex(0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_SameSize_BottomReversed() { var polygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var reversedPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector(-1, 0), new Vector( 0, 1), new Vector( 1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = reversedPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = polygon.GetVertex(0), VertexB = reversedPolygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = reversedPolygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = reversedPolygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = reversedPolygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = reversedPolygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 0), TrailingHitFraction = new Tuple(0, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygon.GetVertex(2), VertexB = reversedPolygon.GetVertex(0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_SameSize_BothReverseWinding() { var polygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector(-1, 0), new Vector( 0, 1), new Vector( 1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = polygon.GetVertex(0), VertexB = polygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(0), EdgeB = polygon.GetEdge(0), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(1), EdgeB = polygon.GetEdge(1), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(2), EdgeB = polygon.GetEdge(2), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygon.GetEdge(3), EdgeB = polygon.GetEdge(3), LeadingHitFraction = new Tuple(1, 1), TrailingHitFraction = new Tuple(0, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygon.GetVertex(2), VertexB = polygon.GetVertex(0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_OneLarger() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -2), new Vector( 2, 0), new Vector( 0, 2), new Vector(-2, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(0), VertexB = largerPolygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(2), VertexB = largerPolygon.GetVertex(0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_OneLarger_BothReverseWinding() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector(-1, 0), new Vector( 0, 1), new Vector( 1, 0), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -2), new Vector(-2, 0), new Vector( 0, 2), new Vector( 2, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(0), VertexB = largerPolygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 1), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(2), VertexB = largerPolygon.GetVertex(0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_OneLarger_LargerReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -2), new Vector(-2, 0), new Vector( 0, 2), new Vector( 2, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(0), VertexB = largerPolygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(2), VertexB = largerPolygon.GetVertex(0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void DiamondDiamond_OneLarger_SmallerReverse() { var smallerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -1), new Vector(-1, 0), new Vector( 0, 1), new Vector( 1, 0), }); var largerPolygon = new SimplePolygon(new Vector[] { new Vector( 0, -2), new Vector( 2, 0), new Vector( 0, 2), new Vector(-2, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = smallerPolygon, motion = new Motion { InitialPosition = new Vector(0, 7), LinearVelocity = new Vector(0, -1), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = largerPolygon, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(0), VertexB = largerPolygon.GetVertex(2), TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(1), EdgeB = largerPolygon.GetEdge(2), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(2), EdgeB = largerPolygon.GetEdge(1), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 6, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(0), EdgeB = largerPolygon.GetEdge(3), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0.5), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = smallerPolygon.GetEdge(3), EdgeB = largerPolygon.GetEdge(0), TrailingHitFraction = new Tuple(0, 0.5), LeadingHitFraction = new Tuple(1, 0), TOI = 8, Transition = PolygonvsPolygon.TransitionState.FeaturesAligning, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = smallerPolygon.GetVertex(2), VertexB = largerPolygon.GetVertex(0), TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } } public class VertexEdge_SolidHit : UnitTestSharp.TestFixture { public void SquareAndDiamond() { var square = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var diamond = new SimplePolygon(new Vector[] { new Vector( 0,-1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = diamond, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = "A", }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = square, motion = new Motion { }, payload = "B", }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(1), VertexB = square.GetVertex(1), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(3), VertexB = square.GetVertex(0), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(1), VertexB = square.GetVertex(2), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(3), VertexB = square.GetVertex(3), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SquareAndDiamond_ReverseMotion() { var square = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var diamond = new SimplePolygon(new Vector[] { new Vector( 0,-1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = square, motion = new Motion { InitialPosition = new Vector(0, -6), LinearVelocity = new Vector(0, 1), }, payload = "B", }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = diamond, motion = new Motion { }, payload = "A", }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_B.payload, PayloadB = input.polygon_A.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = square.GetVertex(0), VertexB = diamond.GetVertex(3), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = square.GetVertex(1), VertexB = diamond.GetVertex(1), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_B.payload, PayloadB = input.polygon_A.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_B.payload, PayloadB = input.polygon_A.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = square.GetVertex(2), VertexB = diamond.GetVertex(1), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = square.GetVertex(3), VertexB = diamond.GetVertex(3), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_B.payload, PayloadB = input.polygon_A.payload, }, }; CheckEqual(expected, output); } public void SquareAndDiamond_ReverseDiamond() { var square = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var diamond = new SimplePolygon(new Vector[] { new Vector( 0,-1), new Vector(-1, 0), new Vector( 0, 1), new Vector( 1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = diamond, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = "A", }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = square, motion = new Motion { }, payload = "B", }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(1), VertexB = square.GetVertex(0), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(3), VertexB = square.GetVertex(1), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(1), VertexB = square.GetVertex(3), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = diamond.GetVertex(3), VertexB = square.GetVertex(2), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SquareAndSmallerDiamond() { var square = new SimplePolygon(new Vector[] { new Vector(-2, 2), new Vector( 2, 2), new Vector( 2,-2), new Vector(-2,-2), }); var diamond = new SimplePolygon(new Vector[] { new Vector( 0,-1), new Vector( 1, 0), new Vector( 0, 1), new Vector(-1, 0), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = diamond, motion = new Motion { InitialPosition = new Vector(0, 6), LinearVelocity = new Vector(0, -1), }, payload = "A", }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = square, motion = new Motion { InitialPosition = new Vector(0, -1), }, payload = "B", }, impactWindow = new Interval(0, 10), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 4, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(1), EdgeB = square.GetEdge(0), HitFraction = 0.75, TOI = 5, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(3), EdgeB = square.GetEdge(0), HitFraction = 0.25, TOI = 5, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(0), HitFraction = 0.5, TOI = 6, Transition = PolygonvsPolygon.TransitionState.Entering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(0), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 8, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(1), EdgeB = square.GetEdge(2), HitFraction = 0.25, TOI = 9, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(3), EdgeB = square.GetEdge(2), HitFraction = 0.75, TOI = 9, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexEdgeCollision { VertexA = diamond.GetVertex(2), EdgeB = square.GetEdge(2), HitFraction = 0.5, TOI = 10, Transition = PolygonvsPolygon.TransitionState.Exiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } } public class GlancingHits : UnitTestSharp.TestFixture { public void SquareSpinning() { var hSqrt2 = Math.Sqrt(2); var polygonDiamond = new SimplePolygon(new Vector[] { new Vector(0, 1), new Vector(1, 0), new Vector(0,-1), new Vector(-1,0), }); var polygonSquare = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonSquare, motion = new Motion { AngularVelocity = Math.PI / 4, InitialPosition = new Vector(0, 1 + hSqrt2), LinearVelocity = new Vector(0, 0), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonDiamond, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 8), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(3), VertexB = polygonDiamond.GetVertex(0), TOI = 1, Transition = PolygonvsPolygon.TransitionState.GlancingOutside, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(0), VertexB = polygonDiamond.GetVertex(0), TOI = 3, Transition = PolygonvsPolygon.TransitionState.GlancingOutside, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(1), VertexB = polygonDiamond.GetVertex(0), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingOutside, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(2), VertexB = polygonDiamond.GetVertex(0), TOI = 7, Transition = PolygonvsPolygon.TransitionState.GlancingOutside, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SquaresSliding() { var polygonSquare = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonSquare, motion = new Motion { InitialPosition = new Vector(3, 2), LinearVelocity = new Vector(-1, 0), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonSquare, motion = new Motion { }, payload = 25, }, impactWindow = new Interval(0, 8), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(3), VertexB = polygonSquare.GetVertex(1), TOI = 1, Transition = PolygonvsPolygon.TransitionState.GlancingParallelEntering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonSquare.GetEdge(2), EdgeB = polygonSquare.GetEdge(0), TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), TOI = 3, Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(2), VertexB = polygonSquare.GetVertex(0), TOI = 5, Transition = PolygonvsPolygon.TransitionState.GlancingParallelExiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } public void SquaresSlideBack() { var polygonSquare = new SimplePolygon(new Vector[] { new Vector(-1, 1), new Vector( 1, 1), new Vector( 1,-1), new Vector(-1,-1), }); var input = new PolygonvsPolygon.Input { polygon_A = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonSquare, motion = new Motion { InitialPosition = new Vector(12, 2), LinearVelocity = new Vector(-3.5, 0), LinearAcceleration = new Vector(0.5, 0), }, payload = 7, }, polygon_B = new PolygonvsPolygon.SimplePolygonInMotion { polygon = polygonSquare, motion = new Motion { InitialPosition = new Vector(0, 0), }, payload = 25, }, impactWindow = new Interval(0, 20), }; int iterations = 0; var output = PolygonvsPolygon.FindIntersectionsInWindow(input, ref iterations); var expected = new PolygonvsPolygon.Hit[] { new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(3), VertexB = polygonSquare.GetVertex(1), TOI = 4, Transition = PolygonvsPolygon.TransitionState.GlancingParallelEntering, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonSquare.GetEdge(2), EdgeB = polygonSquare.GetEdge(0), TOI = 6, TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.EdgeEdgeCollision { EdgeA = polygonSquare.GetEdge(2), EdgeB = polygonSquare.GetEdge(0), TOI = 8, TrailingHitFraction = new Tuple(0, 1), LeadingHitFraction = new Tuple(1, 0), Transition = PolygonvsPolygon.TransitionState.GlancingParallel, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, new PolygonvsPolygon.VertexVertexCollision { VertexA = polygonSquare.GetVertex(3), VertexB = polygonSquare.GetVertex(1), TOI = 10, Transition = PolygonvsPolygon.TransitionState.GlancingParallelExiting, PayloadA = input.polygon_A.payload, PayloadB = input.polygon_B.payload, }, }; CheckEqual(expected, output); } } // edge edge // edge vertex // vertex vertex // Just touch // edge edge // edge vertex // vertex vertex } }