-
-
Save jamesmundy/08bac1dbf070b75627e6 to your computer and use it in GitHub Desktop.
MonoTouch MKMapView with Zoom Level Property
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using MapKit; | |
using CoreLocation; | |
using CoreGraphics; | |
using System.Drawing; | |
using Foundation; | |
namespace BinaryQuest | |
{ | |
[Register("MKMapViewZoomLevel")] | |
public class MKMapViewZoomLevel : MKMapView | |
{ | |
const double MERCATOR_OFFSET = 268435456; | |
const double MERCATOR_RADIUS = 85445659.44705395d; | |
public MKMapViewZoomLevel ():base() | |
{ | |
} | |
public MKMapViewZoomLevel(IntPtr handle):base(handle) | |
{ | |
} | |
private double longitudeToPixelSpaceX(double longitude) | |
{ | |
return Math.Round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * Math.PI / 180.0); | |
} | |
private double latitudeToPixelSpaceY(double latitude) | |
{ | |
return Math.Round(MERCATOR_OFFSET - MERCATOR_RADIUS * Math.Log((1 + Math.Sin(latitude * Math.PI / 180.0)) / (1 - Math.Sin(latitude * Math.PI / 180.0))) / 2.0); | |
} | |
private double pixelSpaceXToLongitude (double pixelX) | |
{ | |
return ((Math.Round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / Math.PI; | |
} | |
private double pixelSpaceYToLatitude (double pixelY) | |
{ | |
return (Math.PI / 2.0 - 2.0 * Math.Atan(Math.Exp((Math.Round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / Math.PI; | |
} | |
private MKCoordinateSpan coordinateSpanWithMapView (MKMapView mapView, CLLocationCoordinate2D centerCoordinate, int zoomLevel) | |
{ | |
// convert center coordiate to pixel space | |
double centerPixelX = longitudeToPixelSpaceX(centerCoordinate.Longitude); | |
double centerPixelY = latitudeToPixelSpaceY(centerCoordinate.Latitude); | |
// determine the scale value from the zoom level | |
int zoomExponent = 20 - zoomLevel; | |
double zoomScale = Math.Pow(2, zoomExponent); | |
// scale the map’s size in pixel space | |
CGSize mapSizeInPixels = mapView.Bounds.Size; | |
double scaledMapWidth = mapSizeInPixels.Width * zoomScale; | |
double scaledMapHeight = mapSizeInPixels.Height * zoomScale; | |
// figure out the position of the top-left pixel | |
double topLeftPixelX = centerPixelX - (scaledMapWidth / 2); | |
double topLeftPixelY = centerPixelY - (scaledMapHeight / 2); | |
// find delta between left and right longitudes | |
var minLng = pixelSpaceXToLongitude(topLeftPixelX); | |
var maxLng = pixelSpaceXToLongitude(topLeftPixelX + scaledMapWidth); | |
var longitudeDelta = maxLng - minLng; | |
// find delta between top and bottom latitudes | |
var minLat = pixelSpaceYToLatitude(topLeftPixelY); | |
var maxLat = pixelSpaceYToLatitude(topLeftPixelY + scaledMapHeight); | |
var latitudeDelta = -1 * (maxLat - minLat); | |
// create and return the lat/lng span | |
MKCoordinateSpan span = new MKCoordinateSpan(latitudeDelta, longitudeDelta); | |
return span; | |
} | |
public void SetCenterCoordinate (CLLocationCoordinate2D centerCoordinate, int zoomLevel, bool animated) | |
{ | |
// clamp large numbers to 28 | |
zoomLevel = Math.Min(zoomLevel, 28); | |
// use the zoom level to compute the region | |
MKCoordinateSpan span = coordinateSpanWithMapView(this, centerCoordinate, zoomLevel); | |
MKCoordinateRegion region = new MKCoordinateRegion(centerCoordinate, span); | |
// set the region like normal | |
this.SetRegion (region, animated); | |
} | |
public int ZoomLevel | |
{ | |
get{ | |
double zoom = 21 - Math.Round(Math.Log(this.Region.Span.LongitudeDelta * MERCATOR_RADIUS * Math.PI / (180.0 * this.Bounds.Size.Width))); | |
Console.WriteLine("Return Zoom:" + zoom); | |
return Convert.ToInt32(zoom); | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Made some changes to the original to take into account some changes with the Xamarin framework.
Originally taken from: http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/