/// <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); }
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)); }
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); }
public CastExpression(IType targetType, IExpression e, CastOperator op) : base(e) { TargetType = targetType; SourceType = e.ResultType; Operator = op; }
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))); }