コード例 #1
0
        /// Uses 2D Newton's method using stereographic parametrization and fancy initial guess
        /// Pass:
        ///   abc - coefficients of the ellipse equation; aka the half-extents
        ///   p - point in ellipse coordinates
        public static Vector3 ClosestPointEllipsoid(
            Vector3 abc_, Vector3 p_, int numIters = 30, double threshold = 0)
        {
            // Doesn't like negative scales & result is the same by symmetry!
            vec3 abc = vec3.abs(new vec3(abc_));

            // WLOG move to the all-positive octant; move back to original octant when done.
            vec3 orig_p = new vec3(p_);
            vec3 p      = vec3.abs(orig_p);

            Stereo uv = Stereo.FromCartesian(InitialGuessClosestPointToEllipsoid(p, abc), abc);

            for (int i = 0; i < numIters; ++i)
            {
                Stereo prevUv = uv;
                uv = Iterate_Stereographic(uv, p, abc);
                if (Math.Abs(prevUv.x - uv.x) < threshold ||
                    Math.Abs(prevUv.y - uv.y) < threshold)
                {
                    break;
                }
            }

            // Move back to correct octant
            vec3 wrongOctant = uv.ToCartesian(abc);
            vec3 rightOctant = wrongOctant * orig_p.sign();

            return((Vector3)rightOctant);
        }