Created
March 8, 2013 08:36
-
-
Save djad442/5115021 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 MonoTouch.MapKit; | |
using MonoTouch.CoreLocation; | |
using System.Drawing; | |
using MonoTouch.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 | |
SizeF 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
This is very handy - just what I needed. Thanks for taking the time to do this!