diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2015-12-20 01:22:52 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2015-12-20 03:57:28 -0800 |
commit | d668c0fa8482c86a2a73e5fc9661e32d89f26c56 (patch) | |
tree | 08fe4d5a1467f774d95af298be2f54a127355cdf /platform/darwin | |
parent | cafe591d2a84d70a2a6c076b9629135e42e68f46 (diff) | |
download | qtlocation-mapboxgl-d668c0fa8482c86a2a73e5fc9661e32d89f26c56.tar.gz |
[ios, osx] Better zoom level–altitude conversion
Greatly simplified conversions between zoom level and altitude. Adjusted field of view to more closely match MapKit. Conversions are now well within the same order of magnitude as MapKit at all latitudes.
Fixes #2266.
Diffstat (limited to 'platform/darwin')
-rw-r--r-- | platform/darwin/MGLGeometry.mm | 25 | ||||
-rw-r--r-- | platform/darwin/MGLGeometry_Private.h | 18 |
2 files changed, 43 insertions, 0 deletions
diff --git a/platform/darwin/MGLGeometry.mm b/platform/darwin/MGLGeometry.mm index b80203d142..70f00afd2f 100644 --- a/platform/darwin/MGLGeometry.mm +++ b/platform/darwin/MGLGeometry.mm @@ -1,5 +1,15 @@ #import "MGLGeometry_Private.h" +#import <mbgl/util/projection.hpp> + +/** Vertical field of view, measured in degrees, for determining the altitude + of the viewpoint. + + TransformState::getProjMatrix() assumes a vertical field of view of + 2 arctan ⅓ rad ≈ 36.9°, but MapKit uses a vertical field of view of 30°. + flyTo() assumes a field of view of 2 arctan ½ rad. */ +const CLLocationDegrees MGLAngularFieldOfView = 30; + const MGLCoordinateSpan MGLCoordinateSpanZero = {0, 0}; CGRect MGLExtendRect(CGRect rect, CGPoint point) { @@ -19,3 +29,18 @@ CGRect MGLExtendRect(CGRect rect, CGPoint point) { } return rect; } + +CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLocationDegrees latitude, CGSize size) { + CLLocationDistance metersPerPixel = mbgl::Projection::getMetersPerPixelAtLatitude(latitude, zoomLevel); + CLLocationDistance metersTall = metersPerPixel * size.height; + CLLocationDistance altitude = metersTall / 2 / std::tan(MGLRadiansFromDegrees(MGLAngularFieldOfView) / 2.); + return altitude * std::sin(M_PI_2 - MGLRadiansFromDegrees(pitch)) / std::sin(M_PI_2); +} + +double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size) { + CLLocationDistance eyeAltitude = altitude / std::sin(M_PI_2 - MGLRadiansFromDegrees(pitch)) * std::sin(M_PI_2); + CLLocationDistance metersTall = eyeAltitude * 2 * std::tan(MGLRadiansFromDegrees(MGLAngularFieldOfView) / 2.); + CLLocationDistance metersPerPixel = metersTall / size.height; + CGFloat mapPixelWidthAtZoom = std::cos(MGLRadiansFromDegrees(latitude)) * mbgl::util::M2PI * mbgl::util::EARTH_RADIUS_M / metersPerPixel; + return ::log2(mapPixelWidthAtZoom / mbgl::util::tileSize); +} diff --git a/platform/darwin/MGLGeometry_Private.h b/platform/darwin/MGLGeometry_Private.h index 49a306701d..bf5bc4e0ff 100644 --- a/platform/darwin/MGLGeometry_Private.h +++ b/platform/darwin/MGLGeometry_Private.h @@ -44,3 +44,21 @@ NS_INLINE mbgl::EdgeInsets MGLEdgeInsetsFromNSEdgeInsets(NSEdgeInsets insets) { return { insets.top, insets.left, insets.bottom, insets.right }; } #endif + +/** Converts a map zoom level to a camera altitude. + + @param zoomLevel The zoom level to convert. + @param pitch The camera pitch, measured in degrees. + @param latitude The latitude of the point at the center of the viewport. + @param size The size of the viewport. + @return An altitude measured in meters. */ +CLLocationDistance MGLAltitudeForZoomLevel(double zoomLevel, CGFloat pitch, CLLocationDegrees latitude, CGSize size); + +/** Converts a camera altitude to a map zoom level. + + @param altitude The altitude to convert, measured in meters. + @param pitch The camera pitch, measured in degrees. + @param latitude The latitude of the point at the center of the viewport. + @param size The size of the viewport. + @return A zero-based zoom level. */ +double MGLZoomLevelForAltitude(CLLocationDistance altitude, CGFloat pitch, CLLocationDegrees latitude, CGSize size); |