/// <summary>
        /// Get interpolated data for a given percentage within the total range of the key points.
        /// TODO: Would it be cleaner not to use a double for percentage, but a generic Percentage type?
        /// </summary>
        /// <param name = "percentage">The percentage in between the first and the last value to get interpolated data for.</param>
        /// <returns>The interpolated data.</returns>
        public TValue Interpolate(double percentage)
        {
            if (KeyPoints.Count <= 0)
            {
                throw new InvalidOperationException("No key points between which to interpolate available.");
            }

            // TODO: Allow extrapolation?
            if (percentage < 0)
            {
                percentage = 0;
            }
            else if (percentage > 1)
            {
                percentage = 1;
            }

            // Find in between which two keypoints the desired position lies.
            TMath position = KeyPoints.DataRange.GetValueAt(percentage);
            BinarySearchResult <TMath> searchResult = KeyPoints.BinarySearch(position);

            // Return exact value when found, or interpolated when not found.
            TValue result;

            if (searchResult.IsObjectFound)
            {
                result = KeyPoints[searchResult.Found.Object];
            }
            else
            {
                // Use double math to calculate the desired value inside the interval. (percentage)
                double smallerValue = CastOperator <TMath, double> .Cast(searchResult.NotFound.Smaller);

                double biggerValue = CastOperator <TMath, double> .Cast(searchResult.NotFound.Bigger);

                result = Interpolate(
                    KeyPoints.IndexAtPosition(searchResult.NotFound.Smaller),
                    KeyPoints.IndexAtPosition(searchResult.NotFound.Bigger),
                    position,
                    new Interval <double>(smallerValue, biggerValue).GetPercentageFor(CastOperator <TMath, double> .Cast(position)));
            }

            return(result);
        }
예제 #2
0
        protected override TValue TangentAt(int smallerIndex, int biggerIndex, TMath position, double percentage)
        {
            AbstractTypeInterpolationProvider <TValue, TMath> typeProvider = KeyPoints.TypeProvider;

            // Retrieve values for all dimensions for all 4 control points.
            double[][] values = RetrieveValues(smallerIndex, biggerIndex, typeProvider);

            // Set up hermite base function derivatives.
            double t              = percentage;
            double t2             = Math.Pow(t, 2);
            double baseFunction00 = (6 * t2) - (6 * t);
            double baseFunction10 = (3 * t2) - (4 * t) + 1;
            double baseFunction01 = (6 * t) - (6 * t2);
            double baseFunction11 = (3 * t2) - (2 * t);

            // Get tangent by calculating derivative.
            double tension = 1 - Tension;
            var    tangent = new TMath[typeProvider.AmountOfDimensions];

            for (int i = 0; i < typeProvider.AmountOfDimensions; ++i)
            {
                // Original: (((2*t^3)-(3*t^2)+1)*b) + (((-2*t^3)+(3*t^2))*c) + ((t^3-(2*t^2)+t)*(n*(c-a))) + ((t^3-t^2)*(n*(d-b)))
                // First derivative: ((3*d+3*c-3*b-3*a)*n-6*c+6*b)*t^2 + ((-2*d-4*c+2*b+4*a)*n+6*c-6*b)*t + (c-a)*n

                // Calculate tangents.
                double tangentSmaller = tension * (values[2][i] - values[0][i]);
                double tangentBigger  = tension * (values[3][i] - values[1][i]);

                // Multiply derived hermite base functions with the points (and tangents) and sum up.
                double result =
                    (baseFunction00 * values[1][i])
                    + (baseFunction01 * values[2][i])
                    + (baseFunction10 * tangentSmaller)
                    + (baseFunction11 * tangentBigger);

                // Sum up all functions.
                tangent[i] = CastOperator <double, TMath> .Cast(result);
            }

            return(typeProvider.CreateInstance(position, tangent));
        }
예제 #3
0
        protected override TValue Interpolate(int smallerIndex, int biggerIndex, TMath position, double percentage)
        {
            AbstractTypeInterpolationProvider <TValue, TMath> typeProvider = KeyPoints.TypeProvider;

            // Retrieve values for all dimensions for all 4 control points.
            double[][] values = RetrieveValues(smallerIndex, biggerIndex, typeProvider);

            // Set up hermite base functions.
            double t              = percentage;
            double t2             = Math.Pow(t, 2);
            double t3             = Math.Pow(t, 3);
            double baseFunction00 = (2 * t3) - (3 * t2) + 1;
            double baseFunction10 = t3 - (2 * t2) + t;
            double baseFunction01 = (-2 * t3) + (3 * t2);
            double baseFunction11 = t3 - t2;

            // Interpolate.
            double tension      = 1 - Tension;
            var    interpolated = new TMath[typeProvider.AmountOfDimensions];

            for (int i = 0; i < typeProvider.AmountOfDimensions; ++i)
            {
                // Calculate tangents.
                double tangentSmaller = tension * (values[2][i] - values[0][i]);
                double tangentBigger  = tension * (values[3][i] - values[1][i]);

                // Multiply hermite base functions with the points (and tangents) and sum up.
                double result =
                    (baseFunction00 * values[1][i])
                    + (baseFunction01 * values[2][i])
                    + (baseFunction10 * tangentSmaller)
                    + (baseFunction11 * tangentBigger);

                // Sum up all functions.
                interpolated[i] = CastOperator <double, TMath> .Cast(result);
            }

            return(typeProvider.CreateInstance(position, interpolated));
        }
        /// <summary>
        ///   Get the tangent at a given percentage within the range of the key points.
        /// </summary>
        /// <param name = "percentage"></param>
        /// <returns>The tangent at a given percentage within the range of the key points.</returns>
        public TValue TangentAt(double percentage)
        {
            // TODO: Allow extrapolation?
            Contract.Requires(percentage >= 0 && percentage <= 1);
            Contract.Requires(KeyPoints.Count > 0);

            // Find in between which two keypoints the desired position lies.
            TMath position = KeyPoints.DataRange.GetValueAt(percentage);
            BinarySearchResult <TMath> searchResult = KeyPoints.BinarySearch(position);

            // Use double math to calculate percentage of desired value inside
            double smallerValue = CastOperator <TMath, double> .Cast(searchResult.NotFound.Smaller);

            double biggerValue = CastOperator <TMath, double> .Cast(searchResult.NotFound.Bigger);

            TValue result = TangentAt(
                KeyPoints.IndexAtPosition(searchResult.NotFound.Smaller),
                KeyPoints.IndexAtPosition(searchResult.NotFound.Bigger),
                position,
                new Interval <double>(smallerValue, biggerValue).GetPercentageFor(CastOperator <TMath, double> .Cast(position)));

            return(result);
        }
예제 #5
0
 public CastExpression(IType targetType, IExpression e, CastOperator op) : base(e)
 {
     TargetType = targetType;
     SourceType = e.ResultType;
     Operator   = op;
 }
예제 #6
0
        public override TMath RelativePosition(AbsoluteKeyPoint <TKey, TValue> from, AbsoluteKeyPoint <TKey, TValue> to)
        {
            TKey key = Operator <TKey> .Subtract(@from.Key, to.Key);

            return(CastOperator <double, TMath> .Cast(CastOperator <TKey, double> .Cast(key)));
        }