/// <summary>
        /// 7. Constructor for a projectile motion Quantities. Computes an elevation angle based on the length.
        /// </summary>
        /// <param name="v">An initial velocity.</param>
        /// <param name="l">The length.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(Length l, InitialVelocity v, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            H = h;
            G = g;
            Α = new ElevationAngle(
                GetResultWithComputeExpection(
                    l.GetBasicVal() == 0 && H.GetBasicVal() == 0 ?
                    double.NaN
                        :
                    EquationSolver.BisectionFindRoot(
                        a => V.GetBasicVal() * Math.Cos(a) * (
                            V.GetBasicVal() * Math.Sin(a) + Math.Sqrt(Math.Pow(V.GetBasicVal() *
                                                                               Math.Sin(a), 2) + 2.0 * G.GetBasicVal() * H.GetBasicVal())
                            ) / G.GetBasicVal() - l.GetBasicVal(),
                        0,
                        new ElevationAngle(ElevationAngle.ElevationAngleTypes.Right).Val,
                        1E-4
                        )
                    ),
                UnitAngle.Basic
                ).Convert(Units.Angle);

            UsedAssignmentType = AssignmentsTypes.ElevationAngleByLength;
        }
        /// <summary>
        /// 13. Constructor for a projectile motion Quantities. Computes an elevation angle based on the duration and the length.
        /// </summary>
        /// <param name="v">An initial velocity.</param>
        /// <param name="l">The length.</param>
        /// <param name="dur">The duration.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(InitialVelocity v, Length l, Duration dur, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            G = g;
            V = v;
            Α = new ElevationAngle(
                GetResultWithComputeExpection(
                    l.GetBasicVal() == 0 && dur.GetBasicVal() == 0 && V.GetBasicVal() > 0 ?
                    0
                        :
                    Math.Acos(l.GetBasicVal() / (V.GetBasicVal() * dur.GetBasicVal()))
                    ),
                UnitAngle.Basic
                ).Convert(Units.Angle);

            H = new InitialHeight(
                GetResultWithComputeExpection(
                    0.5 * G.GetBasicVal() * Math.Pow(dur.GetBasicVal(), 2.0) -
                    Math.Sin(Α.GetBasicVal()) * V.GetBasicVal() * dur.GetBasicVal()
                    ),
                UnitLength.Basic
                ).Convert(Units.Length);

            UsedAssignmentType = AssignmentsTypes.ElevationAngleByLengthAndDur;
        }
        /// <summary>
        /// 1. Constructor for a projectile motion Quantities.
        /// </summary>
        /// <param name="v">An initial velocity.</param>
        /// <param name="α">An elevation angle.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(InitialVelocity v, ElevationAngle α, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            Α = α;
            H = h;
            G = g;

            UsedAssignmentType = AssignmentsTypes.Basic;
        }
    static void Main()
    {
        InitialVelocity  v = new InitialVelocity(40, UnitVelocity.KilometrePerHour);
        ElevationAngle   α = new ElevationAngle(41, UnitAngle.Degree);
        InitialHeight    h = new InitialHeight(169, UnitLength.Centimetre);
        GravAcceleration g = new GravAcceleration(GravAcceleration.GravAccelerations.Earth);


        ProjectileMotionResultsUnits units = new ProjectileMotionResultsUnits()
        {
            Length           = UnitLength.Metre,
            Time             = UnitTime.Second,
            Velocity         = UnitVelocity.KilometrePerHour,
            Angle            = UnitAngle.Degree,
            Area             = UnitArea.SquareMetre,
            GravAcceleration = UnitGravAcceleration.MetrePerSquareSecond
        };


        ProjectileMotion motion = new ProjectileMotion(
            new ProjectileMotionSettings(new ProjectileMotionQuantities(v, α, h, g, units))
        {
            RoundDigits         = 4,
            PathToFiles         = "C:\\Users\\oplan\\Documents\\c#\\ProjectileMotions",
            PointsForTrajectory = 160
        });

        motion.Saving.InfoToTxt();



        ProjectileMotionWithResistance motionWithResistance = new ProjectileMotionWithResistance(
            new ProjectileMotionWithResistanceSettings(
                new ProjectileMotionWithResistanceQuantities(
                    v, α, h, g,
                    new Mass(46, UnitMass.Gram),
                    new Density(Density.Densities.Air),
                    new FrontalArea(Math.Pow(new Length(12.9, UnitLength.Centimetre).GetBasicVal(), 2.0) * Math.PI, UnitArea.SquareMetre),
                    new DragCoefficient(DragCoefficient.DragCoefficients.Sphere),
                    units
                    )
                )
        {
            RoundDigits         = 4,
            PathToFiles         = "C:\\Users\\oplan\\Documents\\c#\\ProjectileMotions",
            PointsForTrajectory = 153
        });

        motionWithResistance.Saving.InfoToTxt();
    }
        /// <summary>
        /// 9. Constructor for a projectile motion Quantities. Computes an initial height based on the maximal height.
        /// </summary>
        /// <param name="α">An elevation angle.</param>
        /// <param name="maxHeight">The maximal height.</param>
        /// <param name="v">An initial velocity.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(MaximalHeight maxHeight, ElevationAngle α, InitialVelocity v, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            Α = α;
            G = g;
            H = new InitialHeight(
                GetResultWithComputeExpection(
                    maxHeight.GetBasicVal() - Math.Pow(V.GetBasicVal() * Math.Sin(Α.GetBasicVal()), 2.0) / (2.0 * G.GetBasicVal())
                    ),
                UnitLength.Basic
                ).Convert(Units.Length);

            UsedAssignmentType = AssignmentsTypes.InitialHeightByMaxHeight;
        }
        /// <summary>
        /// 4. Constructor for a projectile motion Quantities. Computes an initial height based on the duration.
        /// </summary>
        /// <param name="α">An elevation angle.</param>
        /// <param name="dur">The duration.</param>
        /// <param name="v">An initial velocity.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(Duration dur, ElevationAngle α, InitialVelocity v, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            Α = α;
            G = g;
            H = new InitialHeight(
                GetResultWithComputeExpection(
                    (Math.Pow(dur.GetBasicVal(), 2.0) * G.GetBasicVal() -
                     2.0 * Math.Sin(Α.GetBasicVal()) * dur.GetBasicVal() * V.GetBasicVal()) / 2.0
                    ),
                UnitLength.Basic).Convert(Units.Length);

            UsedAssignmentType = AssignmentsTypes.InitialHeightByDuration;
        }
        /// <summary>
        /// 3. Constructor for a projectile motion Quantities. Computes an initial velocity based on the duration.
        /// </summary>
        /// <param name="α">An elevation angle.</param>
        /// <param name="dur">The duration.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(Duration dur, ElevationAngle α, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            Α = α;
            H = h;
            G = g;

            V = new InitialVelocity(
                GetResultWithComputeExpection(
                    dur.GetBasicVal() == 0 && H.GetBasicVal() == 0
                        ? 0
                        :
                    (Math.Pow(dur.GetBasicVal(), 2.0) * G.GetBasicVal() - 2 * H.GetBasicVal()) /
                    (2.0 * Math.Sin(Α.GetBasicVal()) * dur.GetBasicVal())
                    ),
                UnitVelocity.Basic).Convert(Units.Velocity);

            UsedAssignmentType = AssignmentsTypes.InitialVelocityByDuration;
        }
        /// <summary>
        /// 2. Constructor for a projectile motion Quantities. Computes an elevation angle based on the duration.
        /// </summary>
        /// <param name="v">An initial velocity.</param>
        /// <param name="dur">The duration.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(Duration dur, InitialVelocity v, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            H = h;
            G = g;
            Α = new ElevationAngle(
                GetResultWithComputeExpection(
                    V.GetBasicVal() > 0 && H.GetBasicVal() == 0 && dur.GetBasicVal() == 0
                        ? 0
                        :
                    Math.Asin(
                        (Math.Pow(dur.GetBasicVal(), 2.0) * G.GetBasicVal() - 2 * H.GetBasicVal()) /
                        (2.0 * V.GetBasicVal() * dur.GetBasicVal())
                        )
                    ),
                UnitAngle.Basic).Convert(Units.Angle);

            UsedAssignmentType = AssignmentsTypes.ElevationAngleByDuration;
        }
        /// <summary>
        /// 11. Constructor for a projectile motion Quantities. Computes an elevation angle for motion with maximum range.
        /// </summary>
        /// <param name="v">An initial velocity.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(InitialVelocity v, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            H = h;
            G = g;
            Α = new ElevationAngle(
                GetResultWithComputeExpection(
                    Math.Acos(
                        Math.Sqrt(
                            (2.0 * G.GetBasicVal() * H.GetBasicVal() + Math.Pow(V.GetBasicVal(), 2.0)) /
                            (2.0 * G.GetBasicVal() * H.GetBasicVal() + 2.0 * Math.Pow(V.GetBasicVal(), 2.0))
                            )
                        )
                    ),
                UnitAngle.Basic
                ).Convert(Units.Angle);

            UsedAssignmentType = AssignmentsTypes.ElevationAngleGetMaxRange;
        }
        /// <summary>
        /// 10. Constructor for a projectile motion Quantities. Computes an elevation angle based on the maximal height.
        /// </summary>
        /// <param name="v">An initial velocity.</param>
        /// <param name="dur">The maximal height.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(MaximalHeight maxHeight, InitialVelocity v, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            H = h;
            G = g;
            Α = new ElevationAngle(
                GetResultWithComputeExpection(
                    maxHeight.GetBasicVal() == 0 && H.GetBasicVal() == 0 ?
                    double.NaN
                        :
                    Math.Asin(Math.Sqrt(
                                  2.0 * G.GetBasicVal() * (maxHeight.GetBasicVal() - H.GetBasicVal()) /
                                  Math.Pow(V.GetBasicVal(), 2)
                                  ))
                    ),
                UnitAngle.Basic
                ).Convert(Units.Angle);

            UsedAssignmentType = AssignmentsTypes.ElevationAngleByMaxHeight;
        }
        /// <summary>
        /// 8. Constructor for a projectile motion Quantities. Computes an initial velocity based on the maximal height.
        /// </summary>
        /// <param name="α">An elevation angle.</param>
        /// <param name="maxHeight">The maximal height.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(MaximalHeight maxHeight, ElevationAngle α, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            Α = α;
            H = h;
            G = g;
            V = new InitialVelocity(
                GetResultWithComputeExpection(
                    maxHeight.GetBasicVal() == 0 && H.GetBasicVal() == 0 ?
                    Α.GetBasicVal() == 0 ?
                    double.NaN : 0
                        :
                    Math.Sqrt(
                        2.0 * G.GetBasicVal() * (maxHeight.GetBasicVal() - H.GetBasicVal()) /
                        Math.Pow(Math.Sin(Α.GetBasicVal()), 2.0)
                        )
                    ),
                UnitVelocity.Basic
                ).Convert(Units.Velocity);

            UsedAssignmentType = AssignmentsTypes.InitialVelocityByMaxHeight;
        }
        /// <summary>
        /// 5. Constructor for a projectile motion Quantities. Computes an initial height based on the length.
        /// </summary>
        /// <param name="α">An elevation angle.</param>
        /// <param name="l">The length.</param>
        /// <param name="v">An initial velocity.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(Length l, ElevationAngle α, InitialVelocity v, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            V = v;
            Α = α;
            G = g;

            H = new InitialHeight(
                GetResultWithComputeExpection(
                    Α.IsRight() ?
                    double.NaN
                        : (
                        Math.Pow(l.GetBasicVal(), 2.0) * G.GetBasicVal() /
                        Math.Pow(Math.Cos(Α.GetBasicVal()), 2.0) -
                        2.0 * l.GetBasicVal() * Math.Pow(V.GetBasicVal(), 2.0) * Math.Tan(Α.GetBasicVal())
                        ) / (2.0 * Math.Pow(V.GetBasicVal(), 2.0))
                    ),
                UnitLength.Basic
                ).Convert(Units.Length);

            UsedAssignmentType = AssignmentsTypes.InitialHeightByLength;
        }
        /// <summary>
        /// 6. Constructor for a projectile motion Quantities. Computes an initial velocity based on the length.
        /// </summary>
        /// <param name="α">An elevation angle.</param>
        /// <param name="l">The length.</param>
        /// <param name="h">An initial height.</param>
        /// <param name="g">A gravitation acceleration of the planet.</param>
        /// <param name="units">The units of Quantities. By default metre per second, radian, metre and metre per square second.</param>
        public ProjectileMotionQuantities(Length l, ElevationAngle α, InitialHeight h, GravAcceleration g, ProjectileMotionResultsUnits units = null)
        {
            Units = units ?? new ProjectileMotionResultsUnits();

            Α = α;
            H = h;
            G = g;
            V = new InitialVelocity(
                GetResultWithComputeExpection(
                    Α.IsRight() ?
                    double.NaN
                        :
                    l.GetBasicVal() == 0 && H.GetBasicVal() == 0 && Α.GetBasicVal() > 0 ? 0 :
                    l.GetBasicVal() * Math.Sqrt(G.GetBasicVal() / Math.Cos(Α.GetBasicVal())) /
                    Math.Sqrt(
                        2.0 * l.GetBasicVal() * Math.Sin(Α.GetBasicVal()) +
                        2.0 * H.GetBasicVal() * Math.Cos(Α.GetBasicVal())
                        )
                    ),
                UnitVelocity.Basic
                ).Convert(Units.Velocity);

            UsedAssignmentType = AssignmentsTypes.InitialVelocityByLength;
        }
 public ProjectileMotionWithResistanceQuantities(InitialVelocity v, ElevationAngle α, InitialHeight h, GravAcceleration g, Mass m, Density ρ, FrontalArea a, DragCoefficient c, ProjectileMotionResultsUnits units = null) : base(v, α, h, g, units)
 {
     M = m;
     Ρ = ρ;
     C = c;
     A = a;
 }
        public ActionResult Properties(bool?setWithResistance = null)
        {
            SetPropertiesModel viewModel = new SetPropertiesModel()
            {
                Layout     = new LayoutModel("Set properties"),
                Quantities = new SetPropertiesQuantitiesModel()
                {
                    InitialVelocity  = 15.0,
                    InitialHeight    = 0,
                    ElevationAngle   = Math.PI / 4.0,
                    GravAcceleration = GravAcceleration.GetGravAccelerationValue(GravAcceleration.GravAccelerations.Earth),
                    FrontalArea      = Math.Pow(new Length(12.9, UnitLength.Centimetre).GetBasicVal(), 2.0) * Math.PI,
                    DragCoefficient  = DragCoefficient.GetDragCoefficientValue(DragCoefficient.DragCoefficients.Sphere),
                    Mass             = 0.5,
                    Density          = Density.GetDensityValue(Density.Densities.Air),
                    WithResistance   = setWithResistance ?? false,
                },
                RoundDigits         = 6,
                PointsForTrajectory = 80,
                ShowMotionWithoutResistanceTrajectoryToo = false
            };

            viewModel.HexColorOfTrajectory = viewModel.Quantities.WithResistance ? "#007bff" : "#6c757d";

            SessionStore session = GetSession();

            if (session.IsSavedProjectileMotionWithResistance())
            {
                ProjectileMotionWithResistance savedMotion = session.GetSavedProjectileMotionWithResistance();

                viewModel.Quantities.InitialVelocity  = savedMotion.Settings.Quantities.V.Val;
                viewModel.Quantities.InitialHeight    = savedMotion.Settings.Quantities.H.Val;
                viewModel.Quantities.ElevationAngle   = savedMotion.Settings.Quantities.Α.Val;
                viewModel.Quantities.GravAcceleration = savedMotion.Settings.Quantities.G.Val;
                viewModel.Quantities.FrontalArea      = savedMotion.Settings.Quantities.A.Val;
                viewModel.Quantities.DragCoefficient  = savedMotion.Settings.Quantities.C.Val;
                viewModel.Quantities.Mass             = savedMotion.Settings.Quantities.M.Val;
                viewModel.Quantities.Density          = savedMotion.Settings.Quantities.Ρ.Val;
                viewModel.RoundDigits = savedMotion.Settings.RoundDigits;
                viewModel.Quantities.WithResistance = true;

                viewModel.PointsForTrajectory = savedMotion.Settings.PointsForTrajectory;

                viewModel.Quantities.InitialVelocityUnit  = savedMotion.Settings.Quantities.V.Unit.Name;
                viewModel.Quantities.InitialHeightUnit    = savedMotion.Settings.Quantities.H.Unit.Name;
                viewModel.Quantities.ElevationAngleUnit   = savedMotion.Settings.Quantities.Α.Unit.Name;
                viewModel.Quantities.GravAccelerationUnit = savedMotion.Settings.Quantities.G.Unit.Name;
                viewModel.Quantities.FrontalAreaUnit      = savedMotion.Settings.Quantities.A.Unit.Name;
                viewModel.Quantities.MassUnit             = savedMotion.Settings.Quantities.M.Unit.Name;
                viewModel.Quantities.DensityUnit          = savedMotion.Settings.Quantities.Ρ.Unit.Name;

                viewModel.ResultUnitAngle            = savedMotion.Settings.Quantities.Units.Angle.Name;
                viewModel.ResultUnitArea             = savedMotion.Settings.Quantities.Units.Area.Name;
                viewModel.ResultUnitGravAcceleration = savedMotion.Settings.Quantities.Units.GravAcceleration.Name;
                viewModel.ResultUnitLength           = savedMotion.Settings.Quantities.Units.Length.Name;
                viewModel.ResultUnitTime             = savedMotion.Settings.Quantities.Units.Time.Name;
                viewModel.ResultUnitVelocity         = savedMotion.Settings.Quantities.Units.Velocity.Name;

                viewModel.TxtInfoFileName      = savedMotion.Settings.TxtInfoFileName;
                viewModel.CsvDataFileName      = savedMotion.Settings.CsvDataFileName;
                viewModel.PdfInfoFileName      = savedMotion.Settings.PdfInfoFileName;
                viewModel.ChartFileName        = savedMotion.Settings.ChartFileName;
                viewModel.HexColorOfTrajectory = savedMotion.Settings.HexColorOfTrajectory;
                viewModel.ShowMotionWithoutResistanceTrajectoryToo = savedMotion.Settings.ShowMotionWithoutResistanceTrajectoryToo;

                viewModel.Layout.Title = "Edit properties";
            }
            else if (session.IsSavedProjectileMotion())
            {
                ProjectileMotion savedMotion = session.GetSavedProjectileMotion();

                viewModel.Quantities.InitialVelocity  = savedMotion.Settings.Quantities.V.Val;
                viewModel.Quantities.InitialHeight    = savedMotion.Settings.Quantities.H.Val;
                viewModel.Quantities.ElevationAngle   = savedMotion.Settings.Quantities.Α.Val;
                viewModel.Quantities.GravAcceleration = savedMotion.Settings.Quantities.G.Val;
                viewModel.Quantities.WithResistance   = false;


                viewModel.RoundDigits = savedMotion.Settings.RoundDigits;

                viewModel.PointsForTrajectory = savedMotion.Settings.PointsForTrajectory;

                viewModel.Quantities.InitialVelocityUnit  = savedMotion.Settings.Quantities.V.Unit.Name;
                viewModel.Quantities.InitialHeightUnit    = savedMotion.Settings.Quantities.H.Unit.Name;
                viewModel.Quantities.ElevationAngleUnit   = savedMotion.Settings.Quantities.Α.Unit.Name;
                viewModel.Quantities.GravAccelerationUnit = savedMotion.Settings.Quantities.G.Unit.Name;

                viewModel.Quantities.Length        = savedMotion.GetLength().Val;
                viewModel.Quantities.LengthUnit    = savedMotion.GetLength().Unit.Name;
                viewModel.Quantities.MaxHeight     = savedMotion.GetMaxHeight().Val;
                viewModel.Quantities.MaxHeightUnit = savedMotion.GetMaxHeight().Unit.Name;
                viewModel.Quantities.Duration      = savedMotion.GetDur().Val;
                viewModel.Quantities.DurationUnit  = savedMotion.GetDur().Unit.Name;

                viewModel.ResultUnitAngle            = savedMotion.Settings.Quantities.Units.Angle.Name;
                viewModel.ResultUnitArea             = savedMotion.Settings.Quantities.Units.Area.Name;
                viewModel.ResultUnitGravAcceleration = savedMotion.Settings.Quantities.Units.GravAcceleration.Name;
                viewModel.ResultUnitLength           = savedMotion.Settings.Quantities.Units.Length.Name;
                viewModel.ResultUnitTime             = savedMotion.Settings.Quantities.Units.Time.Name;
                viewModel.ResultUnitVelocity         = savedMotion.Settings.Quantities.Units.Velocity.Name;

                viewModel.TxtInfoFileName      = savedMotion.Settings.TxtInfoFileName;
                viewModel.CsvDataFileName      = savedMotion.Settings.CsvDataFileName;
                viewModel.PdfInfoFileName      = savedMotion.Settings.PdfInfoFileName;
                viewModel.ChartFileName        = savedMotion.Settings.ChartFileName;
                viewModel.HexColorOfTrajectory = savedMotion.Settings.HexColorOfTrajectory;
                viewModel.ShowMotionWithoutResistanceTrajectoryToo = false;

                viewModel.Quantities.SelectedAssignmentType = savedMotion.Settings.Quantities.UsedAssignmentType;

                viewModel.Layout.Title = "Edit properties";
            }
            else if (setWithResistance == null)
            {
                return(RedirectToAction(nameof(ChooseController.Neglection), "Choose"));
            }

            viewModel.Layout.Menu.SetWithResistance = viewModel.Quantities.WithResistance;
            viewModel.Layout.Menu.ActiveMenuItem    = LayoutMenuModel.ActiveNavItem.Set;

            return(View(viewModel));
        }
        public ActionResult Properties(SetPropertiesModel postModel)
        {
            if (ModelState.IsValid)
            {
                SessionStore session = GetSession();

                InitialVelocity  v = new InitialVelocity(postModel.Quantities.InitialVelocity, new UnitsReflectionHelper <UnitVelocity>().GetUnit(postModel.Quantities.InitialVelocityUnit));
                InitialHeight    h = new InitialHeight(postModel.Quantities.InitialHeight, new UnitsReflectionHelper <UnitLength>().GetUnit(postModel.Quantities.InitialHeightUnit));
                GravAcceleration g = new GravAcceleration(postModel.Quantities.GravAcceleration, new UnitsReflectionHelper <UnitGravAcceleration>().GetUnit(postModel.Quantities.GravAccelerationUnit));
                ElevationAngle   α = new ElevationAngle(postModel.Quantities.ElevationAngle, new UnitsReflectionHelper <UnitAngle>().GetUnit(postModel.Quantities.ElevationAngleUnit));

                ProjectileMotionResultsUnits units = new ProjectileMotionResultsUnits()
                {
                    Length           = new UnitsReflectionHelper <UnitLength>().GetUnit(postModel.ResultUnitLength),
                    Time             = new UnitsReflectionHelper <UnitTime>().GetUnit(postModel.ResultUnitTime),
                    Velocity         = new UnitsReflectionHelper <UnitVelocity>().GetUnit(postModel.ResultUnitVelocity),
                    Angle            = new UnitsReflectionHelper <UnitAngle>().GetUnit(postModel.ResultUnitAngle),
                    Area             = new UnitsReflectionHelper <UnitArea>().GetUnit(postModel.ResultUnitArea),
                    GravAcceleration = new UnitsReflectionHelper <UnitGravAcceleration>().GetUnit(postModel.ResultUnitGravAcceleration)
                };

                if (postModel.Quantities.WithResistance)
                {
                    session.SaveProjectileMotionWithResistance(new ProjectileMotionWithResistance(
                                                                   new ProjectileMotionWithResistanceSettings(
                                                                       new ProjectileMotionWithResistanceQuantities(
                                                                           v, α, h, g,
                                                                           new Mass(postModel.Quantities.Mass.Value, new UnitsReflectionHelper <UnitMass>().GetUnit(postModel.Quantities.MassUnit)),
                                                                           new Density(postModel.Quantities.Density.Value, new UnitsReflectionHelper <UnitDensity>().GetUnit(postModel.Quantities.DensityUnit)),
                                                                           new FrontalArea(postModel.Quantities.FrontalArea.Value, new UnitsReflectionHelper <UnitArea>().GetUnit(postModel.Quantities.FrontalAreaUnit)),
                                                                           new DragCoefficient(postModel.Quantities.DragCoefficient.Value),
                                                                           units
                                                                           )
                                                                       )
                    {
                        RoundDigits          = postModel.RoundDigits,
                        PointsForTrajectory  = postModel.PointsForTrajectory,
                        TxtInfoFileName      = postModel.TxtInfoFileName,
                        CsvDataFileName      = postModel.CsvDataFileName,
                        PdfInfoFileName      = postModel.PdfInfoFileName,
                        ChartFileName        = postModel.ChartFileName,
                        HexColorOfTrajectory = postModel.HexColorOfTrajectory,
                        ShowMotionWithoutResistanceTrajectoryToo = postModel.ShowMotionWithoutResistanceTrajectoryToo
                    })).SaveProjectileMotion(null);

                    return(RedirectToAction(nameof(DisplayController.MotionWithResistance), "Display"));
                }


                ProjectileMotionQuantities quantitiesWithoutResistance = null;

                try
                {
                    if (new List <ProjectileMotionQuantities.AssignmentsTypes>()
                    {
                        ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByDuration,
                        ProjectileMotionQuantities.AssignmentsTypes.InitialHeightByDuration,
                        ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByDuration
                    }.Contains(postModel.Quantities.SelectedAssignmentType))
                    {
                        Duration d = new Duration(postModel.Quantities.Duration.Value, new UnitsReflectionHelper <UnitTime>().GetUnit(postModel.Quantities.DurationUnit));

                        switch (postModel.Quantities.SelectedAssignmentType)
                        {
                        case ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByDuration:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(d, v, h, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.InitialHeightByDuration:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(d, α, v, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByDuration:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(d, α, h, g, units);
                            break;
                        }
                    }
                    else if (new List <ProjectileMotionQuantities.AssignmentsTypes>()
                    {
                        ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByMaxHeight,
                        ProjectileMotionQuantities.AssignmentsTypes.InitialHeightByMaxHeight,
                        ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByMaxHeight
                    }.Contains(postModel.Quantities.SelectedAssignmentType))
                    {
                        MaximalHeight maxH = new MaximalHeight(postModel.Quantities.MaxHeight.Value, new UnitsReflectionHelper <UnitLength>().GetUnit(postModel.Quantities.MaxHeightUnit));

                        switch (postModel.Quantities.SelectedAssignmentType)
                        {
                        case ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByMaxHeight:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(maxH, v, h, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.InitialHeightByMaxHeight:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(maxH, α, v, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByMaxHeight:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(maxH, α, h, g, units);
                            break;
                        }
                    }
                    else if (new List <ProjectileMotionQuantities.AssignmentsTypes>()
                    {
                        ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByLength,
                        ProjectileMotionQuantities.AssignmentsTypes.InitialHeightByLength,
                        ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByLength
                    }.Contains(postModel.Quantities.SelectedAssignmentType))
                    {
                        Length l = new Length(postModel.Quantities.Length.Value, new UnitsReflectionHelper <UnitLength>().GetUnit(postModel.Quantities.MaxHeightUnit));

                        switch (postModel.Quantities.SelectedAssignmentType)
                        {
                        case ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByLength:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(l, v, h, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.InitialHeightByLength:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(l, α, v, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByLength:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(l, α, h, g, units);
                            break;
                        }
                    }
                    else if (postModel.Quantities.SelectedAssignmentType == ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleGetMaxRange)
                    {
                        quantitiesWithoutResistance = new ProjectileMotionQuantities(v, h, g, units);
                    }
                    else if (new List <ProjectileMotionQuantities.AssignmentsTypes>()
                    {
                        ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByLengthAndDur,
                        ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByLengthAndDur
                    }.Contains(postModel.Quantities.SelectedAssignmentType))
                    {
                        Length   l = new Length(postModel.Quantities.Length.Value, new UnitsReflectionHelper <UnitLength>().GetUnit(postModel.Quantities.MaxHeightUnit));
                        Duration d = new Duration(postModel.Quantities.Duration.Value, new UnitsReflectionHelper <UnitTime>().GetUnit(postModel.Quantities.DurationUnit));

                        switch (postModel.Quantities.SelectedAssignmentType)
                        {
                        case ProjectileMotionQuantities.AssignmentsTypes.InitialVelocityByLengthAndDur:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(α, l, d, g, units);
                            break;

                        case ProjectileMotionQuantities.AssignmentsTypes.ElevationAngleByLengthAndDur:
                            quantitiesWithoutResistance = new ProjectileMotionQuantities(v, l, d, g, units);
                            break;
                        }
                    }
                    else
                    {
                        quantitiesWithoutResistance = new ProjectileMotionQuantities(v, α, h, g, units);
                    }

                    session.SaveProjectileMotion(new ProjectileMotion(
                                                     new ProjectileMotionSettings(quantitiesWithoutResistance)
                    {
                        RoundDigits          = postModel.RoundDigits,
                        PointsForTrajectory  = postModel.PointsForTrajectory,
                        TxtInfoFileName      = postModel.TxtInfoFileName,
                        CsvDataFileName      = postModel.CsvDataFileName,
                        PdfInfoFileName      = postModel.PdfInfoFileName,
                        ChartFileName        = postModel.ChartFileName,
                        HexColorOfTrajectory = postModel.HexColorOfTrajectory
                    })).SaveProjectileMotionWithResistance(null);

                    return(RedirectToAction(nameof(DisplayController.Motion), "Display"));
                }
                catch (UnableToComputeQuantityException ex)
                {
                    ModelState.AddModelError(string.Empty, ex.Message);
                }
            }

            postModel.Layout = new LayoutModel("Repair properties");
            postModel.Layout.Menu.SetWithResistance = postModel.Quantities.WithResistance;
            postModel.Layout.Menu.ActiveMenuItem    = LayoutMenuModel.ActiveNavItem.Set;
            return(View(postModel));
        }