Ejemplo n.º 1
0
        public override Point ValueAtX(double x, out bool interpolated, out bool extrapolated)
        {
            interpolated = false;
            extrapolated = false;

            if (d_bezier == null)
            {
                extrapolated = true;
                return(new Point(0, 0));
            }

            Range xrange = d_polynomial.XRange;

            if (x < xrange.Min)
            {
                extrapolated = true;
                return(new Point(xrange.Min, d_polynomial[0].Begin));
            }
            else if (x > xrange.Max)
            {
                extrapolated = true;
                return(new Point(xrange.Max, d_polynomial[d_polynomial.Count - 1].End));
            }

            if (d_periodic != null && (x < d_periodic.Min || x > d_periodic.Max))
            {
                extrapolated = true;
            }

            // Do the interpolation
            PiecewisePolynomial.Piece piece = d_polynomial.PieceAt(x);

            if (x != piece.Begin || x != piece.End)
            {
                interpolated = true;
            }

            return(new Point(x, piece.Evaluate(x)));
        }
Ejemplo n.º 2
0
        public override PiecewisePolynomial InterpolateSorted(List <Point> points)
        {
            // Remove points that are very close together
            Point[] r = points.ToArray();

            for (int i = 1; i < r.Length; ++i)
            {
                if (System.Math.Abs(r[i - 1].X - r[i].X) < Constants.Epsilon)
                {
                    points.Remove(r[i - 1]);
                }
            }

            int size = points.Count;

            if (size < 2)
            {
                return(new PiecewisePolynomial());
            }

            double[] slopes = new double[size];
            double[] dpdt   = new double[size];
            double[] dt     = new double[size - 1];

            for (int i = 0; i < size - 1; ++i)
            {
                double dp = (points[i + 1].Y - points[i].Y);
                dt[i] = (points[i + 1].X - points[i].X);

                dpdt[i] = dt[i] == 0 ? 0 : (dp / dt[i]);
            }

            dpdt[size - 1] = 0;

            bool[] samesign = new bool[size - 1];

            for (int i = 0; i < size - 2; ++i)
            {
                samesign[i] = (System.Math.Sign(dpdt[i]) == System.Math.Sign(dpdt[i + 1]) && dpdt[i] != 0);
            }

            // Three point derivative
            for (int i = 0; i < size - 2; ++i)
            {
                double dpdt1 = dpdt[i];
                double dpdt2 = dpdt[i + 1];

                if (samesign[i])
                {
                    double hs = dt[i] + dt[i + 1];

                    double w1 = (dt[i] + hs) / (3 * hs);
                    double w2 = (hs + dt[i + 1]) / (3 * hs);

                    double mindpdt;
                    double maxdpdt;

                    if (dpdt1 > dpdt2)
                    {
                        maxdpdt = dpdt1;
                        mindpdt = dpdt2;
                    }
                    else
                    {
                        maxdpdt = dpdt2;
                        mindpdt = dpdt1;
                    }

                    slopes[i + 1] = mindpdt / (w1 * (dpdt[i] / maxdpdt) + w2 * (dpdt[i + 1] / maxdpdt));
                }
                else
                {
                    slopes[i + 1] = 0;
                }
            }

            if (size > 2)
            {
                slopes[0] = ((2 * dt[0] + dt[1]) * dpdt[0] - dt[0] * dpdt[1]) / (dt[0] + dt[1]);
            }

            if (System.Math.Sign(slopes[0]) != System.Math.Sign(dpdt[0]))
            {
                slopes[0] = 0;
            }
            else if (System.Math.Sign(dpdt[0]) != System.Math.Sign(dpdt[1]) &&
                     System.Math.Abs(slopes[0]) > System.Math.Abs(3 * dpdt[0]))
            {
                slopes[0] = 3 * dpdt[0];
            }

            if (size > 2)
            {
                slopes[size - 1] = ((2 * dt[size - 2] + dt[size - 3]) * dpdt[size - 2] -
                                    dt[size - 2] * dpdt[size - 3]) /
                                   (dt[size - 2] + dt[size - 3]);
            }

            if (System.Math.Sign(slopes[size - 1]) != System.Math.Sign(dpdt[size - 2]))
            {
                slopes[size - 1] = 0;
            }
            else if (System.Math.Sign(dpdt[size - 2]) != System.Math.Sign(dpdt[size - 3]) &&
                     System.Math.Abs(slopes[size - 1]) > System.Math.Abs(3 * dpdt[size - 2]))
            {
                slopes[size - 1] = 3 * dpdt[size - 2];
            }

            PiecewisePolynomial.Piece[] pieces = new PiecewisePolynomial.Piece[size - 1];

            for (int i = 0; i < size - 1; ++i)
            {
                double h = points[i + 1].X - points[i].X;

                Point  p0 = points[i];
                Point  p1 = points[i + 1];
                double m0 = slopes[i] * h;
                double m1 = slopes[i + 1] * h;

                // O3: 2 * (c1.p - c2.p) + h * (c1.m + c2.m)
                // O2: 3 * (c2.p - c1.p) - h * (2 * c1.m + c2.m)
                // O1: h * c1.m
                // O0: c1.p
                double[] coefficients = new double[] {
                    2 * (p0.Y - p1.Y) + m0 + m1,
                    3 * (p1.Y - p0.Y) - 2 * m0 - m1,
                    m0,
                    p0.Y
                };

                pieces[i] = new PiecewisePolynomial.Piece(new Range(p0.X, p1.X), coefficients);
            }

            return(new PiecewisePolynomial(pieces));
        }