private LinearInterpolationSurface(double[] values, IPlotFunction[] functions, LinearInterpolationSurfaceProjection projection) { int n = values.Length; if (functions.Length != n) { throw new ArgumentException(); } List<Tuple<double, IPlotFunction>> pairs = new List<Tuple<double, IPlotFunction>>(); for (int i = 0; i < n; i++) { pairs.Add(Tuple.Create<double, IPlotFunction>(values[i], functions[i])); } pairs.Sort((p1, p2) => p1.Item1.CompareTo(p2.Item1)); for (int i = 0; i < n; i++) { values[i] = pairs[i].Item1; functions[i] = pairs[i].Item2; } Count = n; Values = new ImmutableList<double>(values); Functions = new ImmutableList<IPlotFunction>(functions); Projection = projection; }
public LinearInterpolationSurface Add(double value, IPlotFunction function) { return new LinearInterpolationSurface(Values.Concat(new double[] { value }), Functions.Concat(new IPlotFunction[] { function }), Projection); }
public IEnumerable<double> CreatePoints(IPlotFunction function) { return points; }
public IEnumerable<double> CreatePoints(IPlotFunction function) { return generator.CreatePoints(function); }
public IEnumerable<double> CreatePoints(IPlotFunction function) { if (function == null) { throw new ArgumentNullException(); } List<double> points = new List<double>(FunctionPlotSegment.CreatePoints(a, b, n)); List<double> values = new List<double>(); foreach (double x in points) { values.Add(function.Value(x)); } List<double> points2 = new List<double>(); // Always keep the left-most point. points2.Add(a); //yield return a; int i0 = 0; while (i0 < n - 1) { // Find the largest span of points such that deviations in the y-direction between the linear interpolation // and the true function values of intermediate points are no more than the tolerance. // Currently using this left end-point. double xl = points[i0]; double yl = values[i0]; // Perform at least one step. int i = i0 + 1; while (i < n - 1) { // Test with this right end-point one more step ahead. double xr = points[i + 1]; double yr = values[i + 1]; // And then recheck all points in the range between these points. bool stop = false; for (int j = i0 + 1; j < i + 1; j++) { double x = points[j]; // The true value. double y0 = values[j]; // The interpolated value. double lambda = (xr - x) / (xr - xl); double y = (1.0 - lambda) * yr + lambda * yl; if (Math.Abs(y - y0) > tolerance || double.IsNaN(y) || double.IsNaN(y0)) { // Deviation too large. Stop the expansion of the range. stop = true; break; } } if (stop) { break; } // We've confirmed that the range can be expanded by one more point. i++; } points2.Add(points[i]); //yield return points[i]; // Use this point as the next left end-point. i0 = i; } return points2; }
public FunctionPlot(IPlotFunction function, params FunctionPlotSegment[] segments) : this(function, (IEnumerable<FunctionPlotSegment>)segments) { }
public FunctionPlot(IPlotFunction function, IEnumerable<FunctionPlotSegment> segments, params IFunctionPlotStyle[] styles) { Function = function; Segments = new ImmutableList<FunctionPlotSegment>(segments); Properties = new PlotProperties(styles); }
public FunctionPlot(IPlotFunction function, double[] points, params IFunctionPlotStyle[] styles) : this(function, new FunctionPlotSegment[] { new FunctionPlotSegment(points) }, styles) { }
public FunctionPlot(IPlotFunction function, double a, double b, int n, double tolerance, params IFunctionPlotStyle[] styles) : this(function, new FunctionPlotSegment[] { new FunctionPlotSegment(a, b, n, tolerance) }, styles) { }
public FunctionPlot(IPlotFunction function, double a, double b, params IFunctionPlotStyle[] styles) : this(function, a, b, 1000, styles) { }
public SmoothFunctionPlot(IPlotFunction function, double a, double b, int n, params IFunctionPlotStyle[] styles) : this(function, new FunctionPlotSegment[] { new FunctionPlotSegment(a, b, n) }, styles) { }
public static PlotFunction Create(IPlotFunction f) { return Create(x => f.Value(x)); }