/// <summary>
 /// one wheel of the vehicle
 /// </summary>
 /// <param name="wheel">which wheel?</param>
 public Wheel(ImportantClasses.Enums.Wheels wheel)
 {
     _actualCalculation = new WheelOutput();
     _wheel             = wheel;
 }
        /// <summary>
        /// Calculates the overall car according to the results of all the other classes
        /// </summary>
        public void Calculate()
        {
            Vector3 totalLongitudinalAcForce = new Vector3(); //saves the longitudal acceleration force of all wheels
            Vector3 totalLongitudinalDeForce = new Vector3(); //saves the longitudal deceleration force of all wheels
            Vector3 totalLateralAcceleration = new Vector3(); //saves the lateral acceleration of all wheels

            //accumulate the forces of all wheels
            for (int i = 0; i < 4; i++)
            {
                WheelOutput wheelOutput = WheelOutput.GetWheelOutput((ImportantClasses.Enums.Wheels)i);
                totalLongitudinalAcForce += wheelOutput.LongitudinalAccelerationForce * wheelOutput.Direction;
                totalLongitudinalDeForce += wheelOutput.LongitudinalDecelerationForce * wheelOutput.Direction;
                if (!float.IsNaN(wheelOutput.LateralAcceleration))
                {
                    totalLateralAcceleration += wheelOutput.LateralAcceleration *
                                                wheelOutput.Direction.Rotate(-Math.PI / 2);
                }
            }
            //calculate the change of the speed due to the acceleration, the air drag and the deceleration from the brake
            Vector3 velocityChangeAc   = (totalLongitudinalAcForce / Weight + totalLateralAcceleration) * CalculationController.Instance.Duration;
            Vector3 velocityChangeDrag = Drag.Interpolate(OverallCarOutput.LastCalculation.Speed) *
                                         OverallCarOutput.LastCalculation.Direction *
                                         CalculationController.Instance.Duration;
            Vector3 velocityChangeDe = totalLongitudinalDeForce * CalculationController.Instance.Duration / Weight;

            //calculate the speed which would the car have if the brake is not pushed
            _actualCalculation.Speed =
                (OverallCarOutput.LastCalculation.Speed * OverallCarOutput.LastCalculation.Direction +
                 ((Vector2)velocityChangeAc).Projection((Vector2)OverallCarOutput.LastCalculation.Direction) -
                 velocityChangeDrag).Magnitude;

            //calculate the driving direction of the car
            Vector3 directionBuffer =
                (OverallCarOutput.LastCalculation.Speed * OverallCarOutput.LastCalculation.Direction + velocityChangeAc -
                 velocityChangeDrag);

            if (directionBuffer.Magnitude > 1e-3f) //change the direction just if the car is moving. Otherwise the direction can get lost.
            {
                _actualCalculation.Direction = directionBuffer.Normalize();
            }

            //add the deceleration of the brake and make sure that it cannot accelerate the car backwards
            if (velocityChangeDe.Magnitude > Math.Abs(_actualCalculation.Speed))
            {
                _actualCalculation.Speed = 0;
            }
            else if (_actualCalculation.Speed > 0)
            {
                _actualCalculation.Speed -= velocityChangeDe.Magnitude;
            }
            else
            {
                _actualCalculation.Speed += velocityChangeDe.Magnitude;
            }

            //calculates the new position of the car
            _actualCalculation.Position = OverallCarOutput.LastCalculation.Position +
                                          _actualCalculation.Speed * CalculationController.Instance.Duration * _actualCalculation.Direction;

            if (OnCalculationReady != null)
            {
                OnCalculationReady();
            }
        }
 /// <summary>
 /// stores the calculation results of the wheel
 /// </summary>
 public void StoreResult()
 {
     WheelOutput.SetWheelOutput(_wheel, _actualCalculation);
 }