/// <summary>
        /// The closest point on the curve to the point p.
        /// </summary>
        public Vector2 Closest(Vector2 p)
        {
            float px = C0.x - p.x;
            float pz = C0.y - p.y;
            float ax = C1.x - C0.x;
            float az = C1.y - C0.y;
            float bx = C0.x - 2.0f * C1.x + C2.x;
            float bz = C0.y - 2.0f * C1.y + C2.y;

            float a = bx * bx + bz * bz;
            float b = 3 * (ax * bx + az * bz);
            float c = 2 * (ax * ax + az * az) + px * bx + pz * bz;
            float d = px * ax + pz * az;

            var roots = Polynomial3d.Solve(a, b, c, d);

            float   min     = float.PositiveInfinity;
            Vector2 closest = new Vector2(min, min);

            for (int i = 0; i < roots.real; i++)
            {
                float t = (float)roots[i];

                Vector2 v    = Position(t);
                float   dist = (v - p).sqrMagnitude;
                if (dist < min)
                {
                    min     = dist;
                    closest = v;
                }
            }

            return(closest);
        }
        /// <summary>
        /// If the segment ab intersects the curve.
        /// </summary>
        public bool Intersects(Vector2 a, Vector2 b)
        {
            //coefficients of quadratic
            Vector2 c2 = C0 + C1 * -2.0f + C2;
            Vector2 c1 = C0 * -2.0f + C1 * 2.0f;

            //Convert line to normal form: ax + by + c = 0
            //Find normal to line: negative inverse of original line's slope
            Vector2 n = new Vector2(a.y - b.y, b.x - a.x);

            //c coefficient for normal form of line
            float c = a.x * b.y - b.x * a.y;

            //Transform coefficients to line's coordinate system and find roots of cubic
            var roots = Polynomial3d.Solve(1, Vector2.Dot(n, c2), Vector2.Dot(n, c1), Vector2.Dot(n, C0) + c);

            Vector2 min, max;

            min.x = Math.Min(a.x, b.x);
            min.y = Math.Min(a.y, b.y);

            max.x = Math.Max(a.x, b.x);
            max.y = Math.Max(a.y, b.y);

            for (int i = 0; i < roots.real; i++)
            {
                float t = (float)roots[i];
                if (t < 0.0f || t > 1.0f)
                {
                    continue;
                }

                Vector2 v0 = Position(t);

                if (a.x == b.x)
                {
                    if (min.y <= v0.y && v0.y <= max.y)
                    {
                        return(true);
                    }
                }
                else if (a.y == b.y)
                {
                    if (min.x <= v0.x && v0.x <= max.x)
                    {
                        return(true);
                    }
                }
                else if (min.x <= v0.x && v0.x <= max.x && min.y <= v0.y && v0.y <= max.y)
                {
                    return(true);
                }
            }

            return(false);
        }