/// <summary> /// Create a new collection of key points with cumulative values. /// </summary> /// <param name = "typeProvider"> /// The provider which gives information about the type, required to do interpolation between the key points. /// </param> public CumulativeKeyPointCollection(AbstractTypeInterpolationProvider <TValue, TMath> typeProvider) : base(typeProvider) { _zero = CastOperator <double, TMath> .Cast(0); _minusOne = CastOperator <double, TMath> .Cast(-1); }
/// <summary> /// Retrieve values for all dimensions for all 4 control points. /// </summary> /// <returns> /// A 2 dimensional array with all the dimension values for all 4 control points. /// The first dimension of the array indicates the control point, the second the dimension. /// </returns> double[][] RetrieveValues(int smallerIndex, int biggerIndex, AbstractTypeInterpolationProvider <TValue, TMath> typeProvider) { // Retrieve required values. TValue p0 = KeyPoints[smallerIndex != 0 ? smallerIndex - 1 : smallerIndex]; TValue p1 = KeyPoints[smallerIndex]; TValue p2 = KeyPoints[biggerIndex]; TValue p3 = KeyPoints[biggerIndex != KeyPoints.Count - 1 ? biggerIndex + 1 : biggerIndex]; // Retrieve required dimension values. double[] p0Values = typeProvider.GetDimensionValues(p0).Cast <double>().ToArray(); double[] p1Values = typeProvider.GetDimensionValues(p1).Cast <double>().ToArray(); double[] p2Values = typeProvider.GetDimensionValues(p2).Cast <double>().ToArray(); double[] p3Values = typeProvider.GetDimensionValues(p3).Cast <double>().ToArray(); return(new[] { p0Values, p1Values, p2Values, p3Values }); }
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; TMath[] 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 required values. TValue smaller = KeyPoints[smallerIndex]; TValue bigger = KeyPoints[biggerIndex]; // Retrieve required dimension values. TMath[] smallerValues = typeProvider.GetDimensionValues(smaller); TMath[] biggerValues = typeProvider.GetDimensionValues(bigger); // Linear interpolation. TMath[] interpolated = new TMath[typeProvider.AmountOfDimensions]; for (int i = 0; i < typeProvider.AmountOfDimensions; ++i) { var valueRange = new Interval <TMath>(smallerValues[i], biggerValues[i]); interpolated[i] = valueRange.GetValueAt(percentage); } return(typeProvider.CreateInstance(position, interpolated)); }
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; TMath[] 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> /// Create a new interpolation provider which can interpolate over AbsoluteKeyPoints. /// </summary> public AbsoluteKeyPointInterpolationProvider(AbstractTypeInterpolationProvider <TValue, TMath> keyPointInterpolationProvider) : base(keyPointInterpolationProvider.AmountOfDimensions) { _keyPointInterpolationProvider = keyPointInterpolationProvider; }
/// <summary> /// Create a new collection of key points. /// </summary> /// <param name = "typeProvider"> /// The provider which gives information about the type, required to do interpolation between the key points. /// </param> protected AbstractKeyPointCollection(AbstractTypeInterpolationProvider <TValue, TMath> typeProvider) { TypeProvider = typeProvider; }
/// <summary> /// Create a new collection of key points with absolute values. /// </summary> /// <param name = "typeProvider"> /// The provider which gives information about the type, required to do interpolation between the key points. /// </param> /// <param name = "referenceKeyPoint"> /// A key point which is used to measure the distance to all other added key points. /// Don't adjust this key point after adding it. /// </param> public AbsoluteKeyPointCollection(AbstractTypeInterpolationProvider <TValue, TMath> typeProvider, TValue referenceKeyPoint) : base(typeProvider) { _referenceKeyPoint = referenceKeyPoint; }