Esempio n. 1
0
        /// <summary>
        /// The closest point on the curve to the point p.
        /// </summary>
        public Vector2d Closest(Vector2d p)
        {
            double px = C0.x - p.x;
            double pz = C0.y - p.y;
            double ax = C1.x - C0.x;
            double az = C1.y - C0.y;
            double bx = C0.x - 2.0 * C1.x + C2.x;
            double bz = C0.y - 2.0 * C1.y + C2.y;

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

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

            double   min     = double.PositiveInfinity;
            Vector2d closest = new Vector2d(min, min);

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

                Vector2d v    = Position(t);
                double   dist = Vector2d.SqrDistance(v, p);
                if (dist < min)
                {
                    min     = dist;
                    closest = v;
                }
            }

            return(closest);
        }
Esempio n. 2
0
        /// <summary>
        /// The closest point on the curve to the point p.
        /// </summary>
        public Vector2f Closest(Vector2f 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;
            Vector2f closest = new Vector2f(min, min);

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

                Vector2f v    = Position(t);
                float    dist = Vector2f.SqrDistance(v, p);
                if (dist < min)
                {
                    min     = dist;
                    closest = v;
                }
            }

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

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

            //c coefficient for normal form of line
            double 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, Vector2d.Dot(n, c2), Vector2d.Dot(n, c1), Vector2d.Dot(n, C0) + c);

            Vector2d 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++)
            {
                double t = roots[i];
                if (t < 0.0 || t > 1.0)
                {
                    continue;
                }

                Vector2d 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);
        }