/// <summary>
        /// Initializes a new instance of the <see cref="WalkingTrail"/> class. For Internal Use ONLY!
        /// </summary>
        /// <param name="observedPoints">The observed locations.</param>
        /// <param name="velocityMagnitude">The velocity magnitude.</param>
        internal WalkingTrail(UV[] observedPoints, double velocityMagnitude)
        {
            this._length      = new double[observedPoints.Length];
            this._trailLength = 0;
            this._length[0]   = 0;
            for (int i = 0; i < observedPoints.Length - 1; i++)
            {
                double d = observedPoints[i].DistanceTo(observedPoints[i + 1]);
                this._length[i + 1] = this._length[i] + d;
            }
            this._trailLength = this._length[this._length.Length - 1];
            double[] observation_time = new double[this._length.Length];
            observation_time[0] = 0;
            for (int i = 0; i < observedPoints.Length - 1; i++)
            {
                double deltaT = observedPoints[i].DistanceTo(observedPoints[i + 1]) / velocityMagnitude;
                observation_time[i + 1] = observation_time[i] + deltaT;
            }

            this._trailInput      = TrailInput.Location;
            this._observationTime = observation_time;
            this._startTime       = _observationTime[0];
            this._endTime         = _observationTime[_observationTime.Length - 1];
            this._duration        = _observationTime[_observationTime.Length - 1] - _observationTime[0];
            this._timeToLength    = Interpolate.CubicSplineRobust(this._observationTime, this._length);
            this._lengthToTime    = Interpolate.CubicSplineRobust(this._length, this._observationTime);

            //create interpolations
            double[] location_U_values = new double[this._observationTime.Length];
            double[] location_V_values = new double[this._observationTime.Length];
            for (int i = 0; i < this._observationTime.Length; i++)
            {
                location_U_values[i] = observedPoints[i].U;
                location_V_values[i] = observedPoints[i].V;
            }
            this._interpolate_location_U = Interpolate.CubicSplineRobust(this._observationTime, location_U_values);
            this._ULinearInterpolation   = Interpolate.Linear(this._observationTime, location_U_values);

            this._interpolate_location_V = Interpolate.CubicSplineRobust(this._observationTime, location_V_values);
            this._VLinearInterpolation   = Interpolate.Linear(this._observationTime, location_V_values);


            this._observedStates = new StateBase[this._observationTime.Length];
            //this._controlPoints = new UV[this._time.Length];
            for (int i = 0; i < this._observedStates.Length; i++)
            {
                UV location  = observedPoints[i];
                UV velocity  = this.getVelocity(this._observationTime[i]);
                UV direction = this.getDirection(this._observationTime[i]);
                //this._controlPoints[i] = location;
                this._observedStates[i] = new StateBase(location, direction, velocity);
            }
            this.loadNormalizedStates();
            loadApproximatedPolyline();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="WalkingTrail"/> class.
        /// </summary>
        /// <param name="observation_time">The observation time.</param>
        /// <param name="observed_states">The observed states.</param>
        /// <param name="inputMode">The input mode.</param>
        /// <exception cref="ArgumentException">
        /// The size of observation time and observed states are not equal
        /// or
        /// The observation times are not in ascending order!
        /// or
        /// The observed states include null elements that cannot be used for generating a trail model
        /// or
        /// The observed states include null elements that cannot be used for generating a trail model
        /// or
        /// The observed states include null locations that cannot be used for generating a trail model
        /// </exception>
        public WalkingTrail(double[] observation_time, StateBase[] observed_states, TrailInput inputMode)
        {
            if (observation_time.Length != observed_states.Length)
            {
                throw new ArgumentException("The size of observation time and observed states are not equal");
            }
            for (int i = 0; i < observation_time.Length - 1; i++)
            {
                if (observation_time[i] >= observation_time[i + 1])
                {
                    throw new ArgumentException("The observation times are not in ascending order!");
                }
            }
            for (int i = 0; i < observed_states.Length; i++)
            {
                switch (inputMode)
                {
                case TrailInput.Location_Velocity_Direction:
                    if (observed_states[i].Velocity == null || observed_states[i].Direction == null || observed_states[i].Location == null)
                    {
                        throw new ArgumentException("The observed states include null elements that cannot be used for generating a trail model");
                    }
                    break;

                case TrailInput.Location_Direction:
                    if (observed_states[i].Direction == null || observed_states[i].Location == null)
                    {
                        throw new ArgumentException("The observed states include null elements that cannot be used for generating a trail model");
                    }
                    break;

                case TrailInput.Location:
                    if (observed_states[i].Location == null)
                    {
                        throw new ArgumentException("The observed states include null locations that cannot be used for generating a trail model");
                    }
                    break;
                }
            }

            this._trailInput      = inputMode;
            this._observationTime = observation_time;
            this._startTime       = _observationTime[0];
            this._endTime         = _observationTime[_observationTime.Length - 1];
            this._duration        = _observationTime[_observationTime.Length - 1] - _observationTime[0];

            this._length    = new double[observation_time.Length];
            this._length[0] = 0;
            for (int i = 0; i < observed_states.Length - 1; i++)
            {
                double d = observed_states[i].Location.DistanceTo(observed_states[i + 1].Location);
                this._length[i + 1] = this._length[i] + d;
            }
            this._trailLength  = this._length[this._length.Length - 1];
            this._timeToLength = Interpolate.CubicSplineRobust(this._observationTime, this._length);
            this._lengthToTime = Interpolate.CubicSplineRobust(this._length, this._observationTime);

            //create interpolations
            double[] location_U_values = new double[this._observationTime.Length];
            double[] location_V_values = new double[this._observationTime.Length];
            for (int i = 0; i < this._observationTime.Length; i++)
            {
                location_U_values[i] = observed_states[i].Location.U;
                location_V_values[i] = observed_states[i].Location.V;
            }
            this._interpolate_location_U = Interpolate.CubicSplineRobust(this._observationTime, location_U_values);
            this._ULinearInterpolation   = Interpolate.Linear(this._observationTime, location_U_values);

            this._interpolate_location_V = Interpolate.CubicSplineRobust(this._observationTime, location_V_values);
            this._VLinearInterpolation   = Interpolate.Linear(this._observationTime, location_V_values);

            double[] velocity_U_values;
            double[] velocity_V_values;

            double[] direction_U_values;
            double[] direction_V_values;

            switch (this._trailInput)
            {
            case TrailInput.Location_Velocity_Direction:
                velocity_U_values  = new double[this._observationTime.Length];
                velocity_V_values  = new double[this._observationTime.Length];
                direction_U_values = new double[this._observationTime.Length];
                direction_V_values = new double[this._observationTime.Length];
                for (int i = 0; i < this._observationTime.Length; i++)
                {
                    velocity_U_values[i] = observed_states[i].Velocity.U;
                    velocity_V_values[i] = observed_states[i].Velocity.V;
                    observed_states[i].Direction.Unitize();
                    direction_U_values[i] = observed_states[i].Direction.U;
                    direction_V_values[i] = observed_states[i].Direction.V;
                }
                this._interpolate_velocity_U  = Interpolate.CubicSplineRobust(this._observationTime, velocity_U_values);
                this._interpolate_velocity_V  = Interpolate.CubicSplineRobust(this._observationTime, velocity_V_values);
                this._interpolate_direction_U = Interpolate.CubicSplineRobust(this._observationTime, direction_U_values);
                this._interpolate_direction_V = Interpolate.CubicSplineRobust(this._observationTime, direction_V_values);
                break;

            case TrailInput.Location_Direction:
                direction_U_values = new double[this._observationTime.Length];
                direction_V_values = new double[this._observationTime.Length];
                for (int i = 0; i < this._observationTime.Length; i++)
                {
                    observed_states[i].Direction.Unitize();
                    direction_U_values[i] = observed_states[i].Direction.U;
                    direction_V_values[i] = observed_states[i].Direction.V;
                }
                this._interpolate_direction_U = Interpolate.CubicSplineRobust(this._observationTime, direction_U_values);
                this._interpolate_direction_V = Interpolate.CubicSplineRobust(this._observationTime, direction_V_values);
                break;

            case TrailInput.Location:
                //do nothing
                break;
            }
            this._observedStates = new StateBase[this._observationTime.Length];
            //this._controlPoints = new UV[this._time.Length];
            for (int i = 0; i < this._observedStates.Length; i++)
            {
                UV location = observed_states[i].Location;
                //this._controlPoints[i] = location;
                UV velocity = null;
                if (observed_states[i].Velocity == null)
                {
                    velocity = this.getVelocity(this._observationTime[i]);
                }
                else
                {
                    velocity = observed_states[i].Velocity;
                }
                UV direction = null;
                if (observed_states[i].Direction == null)
                {
                    direction = this.getDirection(this._observationTime[i]);
                }
                else
                {
                    direction = observed_states[i].Direction;
                }
                this._observedStates[i] = new StateBase(location, direction, velocity);
            }
            this.loadNormalizedStates();
            loadApproximatedPolyline();
        }