示例#1
0
        /// <summary>
        ///     Solves the equation \f$a0 + a1 x + a2 x^2 + a3 x^3 + a4 x^4 = 0\f$, returning all real values of
        ///		\f$x\f$ for which the equation is true. See https://en.wikipedia.org/wiki/Quartic_function for the
        ///		algorithm used.
        /// </summary>
        public static IEnumerable <double> Solve(double a0, double a1, double a2, double a3, double a4)
        {
            DebugUtil.AssertAllFinite(new double[] { a0, a1, a2, a3, a4 }, "a");
            if (Math.Abs(a4) <= 0.005)
            {
                foreach (double v in CubicFunction.Solve(a0, a1, a2, a3))
                {
                    QuarticFunction f = new QuarticFunction(a0, a1, a2, a3, a4);
                    yield return(f.NewtonRaphson(v));
                }
                yield break;
            }

            double ba = a3 / a4;
            double ca = a2 / a4;
            double da = a1 / a4;
            // double ea = a0/a4;

            double p1 = a2 * a2 * a2 - 4.5 * a3 * a2 * a1 + 13.5 * a4 * a1 * a1 + 13.5 * a3 * a3 * a0 - 36.0 * a4 * a2 * a0;

            double q = a2 * a2 - 3.0 * a3 * a1 + 12.0 * a4 * a0;

            Complex p2 = p1 + Complex.Sqrt(-q * q * q + p1 * p1);

            Complex pow = Complex.Pow(p2, (1.0 / 3.0));

            Complex p3 = q / (3.0 * a4 * pow) + pow / (3.0 * a4);

            Complex p4 = Complex.Sqrt(ba * ba / 4.0 - 2.0 * ca / (3.0) + p3);

            Complex p5 = a3 * a3 / (2.0 * a4 * a4) - 4.0 * a2 / (3.0 * a4) - p3;

            Complex p6 = (-ba * ba * ba + 4.0 * ba * ca - 8.0 * da) / (4.0 * p4);

            List <Complex> roots = new List <Complex>
            {
                -ba / (4.0) - p4 / 2.0 - 0.5 * Complex.Sqrt(p5 - p6),
                -ba / (4.0) - p4 / 2.0 + 0.5 * Complex.Sqrt(p5 - p6),
                -ba / (4.0) + p4 / 2.0 - 0.5 * Complex.Sqrt(p5 + p6),
                -ba / (4.0) + p4 / 2.0 + 0.5 * Complex.Sqrt(p5 + p6),
            };

            foreach (Complex root in roots)
            {
                if (Math.Abs(root.Imaginary) <= 0.005)
                {
                    DebugUtil.AssertFinite(root.Real, nameof(root.Real));
                    yield return(root.Real);
                }
            }
        }
