public void TestIReadonlyDictionaryInterface()
        {
            var context = new PhysicalContext <int>(1, 2);
            var entity1 = new PointMass
                          (
                new AxisStatus(1, 0),
                new AxisStatus(1, 0),
                new AxisStatus(1, 0),
                1
                          );
            var entity2 = new PointMass
                          (
                new AxisStatus(2, 0),
                new AxisStatus(2, 0),
                new AxisStatus(2, 0),
                1
                          );

            context.AddEntity(1, entity1);
            context.AddEntity(2, entity2, c =>
            {
                double val = 0;
                foreach (var key in context.Keys)
                {
                    val += context[key].X.Position;
                }
                return(new Force(val, val, val));
            });
        }
        public void TestTickPredicate()
        {
            var context = new PhysicalContext <int>(1, 1);
            var entity  = new PointMass
                          (
                new AxisStatus(1, 0),
                new AxisStatus(0, 1),
                new AxisStatus(0, 0),
                1
                          );

            context.AddEntity
            (
                0,
                entity
            );

            var source = new System.Threading.CancellationTokenSource();

            source.Cancel();

            context.Tick(1, _ => !source.IsCancellationRequested);
            AreEqual(entity, context[0]);
            AreEqual(0u, context.Ticks);

            var isGoalReached = context.Tick(10, c => c.Ticks < 5);

            AreEqual(5u, context.Ticks);
            IsFalse(isGoalReached);

            isGoalReached = context.Tick(10, c => true);
            AreEqual(15u, context.Ticks);
            IsTrue(isGoalReached);
        }
        public void TestBindedEntities()
        {
            var context = new PhysicalContext <int>(1, 2);
            var entity1 = new PointMass
                          (
                new AxisStatus(2, 0),
                new AxisStatus(0, 0),
                new AxisStatus(0, 0),
                1
                          );
            var entity2 = new PointMass
                          (
                new AxisStatus(0, 0),
                new AxisStatus(3, 0),
                new AxisStatus(0, 0),
                1
                          );

            context.AddEntity
            (
                1,
                entity1,
                c => new Force(c[2].Y.Position, 0, 0)
            );
            context.AddEntity
            (
                2,
                entity2,
                c => new Force(0, c[1].X.Position, 0)
            );

            context.Tick();
            AreEqual(entity1.Next(1, new Force(3, 0, 0)), context[1]);
            AreEqual(entity2.Next(1, new Force(0, 2, 0)), context[2]);
        }
        public void TestZeroForce()
        {
            var context = new PhysicalContext <int>(3, 1);
            var entity  = new PointMass
                          (
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                1
                          );

            context.AddEntity
            (
                0,
                entity,
                c => new Force(-1, -2, -3),
                c => new Force(1, 2, 3)
            );

            AreEqual(entity, context[0]);
            context.Tick();
            AreEqual(entity.Next(3), context[0]);
            context.Tick();
            AreEqual(entity.Next(3).Next(3), context[0]);
        }
        public void TestThrowingException()
        {
            var context    = new PhysicalContext <int>(1, 1);
            var contextSeq = new PhysicalContext <int>(1, 1, SimulationParams.None);
            var entity     = new PointMass
                             (
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                1
                             );

            ThrowsException <UninitializedPhysicalContextException <int> >(() => context.Tick());
            ThrowsException <UninitializedPhysicalContextException <int> >(() => contextSeq.Tick());

            context.AddEntity
            (
                0,
                entity,
                // Unexisting key {1} is here
                c => new Force(c[1].X.Position, 0, 0)
            );
            contextSeq.AddEntity
            (
                0,
                entity,
                // Unexisting key {1} is here
                c => new Force(c[1].X.Position, 0, 0)
            );

            ThrowsException <AggregateException>(() => context.Tick());
            ThrowsException <UnexistingEntityException <int> >(() => contextSeq.Tick());
            ThrowsException <FilledPhysicalContextException <int> >(() => context.AddEntity(1, entity));
            ThrowsException <FilledPhysicalContextException <int> >(() => contextSeq.AddEntity(1, entity));
        }
