diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-01-15 15:13:16 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-01-18 16:54:58 -0800 |
commit | 47b69100f984bfc9e2e69cb7fa731c57d220d7dc (patch) | |
tree | fee8f72c06d55eb0954a058f62c1d893865376a8 | |
parent | bf87eaa7b8aa049358559a96f290603e13ac736b (diff) | |
download | qtlocation-mapboxgl-47b69100f984bfc9e2e69cb7fa731c57d220d7dc.tar.gz |
[core, ios, osx, android, glfw] Flipped origin of Map::latLngForPixel(), Map::pixelForLatLng()
Map and Transform methods assume an origin at the top-left corner of the view, like iOS, Android, and GLFW but unlike OS X. Transform is responsible for flipping coordinates between the top-left origin of Map and the bottom-left origin of TransformState.
Fixes #3574.
-rw-r--r-- | platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java | 6 | ||||
-rw-r--r-- | platform/default/glfw_view.cpp | 13 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 27 | ||||
-rw-r--r-- | platform/osx/src/MGLMapView.mm | 8 | ||||
-rw-r--r-- | src/mbgl/map/map.cpp | 12 | ||||
-rw-r--r-- | src/mbgl/map/transform.cpp | 14 | ||||
-rw-r--r-- | src/mbgl/map/transform.hpp | 4 |
7 files changed, 42 insertions, 42 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java index 5810e390f6..451dbfdcf5 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/views/MapView.java @@ -2264,9 +2264,6 @@ public final class MapView extends FrameLayout { float x = point.x; float y = point.y; - // flip y direction vertically to match core GL - y = getHeight() - y; - return mNativeMapView.latLngForPixel(new PointF(x / mScreenDensity, y / mScreenDensity)); } @@ -2289,9 +2286,6 @@ public final class MapView extends FrameLayout { float x = point.x * mScreenDensity; float y = point.y * mScreenDensity; - // flip y direction vertically to match core GL - y = getHeight() - y; - return new PointF(x, y); } diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp index 66a41b0e10..ebdcae0d4a 100644 --- a/platform/default/glfw_view.cpp +++ b/platform/default/glfw_view.cpp @@ -182,11 +182,11 @@ void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, } mbgl::LatLng GLFWView::makeRandomPoint() const { - const auto sw = map->latLngForPixel({ 0, 0 }); - const auto ne = map->latLngForPixel({ double(width), double(height) }); + const auto nw = map->latLngForPixel({ 0, 0 }); + const auto se = map->latLngForPixel({ double(width), double(height) }); - const double lon = sw.longitude + (ne.longitude - sw.longitude) * (double(std::rand()) / RAND_MAX); - const double lat = sw.latitude + (ne.latitude - sw.latitude) * (double(std::rand()) / RAND_MAX); + const double lon = nw.longitude + (se.longitude - nw.longitude) * (double(std::rand()) / RAND_MAX); + const double lat = se.latitude + (nw.latitude - se.latitude) * (double(std::rand()) / RAND_MAX); return { lat, lon }; } @@ -368,10 +368,9 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) { double dx = x - view->lastX; double dy = y - view->lastY; if (dx || dy) { - double flippedY = view->height - y; view->map->setLatLng( - view->map->latLngForPixel(mbgl::PrecisionPoint(x - dx, flippedY + dy)), - mbgl::PrecisionPoint(x, flippedY)); + view->map->latLngForPixel(mbgl::PrecisionPoint(x - dx, y + dy)), + mbgl::PrecisionPoint(x, y)); } } else if (view->rotating) { view->map->rotateBy({ view->lastX, view->lastY }, { x, y }); diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 1bc725520e..e1d7866d0b 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -144,7 +144,6 @@ public: @property (nonatomic) UIView<MGLCalloutView> *calloutViewForSelectedAnnotation; @property (nonatomic) MGLUserLocationAnnotationView *userLocationAnnotationView; @property (nonatomic) CLLocationManager *locationManager; -@property (nonatomic) CGPoint centerPoint; @property (nonatomic) CGFloat scale; @property (nonatomic) CGFloat angle; @property (nonatomic) CGFloat quickZoomStart; @@ -964,27 +963,15 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration) { [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan]; - self.centerPoint = CGPointMake(0, 0); - self.userTrackingMode = MGLUserTrackingModeNone; [self notifyGestureDidBegin]; } else if (pan.state == UIGestureRecognizerStateChanged) { - CGPoint delta = CGPointMake([pan translationInView:pan.view].x - self.centerPoint.x, - [pan translationInView:pan.view].y - self.centerPoint.y); - - double flippedY = self.bounds.size.height - [pan locationInView:pan.view].y; - _mbglMap->setLatLng( - _mbglMap->latLngForPixel(mbgl::PrecisionPoint( - [pan locationInView:pan.view].x - delta.x, - flippedY + delta.y)), - mbgl::PrecisionPoint( - [pan locationInView:pan.view].x, - flippedY)); - - self.centerPoint = CGPointMake(self.centerPoint.x + delta.x, self.centerPoint.y + delta.y); + CGPoint delta = [pan translationInView:pan.view]; + _mbglMap->moveBy({ delta.x, delta.y }); + [pan setTranslation:CGPointZero inView:pan.view]; [self notifyMapChange:mbgl::MapChangeRegionIsChanging]; } @@ -1946,10 +1933,6 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration) - (mbgl::LatLng)convertPoint:(CGPoint)point toLatLngFromView:(nullable UIView *)view { CGPoint convertedPoint = [self convertPoint:point fromView:view]; - - // Flip y coordinate for iOS view origin in the top left corner. - convertedPoint.y = self.bounds.size.height - convertedPoint.y; - return _mbglMap->latLngForPixel(mbgl::PrecisionPoint(convertedPoint.x, convertedPoint.y)); } @@ -1962,10 +1945,6 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration) - (CGPoint)convertLatLng:(mbgl::LatLng)latLng toPointToView:(nullable UIView *)view { mbgl::vec2<double> pixel = _mbglMap->pixelForLatLng(latLng); - - // Flip y coordinate for iOS view origin in the top left corner. - pixel.y = self.bounds.size.height - pixel.y; - return [self convertPoint:CGPointMake(pixel.x, pixel.y) toView:view]; } diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm index 954717e5c4..302a9e8c44 100644 --- a/platform/osx/src/MGLMapView.mm +++ b/platform/osx/src/MGLMapView.mm @@ -2133,6 +2133,8 @@ public: /// Converts a geographic coordinate to a point in the view’s coordinate system. - (NSPoint)convertLatLng:(mbgl::LatLng)latLng toPointToView:(nullable NSView *)view { mbgl::vec2<double> pixel = _mbglMap->pixelForLatLng(latLng); + // Cocoa origin is at the lower-left corner. + pixel.y = NSHeight(self.bounds) - pixel.y; return [self convertPoint:NSMakePoint(pixel.x, pixel.y) toView:view]; } @@ -2143,7 +2145,11 @@ public: /// Converts a point in the view’s coordinate system to a geographic coordinate. - (mbgl::LatLng)convertPoint:(NSPoint)point toLatLngFromView:(nullable NSView *)view { NSPoint convertedPoint = [self convertPoint:point fromView:view]; - return _mbglMap->latLngForPixel(mbgl::PrecisionPoint(convertedPoint.x, convertedPoint.y)); + return _mbglMap->latLngForPixel({ + convertedPoint.x, + // mbgl origin is at the top-left corner. + NSHeight(self.bounds) - convertedPoint.y, + }); } - (NSRect)convertCoordinateBounds:(MGLCoordinateBounds)bounds toRectToView:(nullable NSView *)view { diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index b0cc49968c..e710ca4c14 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -259,12 +259,13 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed // Calculate the bounds of the possibly rotated shape with respect to the viewport. PrecisionPoint nePixel = {-INFINITY, -INFINITY}; PrecisionPoint swPixel = {INFINITY, INFINITY}; + double viewportHeight = getHeight(); for (LatLng latLng : latLngs) { PrecisionPoint pixel = pixelForLatLng(latLng); swPixel.x = std::min(swPixel.x, pixel.x); nePixel.x = std::max(nePixel.x, pixel.x); - swPixel.y = std::min(swPixel.y, pixel.y); - nePixel.y = std::max(nePixel.y, pixel.y); + swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y); + nePixel.y = std::max(nePixel.y, viewportHeight - pixel.y); } double width = nePixel.x - swPixel.x; double height = nePixel.y - swPixel.y; @@ -289,6 +290,9 @@ CameraOptions Map::cameraForLatLngs(const std::vector<LatLng>& latLngs, const Ed (paddedNEPixel.x + paddedSWPixel.x) / 2, (paddedNEPixel.y + paddedSWPixel.y) / 2, }; + + // CameraOptions origin is at the top-left corner. + centerPixel.y = viewportHeight - centerPixel.y; options.center = latLngForPixel(centerPixel); options.zoom = zoom; @@ -397,11 +401,11 @@ LatLng Map::latLngForProjectedMeters(const ProjectedMeters& projectedMeters) con } PrecisionPoint Map::pixelForLatLng(const LatLng& latLng) const { - return transform->getState().latLngToPoint(latLng); + return transform->latLngToPoint(latLng); } LatLng Map::latLngForPixel(const PrecisionPoint& pixel) const { - return transform->getState().pointToLatLng(pixel); + return transform->pointToLatLng(pixel); } #pragma mark - Annotations diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 69af657ecd..1363e2abd5 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -641,3 +641,17 @@ void Transform::cancelTransitions() { void Transform::setGestureInProgress(bool inProgress) { state.gestureInProgress = inProgress; } + +#pragma mark Conversion and projection + +PrecisionPoint Transform::latLngToPoint(const LatLng& latLng) const { + PrecisionPoint point = state.latLngToPoint(latLng); + point.y = state.height - point.y; + return point; +} + +LatLng Transform::pointToLatLng(const PrecisionPoint& point) const { + PrecisionPoint flippedPoint = point; + flippedPoint.y = state.height - flippedPoint.y; + return state.pointToLatLng(flippedPoint); +} diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp index cb3378a532..bef6c6c87e 100644 --- a/src/mbgl/map/transform.hpp +++ b/src/mbgl/map/transform.hpp @@ -123,6 +123,10 @@ public: bool isRotating() const { return state.isRotating(); } bool isScaling() const { return state.isScaling(); } bool isPanning() const { return state.isPanning(); } + + // Conversion and projection + PrecisionPoint latLngToPoint(const LatLng&) const; + LatLng pointToLatLng(const PrecisionPoint&) const; private: void unwrapLatLng(LatLng&); |