diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 463bee7938c..14595ade631 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -1,6 +1,7 @@ #ifndef MBGL_MAP_MAP #define MBGL_MAP_MAP +#include #include #include #include @@ -98,23 +99,23 @@ class Map : private util::noncopyable { // Position void moveBy(const ScreenCoordinate&, const Duration& = Duration::zero()); - void setLatLng(const LatLng&, const ScreenCoordinate&, const Duration& = Duration::zero()); - void setLatLng(const LatLng&, const EdgeInsets&, const Duration& = Duration::zero()); + void setLatLng(const LatLng&, optional, const Duration& = Duration::zero()); + void setLatLng(const LatLng&, optional, const Duration& = Duration::zero()); void setLatLng(const LatLng&, const Duration& = Duration::zero()); - LatLng getLatLng(const EdgeInsets& = {}) const; - void resetPosition(const EdgeInsets& = {}); + LatLng getLatLng(optional = {}) const; + void resetPosition(optional = {}); // Scale - void scaleBy(double ds, const ScreenCoordinate& = { NAN, NAN }, const Duration& = Duration::zero()); - void setScale(double scale, const ScreenCoordinate& = { NAN, NAN }, const Duration& = Duration::zero()); + void scaleBy(double ds, optional = {}, const Duration& = Duration::zero()); + void setScale(double scale, optional = {}, const Duration& = Duration::zero()); double getScale() const; void setZoom(double zoom, const Duration& = Duration::zero()); - void setZoom(double zoom, const EdgeInsets&, const Duration& = Duration::zero()); + void setZoom(double zoom, optional, const Duration& = Duration::zero()); double getZoom() const; void setLatLngZoom(const LatLng&, double zoom, const Duration& = Duration::zero()); - void setLatLngZoom(const LatLng&, double zoom, const EdgeInsets&, const Duration& = Duration::zero()); - CameraOptions cameraForLatLngBounds(const LatLngBounds&, const EdgeInsets&); - CameraOptions cameraForLatLngs(const std::vector&, const EdgeInsets&); + void setLatLngZoom(const LatLng&, double zoom, optional, const Duration& = Duration::zero()); + CameraOptions cameraForLatLngBounds(const LatLngBounds&, optional); + CameraOptions cameraForLatLngs(const std::vector&, optional); void resetZoom(); void setMinZoom(const double minZoom); double getMinZoom() const; @@ -124,15 +125,15 @@ class Map : private util::noncopyable { // Rotation void rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& second, const Duration& = Duration::zero()); void setBearing(double degrees, const Duration& = Duration::zero()); - void setBearing(double degrees, const ScreenCoordinate&, const Duration& = Duration::zero()); - void setBearing(double degrees, const EdgeInsets&, const Duration& = Duration::zero()); + void setBearing(double degrees, optional, const Duration& = Duration::zero()); + void setBearing(double degrees, optional, const Duration& = Duration::zero()); double getBearing() const; void resetNorth(const Duration& = Milliseconds(500)); - void resetNorth(const EdgeInsets&, const Duration& = Milliseconds(500)); + void resetNorth(optional, const Duration& = Milliseconds(500)); // Pitch void setPitch(double pitch, const Duration& = Duration::zero()); - void setPitch(double pitch, const ScreenCoordinate&, const Duration& = Duration::zero()); + void setPitch(double pitch, optional, const Duration& = Duration::zero()); double getPitch() const; // North Orientation diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index 790b0a4dd78..a931928d6d2 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -326,7 +326,7 @@ void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset) scale = 1.0 / scale; } - view->map->scaleBy(scale, { view->lastX, view->lastY }); + view->map->scaleBy(scale, mbgl::ScreenCoordinate { view->lastX, view->lastY }); } void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) { @@ -363,9 +363,9 @@ void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modi double now = glfwGetTime(); if (now - view->lastClick < 0.4 /* ms */) { if (modifiers & GLFW_MOD_SHIFT) { - view->map->scaleBy(0.5, { view->lastX, view->lastY }, mbgl::Milliseconds(500)); + view->map->scaleBy(0.5, mbgl::ScreenCoordinate { view->lastX, view->lastY }, mbgl::Milliseconds(500)); } else { - view->map->scaleBy(2.0, { view->lastX, view->lastY }, mbgl::Milliseconds(500)); + view->map->scaleBy(2.0, mbgl::ScreenCoordinate { view->lastX, view->lastY }, mbgl::Milliseconds(500)); } } view->lastClick = now; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 21d15ed1dda..7857c8ee136 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1146,7 +1146,7 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch if (log2(newScale) < _mbglMap->getMinZoom()) return; - _mbglMap->setScale(newScale, { centerPoint.x, centerPoint.y }); + _mbglMap->setScale(newScale, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); [self notifyMapChange:mbgl::MapChangeRegionIsChanging]; } @@ -1183,7 +1183,7 @@ - (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch if (velocity) { - _mbglMap->setScale(newScale, { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration)); + _mbglMap->setScale(newScale, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration)); } [self notifyGestureDidEndWithDrift:velocity]; @@ -1229,7 +1229,7 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate newDegrees = fmaxf(newDegrees, -30); } - _mbglMap->setBearing(newDegrees, { centerPoint.x, centerPoint.y }); + _mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); [self notifyMapChange:mbgl::MapChangeRegionIsChanging]; } @@ -1244,7 +1244,7 @@ - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate CGFloat newRadians = radians + velocity * duration * 0.1; CGFloat newDegrees = MGLDegreesFromRadians(newRadians) * -1; - _mbglMap->setBearing(newDegrees, { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration)); + _mbglMap->setBearing(newDegrees, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration)); [self notifyGestureDidEndWithDrift:YES]; @@ -1395,7 +1395,7 @@ - (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom centerPoint = self.userLocationAnnotationViewCenter; } _mbglMap->scaleBy(powf(2, newZoom) / _mbglMap->getScale(), - { centerPoint.x, centerPoint.y }); + mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); [self notifyMapChange:mbgl::MapChangeRegionIsChanging]; } @@ -1430,7 +1430,7 @@ - (void)handleTwoFingerDragGesture:(UIPanGestureRecognizer *)twoFingerDrag { centerPoint = self.userLocationAnnotationViewCenter; } - _mbglMap->setPitch(pitchNew, centerPoint); + _mbglMap->setPitch(pitchNew, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }); [self notifyMapChange:mbgl::MapChangeRegionIsChanging]; } @@ -1992,7 +1992,7 @@ - (void)_setDirection:(CLLocationDirection)direction animated:(BOOL)animated else { CGPoint centerPoint = self.userLocationAnnotationViewCenter; - _mbglMap->setBearing(direction, { centerPoint.x, centerPoint.y }, + _mbglMap->setBearing(direction, mbgl::ScreenCoordinate { centerPoint.x, centerPoint.y }, MGLDurationInSeconds(duration)); } } diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 374e3fe615c..d2ec76f8f9e 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -172,31 +172,29 @@ void Map::moveBy(const ScreenCoordinate& point, const Duration& duration) { } void Map::setLatLng(const LatLng& latLng, const Duration& duration) { - setLatLng(latLng, EdgeInsets(), duration); + setLatLng(latLng, ScreenCoordinate {}, duration); } -void Map::setLatLng(const LatLng& latLng, const EdgeInsets& padding, const Duration& duration) { +void Map::setLatLng(const LatLng& latLng, optional padding, const Duration& duration) { transform->setLatLng(latLng, padding, duration); update(Update::Repaint); } -void Map::setLatLng(const LatLng& latLng, const ScreenCoordinate& point, const Duration& duration) { - transform->setLatLng(latLng, point, duration); +void Map::setLatLng(const LatLng& latLng, optional anchor, const Duration& duration) { + transform->setLatLng(latLng, anchor, duration); update(Update::Repaint); } -LatLng Map::getLatLng(const EdgeInsets& padding) const { +LatLng Map::getLatLng(optional padding) const { return transform->getLatLng(padding); } -void Map::resetPosition(const EdgeInsets& padding) { +void Map::resetPosition(optional padding) { CameraOptions camera; camera.angle = 0; camera.pitch = 0; camera.center = LatLng(0, 0); - if (padding) { - camera.padding = padding; - } + camera.padding = padding; camera.zoom = 0; transform->jumpTo(camera); update(Update::Zoom); @@ -205,13 +203,13 @@ void Map::resetPosition(const EdgeInsets& padding) { #pragma mark - Scale -void Map::scaleBy(double ds, const ScreenCoordinate& point, const Duration& duration) { - transform->scaleBy(ds, point, duration); +void Map::scaleBy(double ds, optional anchor, const Duration& duration) { + transform->scaleBy(ds, anchor, duration); update(Update::Zoom); } -void Map::setScale(double scale, const ScreenCoordinate& point, const Duration& duration) { - transform->setScale(scale, point, duration); +void Map::setScale(double scale, optional anchor, const Duration& duration) { + transform->setScale(scale, anchor, duration); update(Update::Zoom); } @@ -223,7 +221,7 @@ void Map::setZoom(double zoom, const Duration& duration) { setZoom(zoom, {}, duration); } -void Map::setZoom(double zoom, const EdgeInsets& padding, const Duration& duration) { +void Map::setZoom(double zoom, optional padding, const Duration& duration) { transform->setZoom(zoom, padding, duration); update(Update::Zoom); } @@ -236,12 +234,12 @@ void Map::setLatLngZoom(const LatLng& latLng, double zoom, const Duration& durat setLatLngZoom(latLng, zoom, {}, duration); } -void Map::setLatLngZoom(const LatLng& latLng, double zoom, const EdgeInsets& padding, const Duration& duration) { +void Map::setLatLngZoom(const LatLng& latLng, double zoom, optional padding, const Duration& duration) { transform->setLatLngZoom(latLng, zoom, padding, duration); update(Update::Zoom); } -CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeInsets& padding) { +CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, optional padding) { AnnotationSegment segment = { bounds.northwest(), bounds.southwest(), @@ -251,7 +249,7 @@ CameraOptions Map::cameraForLatLngBounds(const LatLngBounds& bounds, const EdgeI return cameraForLatLngs(segment, padding); } -CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, const EdgeInsets& padding) { +CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, optional padding) { CameraOptions options; if (latLngs.empty()) { return options; @@ -272,26 +270,31 @@ CameraOptions Map::cameraForLatLngs(const std::vector& latLngs, const Ed double height = nePixel.y - swPixel.y; // Calculate the zoom level. - double scaleX = (getWidth() - padding.left - padding.right) / width; - double scaleY = (getHeight() - padding.top - padding.bottom) / height; + double scaleX = getWidth() / width; + double scaleY = getHeight() / height; + if (padding && *padding) { + scaleX -= (padding->left + padding->right) / width; + scaleY -= (padding->top + padding->bottom) / height; + } double minScale = ::fmin(scaleX, scaleY); double zoom = ::log2(getScale() * minScale); zoom = util::clamp(zoom, getMinZoom(), getMaxZoom()); // Calculate the center point of a virtual bounds that is extended in all directions by padding. - ScreenCoordinate paddedNEPixel = { - nePixel.x + padding.right / minScale, - nePixel.y + padding.top / minScale, - }; - ScreenCoordinate paddedSWPixel = { - swPixel.x - padding.left / minScale, - swPixel.y - padding.bottom / minScale, - }; - ScreenCoordinate centerPixel = { - (paddedNEPixel.x + paddedSWPixel.x) / 2, - (paddedNEPixel.y + paddedSWPixel.y) / 2, - }; - + ScreenCoordinate centerPixel = nePixel + swPixel; + if (padding && *padding) { + ScreenCoordinate paddedNEPixel = { + padding->right / minScale, + padding->top / minScale, + }; + ScreenCoordinate paddedSWPixel = { + padding->left / minScale, + padding->bottom / minScale, + }; + centerPixel = centerPixel - paddedNEPixel - paddedSWPixel; + } + centerPixel /= 2; + // CameraOptions origin is at the top-left corner. centerPixel.y = viewportHeight - centerPixel.y; @@ -349,12 +352,12 @@ void Map::setBearing(double degrees, const Duration& duration) { setBearing(degrees, EdgeInsets(), duration); } -void Map::setBearing(double degrees, const ScreenCoordinate& center, const Duration& duration) { - transform->setAngle(-degrees * util::DEG2RAD, center, duration); +void Map::setBearing(double degrees, optional anchor, const Duration& duration) { + transform->setAngle(-degrees * util::DEG2RAD, anchor, duration); update(Update::Repaint); } -void Map::setBearing(double degrees, const EdgeInsets& padding, const Duration& duration) { +void Map::setBearing(double degrees, optional padding, const Duration& duration) { transform->setAngle(-degrees * util::DEG2RAD, padding, duration); update(Update::Repaint); } @@ -372,10 +375,10 @@ void Map::resetNorth(const Duration& duration) { #pragma mark - Pitch void Map::setPitch(double pitch, const Duration& duration) { - setPitch(pitch, {NAN, NAN}, duration); + setPitch(pitch, {}, duration); } -void Map::setPitch(double pitch, const ScreenCoordinate& anchor, const Duration& duration) { +void Map::setPitch(double pitch, optional anchor, const Duration& duration) { transform->setPitch(pitch * util::DEG2RAD, anchor, duration); update(Update::Repaint); } diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index ac1f4142a50..9868d964856 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -352,68 +352,57 @@ void Transform::moveBy(const ScreenCoordinate& offset, const Duration& duration) } void Transform::setLatLng(const LatLng& latLng, const Duration& duration) { - setLatLng(latLng, EdgeInsets(), duration); + setLatLng(latLng, optional {}, duration); } -void Transform::setLatLng(const LatLng& latLng, const EdgeInsets& padding, const Duration& duration) { - if (!latLng) { - return; - } - +void Transform::setLatLng(const LatLng& latLng, optional padding, const Duration& duration) { + if (!latLng) return; CameraOptions camera; camera.center = latLng; - if (padding) { - camera.padding = padding; - } + camera.padding = padding; easeTo(camera, duration); } -void Transform::setLatLng(const LatLng& latLng, const ScreenCoordinate& point, const Duration& duration) { - if (!latLng || !point) { - return; - } - - // Pretend the viewport is 0×0 around the passed-in point. +void Transform::setLatLng(const LatLng& latLng, optional anchor, const Duration& duration) { + if (!latLng) return; CameraOptions camera; camera.center = latLng; - EdgeInsets padding; - padding.top = point.y; - padding.left = point.x; - padding.bottom = state.height - point.y; - padding.right = state.width - point.x; - if (padding) camera.padding = padding; + 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; + } easeTo(camera, duration); } void Transform::setLatLngZoom(const LatLng& latLng, double zoom, const Duration& duration) { - setLatLngZoom(latLng, zoom, {}, duration); + setLatLngZoom(latLng, zoom, EdgeInsets {}, duration); } -void Transform::setLatLngZoom(const LatLng& latLng, double zoom, const EdgeInsets& padding, const Duration& duration) { - if (!latLng || std::isnan(zoom)) { - return; - } +void Transform::setLatLngZoom(const LatLng& latLng, double zoom, optional padding, const Duration& duration) { + if (!latLng || std::isnan(zoom)) return; CameraOptions camera; camera.center = latLng; - if (padding) { - camera.padding = padding; - } + camera.padding = padding; camera.zoom = zoom; easeTo(camera, duration); } -LatLng Transform::getLatLng(const EdgeInsets& padding) const { - if (padding) { - return screenCoordinateToLatLng(padding.getCenter(state.width, state.height)); +LatLng Transform::getLatLng(optional padding) const { + if (padding && *padding) { + return screenCoordinateToLatLng(padding->getCenter(state.width, state.height)); } else { return state.getLatLng(); } } -ScreenCoordinate Transform::getScreenCoordinate(const EdgeInsets& padding) const { - if (padding) { - return padding.getCenter(state.width, state.height); +ScreenCoordinate Transform::getScreenCoordinate(optional padding) const { + if (padding && *padding) { + return padding->getCenter(state.width, state.height); } else { return { state.width / 2., state.height / 2. }; } @@ -422,20 +411,24 @@ ScreenCoordinate Transform::getScreenCoordinate(const EdgeInsets& padding) const #pragma mark - Zoom -void Transform::scaleBy(double ds, const ScreenCoordinate& center, const Duration& duration) { - if (std::isnan(ds) || !center) { - return; - } +void Transform::scaleBy(double ds, const Duration& duration) { + scaleBy(ds, optional {}, duration); +} +void Transform::scaleBy(double ds, optional anchor, const Duration& duration) { double scale = util::clamp(state.scale * ds, state.min_scale, state.max_scale); - setScale(scale, center, duration); + setScale(scale, anchor, duration); +} + +void Transform::setZoom(double zoom, const Duration& duration) { + setZoom(zoom, optional {}, duration); } -void Transform::setZoom(double zoom, const ScreenCoordinate& anchor, const Duration& duration) { +void Transform::setZoom(double zoom, optional anchor, const Duration& duration) { setScale(state.zoomScale(zoom), anchor, duration); } -void Transform::setZoom(double zoom, const EdgeInsets& padding, const Duration& duration) { +void Transform::setZoom(double zoom, optional padding, const Duration& duration) { setScale(state.zoomScale(zoom), padding, duration); } @@ -447,19 +440,22 @@ double Transform::getScale() const { return state.scale; } -void Transform::setScale(double scale, const ScreenCoordinate& anchor, const Duration& duration) { - if (std::isnan(scale)) { - return; - } - +void Transform::setScale(double scale, const Duration& duration) { + setScale(scale, optional {}, duration); +} + +void Transform::setScale(double scale, optional anchor, const Duration& duration) { + if (std::isnan(scale)) return; CameraOptions camera; camera.zoom = state.scaleZoom(scale); - if (anchor) camera.anchor = anchor; + camera.anchor = anchor; easeTo(camera, duration); } -void Transform::setScale(double scale, const EdgeInsets& padding, const Duration& duration) { - setScale(scale, getScreenCoordinate(padding), duration); +void Transform::setScale(double scale, optional padding, const Duration& duration) { + optional anchor; + if (padding) anchor = getScreenCoordinate(padding); + setScale(scale, anchor, duration); } void Transform::setMinZoom(const double minZoom) { @@ -502,22 +498,21 @@ void Transform::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate& } void Transform::setAngle(double angle, const Duration& duration) { - setAngle(angle, ScreenCoordinate { NAN, NAN }, duration); + setAngle(angle, optional {}, duration); } -void Transform::setAngle(double angle, const ScreenCoordinate& anchor, const Duration& duration) { - if (std::isnan(angle)) { - return; - } - +void Transform::setAngle(double angle, optional anchor, const Duration& duration) { + if (std::isnan(angle)) return; CameraOptions camera; camera.angle = angle; - if (anchor) camera.anchor = anchor; + camera.anchor = anchor; easeTo(camera, duration); } -void Transform::setAngle(double angle, const EdgeInsets& padding, const Duration& duration) { - setAngle(angle, getScreenCoordinate(padding), duration); +void Transform::setAngle(double angle, optional padding, const Duration& duration) { + optional anchor; + if (padding && *padding) anchor = getScreenCoordinate(padding); + setAngle(angle, anchor, duration); } double Transform::getAngle() const { @@ -527,17 +522,14 @@ double Transform::getAngle() const { #pragma mark - Pitch void Transform::setPitch(double pitch, const Duration& duration) { - setPitch(pitch, ScreenCoordinate {}, duration); + setPitch(pitch, optional {}, duration); } -void Transform::setPitch(double pitch, const ScreenCoordinate& anchor, const Duration& duration) { - if (std::isnan(pitch)) { - return; - } - +void Transform::setPitch(double pitch, optional anchor, const Duration& duration) { + if (std::isnan(pitch)) return; CameraOptions camera; camera.pitch = pitch; - if (anchor) camera.anchor = anchor; + camera.anchor = anchor; easeTo(camera, duration); } diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index e904b3956a2..1e84b013c98 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -43,38 +44,47 @@ class Transform : private util::noncopyable { top to bottom and from left to right. */ void moveBy(const ScreenCoordinate& offset, const Duration& = Duration::zero()); void setLatLng(const LatLng&, const Duration& = Duration::zero()); - void setLatLng(const LatLng&, const EdgeInsets&, const Duration& = Duration::zero()); - void setLatLng(const LatLng&, const ScreenCoordinate&, const Duration& = Duration::zero()); + void setLatLng(const LatLng&, optional, const Duration& = Duration::zero()); + void setLatLng(const LatLng&, optional, const Duration& = Duration::zero()); void setLatLngZoom(const LatLng&, double zoom, const Duration& = Duration::zero()); - void setLatLngZoom(const LatLng&, double zoom, const EdgeInsets&, const Duration& = Duration::zero()); - LatLng getLatLng(const EdgeInsets& = {}) const; - ScreenCoordinate getScreenCoordinate(const EdgeInsets& = {}) const; + void setLatLngZoom(const LatLng&, double zoom, optional, const Duration& = Duration::zero()); + LatLng getLatLng(optional = {}) const; + ScreenCoordinate getScreenCoordinate(optional = {}) const; // Zoom + /** Scales the map, keeping the given point fixed within the view. + @param ds The difference in scale factors to scale the map by. */ + void scaleBy(double ds, const Duration& = Duration::zero()); /** Scales the map, keeping the given point fixed within the view. @param ds The difference in scale factors to scale the map by. @param anchor A point relative to the top-left corner of the view. If unspecified, the center point is fixed within the view. */ - void scaleBy(double ds, const ScreenCoordinate& anchor = {}, const Duration& = Duration::zero()); + void scaleBy(double ds, optional anchor, const Duration& = Duration::zero()); + /** Sets the scale factor, keeping the given point fixed within the view. + @param scale The new scale factor. */ + void setScale(double scale, const Duration& = Duration::zero()); /** Sets the scale factor, keeping the given point fixed within the view. @param scale The new scale factor. @param anchor A point relative to the top-left corner of the view. If unspecified, the center point is fixed within the view. */ - void setScale(double scale, const ScreenCoordinate& anchor = {}, const Duration& = Duration::zero()); + void setScale(double scale, optional anchor, const Duration& = Duration::zero()); /** Sets the scale factor, keeping the center point fixed within the inset view. @param scale The new scale factor. @param padding The viewport padding that affects the fixed center point. */ - void setScale(double scale, const EdgeInsets& padding, const Duration& = Duration::zero()); + void setScale(double scale, optional padding, const Duration& = Duration::zero()); + /** Sets the zoom level, keeping the given point fixed within the view. + @param zoom The new zoom level. */ + void setZoom(double zoom, const Duration& = Duration::zero()); /** Sets the zoom level, keeping the given point fixed within the view. @param zoom The new zoom level. @param anchor A point relative to the top-left corner of the view. If unspecified, the center point is fixed within the view. */ - void setZoom(double zoom, const ScreenCoordinate& anchor = {}, const Duration& = Duration::zero()); + void setZoom(double zoom, optional anchor, const Duration& = Duration::zero()); /** Sets the zoom level, keeping the center point fixed within the inset view. @param zoom The new zoom level. @param padding The viewport padding that affects the fixed center point. */ - void setZoom(double zoom, const EdgeInsets& padding, const Duration& = Duration::zero()); + void setZoom(double zoom, optional padding, const Duration& = Duration::zero()); /** Returns the zoom level. */ double getZoom() const; /** Returns the scale factor. */ @@ -94,12 +104,12 @@ class Transform : private util::noncopyable { @param angle The new angle of rotation, measured in radians counterclockwise from true north. @param anchor A point relative to the top-left corner of the view. */ - void setAngle(double angle, const ScreenCoordinate& anchor, const Duration& = Duration::zero()); + void setAngle(double angle, optional anchor, const Duration& = Duration::zero()); /** Sets the angle of rotation, keeping the center point fixed within the inset view. @param angle The new angle of rotation, measured in radians counterclockwise from true north. @param padding The viewport padding that affects the fixed center point. */ - void setAngle(double angle, const EdgeInsets& padding, const Duration& = Duration::zero()); + void setAngle(double angle, optional padding, const Duration& = Duration::zero()); /** Returns the angle of rotation. @return The angle of rotation, measured in radians counterclockwise from true north. */ @@ -114,7 +124,7 @@ class Transform : private util::noncopyable { @param angle The new pitch angle, measured in radians toward the horizon. @param anchor A point relative to the top-left corner of the view. */ - void setPitch(double pitch, const ScreenCoordinate& anchor, const Duration& = Duration::zero()); + void setPitch(double pitch, optional anchor, const Duration& = Duration::zero()); double getPitch() const; // North Orientation diff --git a/test/map/transform.cpp b/test/map/transform.cpp index 4a040e90220..c490ca48948 100644 --- a/test/map/transform.cpp +++ b/test/map/transform.cpp @@ -222,17 +222,90 @@ TEST(Transform, Anchor) { ASSERT_DOUBLE_EQ(10, transform.getZoom()); ASSERT_DOUBLE_EQ(0, transform.getAngle()); + const ScreenCoordinate invalidAnchorPoint = ScreenCoordinate::null(); + const ScreenCoordinate anchorPoint = { 150, 150 }; + + const LatLng anchorLatLng = transform.getState().screenCoordinateToLatLng(anchorPoint); + ASSERT_NE(latLng.latitude, anchorLatLng.latitude); + ASSERT_NE(latLng.longitude, anchorLatLng.longitude); + + transform.setLatLngZoom(latLng, 2); + transform.scaleBy(1); + ASSERT_DOUBLE_EQ(4, transform.getScale()); + ASSERT_DOUBLE_EQ(latLng.latitude, transform.getLatLng().latitude); + ASSERT_DOUBLE_EQ(latLng.longitude, transform.getLatLng().longitude); + + transform.scaleBy(1.5, invalidAnchorPoint); + ASSERT_DOUBLE_EQ(6, transform.getScale()); + ASSERT_DOUBLE_EQ(latLng.latitude, transform.getLatLng().latitude); + ASSERT_DOUBLE_EQ(latLng.longitude, transform.getLatLng().longitude); + + transform.scaleBy(2, anchorPoint); + ASSERT_DOUBLE_EQ(12, transform.getScale()); + ASSERT_NE(latLng.latitude, transform.getLatLng().latitude); + ASSERT_NE(latLng.longitude, transform.getLatLng().longitude); + + transform.setLatLngZoom(latLng, 10); + transform.setScale(2 << 2); + ASSERT_DOUBLE_EQ(2 << 2, transform.getScale()); + ASSERT_NEAR(latLng.latitude, transform.getLatLng().latitude, 0.000001); + ASSERT_NEAR(latLng.longitude, transform.getLatLng().longitude, 0.000001); + + transform.setScale(2 << 4, invalidAnchorPoint); + ASSERT_DOUBLE_EQ(2 << 4, transform.getScale()); + ASSERT_NEAR(latLng.latitude, transform.getLatLng().latitude, 0.000001); + ASSERT_NEAR(latLng.longitude, transform.getLatLng().longitude, 0.000001); + + transform.setScale(2 << 6, anchorPoint); + ASSERT_DOUBLE_EQ(2 << 6, transform.getScale()); + ASSERT_NE(latLng.latitude, transform.getLatLng().latitude); + ASSERT_NE(latLng.longitude, transform.getLatLng().longitude); + + transform.setLatLngZoom(latLng, 10); + transform.setZoom(2); + ASSERT_DOUBLE_EQ(2, transform.getZoom()); + ASSERT_NEAR(latLng.latitude, transform.getLatLng().latitude, 0.000001); + ASSERT_NEAR(latLng.longitude, transform.getLatLng().longitude, 0.000001); + + transform.setZoom(4, invalidAnchorPoint); + ASSERT_DOUBLE_EQ(4, transform.getZoom()); + ASSERT_NEAR(latLng.latitude, transform.getLatLng().latitude, 0.000001); + ASSERT_NEAR(latLng.longitude, transform.getLatLng().longitude, 0.000001); + + transform.setZoom(8, anchorPoint); + ASSERT_DOUBLE_EQ(8, transform.getZoom()); + ASSERT_NE(latLng.latitude, transform.getLatLng().latitude); + ASSERT_NE(latLng.longitude, transform.getLatLng().longitude); + + transform.setLatLngZoom(latLng, 10); transform.setAngle(M_PI_4); ASSERT_NEAR(M_PI_4, transform.getAngle(), 0.000001); ASSERT_DOUBLE_EQ(latLng.latitude, transform.getLatLng().latitude); ASSERT_DOUBLE_EQ(latLng.longitude, transform.getLatLng().longitude); - const ScreenCoordinate anchorPoint = { 150, 150 }; - const LatLng anchorLatLng = transform.getState().screenCoordinateToLatLng(anchorPoint); + transform.setAngle(0, invalidAnchorPoint); + ASSERT_DOUBLE_EQ(0, transform.getAngle()); + ASSERT_DOUBLE_EQ(latLng.latitude, transform.getLatLng().latitude); + ASSERT_DOUBLE_EQ(latLng.longitude, transform.getLatLng().longitude); + transform.setAngle(-45 * util::DEG2RAD, anchorPoint); ASSERT_NEAR(-45 / util::RAD2DEG, transform.getAngle(), 0.000001); - ASSERT_NE(latLng.latitude, transform.getLatLng().latitude); - ASSERT_NE(latLng.longitude, transform.getLatLng().longitude); + ASSERT_NEAR(anchorLatLng.latitude, transform.getLatLng().latitude, 1); + ASSERT_NEAR(anchorLatLng.longitude, transform.getLatLng().longitude, 1); + + transform.setLatLngZoom(latLng, 10); + transform.setPitch(10 * util::DEG2RAD); + ASSERT_DOUBLE_EQ(10 / util::RAD2DEG, transform.getPitch()); + ASSERT_DOUBLE_EQ(latLng.latitude, transform.getLatLng().latitude); + ASSERT_DOUBLE_EQ(latLng.longitude, transform.getLatLng().longitude); + + transform.setPitch(15 * util::DEG2RAD, invalidAnchorPoint); + ASSERT_DOUBLE_EQ(15 / util::RAD2DEG, transform.getPitch()); + ASSERT_DOUBLE_EQ(latLng.latitude, transform.getLatLng().latitude); + ASSERT_DOUBLE_EQ(latLng.longitude, transform.getLatLng().longitude); + + transform.setPitch(20 * util::DEG2RAD, anchorPoint); + ASSERT_DOUBLE_EQ(20 / util::RAD2DEG, transform.getPitch()); ASSERT_NEAR(anchorLatLng.latitude, transform.getLatLng().latitude, 1); ASSERT_NEAR(anchorLatLng.longitude, transform.getLatLng().longitude, 1); }