Example #6
0
        public void TestCheckPoints()
        {
            var context = new PhysicalContext <int>(0.5, 1);

            context.AddEntity(0, new PointMass());

            context.Tick();

            ThrowsException <ArgumentOutOfRangeException>(() => new ContextProgressTracker <int>(context, 10, 0));
            ThrowsException <ArgumentOutOfRangeException>(() => new ContextProgressTracker <int>(context, 10, 12));

            context.Tick();
            var trackerInt    = new ContextProgressTracker <int>(context, 10, 3, 9);
            var trackerDouble = ContextProgressTracker <int> .FromTime(context, 10, 3, 9);

            int reachedInt = 0, reachedDouble = 0;

            trackerInt.OnCheckPoint    += (c, _) => reachedInt++;
            trackerDouble.OnCheckPoint += (c, _) => reachedDouble++;

            for (int i = 0; i < 12; i++)
            {
                context.Tick();
            }
            AreEqual(2, reachedInt);
            AreEqual(1, reachedDouble);
        }
        public void TestInit1()
        {
            var context = new PhysicalContext <int>(0.1, 1);
            var entity  = new PointMass(new AxisStatus(1, 3), new AxisStatus(0, 0), new AxisStatus(0, 0), 1);

            context.AddEntity(0, entity);

            var tracker = new ContextTracker <int, double>(context, c => c[0].X.Position);

            AreEqual(1, tracker[0]);
            AreEqual(0ul, tracker.ObservationBeginTick);
            ThrowsException <ArgumentOutOfRangeException>(() => tracker[2]);

            context.Tick(0.5);
            AreEqual(1, tracker[0]);
            var pos05 = context[0].X.Position;

            AreEqual(pos05, tracker[5]);
            AreEqual(pos05, tracker.GetApproximately(0.5));

            context.Tick(0.5);
            AreEqual(1, tracker[0]);
            AreEqual(pos05, tracker.GetApproximately(0.5));
            AreEqual(pos05, tracker.GetApproximately(0.478));
            AreEqual(pos05, tracker.GetApproximately(0.505));
            AreEqual(context[0].X.Position, tracker[context.Ticks]);
        }
        public void TestDispose()
        {
            var context = new PhysicalContext <int>(0.1, 2);
            var entity  = new PointMass(0, 0, 0, 1);

            context.AddEntity(0, entity, c => new Force(1, 0, 0));
            context.AddEntity(1, entity, c => new Force(1, 0, 0));

            context.Tick(1);

            var tracker = new ContextTracker <int, int>(context, c => (int)Math.Round(c[0].X.Velocity + c[1].X.Velocity));

            AreEqual(2, tracker[context.Ticks]);
            AreEqual(10ul, tracker.ObservationBeginTick);
            ThrowsException <ArgumentOutOfRangeException>(() => tracker.GetApproximately(0));
            ThrowsException <ArgumentOutOfRangeException>(() => tracker.GetApproximately(2));

            context.Tick(1);
            AreEqual(2, tracker.GetApproximately(1));
            AreEqual(1, tracker.ObservationBeginTime);
            AreEqual(4, tracker[context.Ticks]);
            AreEqual(20ul, tracker.LastObservedTick);

            tracker.Dispose();

            context.Tick(1);
            AreEqual(20ul, tracker.LastObservedTick);
            ThrowsException <ArgumentOutOfRangeException>(() => tracker[context.Ticks]);
        }
        public void TestOnTick()
        {
            var context = new PhysicalContext <int>(1, 1);
            var entity  = new PointMass
                          (
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                1
                          );

            context.AddEntity
            (
                0,
                entity,
                c => new Force(0, 1, 2)
            );

            var count = 0;

            context.Tick();

            context.OnTick += (c, e) => count++;
            context.Tick();
            AreEqual(1, count);

            context.OnTick += (c, e) => count++;
            context.Tick();
            AreEqual(3, count);

            context.OnTick += (c, e) => ((PhysicalContext <int>)c).Tick();
            ThrowsException <LockedPhysicalContextException <int> >(() => context.Tick());
        }
        public void TestTimer()
        {
            var context = new PhysicalContext <int>(0.3, 1);

            context.AddEntity(0, new PointMass());
            AreEqual(0, context.Timer);
            context.Tick();
            context.Tick();
            AreEqual(0.6, context.Timer);
            context.Tick(1);
            AreEqual(1.5, context.Timer);
        }
        public void TestLaw1()
        {
            var context = new PhysicalContext <int>(1, 2);

            context.AddEntity(0, new PointMass(new AxisStatus(0, 1), new AxisStatus(0, -2), new AxisStatus(0, 0), 0));
            context.AddEntity(1, new PointMass(3, 4, 0, 0));

            var law = StokesDragLaw.GetLaw(0, 10);

            AreEqual(new Force(-10, 20, 0), law(context));

            law = StokesDragLaw.GetLaw(1, 3);
            AreEqual(new Force(0, 0, 0), law(context));
        }
        public void TestBindedEntities2()
        {
            var context = new PhysicalContext <int>(1, 2);
            var entity1 = new PointMass
                          (
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                new AxisStatus(0, 1),
                1
                          );
            var entity2 = new PointMass
                          (
                new AxisStatus(0, 2),
                new AxisStatus(0, 2),
                new AxisStatus(0, 2),
                1
                          );

            context.AddEntity
            (
                1,
                entity1,
                (c) => new Force(c[2].X.Velocity, c[2].Y.Velocity, c[2].Z.Velocity)
            );
            context.AddEntity
            (
                2,
                entity2,
                c => new Force(c[1].X.Velocity, c[1].Y.Velocity, c[1].Z.Velocity)
            );

            context.Tick();
            entity1 = entity1.Next(1, new Force(2, 2, 2));
            entity2 = entity2.Next(1, new Force(1, 1, 1));
            AreEqual(entity1, context[1]);
            AreEqual(entity2, context[2]);

            context.Tick();
            entity1 = entity1.Next(1, new Force(3, 3, 3));
            entity2 = entity2.Next(1, new Force(3, 3, 3));
            AreEqual(entity1, context[1]);
            AreEqual(entity2, context[2]);

            context.Tick();
            entity1 = entity1.Next(1, new Force(6, 6, 6));
            entity2 = entity2.Next(1, new Force(6, 6, 6));
            AreEqual(entity1, context[1]);
            AreEqual(entity2, context[2]);
        }
        public void TestLocking()
        {
            var context = new PhysicalContext <int>(1, 1);
            var entity  = new PointMass();

            context.AddEntity(0, entity, c => { context.Tick(); return(new Force()); });

            try
            {
                context.Tick();
            }
            catch (AggregateException e)
            {
                IsTrue(e.InnerExceptions.First() is LockedPhysicalContextException <int>);
            }
        }
        public void TestObserving()
        {
            var context = new PhysicalContext <int>(1, 1);
            var entity  = new PointMass(new AxisStatus(3, 0), new AxisStatus(1, 1), new AxisStatus(0, 0), 1);

            context.AddEntity(0, entity);

            var max0X = new ContextDependentValue <int, double>
                        (
                context[0].X.Position,
                context,
                (c, old) => c[0].X.Position > old ? new double?(c[0].X.Position) : null
                        );

            context.Tick();
            context.Tick();

            var max0Y = new ContextDependentValue <int, double>
                        (
                context[0].Y.Position,
                context,
                (c, old) => c[0].Y.Position > old ? new double?(c[0].Y.Position) : null
                        );

            AreEqual(0ul, max0X.ObservationBeginTick);
            AreEqual(2ul, max0X.LastObservedTick);
            AreEqual(0ul, max0X.LastValueChangeTick);
            AreEqual(3ul, max0X.Value);

            context.Tick();
            context.Tick();

            AreEqual(2ul, max0Y.ObservationBeginTick);
            AreEqual(4ul, max0Y.LastObservedTick);
            AreEqual(4ul, max0Y.LastValueChangeTick);
            AreEqual(5ul, max0Y.Value);

            max0Y.Dispose();

            context.Tick();
            context.Tick();

            AreEqual(2ul, max0Y.ObservationBeginTick);
            AreEqual(4ul, max0Y.LastObservedTick);
            AreEqual(4ul, max0Y.LastValueChangeTick);
            AreEqual(5ul, max0Y.Value);
        }
