Пример #1
0
        /**
         * Return the center of the rectangle in latitude-longitude space (in general
         * this is not the center of the region on the sphere).
         */

        /**
         * Return the minimum distance (measured along the surface of the sphere)
         * from a given point to the rectangle (both its boundary and its interior).
         * The latLng must be valid.
         */

        public S1Angle GetDistance(S2LatLng p)
        {
            // The algorithm here is the same as in getDistance(S2LagLngRect), only
            // with simplified calculations.
            var a = this;

            Preconditions.CheckState(!a.IsEmpty);
            Preconditions.CheckArgument(p.IsValid);

            if (a.Lng.Contains(p.Lng.Radians))
            {
                return(S1Angle.FromRadians(Math.Max(0.0, Math.Max(p.Lat.Radians - a.Lat.Hi,
                                                                  a.Lat.Lo - p.Lat.Radians))));
            }

            var interval = new S1Interval(a.Lng.Hi, a.Lng.Complement.Center);
            var aLng     = a.Lng.Lo;

            if (interval.Contains(p.Lng.Radians))
            {
                aLng = a.Lng.Hi;
            }

            var lo        = S2LatLng.FromRadians(a.Lat.Lo, aLng).ToPoint();
            var hi        = S2LatLng.FromRadians(a.Lat.Hi, aLng).ToPoint();
            var loCrossHi =
                S2LatLng.FromRadians(0, aLng - S2.PiOver2).Normalized.ToPoint();

            return(S2EdgeUtil.GetDistance(p.ToPoint(), lo, hi, loCrossHi));
        }
Пример #2
0
        /**
         * Return true if the edge AB intersects the given edge of constant latitude.
         */

        private static bool IntersectsLatEdge(S2Point a, S2Point b, double lat,
                                              S1Interval lng)
        {
            // Return true if the segment AB intersects the given edge of constant
            // latitude. Unfortunately, lines of constant latitude are curves on
            // the sphere. They can intersect a straight edge in 0, 1, or 2 points.
            // assert (S2.isUnitLength(a) && S2.isUnitLength(b));

            // First, compute the normal to the plane AB that points vaguely north.
            var z = S2Point.Normalize(S2.RobustCrossProd(a, b));

            if (z.Z < 0)
            {
                z = -z;
            }

            // Extend this to an orthonormal frame (x,y,z) where x is the direction
            // where the great circle through AB achieves its maximium latitude.
            var y = S2Point.Normalize(S2.RobustCrossProd(z, new S2Point(0, 0, 1)));
            var x = S2Point.CrossProd(y, z);
            // assert (S2.isUnitLength(x) && x.z >= 0);

            // Compute the angle "theta" from the x-axis (in the x-y plane defined
            // above) where the great circle intersects the given line of latitude.
            var sinLat = Math.Sin(lat);

            if (Math.Abs(sinLat) >= x.Z)
            {
                return(false); // The great circle does not reach the given latitude.
            }
            // assert (x.z > 0);
            var cosTheta = sinLat / x.Z;
            var sinTheta = Math.Sqrt(1 - cosTheta * cosTheta);
            var theta    = Math.Atan2(sinTheta, cosTheta);

            // The candidate intersection points are located +/- theta in the x-y
            // plane. For an intersection to be valid, we need to check that the
            // intersection point is contained in the interior of the edge AB and
            // also that it is contained within the given longitude interval "lng".

            // Compute the range of theta values spanned by the edge AB.
            var abTheta = S1Interval.FromPointPair(Math.Atan2(
                                                       a.DotProd(y), a.DotProd(x)), Math.Atan2(b.DotProd(y), b.DotProd(x)));

            if (abTheta.Contains(theta))
            {
                // Check if the intersection point is also in the given "lng" interval.
                var isect = (x * cosTheta) + (y * sinTheta);
                if (lng.Contains(Math.Atan2(isect.Y, isect.X)))
                {
                    return(true);
                }
            }
            if (abTheta.Contains(-theta))
            {
                // Check if the intersection point is also in the given "lng" interval.
                var intersection = (x * cosTheta) - (y * sinTheta);
                if (lng.Contains(Math.Atan2(intersection.Y, intersection.X)))
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #3
0
        /**
         * Return the width and height of this rectangle in latitude-longitude space.
         * Empty rectangles have a negative width and height.
         */

        /**
         * More efficient version of Contains() that accepts a S2LatLng rather than an
         * S2Point.
         */

        public bool Contains(S2LatLng ll)
        {
            // assert (ll.isValid());
            return(_lat.Contains(ll.Lat.Radians) && _lng.Contains(ll.Lng.Radians));
        }