/// <returns> /// A new OpenLocationCode instance representing a full Open Location Code from this /// (short) Open Location Code, given the reference location /// </returns> /// <param name="referenceLatitude">The reference latitude in decimal degrees.</param> /// <param name="referenceLongitude">The reference longitude in decimal degrees.</param> public OpenLocationCode Recover(double referenceLatitude, double referenceLongitude) { if (IsFull()) { // Note: each code is either full xor short, no other option. return(this); } referenceLatitude = ClipLatitude(referenceLatitude); referenceLongitude = NormalizeLongitude(referenceLongitude); int digitsToRecover = SeparatorPosition - Code.IndexOf(Separator); // The precision (height and width) of the missing prefix in degrees. double prefixPrecision = Math.Pow(EncodingBase, 2 - (digitsToRecover / 2)); // Use the reference location to generate the prefix. string recoveredPrefix = new OpenLocationCode(referenceLatitude, referenceLongitude).Code.Substring(0, digitsToRecover); // Combine the prefix with the short code and decode it. OpenLocationCode recovered = new OpenLocationCode(recoveredPrefix + Code); CodeArea recoveredCodeArea = recovered.Decode(); // Work out whether the new code area is too far from the reference location. If it is, we // move it. It can only be out by a single precision step. double recoveredLatitude = recoveredCodeArea.CenterLatitude; double recoveredLongitude = recoveredCodeArea.CenterLongitude; // Move the recovered latitude by one precision up or down if it is too far from the reference, // unless doing so would lead to an invalid latitude. double latitudeDiff = recoveredLatitude - referenceLatitude; if (latitudeDiff > prefixPrecision / 2 && recoveredLatitude - prefixPrecision > -LatitudeMax) { recoveredLatitude -= prefixPrecision; } else if (latitudeDiff < -prefixPrecision / 2 && recoveredLatitude + prefixPrecision < LatitudeMax) { recoveredLatitude += prefixPrecision; } // Move the recovered longitude by one precision up or down if it is too far from the // reference. double longitudeDiff = recoveredCodeArea.CenterLongitude - referenceLongitude; if (longitudeDiff > prefixPrecision / 2) { recoveredLongitude -= prefixPrecision; } else if (longitudeDiff < -prefixPrecision / 2) { recoveredLongitude += prefixPrecision; } return(new OpenLocationCode(recoveredLatitude, recoveredLongitude, recovered.Code.Length - 1)); }
private static OpenLocationCode RecoverNearestValid(string shortCode, double referenceLatitude, double referenceLongitude) { referenceLatitude = ClipLatitude(referenceLatitude); referenceLongitude = NormalizeLongitude(referenceLongitude); int digitsToRecover = SeparatorPosition - shortCode.IndexOf(SeparatorCharacter); // The precision (height and width) of the missing prefix in degrees. double prefixPrecision = Math.Pow(EncodingBase, 2 - (digitsToRecover / 2)); // Use the reference location to generate the prefix. string recoveredPrefix = new OpenLocationCode(referenceLatitude, referenceLongitude).Code.Substring(0, digitsToRecover); // Combine the prefix with the short code and decode it. OpenLocationCode recovered = new OpenLocationCode(recoveredPrefix + shortCode); GeoPoint recoveredCodeAreaCenter = recovered.Decode().Center; // Work out whether the new code area is too far from the reference location. If it is, we // move it. It can only be out by a single precision step. double recoveredLatitude = recoveredCodeAreaCenter.Latitude; double recoveredLongitude = recoveredCodeAreaCenter.Longitude; // Move the recovered latitude by one precision up or down if it is too far from the reference, // unless doing so would lead to an invalid latitude. double latitudeDiff = recoveredLatitude - referenceLatitude; if (latitudeDiff > prefixPrecision / 2 && recoveredLatitude - prefixPrecision > -LatitudeMax) { recoveredLatitude -= prefixPrecision; } else if (latitudeDiff < -prefixPrecision / 2 && recoveredLatitude + prefixPrecision < LatitudeMax) { recoveredLatitude += prefixPrecision; } // Move the recovered longitude by one precision up or down if it is too far from the reference. double longitudeDiff = recoveredCodeAreaCenter.Longitude - referenceLongitude; if (longitudeDiff > prefixPrecision / 2) { recoveredLongitude -= prefixPrecision; } else if (longitudeDiff < -prefixPrecision / 2) { recoveredLongitude += prefixPrecision; } return(new OpenLocationCode(recoveredLatitude, recoveredLongitude, recovered.CodeDigits.Length)); }