Example #15
0
        public void TestLaw2()
        {
            var context = new PhysicalContext <int>(1, 2);

            context.AddEntity(0, new PointMass(1, 1, 1, 0));
            context.AddEntity(1, new PointMass(1, 1, 2, 0));

            var law = HookesLaw.GetLaw(1, 0, undeformedDistance: 0, elasticityCoefficient: 1);

            AreEqual(new Force(0, 0, -1), law(context));

            law = HookesLaw.GetLaw(1, 0, undeformedDistance: 3, elasticityCoefficient: 2);
            AreEqual(new Force(0, 0, 4), law(context));

            law = HookesLaw.GetLaw(1, 0, undeformedDistance: 12, elasticityCoefficient: 0);
            AreEqual(new Force(0, 0, 0), law(context));
        }
        public void TestStoryboard()
        {
            var context = new PhysicalContext <int>(1, 1);
            var entity  = new PointMass(new AxisStatus(0, 1), new AxisStatus(1, 0), new AxisStatus(0, 0), 1);

            context.AddEntity(0, entity);

            var tracker = new ContextTracker <int, double>(context, c => c[0].X.Position);

            AreEqual(1, tracker.Count);
            IsTrue(tracker.Keys.Contains <ulong>(0));

            context.Tick();
            AreEqual(2, tracker.Count);
            IsTrue(tracker.Keys.Contains <ulong>(0));
            IsTrue(tracker.Keys.Contains <ulong>(1));
            IsFalse(tracker.Keys.Contains <ulong>(2));
        }
