From abe3f9ce7ab8087b13871472a11e7f5021084642 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Wed, 24 Feb 2016 00:54:03 +0200 Subject: [core] Moved wrapping to LatLng scope Fixes a precision loss when converting unwrapped LatLngs. --- include/mbgl/util/geo.hpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'include/mbgl/util/geo.hpp') diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp index fa36896869..5636cd0bdf 100644 --- a/include/mbgl/util/geo.hpp +++ b/include/mbgl/util/geo.hpp @@ -2,6 +2,7 @@ #define MBGL_UTIL_GEO #include +#include #include @@ -13,11 +14,28 @@ using ScreenCoordinate = vec2; class LatLng { public: - double latitude = 0; - double longitude = 0; + double latitude; + double longitude; - LatLng(double lat = 0, double lon = 0) - : latitude(lat), longitude(lon) {} + enum WrapMode : bool { Unwrapped, Wrapped }; + + LatLng(double lat = 0, double lon = 0, WrapMode mode = Unwrapped) + : latitude(lat), longitude(lon) { if (mode == Wrapped) wrap(); } + + LatLng wrapped() const { return { latitude, longitude, Wrapped }; } + + void wrap() { + if (longitude < -util::LONGITUDE_MAX) longitude = std::fmod(longitude, util::LONGITUDE_MAX * 2); + if (longitude > util::LONGITUDE_MAX) longitude = -util::LONGITUDE_MAX + std::fmod(longitude, util::LONGITUDE_MAX); + } + + /** If a path crossing the antemeridian would be shorter, extend the final + coordinate so that interpolating between the two endpoints will cross it. */ + void unwrapForShortestPath(const LatLng& start) { + if (std::abs(start.longitude) + std::abs(longitude) > util::LONGITUDE_MAX) { + longitude += (start.longitude > 0 && longitude < 0) ? 360 : -360; + } + } explicit operator bool() const { return !(std::isnan(latitude) || std::isnan(longitude)); -- cgit v1.2.1