using System; using System.Collections.Generic; using System.Linq; using System.Text; using Annulus.SweptCollisionDetection; using Azimuth; using Azimuth.RootFinding; using Azimuth.Approximation; namespace Annulus.UnitTests.SweptCollisionDetection { public class LinevsPointTests : UnitTestSharp.TestFixture { public class FindIntersectionsInWindow : UnitTestSharp.TestFixture { public void NoMotion_NotIntersecting() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); CheckEqual(0, hits.Count); } public void NoMotion_Intersecting() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 0), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = Scalar.PositiveInfinity, Transition = LinevsPoint.Hit.TransitionType.GlancingParallel, }, }; CheckEqual(expected, hits); } public void SimpleLinearMotion_Velocity() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 1), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 0), LinearVelocity = new Vector(0, -1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1, }, }; CheckEqual(expected, hits); } public void SimpleLinearMotion_Acceleration() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 1), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { LinearAcceleration = new Vector(0, -1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = Math.Sqrt(2), }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_XAxis_GlancingHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = 1, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, new LinevsPoint.Hit { TOI = 5, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, new LinevsPoint.Hit { TOI = 9, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_XAxis_SolidHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(2, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 5.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 13.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 17.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 25.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 29.0/3.0, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_Backwards_XAxis_Glancing() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = 3, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, new LinevsPoint.Hit { TOI = 7, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_Backwards_XAxis_SolidHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(2, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 7.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 11.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 19.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 23.0/3.0, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_YAxis_Glancing() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 1), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = -Math.PI / 2, InitialOrientation = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = 1, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, new LinevsPoint.Hit { TOI = 5, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, new LinevsPoint.Hit { TOI = 9, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_YAxis_SolidHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 2), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = -Math.PI / 2, InitialOrientation = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 5.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 13.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 17.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 25.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 29.0/3.0, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_Backwards_YAxis_Glancing() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 1), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = Math.PI / 2, InitialOrientation = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = 3, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, new LinevsPoint.Hit { TOI = 7, Transition = LinevsPoint.Hit.TransitionType.GlancingPositive, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Point_Backwards_YAxis_SolidHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 2), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = Math.PI / 2, InitialOrientation = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 7.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 11.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 19.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 23.0/3.0, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Line_XAxis() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { AngularVelocity = Math.PI / 4, }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 5, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 9, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Line_XAxis_Backwards() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { AngularVelocity = -Math.PI / 4, }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 3, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 7, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Line_YAxis() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { InitialOrientation = Math.PI / 2, AngularVelocity = -Math.PI / 4, }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 1, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 5, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 9, }, }; CheckEqual(expected, hits); } public void SimpleAngularMotion_Line_YAxis_Backwards() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { InitialOrientation = Math.PI / 2, AngularVelocity = Math.PI / 4, }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 3, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 7, }, }; CheckEqual(expected, hits); } public void LineElevation_Angular_Glancing() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { AngularVelocity = Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 1); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = 1, Transition = LinevsPoint.Hit.TransitionType.GlancingNegative, }, new LinevsPoint.Hit { TOI = 5, Transition = LinevsPoint.Hit.TransitionType.GlancingNegative, }, new LinevsPoint.Hit { TOI = 9, Transition = LinevsPoint.Hit.TransitionType.GlancingNegative, }, }; CheckEqual(expected, hits); } public void LineElevation_Angular_SolidHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(2, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { AngularVelocity = Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 1); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 1.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 5.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 13.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 17.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 25.0/3.0, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 29.0/3.0, }, }; CheckEqual(expected, hits); } public void LineElevation_AngularAndLinearVelocity() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { AngularVelocity = Math.PI / 2, LinearVelocity = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 2); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 1, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 2, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 3, }, }; CheckEqual(expected, hits); } public void LineElevation_AngularAndLinearAcceleration() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { AngularVelocity = Math.PI / 4, LinearAcceleration = new Vector(0, 0.5), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 2); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 2, }, }; CheckEqual(expected, hits); } public void ParallelMotion_Miss() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { LinearVelocity = new Vector(100, 0), LinearAcceleration = new Vector(-1, 0), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 1); var expected = new LinevsPoint.Hit[] { }; CheckEqual(expected, hits); } public void ParallelMotion_Hit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { LinearVelocity = new Vector(100, 0), LinearAcceleration = new Vector(-1, 0), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = Scalar.PositiveInfinity, Transition = LinevsPoint.Hit.TransitionType.GlancingParallel, }, }; CheckEqual(expected, hits); } public void SlightlyComplexMotion_1() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { AngularVelocity = Math.PI / 2, }, pointMotion = new Motion { InitialOrientation = -Math.PI, InitialPosition = new Vector(-3, 3), AngularVelocity = Math.PI, LinearVelocity = new Vector(2, 0), }, impactWindow = new Interval(0, 3), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 2.5, }, }; CheckEqual(expected, hits); } public void SlightlyComplexMotion_1_Acceleration() { var input = new CollidingInput { collideeFrame = new RotatingFrame { AngularVelocity = Math.PI / 2, }, pointMotion = new Motion { InitialOrientation = -Math.PI, AngularVelocity = Math.PI, InitialPosition = new Vector(-3, 3), LinearVelocity = new Vector(1.5, 0), LinearAcceleration = new Vector(1, 0), }, pointLeverArm = new Vector(1, 0), impactWindow = new Interval(0, 2.5), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 2.3806480354, }, }; CheckEqual(expected, hits); } public void SlightlyComplexMotion_2() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(3, 4), collideeFrame = new RotatingFrame { AngularVelocity = -Math.PI / 8, }, pointMotion = new Motion { InitialOrientation = -Math.Atan2(4, 3), InitialPosition = new Vector(10, 10), AngularVelocity = Math.PI / 2, LinearVelocity = new Vector(-5, -2.5), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 2, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 6.8692116979, }, }; CheckEqual(expected, hits); } public void SlightlyComplexMotion_2_Acceleration() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(3, 4), collideeFrame = new RotatingFrame { AngularVelocity = -Math.PI / 8, }, pointMotion = new Motion { InitialOrientation = -Math.Atan2(4, 3), InitialPosition = new Vector(10, 10), AngularVelocity = Math.PI / 2, LinearVelocity = new Vector(-3, -.5), LinearAcceleration = new Vector(-2, -2), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 0); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 2, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 6.4519878594, }, }; CheckEqual(expected, hits); } public void AwkwardDoubleRoot() { var input = new Annulus.SweptCollisionDetection.CollidingInput { collideeFrame = new RotatingFrame { AngularVelocity = 2.4410157268, InitialOrientation = -2.9562880943, }, pointMotion = new Motion { InitialPosition = new Vector(7, 0), AngularVelocity = 1, }, pointLeverArm = new Vector(5, 0), impactWindow = new Interval(0, 15), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, 3); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 0.0332997141, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 1.2954858927, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 4.9876994145, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 6.2498855931, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 8.0993275495, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 8.8723870107, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 10.173281710, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 11.136292104, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, TOI = 12.968129194, }, new LinevsPoint.Hit { Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, TOI = 14.192681105, }, }; CheckEqual(expected, hits); } public void NumericallyProblematic() { var input = new Annulus.SweptCollisionDetection.CollidingInput { collideeFrame = new RotatingFrame { InitialOrientation = -2.3561944902, }, pointMotion = new Motion { InitialPosition = new Vector(0, -999.9759999232), LinearVelocity = new Vector(0, -4.8989873223), LinearAcceleration = new Vector(0, 500), }, pointLeverArm = new Vector(-1000, 10), impactWindow = new Interval(0, 0.0166666667), maxIterations = 1000, }; var hits = LinevsPoint.FindIntersectionsInWindow(input, -7.0710678119); var expected = new LinevsPoint.Hit[] { new LinevsPoint.Hit { TOI = 0.0097901602, Transition = LinevsPoint.Hit.TransitionType.EnteringPositive, }, new LinevsPoint.Hit { TOI = 0.0098057891, Transition = LinevsPoint.Hit.TransitionType.EnteringNegative, }, }; CheckEqual(expected, hits); } } public class FindChebyshevBasisDirectly : UnitTestSharp.TestFixture { public void NoMotionIntersection() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 0), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var calc = new LinevsPoint.SeparationCalculator { initialLineElevation = 0, input = input, }; var expected = new Chebyshev(calc.VerticalDistanceFunction, input.impactWindow); var actual = calc.VerticalDistanceChebyshevBasis(); CheckEqual(expected, actual); } public void SimpleLinearMotion() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 1), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 0), LinearVelocity = new Vector(0, -1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var calc = new LinevsPoint.SeparationCalculator { initialLineElevation = 0, input = input, }; var expected = new Chebyshev(calc.VerticalDistanceFunction, input.impactWindow); var actual = calc.VerticalDistanceChebyshevBasis(); CheckEqual(expected, actual); } public void SimpleLinearMotionAcceleration() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(0, 1), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { LinearAcceleration = new Vector(0, -1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var calc = new LinevsPoint.SeparationCalculator { initialLineElevation = 0, input = input, }; var expected = new Chebyshev(calc.VerticalDistanceFunction, input.impactWindow); var actual = calc.VerticalDistanceChebyshevBasis(); CheckEqual(expected, actual); } public void SimpleAngularMotion_Point_XAxis_GlancingHit() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), AngularVelocity = -Math.PI / 2, }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var calc = new LinevsPoint.SeparationCalculator { initialLineElevation = 0, input = input, }; var expected = new Chebyshev(calc.VerticalDistanceFunction, input.impactWindow); var actual = calc.VerticalDistanceChebyshevBasis(); for (int i = 0; i < 100; ++i) { var x = input.impactWindow.Min + i / 100.0 * (input.impactWindow.Max - input.impactWindow.Min); CheckEqual(expected.Evaluate(x), actual.Evaluate(x)); } } public void SimpleAngularMotion_Line_XAxis() { var input = new Annulus.SweptCollisionDetection.CollidingInput { pointLeverArm = new Vector(1, 0), collideeFrame = new RotatingFrame { AngularVelocity = Math.PI / 4, }, pointMotion = new Motion { InitialPosition = new Vector(0, 1), }, impactWindow = new Interval(0, 10), maxIterations = 1000, }; var calc = new LinevsPoint.SeparationCalculator { initialLineElevation = 0, input = input, }; var expected = new Chebyshev(calc.VerticalDistanceFunction, input.impactWindow); var actual = calc.VerticalDistanceChebyshevBasis(); CheckEqual(expected, actual); for (int i = 0; i < 100; ++i) { var x = input.impactWindow.Min + i / 100.0 * (input.impactWindow.Max - input.impactWindow.Min); CheckEqual(expected.Evaluate(x), actual.Evaluate(x)); } } public void AwkwardDoubleRoot() { var input = new Annulus.SweptCollisionDetection.CollidingInput { collideeFrame = new RotatingFrame { AngularVelocity = 2.4410157268, InitialOrientation = -2.9562880943, }, pointMotion = new Motion { InitialPosition = new Vector(7, 0), AngularVelocity = 1, }, pointLeverArm = new Vector(5, 0), impactWindow = new Interval(0, 15), maxIterations = 1000, }; var calc = new LinevsPoint.SeparationCalculator { initialLineElevation = 3, input = input, }; var expected = new Chebyshev(calc.VerticalDistanceFunction, input.impactWindow); var actual = calc.VerticalDistanceChebyshevBasis(); for (int i = 0; i < 100; ++i) { var x = input.impactWindow.Min + i / 100.0 * (input.impactWindow.Max - input.impactWindow.Min); CheckEqual(expected.Evaluate(x), actual.Evaluate(x)); } } } } }