Example #17
0
        public void TestLaw1()
        {
            var context = new PhysicalContext <int>(1, 2);

            context.AddEntity(0, new PointMass(0, 0, 0, 0));
            context.AddEntity(1, new PointMass(3, 4, 0, 0));

            var law = HookesLaw.GetLaw(1, 0, undeformedDistance: 5, elasticityCoefficient: 1);

            AreEqual(new Force(0, 0, 0), law(context));

            law = HookesLaw.GetLaw(1, 0, undeformedDistance: 10, elasticityCoefficient: 1);
            AreEqual(new Force(3, 4, 0), law(context));

            law = HookesLaw.GetLaw(1, 0, undeformedDistance: 10, elasticityCoefficient: 2);
            AreEqual(new Force(6, 8, 0), law(context));

            law = HookesLaw.GetLaw(1, 0, undeformedDistance: 0, elasticityCoefficient: 0.1);
            AreEqual(new Force(-0.3, -0.4, 0), law(context));
        }
Example #18
0
        public void TestLaw1()
        {
            var context = new PhysicalContext <int>(1, 2);

            context.AddEntity(0, new PointMass(0, 0, 0, 0));
            context.AddEntity(1, new PointMass(3, 4, 0, 0));

            var law = RadialCollisionLaw.GetLaw(1, 0, criticalDistance: 3, elasticityCoefficient: 1);

            AreEqual(new Force(0, 0, 0), law(context));

            law = RadialCollisionLaw.GetLaw(1, 0, criticalDistance: 10, elasticityCoefficient: 1);
            AreEqual(new Force(3, 4, 0), law(context));

            law = RadialCollisionLaw.GetLaw(1, 0, criticalDistance: 5, elasticityCoefficient: 1);
            AreEqual(new Force(0, 0, 0), law(context));

            law = RadialCollisionLaw.GetLaw(1, 0, criticalDistance: 6, elasticityCoefficient: 50);
            AreEqual(new Force(30, 40, 0), law(context));
        }
        public void TestInterval()
        {
            ulong[] intervals = { 1, 3, 11, 100 };
            foreach (var i in intervals)
            {
                var context = new PhysicalContext <int>(1, 1);
                var entity  = new PointMass(new AxisStatus(0, 1), new AxisStatus(1, 0), new AxisStatus(0, 0), 1);
                context.AddEntity(0, entity);

                var tracker = new ContextTracker <int, double>(context, c => c[0].X.Position, i);

                context.Tick(42);
                AreEqual((int)(42 / i + 1), tracker.Count);
                AreEqual(42 - 42 % i, tracker.LastRecordTick);
                ThrowsException <ArgumentOutOfRangeException>(() => tracker[43]);
                if (i > 1)
                {
                    ThrowsException <ArgumentOutOfRangeException>(() => tracker[i + 1]);
                }

                var noException = tracker[0];
            }
        }
        public void TestTickSequential()
        {
            var context = new PhysicalContext <int>(0.23, 1, SimulationParams.None);
            var entity  = new PointMass
                          (
                new AxisStatus(1, 0),
                new AxisStatus(0, 1),
                new AxisStatus(0, 0),
                1
                          );

            context.AddEntity
            (
                0,
                entity,
                c => new Force(c[0].X.Velocity, c[0].Y.Velocity, c[0].Z.Velocity)
            );

            AreEqual(entity, context[0]);

            context.Tick();
            AreEqual(entity.Next(0.23, new Force(0, 1, 0)), context[0]);
        }
        public void TestUniformForce()
        {
            var context = new PhysicalContext <int>(0.1, 1);
            var entity  = new PointMass
                          (
                new AxisStatus(1, 2),
                new AxisStatus(2, 3),
                new AxisStatus(3, 4),
                1
                          );

            context.AddEntity
            (
                0,
                entity,
                c => new Force(3, 4, 5)
            );

            AreEqual(entity, context[0]);

            context.Tick();
            AreEqual(entity.Next(0.1, new Force(3, 4, 5)), context[0]);
        }
