| 254 | } |
| 255 | |
| 256 | std::string Shorten(const std::string &code, const LatLng &reference_location) { |
| 257 | if (!IsFull(code)) { |
| 258 | return code; |
| 259 | } |
| 260 | if (code.find(internal::kPaddingCharacter) != std::string::npos) { |
| 261 | return code; |
| 262 | } |
| 263 | CodeArea code_area = Decode(code); |
| 264 | LatLng center = code_area.GetCenter(); |
| 265 | // Ensure that latitude and longitude are valid. |
| 266 | double latitude = |
| 267 | adjust_latitude(reference_location.latitude, CodeLength(code)); |
| 268 | double longitude = normalize_longitude(reference_location.longitude); |
| 269 | // How close are the latitude and longitude to the code center. |
| 270 | double range = std::max(fabs(center.latitude - latitude), |
| 271 | fabs(center.longitude - longitude)); |
| 272 | std::string code_copy(code); |
| 273 | const double safety_factor = 0.3; |
| 274 | const int removal_lengths[3] = {8, 6, 4}; |
| 275 | for (int removal_length : removal_lengths) { |
| 276 | // Check if we're close enough to shorten. The range must be less than 1/2 |
| 277 | // the resolution to shorten at all, and we want to allow some safety, so |
| 278 | // use 0.3 instead of 0.5 as a multiplier. |
| 279 | double area_edge = |
| 280 | compute_precision_for_length(removal_length) * safety_factor; |
| 281 | if (range < area_edge) { |
| 282 | code_copy = code_copy.substr(removal_length); |
| 283 | break; |
| 284 | } |
| 285 | } |
| 286 | return code_copy; |
| 287 | } |
| 288 | |
| 289 | std::string RecoverNearest(const std::string &short_code, |
| 290 | const LatLng &reference_location) { |
nothing calls this directly
no test coverage detected