Example #1
0
        /**
         * A slightly more efficient version of getDistance() where the cross product
         * of the two endpoints has been precomputed. The cross product does not need
         * to be normalized, but should be computed using S2.robustCrossProd() for the
         * most accurate results.
         */

        public static S1Angle GetDistance(S2Point x, S2Point a, S2Point b, S2Point aCrossB)
        {
            Preconditions.CheckArgument(S2.IsUnitLength(x));
            Preconditions.CheckArgument(S2.IsUnitLength(a));
            Preconditions.CheckArgument(S2.IsUnitLength(b));

            // There are three cases. If X is located in the spherical wedge defined by
            // A, B, and the axis A x B, then the closest point is on the segment AB.
            // Otherwise the closest point is either A or B; the dividing line between
            // these two cases is the great circle passing through (A x B) and the
            // midpoint of AB.

            if (S2.SimpleCcw(aCrossB, a, x) && S2.SimpleCcw(x, b, aCrossB))
            {
                // The closest point to X lies on the segment AB. We compute the distance
                // to the corresponding great circle. The result is accurate for small
                // distances but not necessarily for large distances (approaching Pi/2).

                var sinDist = Math.Abs(x.DotProd(aCrossB)) / aCrossB.Norm;
                return(S1Angle.FromRadians(Math.Asin(Math.Min(1.0, sinDist))));
            }

            // Otherwise, the closest point is either A or B. The cheapest method is
            // just to compute the minimum of the two linear (as opposed to spherical)
            // distances and convert the result to an angle. Again, this method is
            // accurate for small but not large distances (approaching Pi).

            var linearDist2 = Math.Min((x - a).Norm2, (x - b).Norm2);

            return(S1Angle.FromRadians(2 * Math.Asin(Math.Min(1.0, 0.5 * Math.Sqrt(linearDist2)))));
        }
Example #2
0
        /**
         * Returns the point on edge AB closest to X. x, a and b must be of unit
         * length. Throws IllegalArgumentException if this is not the case.
         *
         */

        public static S2Point GetClosestPoint(S2Point x, S2Point a, S2Point b)
        {
            Preconditions.CheckArgument(S2.IsUnitLength(x));
            Preconditions.CheckArgument(S2.IsUnitLength(a));
            Preconditions.CheckArgument(S2.IsUnitLength(b));

            var crossProd = S2.RobustCrossProd(a, b);
            // Find the closest point to X along the great circle through AB.
            var p = x - (crossProd * x.DotProd(crossProd) / crossProd.Norm2);

            // If p is on the edge AB, then it's the closest point.
            if (S2.SimpleCcw(crossProd, a, p) && S2.SimpleCcw(p, b, crossProd))
            {
                return(S2Point.Normalize(p));
            }
            // Otherwise, the closest point is either A or B.
            return((x - a).Norm2 <= (x - b).Norm2 ? a : b);
        }