Example #22
0
        public void TestGoal()
        {
            var context = new PhysicalContext <int>(1, 1);

            context.AddEntity(0, new PointMass());

            context.Tick();
            context.Tick();

            var tracker = new ContextProgressTracker <int>(context, 10);

            AreEqual(0, tracker.Progress);

            bool goal = false;

            tracker.OnGoal += (c, e) => goal = true;

            context.Tick(4);
            AreEqual(0.5, tracker.Progress);
            context.Tick(4);
            AreEqual(1, tracker.Progress);
            IsFalse(tracker.IsActive);
            IsTrue(goal);
        }
Example #23
0
        static void Main(string[] args)
        {
            //PhysicalContext is the core class represents set of entities and
            //set of force evaluation laws binded to it.
            //Type parameter represents the type of keys used to adding and retrieving entities.
            var context = new PhysicalContext <string>
                          (
                timePerTick: dt, //The time, that is considered to be as small, as force values are uniform.
                //The smaller timePerTick is, the better precision we get.
                //Be aware, time for evaluating state of entities after certain period of time
                //is proportional to (timePerTick)^-1.
                capacity: 1 //Number of entities required to be added to context.
                          );

            //Adding entity
            var freeFallEntity = new PointMass
                                 (
                x: new AxisStatus(3.4),    //Position = 3.4, zero velocity
                y: new AxisStatus(0, 10),  //Zero position, velocity = 10
                z: new AxisStatus(1.1, 2), //Position = 1.1, Velocity = 2
                mass: 77.7
                                 );

            context.AddEntity
            (
                "freeFallEntity", //key
                freeFallEntity,   //entity
                c =>              //Only force that have impact on this entity
                - new Force
                (
                    xComponent: 0,
                    yComponent: c["freeFallEntity"].Mass * freeFallAcceleration,
                    zComponent: 0
                )
                //This force is always vertical and equal to mass of entity multiplied
                //by free fall acceleration.
            );

            Console.WriteLine($"Start state is \n{context["freeFallEntity"]}");
            //Evaluating the state of context after 1 second.
            context.Tick(timeSpan: 1);
            Console.WriteLine($"\nState of entity after 1 second is \n{context["freeFallEntity"]}");

            //If you want to record some data while context is updating,
            //you may subscribe to OnTick event or better use class derived from ContextObserver.
            var yPositionTracker = new ContextTracker <string, double>
                                   (
                context,
                c => c["freeFallEntity"].Y.Position
                                   );

            context.Tick(1);

            //Context tracker implements IReadonlyDictionary.
            Console.WriteLine($"\nOn tick 10345 y position is {yPositionTracker[10345]}");
            Console.WriteLine($"\nOn time 1.27 y position is {yPositionTracker.GetApproximately(1.27)}");
            //Throws exception because tracker has started recording when time is context
            //was already 1.00.
            //Console.WriteLine($"On time 0.4 y position is {yPositionTracker.GetApproximately(0.4)}");
            //Throws exception because tracker hasn't record data yet because time in context is 2.00.
            //Console.WriteLine($"On time 2.7 y position is {yPositionTracker.GetApproximately(2.7)}");

            //Don't forget to dispose tracker when you don't need it anymore.
            //It will increase performance because tracker doesn't record data anymore.
            yPositionTracker.Dispose();
            context.Tick(1);
            //Time is context is 3.0, but tracker is already disposed and doesn't record data anymore.
            Console.WriteLine
            (
                $"\nTracker records data during time span {yPositionTracker.ObservationBeginTime} - {yPositionTracker.LastObservationTime}" +
                $"\nAverage y position is {yPositionTracker.Sum(record => record.Value) / yPositionTracker.Count}"
            );

            //However, if you want to record only max, min, average value etc,
            //better use ContextDependentValue, because it doesn't use a lot of memory
            //to record value in each tick.
            var maxYVelocity = new ContextDependentValue <string, double>
                               (
                startValue: context["freeFallEntity"].Y.Velocity,
                observableContext: context,
                newValueFunc: (c, oldValue) =>
                c["freeFallEntity"].Velocity > oldValue ? new double?(c["freeFallEntity"].Velocity) : null
                //null value means that there is no reason to change value
                               );

            context.Tick(1);
            Console.WriteLine
            (
                $"\nMax y velocity in time span {maxYVelocity.ObservationBeginTime} - " +
                $"{maxYVelocity.LastObservationTime} is {maxYVelocity.Value}"
            );

            //So, lets create something more complex.
            //What about the spring pendulum with air resistance?
            var pendulumContext = new PhysicalContext <PendulumEntities>(dt, 2);
            var axis            = new PointMass(0, 0, 0, 0);
            var mass            = new PointMass(1, 0, 0, 0);

            pendulumContext.AddEntity(PendulumEntities.Axis, axis);
            pendulumContext.AddEntity
            (
                PendulumEntities.Mass,
                mass,
                c => new Force(0, c[PendulumEntities.Mass].Mass * freeFallAcceleration, 0), //Gravity
                HookesLaw.GetLaw                                                            //Mechanix.Laws contains amount of static classes to help force evaluating.
                (
                    PendulumEntities.Mass,
                    PendulumEntities.Axis,
                    1, //undeformed length of spring
                    10 //elasticity coefficient
                )
            );

            //Or set of elastic balls.
            var          ballsContext = new PhysicalContext <int>(dt, 100);
            var          random       = new Random();
            const double radius       = 1;
            const double elasticity   = 100;

            for (int i = 0; i < 100; ++i)
            {
                var ball = new PointMass
                           (
                    new AxisStatus(random.NextDouble(), random.NextDouble()),
                    new AxisStatus(random.NextDouble(), random.NextDouble()),
                    new AxisStatus(random.NextDouble(), random.NextDouble()),
                    random.NextDouble()
                           );
                ballsContext.AddEntity
                (
                    i,
                    ball,
                    c =>
                {
                    var force = Force.Zero;
                    foreach (var pair in c)
                    {
                        if (pair.Key != i)
                        {
                            force += RadialCollisionLaw.Eval
                                     (
                                c[i],
                                pair.Value,
                                radius,
                                elasticity
                                     );
                        }
                    }
                    return(force);
                }
                );
            }
        }
