/// <summary>
        /// Approximate a cubic Bezier curve with a spline of n quadratics.
        /// </summary>
        /// <param name="curve">The four vectors representing the control points of the cubic Bezier curve</param>
        /// <param name="maxError">Permitted deviation from the original curve</param>
        /// <param name="spline">A list of 2D tuples, representing control points of the quadratic
        /// spline if it fits within the given tolerance, or null if no
        /// suitable spline could be calculated</param>
        /// <returns>True if the curve could be converted, else false</returns>
        internal static bool CurveToQuadratic(CubicCurve curve, float maxError, out Complex[] spline)
        {
            spline = null;

            for (var n = 1; n < MaxN + 1; n++)
            {
                if (CubicApproximateSpline(curve, n, maxError, out spline))
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Approximate a cubic Bezier with a single quadratic within a given tolerance.
        /// </summary>
        /// <param name="controlPoints">Four complex numbers representing control points of the cubic Bezier curve.</param>
        /// <param name="maxError">Permitted deviation from the original curve.</param>
        /// <param name="quadraticCurve">Three complex numbers representing control points of the quadratic
        /// curve if it fits within the given tolerance, or null if no suitable
        /// curve could be calculated.</param>
        /// <returns>True if the curve could be converted, else false</returns>
        private static bool CubicApproximateQuadratic(CubicCurve controlPoints, float maxError, out QuadraticCurve quadraticCurve)
        {
            if (!TryCalculateIntersection(controlPoints.Point0, controlPoints.Point1, controlPoints.Point2, controlPoints.Point3, out var q1))
            {
                return(false);
            }

            var c0 = controlPoints.Point0;
            var c3 = controlPoints.Point3;
            var c1 = c0 + (q1 - c0) * TwoOverThree;
            var c2 = c3 + (q1 - c3) * TwoOverThree;

            if (CubicFarthestFitsInside(0, c1 - controlPoints.Point1, c2 - controlPoints.Point2, 0, maxError))
            {
                return(false);
            }

            quadraticCurve = new QuadraticCurve(c0, q1, c3);
            return(true);
        }
        // Cubic bezier curve
        public void Curve4(float x1, float y1, float x2, float y2, float x3, float y3)
        {
            var curve = new CubicCurve(
                new Complex(lastX, lastY),
                new Complex(x1, y1),
                new Complex(x2, y2),
                new Complex(x3, y3)
                );

            if (!CubicToQuadraticConverter.CurveToQuadratic(curve, 1, out var spline))
            {
                throw new Exception("Couldn't create a spline from the bezier curve");
            }

            for (var i = 0; i + 2 < spline.Length; i += 2)
            {
                var p1 = spline[i + 1];
                var p2 = spline[i + 2];
                Curve3((float)p1.Real, (float)p1.Imaginary, (float)p2.Real, (float)p2.Imaginary);
            }
        }
        /// <summary>
        /// Approximate a cubic Bezier curve with a spline of n quadratics.
        /// </summary>
        /// <param name="curve">The four complex numbers representing control points of the cubic Bezier curve.</param>
        /// <param name="n">Number of quadratic Bezier curves in the spline.</param>
        /// <param name="maxError">Permitted deviation from the original curve.</param>
        /// <param name="spline">A list of `n+2` complex numbers, representing control points of the
        /// quadratic spline if it fits within the given tolerance, or null if
        /// no suitable spline could be calculated.</param>
        /// <returns>True if the curve could be converted, else false</returns>
        private static bool CubicApproximateSpline(CubicCurve curve, int n, float maxError, out Complex[] spline)
        {
            spline = null;

            if (n == 1)
            {
                if (CubicApproximateQuadratic(curve, maxError, out var quadraticCurve))
                {
                    spline = new Complex[] { quadraticCurve.Point0, quadraticCurve.Point1, quadraticCurve.Point2 };
                    return(true);
                }
            }

            var cubics = SplitCubicIntoNIterations(curve.Point0, curve.Point1, curve.Point2, curve.Point3, n).ToArray();

            // Calculate the spline of quadratics and check errors at the same time
            var nextCurve = cubics[0];
            var nextQ1    = CubicApproximateControl(0, nextCurve.Point0, nextCurve.Point1, nextCurve.Point2, nextCurve.Point3);
            var q2        = curve.Point0;
            var d1        = Complex.Zero;

            var splineTemp = new List <Complex> {
                curve.Point0, nextQ1
            };

            for (var i = 1; i < n + 1; i++)
            {
                // Current cubic to convert
                var(_, c1, c2, c3) = nextCurve;

                // Current quadratic approximation of current cubic
                var q0 = q2;
                var q1 = nextQ1;

                if (i < n)
                {
                    nextCurve = cubics[i];
                    nextQ1    = CubicApproximateControl(i / (n - 1), nextCurve.Point0, nextCurve.Point1, nextCurve.Point2, nextCurve.Point3);
                    splineTemp.Add(nextQ1);
                    q2 = (q1 + nextQ1) * 0.5f;
                }
                else
                {
                    q2 = c3;
                }

                // End-point deltas
                var d0 = d1;
                d1 = q2 - c3;

                var f1 = q0 + (q1 - q0) * TwoOverThree - c1;
                var f2 = q2 + (q1 - q2) * TwoOverThree - c2;

                if (Complex.Abs(d1) > maxError || !CubicFarthestFitsInside(d0, f1, f2, d1, maxError))
                {
                    return(false);
                }
            }

            splineTemp.Add(curve.Point3);
            spline = splineTemp.ToArray();

            return(true);
        }