using System; using System.Collections.Generic; using System.Linq; using System.Text; using Annulus; using Azimuth; using Annulus.SweptCollisionDetection; namespace Annulus.UnitTests.SweptCollisionDetection { public class CirclevsCircleTests { public class NoMotionTests : UnitTestSharp.TestFixture { public void NoMotion_Cocentric_DifferentSizes() { Motion stationary_Origin = new Motion(); var circle1 = new Circle { Radius = 5.0, }; var circle2 = new Circle { Radius = 2.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Origin); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.IntersectingNoMotion, }, }; CheckEqual(expected, hits); } public void NoMotion_Cocentric_SameSize() { Motion stationary_Origin = new Motion(); var circle1 = new Circle { Radius = 5.0, }; var circle2 = new Circle { Radius = 5.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Origin); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.IntersectingNoMotion, }, }; CheckEqual(expected, hits); } public void NoMotion_Intersecting() { Motion stationary_Origin = new Motion(); Motion stationary_Side = new Motion { InitialPosition = new Vector(9, 0), }; var circle1 = new Circle { Radius = 5.0, }; var circle2 = new Circle { Radius = 5.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.IntersectingNoMotion, }, }; CheckEqual(expected, hits); } public void NoMotion_Intersecting_Incident() { Motion stationary_Origin = new Motion(); Motion stationary_Side = new Motion { InitialPosition = new Vector(10, 0), }; var circle1 = new Circle { Radius = 5.0, }; var circle2 = new Circle { Radius = 5.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.GlancingNoMotion, }, }; CheckEqual(expected, hits); } public void NoMotion_Disparate() { Motion stationary_Origin = new Motion(); Motion stationary_Side = new Motion { InitialPosition = new Vector(11, 0), }; var circle1 = new Circle { Radius = 5.0, }; var circle2 = new Circle { Radius = 5.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { }; CheckEqual(expected, hits); } } public class LinearMotionTests : UnitTestSharp.TestFixture { public void OneSecond_OneSecond() { Motion stationary_Origin = new Motion(); Motion stationary_Side = new Motion { InitialPosition = new Vector(6, 0), LinearVelocity = new Vector(-4, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Entering, TOI = 1, HitPosition = new Vector(1, 0), }, new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Exiting, TOI = 2, HitPosition = new Vector(-1, 0), }, }; CheckEqual(expected, hits); } public void Miss() { Motion stationary_Origin = new Motion(); Motion stationary_Side = new Motion { InitialPosition = new Vector(6, 6), LinearVelocity = new Vector(4, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { }; CheckEqual(expected, hits); } public void CoMovement_JustIntersecting() { Motion stationary_Origin = new Motion { LinearVelocity = new Vector(4, 0), }; Motion stationary_Side = new Motion { InitialPosition = new Vector(2, 0), LinearVelocity = new Vector(4, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.GlancingNoMotion, }, }; CheckEqual(expected, hits); } public void Conjoined_Separate() { Motion stationary_Origin = new Motion { LinearVelocity = new Vector(-4, 0), }; Motion stationary_Side = new Motion { InitialPosition = new Vector(2, 0), LinearVelocity = new Vector(4, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { HitPosition = new Vector(1, 0), TOI = -0.5, Transition = CirclevsCircle.TransitionState.Entering, }, new CirclevsCircle.Hit { HitPosition = new Vector(1, 0), TOI = 0, Transition = CirclevsCircle.TransitionState.Exiting, }, }; CheckEqual(expected, hits); } public void Conjoined_Converge() { Motion stationary_Origin = new Motion { LinearVelocity = new Vector(2, 0), }; Motion stationary_Side = new Motion { InitialPosition = new Vector(2, 0), LinearVelocity = new Vector(-2, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Entering, TOI = 0, HitPosition = new Vector(1, 0), }, new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Exiting, TOI = 1, HitPosition = new Vector(1, 0), }, }; CheckEqual(expected, hits); } public void Glancing_Converge() { Motion stationary_Origin = new Motion { LinearVelocity = new Vector(2, 0), }; Motion stationary_Side = new Motion { InitialPosition = new Vector(6, -2), LinearVelocity = new Vector(-2, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { HitPosition = new Vector(3, -1), TOI = 1.5, Transition = CirclevsCircle.TransitionState.GlancingOutside, }, }; CheckEqual(expected, hits); } public void Glancing_Separate() { Motion stationary_Origin = new Motion { LinearVelocity = new Vector(2, 0), }; Motion stationary_Side = new Motion { InitialPosition = new Vector(0, -2), LinearVelocity = new Vector(-2, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { HitPosition = new Vector(0, -1), TOI = 0, Transition = CirclevsCircle.TransitionState.GlancingOutside, }, }; CheckEqual(expected, hits); } } public class LinearAccelerationMotionTests : UnitTestSharp.TestFixture { public void OneSecond_OneSecond() { Motion stationary_Origin = new Motion(); Motion stationary_Side = new Motion { LinearAcceleration = new Vector(-8.0/3.0, 0), InitialPosition = new Vector(10.0/3.0, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, stationary_Origin, circle2, stationary_Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(-1, 0), TOI = -2, }, new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(1, 0), TOI = -1, }, new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(1, 0), TOI = 1, }, new CirclevsCircle.Hit { Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(-1, 0), TOI = 2, }, }; CheckEqual(expected, hits); } public void Miss() { Motion Origin = new Motion(); Motion Side = new Motion { InitialPosition = new Vector(6, 0), LinearAcceleration = new Vector(1, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, Origin, circle2, Side); var expected = new CirclevsCircle.Hit[] { }; CheckEqual(expected, hits); } public void DoublePenetrate() //heh heh { Motion Origin = new Motion(); Motion Side = new Motion { InitialPosition = new Vector(0, -6), LinearVelocity = new Vector(0, 6), LinearAcceleration = new Vector(0, -1), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, Origin, circle2, Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { TOI = 6 - Math.Sqrt(28), Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(0, -1), }, new CirclevsCircle.Hit { TOI = 6 - Math.Sqrt(20), Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(0, 1), }, new CirclevsCircle.Hit { TOI = 6 + Math.Sqrt(20), Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(0, 1), }, new CirclevsCircle.Hit { TOI = 6 + Math.Sqrt(28), Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(0, -1), }, }; CheckEqual(expected, hits); } public void GlancingThenOverlap() { Motion Origin = new Motion() { InitialPosition = new Vector(-2, 0), LinearVelocity = new Vector(0, 12), LinearAcceleration = new Vector(0, -1), }; Motion Side = new Motion { LinearVelocity = new Vector(12, 0), LinearAcceleration = new Vector(-1, 0), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, Origin, circle2, Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { TOI = -0.1655250606, Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(-2, -1), }, new CirclevsCircle.Hit { TOI = 0, Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(-1, 0), }, new CirclevsCircle.Hit { TOI = 24, Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(-1, 0), }, new CirclevsCircle.Hit { TOI = 24.165525061, Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(-2, -1), //HitPosition = TODO }, }; CheckEqual(expected, hits); } public void DoubleRootWhileLeaving() { Motion Origin = new Motion() { }; Motion Side = new Motion { InitialPosition = new Vector(0, -98), LinearVelocity = new Vector(0, 20), LinearAcceleration = new Vector(0, -2), }; var circle1 = new Circle { Radius = 1.0, }; var circle2 = new Circle { Radius = 1.0, }; var hits = CirclevsCircle.FindIntersections( circle1, Origin, circle2, Side); var expected = new CirclevsCircle.Hit[] { new CirclevsCircle.Hit { TOI = 10 - Math.Sqrt(100 - 96), Transition = CirclevsCircle.TransitionState.Entering, HitPosition = new Vector(0, -1), }, new CirclevsCircle.Hit { TOI = 10, Transition = CirclevsCircle.TransitionState.GlancingInside, HitPosition = new Vector(0, 1), }, new CirclevsCircle.Hit { TOI = 10 + Math.Sqrt(100 - 96), Transition = CirclevsCircle.TransitionState.Exiting, HitPosition = new Vector(0, -1), }, }; CheckEqual(expected, hits); } } } }