Example #24
0
        private async void EvalButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                SetPanelEnablity(false);
                _isCancelationRequested = false;

                var k            = double.Parse(kValBox.Text);
                var alpha        = double.Parse(alphaValueBox.Text);
                var dt           = double.Parse(dtBox.Text);
                var timeSpan     = double.Parse(timeSpanBox.Text);
                var planetRadius = double.Parse(planetRadiusBox.Text);

                var interval         = ulong.Parse(renderingIntervalBox.Text);
                var progressBarSteps = uint.Parse(progressBarStepsBox.Text);

                var context = new PhysicalContext <Entities>(timePerTick: dt, capacity: 2);
                context.AddEntity
                (
                    Entities.Planet,
                    new PointMass(0, 0, 0, 1)
                );
                context.AddEntity
                (
                    Entities.Ship,
                    new PointMass
                    (
                        new AxisStatus(double.Parse(xPosBox.Text), double.Parse(xVelBox.Text)),
                        new AxisStatus(double.Parse(yPosBox.Text), double.Parse(yVelBox.Text)),
                        new AxisStatus(),
                        1
                    ),
                    c => ModifiedGravityLaw <Entities>(c[Entities.Ship], c[Entities.Planet], alpha, k)
                );

                var xTracker = new ContextTracker <Entities, double>(context, c => c[Entities.Ship].X.Position, interval);
                var yTracker = new ContextTracker <Entities, double>(context, c => c[Entities.Ship].Y.Position, interval);

                var progress = ContextProgressTracker <Entities> .FromTime
                               (
                    context,
                    timeSpan,
                    Enumerable.Range(1, (int)progressBarSteps).Select(i => timeSpan *i / progressBarSteps).ToArray()
                               );

                progress.OnCheckPoint += (c, _) => Dispatcher.Invoke(() => progressBar.Value = progress.Progress);

                bool isSuccesful = await Task.Run
                                   (
                    () => context.Tick
                    (
                        timeSpan,
                        c =>
                        !_isCancelationRequested &&
                        (
                            c[Entities.Ship].X.Position *c[Entities.Ship].X.Position +
                            c[Entities.Ship].Y.Position *c[Entities.Ship].Y.Position >=
                            planetRadius *planetRadius
                        ),
                        false
                    )
                                   );

                if (!isSuccesful && !_isCancelationRequested)
                {
                    Task.Run(() => MessageBox.Show($"Ship has crashed at {context.Timer}"));
                }

                var title = $"Start position = ({xPosBox.Text}; {yPosBox.Text})\n" +
                            $"Start velocity = ({xVelBox.Text}; {yVelBox.Text})\n" +
                            $"dt = {dtBox.Text}, K = {kValBox.Text}, Alpha = {alphaValueBox.Text}";

                var xSeries = new LineSeries()
                {
                    CanTrackerInterpolatePoints = false,
                    Title = title
                };
                var ySeries = new LineSeries()
                {
                    CanTrackerInterpolatePoints = false,
                    Title = title
                };
                var orbitSeries = new LineSeries()
                {
                    CanTrackerInterpolatePoints = false,
                    Title = title
                };

                xSeries.Points.AddRange(from p in xTracker select new DataPoint(p.Key * dt, p.Value));
                ySeries.Points.AddRange(from p in yTracker select new DataPoint(p.Key * dt, p.Value));
                orbitSeries.Points.AddRange(xTracker.Zip(yTracker, (x, y) => new DataPoint(x.Value, y.Value)));

                plotX.Model.Series.Add(xSeries);
                plotY.Model.Series.Add(ySeries);
                orbitPlot.Model.Series.Add(orbitSeries);
                orbitPlot.Model.PlotType = PlotType.Cartesian;
                plotX.InvalidatePlot();
                plotY.InvalidatePlot();
                orbitPlot.InvalidatePlot();

                progressBar.Value = 0;
                SetPanelEnablity(true);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }