Exemple #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));
        }
Exemple #2
0
        /**
         * Return true if the edge AB intersects the given edge of constant longitude.
         */

        private static bool IntersectsLngEdge(S2Point a, S2Point b,
                                              R1Interval lat, double lng)
        {
            // Return true if the segment AB intersects the given edge of constant
            // longitude. The nice thing about edges of constant longitude is that
            // they are straight lines on the sphere (geodesics).

            return(S2.SimpleCrossing(a, b, S2LatLng.FromRadians(lat.Lo, lng)
                                     .ToPoint(), S2LatLng.FromRadians(lat.Hi, lng).ToPoint()));
        }
Exemple #3
0
        /**
         * Return true if the rectangle is valid, which essentially just means that
         * the latitude bounds do not exceed Pi/2 in absolute value and the longitude
         * bounds do not exceed Pi in absolute value.
         *
         */

        /** Return the k-th vertex of the rectangle (k = 0,1,2,3) in CCW order. */

        public S2LatLng GetVertex(int k)
        {
            // Return the points in CCW order (SW, SE, NE, NW).
            switch (k)
            {
            case 0:
                return(S2LatLng.FromRadians(_lat.Lo, _lng.Lo));

            case 1:
                return(S2LatLng.FromRadians(_lat.Lo, _lng.Hi));

            case 2:
                return(S2LatLng.FromRadians(_lat.Hi, _lng.Hi));

            case 3:
                return(S2LatLng.FromRadians(_lat.Hi, _lng.Lo));

            default:
                throw new ArgumentException("Invalid vertex index.");
            }
        }
Exemple #4
0
        /**
         * Return the minimum distance (measured along the surface of the sphere) to
         * the given S2LatLngRect. Both S2LatLngRects must be non-empty.
         */

        public S1Angle GetDistance(S2LatLngRect other)
        {
            var a = this;
            var b = other;

            Preconditions.CheckState(!a.IsEmpty);
            Preconditions.CheckArgument(!b.IsEmpty);

            // First, handle the trivial cases where the longitude intervals overlap.
            if (a.Lng.Intersects(b.Lng))
            {
                if (a.Lat.Intersects(b.Lat))
                {
                    return(S1Angle.FromRadians(0)); // Intersection between a and b.
                }

                // We found an overlap in the longitude interval, but not in the latitude
                // interval. This means the shortest path travels along some line of
                // longitude connecting the high-latitude of the lower rect with the
                // low-latitude of the higher rect.
                S1Angle lo, hi;
                if (a.Lat.Lo > b.Lat.Hi)
                {
                    lo = b.LatHi;
                    hi = a.LatLo;
                }
                else
                {
                    lo = a.LatHi;
                    hi = b.LatLo;
                }
                return(S1Angle.FromRadians(hi.Radians - lo.Radians));
            }

            // The longitude intervals don't overlap. In this case, the closest points
            // occur somewhere on the pair of longitudinal edges which are nearest in
            // longitude-space.
            S1Angle aLng, bLng;
            var     loHi = S1Interval.FromPointPair(a.Lng.Lo, b.Lng.Hi);
            var     hiLo = S1Interval.FromPointPair(a.Lng.Hi, b.Lng.Lo);

            if (loHi.Length < hiLo.Length)
            {
                aLng = a.LngLo;
                bLng = b.LngHi;
            }
            else
            {
                aLng = a.LngHi;
                bLng = b.LngLo;
            }

            // The shortest distance between the two longitudinal segments will include
            // at least one segment endpoint. We could probably narrow this down further
            // to a single point-edge distance by comparing the relative latitudes of the
            // endpoints, but for the sake of clarity, we'll do all four point-edge
            // distance tests.
            var aLo        = new S2LatLng(a.LatLo, aLng).ToPoint();
            var aHi        = new S2LatLng(a.LatHi, aLng).ToPoint();
            var aLoCrossHi =
                S2LatLng.FromRadians(0, aLng.Radians - S2.PiOver2).Normalized.ToPoint();
            var bLo        = new S2LatLng(b.LatLo, bLng).ToPoint();
            var bHi        = new S2LatLng(b.LatHi, bLng).ToPoint();
            var bLoCrossHi =
                S2LatLng.FromRadians(0, bLng.Radians - S2.PiOver2).Normalized.ToPoint();

            return(S1Angle.Min(S2EdgeUtil.GetDistance(aLo, bLo, bHi, bLoCrossHi),
                               S1Angle.Min(S2EdgeUtil.GetDistance(aHi, bLo, bHi, bLoCrossHi),
                                           S1Angle.Min(S2EdgeUtil.GetDistance(bLo, aLo, aHi, aLoCrossHi),
                                                       S2EdgeUtil.GetDistance(bHi, aLo, aHi, aLoCrossHi)))));
        }