diff --git a/include/mbgl/util/geo.hpp b/include/mbgl/util/geo.hpp index 4af89064659..d523ebe5866 100644 --- a/include/mbgl/util/geo.hpp +++ b/include/mbgl/util/geo.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace mbgl { @@ -21,17 +22,19 @@ using ScreenBox = mapbox::geometry::box; class LatLng { public: - struct null {}; - double latitude; double longitude; enum WrapMode : bool { Unwrapped, Wrapped }; - LatLng(null) : latitude(std::numeric_limits::quiet_NaN()), longitude(latitude) {} - LatLng(double lat = 0, double lon = 0, WrapMode mode = Unwrapped) - : latitude(lat), longitude(lon) { if (mode == Wrapped) wrap(); } + : latitude(lat), longitude(lon) { + if (std::isnan(lat)) throw std::domain_error("latitude must not be NaN"); + if (std::isnan(lon)) throw std::domain_error("longitude must not be NaN"); + if (std::abs(lat) > 90.0) throw std::domain_error("latitude must be between -90 and 90"); + if (!std::isfinite(lon)) throw std::domain_error("longitude must not be infinite"); + if (mode == Wrapped) wrap(); + } LatLng wrapped() const { return { latitude, longitude, Wrapped }; } @@ -48,10 +51,6 @@ class LatLng { else if (longitude < 0 && end.longitude > 0) longitude += util::DEGREES_MAX; } - explicit operator bool() const { - return !(std::isnan(latitude) || std::isnan(longitude)); - } - // Constructs a LatLng object with the top left position of the specified tile. LatLng(const CanonicalTileID& id); LatLng(const UnwrappedTileID& id); @@ -72,10 +71,6 @@ class ProjectedMeters { ProjectedMeters(double n = 0, double e = 0) : northing(n), easting(e) {} - - explicit operator bool() const { - return !(std::isnan(northing) || std::isnan(easting)); - } }; inline bool operator==(const ProjectedMeters& a, const ProjectedMeters& b) { @@ -193,14 +188,9 @@ class EdgeInsets { double right = 0; ///< Number of pixels inset from the right edge. EdgeInsets() {} - + EdgeInsets(const double t, const double l, const double b, const double r) : top(t), left(l), bottom(b), right(r) {} - - explicit operator bool() const { - return !(std::isnan(top) || std::isnan(left) || std::isnan(bottom) || std::isnan(right)) - && (top || left || bottom || right); - } void operator+=(const EdgeInsets& o) { top += o.top; @@ -214,7 +204,7 @@ class EdgeInsets { top + o.top, left + o.left, bottom + o.bottom, right + o.right, }; } - + ScreenCoordinate getCenter(uint16_t width, uint16_t height) const; }; diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index ae9330abae7..952777b0ada 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -505,7 +505,7 @@ CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, optional // Calculate the zoom level. double scaleX = getWidth() / width; double scaleY = getHeight() / height; - if (padding && *padding) { + if (padding) { scaleX -= (padding->left + padding->right) / width; scaleY -= (padding->top + padding->bottom) / height; } @@ -515,7 +515,7 @@ CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, optional // Calculate the center point of a virtual bounds that is extended in all directions by padding. ScreenCoordinate centerPixel = nePixel + swPixel; - if (padding && *padding) { + if (padding) { ScreenCoordinate paddedNEPixel = { padding->right / minScale, padding->top / minScale, @@ -580,7 +580,7 @@ void Map::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second } void Map::setBearing(double degrees, const Duration& duration) { - setBearing(degrees, EdgeInsets(), duration); + setBearing(degrees, optional(), duration); } void Map::setBearing(double degrees, optional anchor, const Duration& duration) { diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index bf95dd07144..ca7903249c9 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -97,13 +97,12 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim double angle = camera.angle.value_or(getAngle()); double pitch = camera.pitch.value_or(getPitch()); - if (!latLng || std::isnan(zoom)) { + if (std::isnan(zoom)) { return; } // Determine endpoints. - EdgeInsets padding; - if (camera.padding) padding = *camera.padding; + optional padding = camera.padding; LatLng startLatLng = getLatLng(padding); // If gesture in progress, we transfer the world rounds from the end // longitude into start, so we can guarantee the "scroll effect" of rounding @@ -176,13 +175,12 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima double angle = camera.angle.value_or(getAngle()); double pitch = camera.pitch.value_or(getPitch()); - if (!latLng || std::isnan(zoom)) { + if (std::isnan(zoom)) { return; } // Determine endpoints. - EdgeInsets padding; - if (camera.padding) padding = *camera.padding; + optional padding = camera.padding; LatLng startLatLng = getLatLng(padding).wrapped(); startLatLng.unwrapForShortestPath(latLng); @@ -206,9 +204,9 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima /// w₀: Initial visible span, measured in pixels at the initial scale. /// Known henceforth as a screenful. - double w0 = padding ? std::max(state.width, state.height) - : std::max(state.width - padding.left - padding.right, - state.height - padding.top - padding.bottom); + double w0 = padding ? std::max(state.width - padding->left - padding->right, + state.height - padding->top - padding->bottom) + : std::max(state.width, state.height); /// w₁: Final visible span, measured in pixels with respect to the initial /// scale. double w1 = w0 / state.zoomScale(zoom - startZoom); @@ -346,7 +344,6 @@ void Transform::setLatLng(const LatLng& latLng, const Duration& duration) { } void Transform::setLatLng(const LatLng& latLng, optional padding, const Duration& duration) { - if (!latLng) return; CameraOptions camera; camera.center = latLng; camera.padding = padding; @@ -354,26 +351,20 @@ void Transform::setLatLng(const LatLng& latLng, optional padding, co } void Transform::setLatLng(const LatLng& latLng, optional anchor, const Duration& duration) { - if (!latLng) return; CameraOptions camera; camera.center = latLng; if (anchor) { - EdgeInsets padding; - padding.top = anchor->y; - padding.left = anchor->x; - padding.bottom = state.height - anchor->y; - padding.right = state.width - anchor->x; - if (padding) camera.padding = padding; + camera.padding = EdgeInsets(anchor->y, anchor->x, state.height - anchor->y, state.width - anchor->x); } easeTo(camera, duration); } void Transform::setLatLngZoom(const LatLng& latLng, double zoom, const Duration& duration) { - setLatLngZoom(latLng, zoom, EdgeInsets {}, duration); + setLatLngZoom(latLng, zoom, optional(), duration); } void Transform::setLatLngZoom(const LatLng& latLng, double zoom, optional padding, const Duration& duration) { - if (!latLng || std::isnan(zoom)) return; + if (std::isnan(zoom)) return; CameraOptions camera; camera.center = latLng; @@ -383,7 +374,7 @@ void Transform::setLatLngZoom(const LatLng& latLng, double zoom, optional padding) const { - if (padding && *padding) { + if (padding) { return screenCoordinateToLatLng(padding->getCenter(state.width, state.height)); } else { return state.getLatLng(); @@ -391,7 +382,7 @@ LatLng Transform::getLatLng(optional padding) const { } ScreenCoordinate Transform::getScreenCoordinate(optional padding) const { - if (padding && *padding) { + if (padding) { return padding->getCenter(state.width, state.height); } else { return { state.width / 2., state.height / 2. }; @@ -494,7 +485,7 @@ void Transform::setAngle(double angle, optional anchor, const void Transform::setAngle(double angle, optional padding, const Duration& duration) { optional anchor; - if (padding && *padding) anchor = getScreenCoordinate(padding); + if (padding) anchor = getScreenCoordinate(padding); setAngle(angle, anchor, duration); } diff --git a/test/map/transform.cpp b/test/map/transform.cpp index afb655abca4..b4912be0403 100644 --- a/test/map/transform.cpp +++ b/test/map/transform.cpp @@ -44,40 +44,6 @@ TEST(Transform, InvalidScale) { ASSERT_DOUBLE_EQ(2, transform.getScale()); } -TEST(Transform, InvalidLatLng) { - Transform transform; - - ASSERT_DOUBLE_EQ(0, transform.getLatLng().latitude); - ASSERT_DOUBLE_EQ(0, transform.getLatLng().longitude); - ASSERT_DOUBLE_EQ(1, transform.getScale()); - - transform.setScale(2 << 0); - transform.setLatLng({ 8, 10 }); - - ASSERT_DOUBLE_EQ(8, transform.getLatLng().latitude); - ASSERT_DOUBLE_EQ(10, transform.getLatLng().longitude); - ASSERT_DOUBLE_EQ(2, transform.getScale()); - - transform.setLatLngZoom({ 10, 8 }, 2); - - ASSERT_DOUBLE_EQ(10, transform.getLatLng().latitude); - ASSERT_DOUBLE_EQ(8, transform.getLatLng().longitude); - ASSERT_DOUBLE_EQ(4, transform.getScale()); - - const double invalid = std::nan(""); - transform.setLatLngZoom({ invalid, 8 }, 2); - - ASSERT_DOUBLE_EQ(10, transform.getLatLng().latitude); - ASSERT_DOUBLE_EQ(8, transform.getLatLng().longitude); - ASSERT_DOUBLE_EQ(4, transform.getScale()); - - transform.setLatLngZoom({ 10, invalid }, 2); - - ASSERT_DOUBLE_EQ(10, transform.getLatLng().latitude); - ASSERT_DOUBLE_EQ(8, transform.getLatLng().longitude); - ASSERT_DOUBLE_EQ(4, transform.getScale()); -} - TEST(Transform, InvalidBearing) { Transform transform; @@ -320,17 +286,7 @@ TEST(Transform, Padding) { 1000.0 / 4.0, }); - EdgeInsets padding; - - padding.top = 0; - ASSERT_FALSE(bool(padding)); - - padding.top = NAN; - ASSERT_FALSE(bool(padding)); - - padding.top = 1000.0 / 2.0; - ASSERT_TRUE(bool(padding)); - + EdgeInsets padding(1000.0 / 2.0, 0, 0, 0); const LatLng shiftedCenter = transform.getLatLng(padding); ASSERT_NE(trueCenter.latitude, shiftedCenter.latitude); ASSERT_DOUBLE_EQ(trueCenter.longitude, shiftedCenter.longitude);