From 026b6d4c01a3d96af9629cc1790373137ecab950 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Mon, 7 Mar 2016 18:07:23 +0200 Subject: [core] Coordinate wrapping fixes - Make returning LatLngs unwrapped by default. - PointAnnotation and ShapeAnnotation are always wrapped so they can be selected via intersection from the visible tile boundaries. - Fixes LatLng::wrap() calculation. - Fixes LatLng::unwrapForShortestPath() calculation. The new unwrapForShortestPath algorithm unwraps the start coordinate either forwards or backwards depending on the end coordinate value, so we can always cross the antimeridian when needed and still obtain a wrapped end coordinate in the end. Fixes #4214. --- include/mbgl/annotation/point_annotation.hpp | 5 ++--- include/mbgl/annotation/shape_annotation.hpp | 17 +++++++++++++++-- include/mbgl/util/geo.hpp | 24 +++++++++++------------- 3 files changed, 28 insertions(+), 18 deletions(-) (limited to 'include/mbgl') diff --git a/include/mbgl/annotation/point_annotation.hpp b/include/mbgl/annotation/point_annotation.hpp index e226673997..3dea9a3e3e 100644 --- a/include/mbgl/annotation/point_annotation.hpp +++ b/include/mbgl/annotation/point_annotation.hpp @@ -9,9 +9,8 @@ namespace mbgl { class PointAnnotation { public: - inline PointAnnotation(const LatLng& position_, const std::string& icon_ = "") - : position(position_), icon(icon_) { - } + PointAnnotation(const LatLng& position_, const std::string& icon_ = "") + : position(position_.wrapped()), icon(icon_) {} const LatLng position; const std::string icon; diff --git a/include/mbgl/annotation/shape_annotation.hpp b/include/mbgl/annotation/shape_annotation.hpp index fffa7dab6e..121cb7f1d7 100644 --- a/include/mbgl/annotation/shape_annotation.hpp +++ b/include/mbgl/annotation/shape_annotation.hpp @@ -33,11 +33,24 @@ public: std::string>; // creates an annotation whose type and properties are sourced from a style layer ShapeAnnotation(const AnnotationSegments& segments_, const Properties& properties_) - : segments(segments_), properties(properties_) { - } + : segments(wrapCoordinates(segments_)), properties(properties_) {} const AnnotationSegments segments; const Properties properties; + +private: + AnnotationSegments wrapCoordinates(const AnnotationSegments& segments_) { + AnnotationSegments wrappedSegments; + // Wrap all segments coordinates. + for (const auto& segment_ : segments_) { + AnnotationSegment wrappedSegment; + for (const auto& latLng_ : segment_) { + wrappedSegment.push_back(latLng_.wrapped()); + } + wrappedSegments.push_back(wrappedSegment); + } + return wrappedSegments; + } }; } // namespace mbgl diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp index 56d575ceaa..9e2d7a2bb1 100644 --- a/include/mbgl/util/geo.hpp +++ b/include/mbgl/util/geo.hpp @@ -25,19 +25,17 @@ public: 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) { - if (start.longitude > 0 && longitude < 0) { - longitude += util::DEGREES_MAX; - } else if (start.longitude < 0 && longitude > 0) { - longitude -= util::DEGREES_MAX; - } + if (longitude < -util::LONGITUDE_MAX) longitude = util::LONGITUDE_MAX + std::fmod(longitude + util::LONGITUDE_MAX, util::DEGREES_MAX); + if (longitude > util::LONGITUDE_MAX) longitude = -util::LONGITUDE_MAX + std::fmod(longitude + util::LONGITUDE_MAX, util::DEGREES_MAX); + } + + // If we pass through the antimeridian, we update the start coordinate to make sure + // the end coordinate is always wrapped. + void unwrapForShortestPath(const LatLng& end) { + if (end.longitude < -util::LONGITUDE_MAX) { + longitude += util::DEGREES_MAX; + } else if (end.longitude > util::LONGITUDE_MAX) { + longitude -= util::DEGREES_MAX; } } -- cgit v1.2.1