示例#2
0
        /// <summary>
        ///     Solves the equation \f$(q(x))^2 = b_0 + b_1 x + b_2 x^2 + b_3 x^3 + b_4 x^4\f$, returning all values of
        ///		\f$x\f$ for which the equation is true. \f$q(x)\f$ is the quadratic spline. The _parameters z0 and c
        ///		can be used to substitute x, such that \f$x = z0 + c t\f$. This is useful for raytracing.
        /// </summary>
        public override IEnumerable <double> SolveRaytrace(QuarticFunction surfaceFunction, double z0 = 0.0, double c = 1.0)
        {
            // Solve the polynomial equation for each segment:
            for (int i = 1; i < Points.Count; i++)
            {
                double x1 = Points.Key[i - 1];
                double x2 = Points.Key[i];
                double y1 = Points.Value[i - 1];
                double y2 = Points.Value[i];

                // Calculate and return the interpolated value:
                double dx  = x2 - x1;
                double div = 1.0 / dx;
                double dy  = y2 - y1;

                double a = -_parameters[i] * dx + dy;

                // Write in the form of a0 + a1 z + a2 z^2:
                double a0 = -a * x1 * x1 * div * div - (a + dy) * x1 * div + y1;
                double a1 = 2.0 * a * x1 * div * div + (a + dy) * div;
                double a2 = -a * div * div;

                // Substitute z = z0 + c t:
                double A0 = a0 + a1 * z0 + a2 * z0 * z0;
                double A1 = (a1 + 2.0 * a2 * z0) * c;
                double A2 = a2 * c * c;

                // Find the quartic polynomial to solve:
                double p0 = surfaceFunction.a0 - A0 * A0;
                double p1 = surfaceFunction.a1 - 2.0 * A0 * A1;
                double p2 = surfaceFunction.a2 - (2.0 * A0 * A2 + A1 * A1);
                double p3 = surfaceFunction.a3 - 2.0 * A1 * A2;
                double p4 = surfaceFunction.a4 - A2 * A2;

                // Solve the quartic polynomial:
                IEnumerable <double> intersections = QuarticFunction.Solve(p0, p1, p2, p3, p4);

                // Only return the value if it is sampled within the segment that we are currently considering,
                // otherwise the value we got is invalid:
                foreach (var j in intersections)
                {
                    if (((z0 + c * j) > x1) && ((z0 + c * j) <= x2))
                    {
                        yield return(j);
                    }
                }
            }
        }
        /// <summary>
        ///     Solves the equation \f$(q(x))^2 = b_0 + b_1 x + b_2 x^2 + b_3 x^3 + b_4 x^4\f$, returning all values of
        ///		\f$x\f$ for which the equation is true. \f$q(x)\f$ is the quadratic spline. The parameters z0 and c
        ///		can be used to substitute x, such that \f$x = z0 + c t\f$. This is useful for raytracing.
        /// </summary>
        public override IEnumerable <float> SolveRaytrace(QuarticFunction surfaceFunction, float z0 = 0.0f, float c = 1.0f)
        {
            // Solve the polynomial equation for each segment:
            for (int i = 1; i < Points.Count; i++)
            {
                Real x1 = Points.Key[i - 1];
                Real x2 = Points.Key[i];
                Real y1 = Points.Value[i - 1];
                Real y2 = Points.Value[i];

                // Calculate and return the interpolated value:
                Real dx  = x2 - x1;
                Real div = 1.0 / dx;
                Real dy  = y2 - y1;

                Real a = -parameters[i] * dx + dy;

                // Write in the form of a0 + a1 z + a2 z^2:
                Real a0 = -a * x1 * x1 * div * div - (a + dy) * x1 * div + y1;
                Real a1 = 2.0 * a * x1 * div * div + (a + dy) * div;
                Real a2 = -a * div * div;

                // Substitute z = z0 + c t:
                Real A0 = a0 + a1 * z0 + a2 * z0 * z0;
                Real A1 = (a1 + 2.0 * a2 * z0) * c;
                Real A2 = a2 * c * c;

                // Find the quartic polynomial to solve:
                Real p0 = surfaceFunction.a0 - A0 * A0;
                Real p1 = surfaceFunction.a1 - 2.0 * A0 * A1;
                Real p2 = surfaceFunction.a2 - (2.0 * A0 * A2 + A1 * A1);
                Real p3 = surfaceFunction.a3 - 2.0 * A1 * A2;
                Real p4 = surfaceFunction.a4 - A2 * A2;

                // Solve the quartic polynomial:
                IEnumerable <float> intersections = QuarticFunction.Solve((float)p0, (float)p1, (float)p2, (float)p3, (float)p4);

                // Only return the value if it is sampled within the segment that we are currently considering,
                // otherwise the value we got is invalid:
                foreach (var j in intersections)
                {
                    if (((z0 + c * j) > x1) && ((z0 + c * j) <= x2))
                    {
                        yield return(j);
                    }
                }
            }
        }
示例#4
0
 public IEnumerable <double> Roots()
 {
     return(QuarticFunction.Solve(A0, A1, A2, A3, A4));
 }
 /// <summary>
 /// Solves the equation \f$(q(x))^2 = b_0 + b_1 x + b_2 x^2 + b_3 x^3 + b_4 x^4\f$, returning all values of
 ///	\f$x\f$ for which the equation is true. \f$q(x)\f$ is the continuous map. The parameters z0 and c
 ///	can be used to substitute x, such that \f$x = z0 + c t\f$. This is useful for raytracing.
 /// </summary>
 public abstract IEnumerable <float> SolveRaytrace(QuarticFunction surfaceFunction, float z0 = 0.0f, float c = 1.0f);
示例#6
0
 public IEnumerable <double> Roots()
 {
     return(QuarticFunction.Solve(a0, a1, a2, a3, a4));
 }
示例#7
0
 /// <summary>
 ///     Solves the equation \f$(q(x))^2 = b_0 + b_1 x + b_2 x^2 + b_3 x^3 + b_4 x^4\f$, returning all values of
 ///		\f$x\f$ for which the equation is true. \f$q(x)\f$ is the linear spline. The _parameters z0 and c
 ///		can be used to substitute x, such that \f$x = z0 + c t\f$. This is useful for raytracing.
 /// </summary>
 public override IEnumerable <double> SolveRaytrace(QuarticFunction surfaceFunction, double z0 = 0.0, double c = 1.0)
 {
     throw new NotImplementedException();
     return(null);
 }
示例#8
0
 /// <summary>
 /// Solves the equation \f$(q(x))^2 = b_0 + b_1 x + b_2 x^2 + b_3 x^3 + b_4 x^4\f$, returning all values of
 ///	\f$x\f$ for which the equation is true. \f$q(x)\f$ is the continuous map. The parameters z0 and c
 ///	can be used to substitute x, such that \f$x = z0 + c t\f$. This is useful for raytracing.
 /// </summary>
 public abstract IEnumerable <double> SolveRaytrace(QuarticFunction surfaceFunction, double z0 = 0.0, double c = 1.0);