Esempio n. 1
0
        /*
         * Given two edges AB and CD such that robustCrossing() is true, return their
         * intersection point. Useful properties of getIntersection (GI):
         *
         * (1) GI(b,a,c,d) == GI(a,b,d,c) == GI(a,b,c,d) (2) GI(c,d,a,b) ==
         * GI(a,b,c,d)
         *
         * The returned intersection point X is guaranteed to be close to the edges AB
         * and CD, but if the edges intersect at a very small angle then X may not be
         * close to the true mathematical intersection point P. See the description of
         * "DEFAULT_INTERSECTION_TOLERANCE" below for details.
         */

        public static S2Point GetIntersection(S2Point a0, S2Point a1, S2Point b0, S2Point b1)
        {
            Preconditions.CheckArgument(RobustCrossing(a0, a1, b0, b1) > 0,
                                        "Input edges a0a1 and b0b1 muct have a true robustCrossing.");

            // We use robustCrossProd() to get accurate results even when two endpoints
            // are close together, or when the two line segments are nearly parallel.
            var aNorm = S2Point.Normalize(S2.RobustCrossProd(a0, a1));
            var bNorm = S2Point.Normalize(S2.RobustCrossProd(b0, b1));
            var x     = S2Point.Normalize(S2.RobustCrossProd(aNorm, bNorm));

            // Make sure the intersection point is on the correct side of the sphere.
            // Since all vertices are unit length, and edges are less than 180 degrees,
            // (a0 + a1) and (b0 + b1) both have positive dot product with the
            // intersection point. We use the sum of all vertices to make sure that the
            // result is unchanged when the edges are reversed or exchanged.
            if (x.DotProd(a0 + a1 + b0 + b1) < 0)
            {
                x = -x;
            }

            // The calculation above is sufficient to ensure that "x" is within
            // DEFAULT_INTERSECTION_TOLERANCE of the great circles through (a0,a1) and
            // (b0,b1).
            // However, if these two great circles are very close to parallel, it is
            // possible that "x" does not lie between the endpoints of the given line
            // segments. In other words, "x" might be on the great circle through
            // (a0,a1) but outside the range covered by (a0,a1). In this case we do
            // additional clipping to ensure that it does.

            if (S2.OrderedCcw(a0, x, a1, aNorm) && S2.OrderedCcw(b0, x, b1, bNorm))
            {
                return(x);
            }

            // Find the acceptable endpoint closest to x and return it. An endpoint is
            // acceptable if it lies between the endpoints of the other line segment.
            var r = new CloserResult(10, x);

            if (S2.OrderedCcw(b0, a0, b1, bNorm))
            {
                r.ReplaceIfCloser(x, a0);
            }
            if (S2.OrderedCcw(b0, a1, b1, bNorm))
            {
                r.ReplaceIfCloser(x, a1);
            }
            if (S2.OrderedCcw(a0, b0, a1, aNorm))
            {
                r.ReplaceIfCloser(x, b0);
            }
            if (S2.OrderedCcw(a0, b1, a1, aNorm))
            {
                r.ReplaceIfCloser(x, b1);
            }
            return(r.Vmin);
        }
        /*
   * Given two edges AB and CD such that robustCrossing() is true, return their
   * intersection point. Useful properties of getIntersection (GI):
   *
   * (1) GI(b,a,c,d) == GI(a,b,d,c) == GI(a,b,c,d) (2) GI(c,d,a,b) ==
   * GI(a,b,c,d)
   *
   * The returned intersection point X is guaranteed to be close to the edges AB
   * and CD, but if the edges intersect at a very small angle then X may not be
   * close to the true mathematical intersection point P. See the description of
   * "DEFAULT_INTERSECTION_TOLERANCE" below for details.
   */

        public static S2Point GetIntersection(S2Point a0, S2Point a1, S2Point b0, S2Point b1)
        {
            Preconditions.CheckArgument(RobustCrossing(a0, a1, b0, b1) > 0,
                                        "Input edges a0a1 and b0b1 muct have a true robustCrossing.");

            // We use robustCrossProd() to get accurate results even when two endpoints
            // are close together, or when the two line segments are nearly parallel.
            var aNorm = S2Point.Normalize(S2.RobustCrossProd(a0, a1));
            var bNorm = S2Point.Normalize(S2.RobustCrossProd(b0, b1));
            var x = S2Point.Normalize(S2.RobustCrossProd(aNorm, bNorm));

            // Make sure the intersection point is on the correct side of the sphere.
            // Since all vertices are unit length, and edges are less than 180 degrees,
            // (a0 + a1) and (b0 + b1) both have positive dot product with the
            // intersection point. We use the sum of all vertices to make sure that the
            // result is unchanged when the edges are reversed or exchanged.
            if (x.DotProd(a0 + a1 + b0 + b1) < 0)
            {
                x = -x;
            }

            // The calculation above is sufficient to ensure that "x" is within
            // DEFAULT_INTERSECTION_TOLERANCE of the great circles through (a0,a1) and
            // (b0,b1).
            // However, if these two great circles are very close to parallel, it is
            // possible that "x" does not lie between the endpoints of the given line
            // segments. In other words, "x" might be on the great circle through
            // (a0,a1) but outside the range covered by (a0,a1). In this case we do
            // additional clipping to ensure that it does.

            if (S2.OrderedCcw(a0, x, a1, aNorm) && S2.OrderedCcw(b0, x, b1, bNorm))
            {
                return x;
            }

            // Find the acceptable endpoint closest to x and return it. An endpoint is
            // acceptable if it lies between the endpoints of the other line segment.
            var r = new CloserResult(10, x);
            if (S2.OrderedCcw(b0, a0, b1, bNorm))
            {
                r.ReplaceIfCloser(x, a0);
            }
            if (S2.OrderedCcw(b0, a1, b1, bNorm))
            {
                r.ReplaceIfCloser(x, a1);
            }
            if (S2.OrderedCcw(a0, b0, a1, aNorm))
            {
                r.ReplaceIfCloser(x, b0);
            }
            if (S2.OrderedCcw(a0, b1, a1, aNorm))
            {
                r.ReplaceIfCloser(x, b1);
            }
            return r.Vmin;
        }