/// <summary> /// Construct a linear spline using a set of input points. /// <example>For example: /// <code> /// SortedList<double, double> splinePoints = new SortedList<double, double>(); /// splinePoints.Add(0.0f, 1.1f); /// splinePoints.Add(0.3f, 0.4f); /// splinePoints.Add(1.0f, 2.0f); /// LinearSpline1D spline = new LinearSpline1D(splinePoints); /// </code> /// creates a linear spline that passes through three points: (0.0, 1.1), (0.3, 0.4) and (1.0, 2.0). /// </example> /// </summary> /// <param name="points">A list of points that is sorted by the x-coordinate. This collection is copied.</param> /// <exception cref="ArgumentException"> /// A linear spline must have at least two points to be properly defined. If <c>points</c> contains less than /// two points, the spline is undefined, so an <c>ArgumentException</c> is thrown. /// </exception> public LinearSpline1D(SortedList <double, double> points) { if (points.Count < 2) { if (points.Count == 1) { throw new ArgumentException("List contains only a single point. A spline must have at least two points.", nameof(points)); } else { throw new ArgumentException("List is empty. A spline must have at least two points.", nameof(points)); } } Points = new SortedPointsList <double>(points); DebugUtil.AssertAllFinite(Points, nameof(Points)); // Calculate the coefficients for each segment of the spline: _parameters = new double[points.Count]; // Recursively find the _parameters: for (int i = 1; i < points.Count; i++) { double dx = Points.Key[i] - Points.Key[i - 1]; double dy = Points.Value[i] - Points.Value[i - 1]; _parameters[i] = dy / dx; } DebugUtil.AssertAllFinite(_parameters, nameof(_parameters)); }
/// <summary> /// Construct a linear spline using a set of input points. /// <example>For example: /// <code> /// SortedList{double, double} splinePoints = new SortedList{double, double}(); /// splinePoints.Add(0.0f, 1.1f); /// splinePoints.Add(0.3f, 0.4f); /// splinePoints.Add(1.0f, 2.0f); /// LinearSpline1D spline = new LinearSpline1D(splinePoints); /// </code> /// creates a linear spline that passes through three points: (0.0, 1.1), (0.3, 0.4) and (1.0, 2.0). /// </example> /// </summary> /// <param name="points">A list of points that is sorted by the x-coordinate. This collection is copied.</param> /// <exception cref="ArgumentException"> /// A linear spline must have at least two points to be properly defined. If <c>points</c> contains less than /// two points, the spline is undefined, so an <c>ArgumentException</c> is thrown. /// </exception> public LinearSpline1D(SortedList <double, double> points) { if (points.Count < 2) { if (points.Count == 1) { throw new ArgumentException("List contains only a single point. A spline must have at least two points.", nameof(points)); } else { throw new ArgumentException("List is empty. A spline must have at least two points.", nameof(points)); } } Points = new SortedPointsList <double>(points); DebugUtil.AssertAllFinite(Points, nameof(Points)); }
/// <summary> /// Construct a quadratic spline using a set of input points. /// <example>For example: /// <code> /// SortedList<double, double> splinePoints = new SortedList<double, double>(); /// splinePoints.Add(0.0f, 1.1f); /// splinePoints.Add(0.3f, 0.4f); /// splinePoints.Add(1.0f, 2.0f); /// QuadraticSpline1D spline = new QuadraticSpline1D(splinePoints); /// </code> /// creates a quadratic spline that passes through three points: (0.0, 1.1), (0.3, 0.4) and (1.0, 2.0). /// </example> /// </summary> /// <param name="points">A list of points that is sorted by the x-coordinate. This collection is copied.</param> /// <exception cref="ArgumentException"> /// A spline must have at least two points to be properly defined. If <c>points</c> contains less than two /// points, the spline is undefined, so an <c>ArgumentException</c> is thrown. /// </exception> public QuadraticSpline1D(SortedList <double, double> points) { if (points.Count < 2) { if (points.Count == 1) { throw new ArgumentException("List contains only a single point. A spline must have at least two points.", nameof(points)); } else { throw new ArgumentException("List is empty. A spline must have at least two points.", nameof(points)); } } Points = new SortedPointsList <double>(points); // Calculate the coefficients of the spline: _parameters = new double[points.Count]; // Find the first segment parameter, which will be a straight line: { double dx = Points.Key[1] - Points.Key[0]; double dy = Points.Value[1] - Points.Value[0]; _parameters[0] = dy / dx; } // Recursively find the other _parameters: for (int i = 1; i < points.Count; i++) { double dx = Points.Key[i] - Points.Key[i - 1]; double dy = Points.Value[i] - Points.Value[i - 1]; _parameters[i] = -_parameters[i - 1] + 2.0f * dy / dx; } }
/// <summary> /// Construct a cubic spline using a set of input points. /// <example>For example: /// <code> /// SortedList<float, float> splinePoints = new SortedList<float, float>(); /// splinePoints.Add(0.0f, 1.1f); /// splinePoints.Add(0.3f, 0.4f); /// splinePoints.Add(1.0f, 2.0f); /// CubicSpline1D spline = new CubicSpline1D(splinePoints); /// </code> /// creates a cubic spline that passes through three points: (0.0, 1.1), (0.3, 0.4) and (1.0, 2.0). /// </example> /// </summary> /// <param name="points">A list of points that is sorted by the x-coordinate. This collection is copied.</param> /// <exception cref="ArgumentException"> /// A cubic spline must have at least two points to be properly defined. If <c>points</c> contains less than /// two points, the spline is undefined, so an <c>ArgumentException</c> is thrown. /// </exception> public CubicSpline1D(SortedList<float, float> points) { if (points.Count < 2) { if (points.Count == 1) { throw new ArgumentException("List contains only a single point. A spline must have at least two points.", "points"); } else { throw new ArgumentException("List is empty. A spline must have at least two points.", "points"); } } Points = new SortedPointsList<float>(points); // Calculate the coefficients of the spline: float[] a = new float[points.Count]; float[] b = new float[points.Count]; float[] c = new float[points.Count]; float[] d = new float[points.Count]; // Set up the boundary condition for a natural spline: { float x2 = 1.0f/(Points.Key[1] - Points.Key[0]); float y2 = Points.Value[1] - Points.Value[0]; a[0] = 0.0f; b[0] = 2.0f*x2; c[0] = x2; d[0] = 3.0f*(y2*x2*x2); } // Set up the tridiagonal matrix linear system: for (int i = 1; i < points.Count-1; i++) { float x1 = 1.0f/(Points.Key[i] - Points.Key[i-1]); float x2 = 1.0f/(Points.Key[i+1] - Points.Key[i]); float y1 = Points.Value[i] - Points.Value[i-1]; float y2 = Points.Value[i+1] - Points.Value[i]; a[i] = x1; b[i] = 2.0f*(x1 + x2); c[i] = x2; d[i] = 3.0f*(y1*x1*x1 + y2*x2*x2); } // Set up the boundary condition for a natural spline: { float x1 = 1.0f/(Points.Key[points.Count-1] - Points.Key[points.Count-2]); float y1 = (Points.Value[points.Count-1] - Points.Value[points.Count-2]); a[points.Count-1] = x1; b[points.Count-1] = 2.0f*x1; c[points.Count-1] = 0.0f; d[points.Count-1] = 3.0f*(y1*x1*x1); } // Solve the linear system using the Thomas algorithm: this.parameters = ThomasAlgorithm(a, b, c, d); }