Exemple #1
0
        /// <summary>
        /// Shortens the full code by removing four or six digits, depending on the provided reference point
        /// </summary>
        /// <param name="latitude">Reference location latitude</param>
        /// <param name="longitude">Reference location longitude</param>
        /// <returns>Returns a new Open Location Code with less digits</returns>
        public static OpenLocationCode Shorten(this OpenLocationCode code, double latitude, double longitude)
        {
            if (!code.IsFull)
            {
                throw new InvalidOperationException("Can only shorten a full Open Location Code.");
            }

            if (code.IsPadded)
            {
                throw new InvalidOperationException("Can only shorten an Open Location Code that isn't padded.");
            }

            Bounds bounds = code.Decode();

            double latitudeDiff  = Math.Abs(latitude - bounds.CenterLatitude);
            double longitudeDiff = Math.Abs(longitude - bounds.CenterLongitude);

            if (latitudeDiff < Constants.LatitudePrecision8Digits && longitudeDiff < Constants.LatitudePrecision8Digits)
            {
                return(new OpenLocationCode(code.Code.Substring(8)));
            }
            else if (latitudeDiff < Constants.LatitudePrecision6Digits && longitudeDiff < Constants.LatitudePrecision6Digits)
            {
                return(new OpenLocationCode(code.Code.Substring(6)));
            }
            else if (latitudeDiff < Constants.LatitudePrecision4Digits && longitudeDiff < Constants.LatitudePrecision4Digits)
            {
                return(new OpenLocationCode(code.Code.Substring(4)));
            }

            throw new ArgumentException("Location is too far from the Open Location Code center.");
        }
        public static OpenLocationCode Recover(this OpenLocationCode code, double latitude, double longitude)
        {
            if (code.IsFull)
            {
                return(code);
            }

            latitude  = Builder.ClipLatitude(latitude);
            longitude = Builder.NormalizeLongitude(longitude);

            int    digitsToRecover = 8 - code.Code.IndexOf(Constants.Separator);
            double paddedArea      = Math.Pow(20, 2 - (digitsToRecover / 2));

            // use reference location to pad the supplied code
            string prefix = OpenLocationCode.Encode(latitude, longitude)
                            .Substring(0, digitsToRecover);

            var recoveredCode       = new OpenLocationCode(prefix + code.Code);
            var recoveredCodeBounds = recoveredCode.Decode();

            double recoveredLatitude  = recoveredCodeBounds.CenterLatitude;
            double recoveredLongitude = recoveredCodeBounds.CenterLongitude;

            // adjust latitude resolution
            double latitudeDiff = recoveredLatitude - latitude;

            if (latitudeDiff > (paddedArea / 2))
            {
                recoveredLatitude -= paddedArea;
            }
            else if (latitudeDiff < (-paddedArea / 2))
            {
                recoveredLatitude += paddedArea;
            }

            // adjust longitude resolution
            double longitudeDiff = recoveredLongitude - longitude;

            if (longitudeDiff > (paddedArea / 2))
            {
                recoveredLongitude -= paddedArea;
            }
            else if (longitudeDiff < (-paddedArea / 2))
            {
                recoveredLongitude += paddedArea;
            }

            return(new OpenLocationCode(recoveredLatitude, recoveredLongitude, recoveredCode.Code.Length - 1));
        }
Exemple #3
0
        /// <summary>
        /// Decodes code into object encapsulating latitude/longitude bounding box
        /// </summary>
        /// <returns>Returns the area boundaries for the provided code</returns>
        public static Bounds Decode(this OpenLocationCode code)
        {
            if (!code.IsFull)
            {
                throw new InvalidOperationException(string.Format("'{0}' is not a full Open Location Code. Only full codes can be decoded.", code.Code));
            }

            string decoded = Regex.Replace(code.Code, "[0+]", "");

            // Decode the lat/lng pair component.
            decimal southLatitude = 0;
            decimal westLongitude = 0;

            int    digit = 0;
            double latitudeResolution  = 400;
            double longitudeResolution = 400;

            // Decode pair
            while (digit < decoded.Length)
            {
                if (digit < 10)
                {
                    latitudeResolution  /= 20.0;
                    longitudeResolution /= 20.0;
                    southLatitude       += new decimal(latitudeResolution * Constants.AlphabetIndex[decoded[digit]]);
                    westLongitude       += new decimal(longitudeResolution * Constants.AlphabetIndex[decoded[digit + 1]]);
                    digit += 2;
                }
                else
                {
                    latitudeResolution  /= 5;
                    longitudeResolution /= 4;
                    southLatitude       += new decimal(latitudeResolution * (Constants.AlphabetIndex[decoded[digit]] / 4.0));
                    westLongitude       += new decimal(longitudeResolution * (Constants.AlphabetIndex[decoded[digit]] % 4.0));
                    digit += 1;
                }
            }

            var bounds = new Bounds(
                southLatitude - 90
                , westLongitude - 180
                , (southLatitude - 90) + new decimal(latitudeResolution)
                , (westLongitude - 180) + new decimal(longitudeResolution));

            return(bounds);
        }