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;
            }
Ejemplo n.º 2
0
 public static PlotFunction Create(IPlotFunction f)
 {
     return Create(x => f.Value(x));
 }