From 152155d246db5b6442fd2534470a347cde0c59e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Fri, 26 Jul 2019 18:35:44 +0200 Subject: wip --- include/mbgl/map/map.hpp | 2 +- platform/android/MapboxGLAndroidSDK/build.gradle | 1 + .../mapbox/mapboxsdk/location/LatLngEvaluator.java | 2 +- .../mapbox/mapboxsdk/maps/MapGestureDetector.java | 164 ++++++++++++++------- .../java/com/mapbox/mapboxsdk/maps/NativeMap.java | 4 +- .../com/mapbox/mapboxsdk/maps/NativeMapView.java | 25 +++- .../java/com/mapbox/mapboxsdk/maps/Projection.java | 14 ++ .../java/com/mapbox/mapboxsdk/maps/Transform.java | 4 +- platform/android/src/native_map_view.cpp | 16 +- platform/android/src/native_map_view.hpp | 6 +- src/mbgl/map/map.cpp | 4 +- 11 files changed, 179 insertions(+), 63 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index b1d4b14e4f..88b89bf785 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -96,7 +96,7 @@ public: // Projection ScreenCoordinate pixelForLatLng(const LatLng&) const; - LatLng latLngForPixel(const ScreenCoordinate&) const; + LatLng latLngForPixel(const ScreenCoordinate&, LatLng::WrapMode = LatLng::Wrapped) const; // Annotations void addAnnotationImage(std::unique_ptr); diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle index 5ee3af61e2..59c686d688 100644 --- a/platform/android/MapboxGLAndroidSDK/build.gradle +++ b/platform/android/MapboxGLAndroidSDK/build.gradle @@ -14,6 +14,7 @@ dependencies { implementation dependenciesList.supportFragmentV4 implementation dependenciesList.okhttp3 implementation dependenciesList.soLoader + implementation "com.android.support:support-v4:28.0.0" testImplementation dependenciesList.junit testImplementation dependenciesList.mockito testImplementation dependenciesList.mockk diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java index c631b1b75d..e05dec42ad 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LatLngEvaluator.java @@ -5,7 +5,7 @@ import android.animation.TypeEvaluator; import android.support.annotation.NonNull; import com.mapbox.mapboxsdk.geometry.LatLng; -class LatLngEvaluator implements TypeEvaluator { +public class LatLngEvaluator implements TypeEvaluator { private final LatLng latLng = new LatLng(); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java index 74a864a6a1..408e14b037 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java @@ -2,12 +2,14 @@ package com.mapbox.mapboxsdk.maps; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.PointF; import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.view.animation.PathInterpolatorCompat; import android.view.InputDevice; import android.view.MotionEvent; import android.view.animation.DecelerateInterpolator; @@ -22,6 +24,9 @@ import com.mapbox.android.gestures.StandardGestureDetector; import com.mapbox.android.gestures.StandardScaleGestureDetector; import com.mapbox.mapboxsdk.R; import com.mapbox.mapboxsdk.constants.MapboxConstants; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.location.LatLngEvaluator; +import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.utils.MathUtils; import java.util.ArrayList; @@ -76,6 +81,7 @@ final class MapGestureDetector { private Animator scaleAnimator; private Animator rotateAnimator; + private Animator moveAnimator; private final List scheduledAnimators = new ArrayList<>(); /** @@ -211,10 +217,23 @@ final class MapGestureDetector { if (!scheduledAnimators.isEmpty()) { // Start all awaiting velocity animations animationsTimeoutHandler.removeCallbacksAndMessages(null); +// for (Animator animator : scheduledAnimators) { +// animator.start(); +// } + + AnimatorSet set = new AnimatorSet(); + long maxDuration = 0; for (Animator animator : scheduledAnimators) { - animator.start(); + long duration = animator.getDuration(); + if (duration > maxDuration) { + maxDuration = duration; + } } - scheduledAnimators.clear(); + set.setDuration(maxDuration); + set.setInterpolator(PathInterpolatorCompat.create(0f, 1.97f, 0f, -0.69f)); + set.playTogether(scheduledAnimators); + set.start(); +// scheduledAnimators.clear(); } break; @@ -234,6 +253,7 @@ final class MapGestureDetector { cancelAnimator(scaleAnimator); cancelAnimator(rotateAnimator); + cancelAnimator(moveAnimator); dispatchCameraIdle(); } @@ -385,46 +405,6 @@ final class MapGestureDetector { PointF longClickPoint = new PointF(motionEvent.getX(), motionEvent.getY()); notifyOnMapLongClickListeners(longClickPoint); } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - if (!uiSettings.isScrollGesturesEnabled()) { - // don't allow a fling if scroll is disabled - return false; - } - - notifyOnFlingListeners(); - - if (!uiSettings.isFlingVelocityAnimationEnabled()) { - return false; - } - - float screenDensity = uiSettings.getPixelRatio(); - - // calculate velocity vector for xy dimensions, independent from screen size - double velocityXY = Math.hypot(velocityX / screenDensity, velocityY / screenDensity); - if (velocityXY < MapboxConstants.VELOCITY_THRESHOLD_IGNORE_FLING) { - // ignore short flings, these can occur when other gestures just have finished executing - return false; - } - - transform.cancelTransitions(); - cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); - - // tilt results in a bigger translation, limiting input for #5281 - double tilt = transform.getTilt(); - double tiltFactor = 1.5 + ((tilt != 0) ? (tilt / 10) : 0); - double offsetX = velocityX / tiltFactor / screenDensity; - double offsetY = velocityY / tiltFactor / screenDensity; - - // calculate animation time based on displacement - long animationTime = (long) (velocityXY / 7 / tiltFactor + MapboxConstants.ANIMATION_DURATION_FLING_BASE); - - // update transformation - transform.moveBy(offsetX, offsetY, animationTime); - - return true; - } } private void doubleTapStarted() { @@ -463,6 +443,16 @@ final class MapGestureDetector { // Scroll the map transform.moveBy(-distanceX, -distanceY, 0 /*no duration*/); +// PointF startPoint = projection.toScreenLocation(transform.getCenterCoordinate()); +// PointF endPoint = new PointF(startPoint.x + distanceX, startPoint.y + distanceY); +// Logger.e("move", "start: " + startPoint); +// Logger.e("move", "end: " + endPoint); +// +// LatLng latLng1 = projection.fromScreenLocation(startPoint); +// LatLng latLng = projection.fromScreenLocation(endPoint); +// Logger.e("move", "start latttt: " + latLng1); +// Logger.e("move", "end latttt: " + latLng); +// transform.setCenterCoordinate(latLng); notifyOnMoveListeners(detector); } @@ -471,8 +461,79 @@ final class MapGestureDetector { @Override public void onMoveEnd(@NonNull MoveGestureDetector detector, float velocityX, float velocityY) { - dispatchCameraIdle(); notifyOnMoveEndListeners(detector); + + float screenDensity = uiSettings.getPixelRatio(); + // calculate velocity vector for xy dimensions, independent from screen size + double velocityXY = Math.hypot(velocityX / screenDensity, velocityY / screenDensity); + if (!uiSettings.isFlingVelocityAnimationEnabled() + || velocityXY < MapboxConstants.VELOCITY_THRESHOLD_IGNORE_FLING) { + dispatchCameraIdle(); + // don't allow a fling if scroll is disabled + // ignore short flings, these can occur when other gestures just have finished executing + return; + } + + notifyOnFlingListeners(); + + transform.cancelTransitions(); + + // tilt results in a bigger translation, limiting input for #5281 + double tilt = transform.getTilt(); + double tiltFactor = 1.5 + ((tilt != 0) ? (tilt / 10) : 0); + double offsetX = velocityX / tiltFactor / screenDensity; + double offsetY = velocityY / tiltFactor / screenDensity; + + // calculate animation time based on displacement + long animationTime = (long) (velocityXY / 7 / tiltFactor + MapboxConstants.ANIMATION_DURATION_FLING_BASE); + + PointF startPoint = projection.toScreenLocation(transform.getCenterCoordinate()); + PointF endPoint = new PointF(startPoint.x - (float) offsetX, startPoint.y - (float) offsetY); + moveAnimator = createMoveAnimator(startPoint, endPoint, animationTime); + scheduleAnimator(moveAnimator); + } + + private Animator createMoveAnimator(PointF startPoint, PointF endPoint, long animationTime) { + LatLng startLatLng = projection.fromScreenLocation(startPoint); + LatLng endLatLng = projection.fromScreenLocationUnwrapped(endPoint); + Logger.e("move", "start: " + startPoint); + Logger.e("move", "end: " + endPoint); + Logger.e("move", "start latt: " + startLatLng); + Logger.e("move", "end latt: " + endLatLng); + ValueAnimator animator = ValueAnimator.ofObject(new LatLngEvaluator(), startLatLng, endLatLng); + animator.setDuration(animationTime); + animator.setInterpolator(PathInterpolatorCompat.create(0f, 1.97f, 0f, -0.69f)); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(@NonNull ValueAnimator animation) { + transform.setCenterCoordinate(((LatLng) animation.getAnimatedValue())); + } + }); + + animator.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationStart(Animator animation) { + transform.cancelTransitions(); + cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE); + transform.setGestureInProgress(true); + } + + @Override + public void onAnimationCancel(Animator animation) { + transform.setGestureInProgress(false); + transform.cancelTransitions(); + } + + @Override + public void onAnimationEnd(Animator animation) { + transform.setGestureInProgress(false); + dispatchCameraIdle(); + } + }); + + return animator; } } @@ -523,7 +584,11 @@ final class MapGestureDetector { float scaleFactor = detector.getScaleFactor(); double zoomBy = getNewZoom(scaleFactor, quickZoom); - PointF focalPoint = getScaleFocalPoint(detector); + PointF focalPoint = getScaleFocalPoint(); + if (focalPoint == null) { + // around gesture + focalPoint = detector.getFocalPoint(); + } transform.zoomBy(zoomBy, focalPoint); notifyOnScaleListeners(detector); @@ -557,14 +622,14 @@ final class MapGestureDetector { double zoomAddition = calculateScale(velocityXY, detector.isScalingOut()); double currentZoom = transform.getRawZoom(); - PointF focalPoint = getScaleFocalPoint(detector); + PointF focalPoint = getScaleFocalPoint(); long animationTime = (long) (Math.abs(zoomAddition) * 1000 / 4); scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, focalPoint, animationTime); scheduleAnimator(scaleAnimator); } - @NonNull - private PointF getScaleFocalPoint(@NonNull StandardScaleGestureDetector detector) { + @Nullable + private PointF getScaleFocalPoint() { if (constantFocalPoint != null) { // around user provided focal point return constantFocalPoint; @@ -572,8 +637,7 @@ final class MapGestureDetector { // around center return new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2); } else { - // around gesture - return detector.getFocalPoint(); + return null; } } @@ -805,7 +869,7 @@ final class MapGestureDetector { } private Animator createScaleAnimator(double currentZoom, double zoomAddition, - @NonNull final PointF animationFocalPoint, long animationTime) { + @Nullable final PointF animationFocalPoint, long animationTime) { ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition)); animator.setDuration(animationTime); animator.setInterpolator(new DecelerateInterpolator()); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java index da70013713..186cbb91da 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMap.java @@ -72,7 +72,7 @@ interface NativeMap { double getPitch(); - void setZoom(double zoom, @NonNull PointF focalPoint, long duration); + void setZoom(double zoom, @Nullable PointF focalPoint, long duration); double getZoom(); @@ -194,6 +194,8 @@ interface NativeMap { LatLng latLngForPixel(@NonNull PointF pixel); + LatLng latLngForPixelUnwrapped(@NonNull PointF pixel); + // // Utils API // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index fc68a408fa..348a53e26b 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -309,11 +309,15 @@ final class NativeMapView implements NativeMap { } @Override - public void setZoom(double zoom, @NonNull PointF focalPoint, long duration) { + public void setZoom(double zoom, @Nullable PointF focalPoint, long duration) { if (checkState("setZoom")) { return; } - nativeSetZoom(zoom, focalPoint.x / pixelRatio, focalPoint.y / pixelRatio, duration); + if (focalPoint != null) { + nativeSetZoomWithAnchor(zoom, focalPoint.x / pixelRatio, focalPoint.y / pixelRatio, duration); + } else { + nativeSetZoom(zoom, duration); + } } @Override @@ -663,6 +667,14 @@ final class NativeMapView implements NativeMap { return nativeLatLngForPixel(pixel.x / pixelRatio, pixel.y / pixelRatio); } + @Override + public LatLng latLngForPixelUnwrapped(@NonNull PointF pixel) { + if (checkState("latLngForPixelUnwrapped")) { + return new LatLng(); + } + return nativeLatLngForPixelUnwrapped(pixel.x / pixelRatio, pixel.y / pixelRatio); + } + @Override public double getTopOffsetPixelsForAnnotationSymbol(String symbolName) { if (checkState("getTopOffsetPixelsForAnnotationSymbol")) { @@ -1152,7 +1164,10 @@ final class NativeMapView implements NativeMap { private native void nativeSetPitch(double pitch, long duration); @Keep - private native void nativeSetZoom(double zoom, double cx, double cy, long duration); + private native void nativeSetZoom(double zoom, long duration); + + @Keep + private native void nativeSetZoomWithAnchor(double zoom, double cx, double cy, long duration); @Keep private native double nativeGetZoom(); @@ -1266,6 +1281,10 @@ final class NativeMapView implements NativeMap { @Keep private native LatLng nativeLatLngForPixel(float x, float y); + @NonNull + @Keep + private native LatLng nativeLatLngForPixelUnwrapped(float x, float y); + @Keep private native double nativeGetTopOffsetPixelsForAnnotationSymbol(String symbolName); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java index 8ed003b821..8ac0eb3fa0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java @@ -92,6 +92,20 @@ public class Projection { return nativeMapView.latLngForPixel(point); } + /** + * Returns the geographic location that corresponds to a screen location. + * The screen location is specified in screen pixels (not display pixels) relative to the + * top left of the map (not the top left of the whole screen). + * + * @param point A Point on the screen in screen pixels. + * @return The LatLng corresponding to the point on the screen, or null if the ray through + * the given screen point does not intersect the ground plane. + */ + @NonNull + public LatLng fromScreenLocationUnwrapped(@NonNull PointF point) { + return nativeMapView.latLngForPixelUnwrapped(point); + } + /** * Gets a projection of the viewing frustum for converting between screen coordinates and * geo-latitude/longitude coordinates. diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java index 1961cf0450..0e47d7da52 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java @@ -219,11 +219,11 @@ public final class Transform implements MapView.OnCameraDidChangeListener { return nativeMap.getZoom(); } - void zoomBy(double zoomAddition, @NonNull PointF focalPoint) { + void zoomBy(double zoomAddition, @Nullable PointF focalPoint) { setZoom(nativeMap.getZoom() + zoomAddition, focalPoint); } - void setZoom(double zoom, @NonNull PointF focalPoint) { + void setZoom(double zoom, @Nullable PointF focalPoint) { nativeMap.setZoom(zoom, focalPoint, 0); } diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 47f2c6d9aa..d5efb906cb 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -435,7 +435,11 @@ void NativeMapView::setPitch(jni::JNIEnv&, jni::jdouble pitch, jni::jlong durati mbgl::AnimationOptions{ mbgl::Milliseconds(duration) }); } -void NativeMapView::setZoom(jni::JNIEnv&, jni::jdouble zoom, jni::jdouble x, jni::jdouble y, jni::jlong duration) { +void NativeMapView::setZoom(jni::JNIEnv&, jni::jdouble zoom, jni::jlong duration) { + map->easeTo(mbgl::CameraOptions().withZoom(zoom), mbgl::AnimationOptions{ mbgl::Milliseconds(duration) }); +} + +void NativeMapView::setZoomWithAnchor(jni::JNIEnv&, jni::jdouble zoom, jni::jdouble x, jni::jdouble y, jni::jlong duration) { map->easeTo(mbgl::CameraOptions().withZoom(zoom).withAnchor(mbgl::ScreenCoordinate{ x, y }), mbgl::AnimationOptions{ mbgl::Milliseconds(duration) }); } @@ -625,7 +629,13 @@ jni::Local> NativeMapView::pixelForLatLng(JNIEnv& env, jdoub } jni::Local> NativeMapView::latLngForPixel(JNIEnv& env, jfloat x, jfloat y) { - return LatLng::New(env, map->latLngForPixel(mbgl::ScreenCoordinate(x, y))); + mbgl::LatLng latLng = map->latLngForPixel(mbgl::ScreenCoordinate(x, y)); + return LatLng::New(env, latLng); +} + +jni::Local> NativeMapView::latLngForPixelUnwrapped(JNIEnv& env, jfloat x, jfloat y) { + mbgl::LatLng latLng = map->latLngForPixel(mbgl::ScreenCoordinate(x, y), mbgl::LatLng::Unwrapped); + return LatLng::New(env, latLng); } jni::Local> NativeMapView::addPolylines(JNIEnv& env, const jni::Array>& polylines) { @@ -1087,6 +1097,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::setPitch, "nativeSetPitch"), METHOD(&NativeMapView::getZoom, "nativeGetZoom"), METHOD(&NativeMapView::setZoom, "nativeSetZoom"), + METHOD(&NativeMapView::setZoomWithAnchor, "nativeSetZoomWithAnchor"), METHOD(&NativeMapView::resetZoom, "nativeResetZoom"), METHOD(&NativeMapView::setMinZoom, "nativeSetMinZoom"), METHOD(&NativeMapView::getMinZoom, "nativeGetMinZoom"), @@ -1114,6 +1125,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::pixelForLatLng, "nativePixelForLatLng"), METHOD(&NativeMapView::latLngForProjectedMeters, "nativeLatLngForProjectedMeters"), METHOD(&NativeMapView::latLngForPixel, "nativeLatLngForPixel"), + METHOD(&NativeMapView::latLngForPixelUnwrapped, "nativeLatLngForPixelUnwrapped"), METHOD(&NativeMapView::addPolylines, "nativeAddPolylines"), METHOD(&NativeMapView::addPolygons, "nativeAddPolygons"), METHOD(&NativeMapView::updatePolyline, "nativeUpdatePolyline"), diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index 4ea4781b36..55b8d05bda 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -113,7 +113,9 @@ public: void setPitch(jni::JNIEnv&, jni::jdouble, jni::jlong); - void setZoom(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong); + void setZoom(jni::JNIEnv&, jni::jdouble, jni::jlong); + + void setZoomWithAnchor(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jdouble, jni::jlong); jni::jdouble getZoom(jni::JNIEnv&); @@ -171,6 +173,8 @@ public: jni::Local> latLngForPixel(JNIEnv&, jfloat, jfloat); + jni::Local> latLngForPixelUnwrapped(JNIEnv&, jfloat, jfloat); + jni::Local> addPolylines(JNIEnv&, const jni::Array>&); jni::Local> addPolygons(JNIEnv&, const jni::Array>&); diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index c35f33305c..febf53e96c 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -360,8 +360,8 @@ ScreenCoordinate Map::pixelForLatLng(const LatLng& latLng) const { return impl->transform.latLngToScreenCoordinate(unwrappedLatLng); } -LatLng Map::latLngForPixel(const ScreenCoordinate& pixel) const { - return impl->transform.screenCoordinateToLatLng(pixel); +LatLng Map::latLngForPixel(const ScreenCoordinate& pixel, LatLng::WrapMode wrapMode) const { + return impl->transform.screenCoordinateToLatLng(pixel, wrapMode); } #pragma mark - Annotations -- cgit v1.2.1