MKMapView+ZoomLevel.m 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //
  2. // MKMapView+ZoomLevel.m
  3. // CommonLibrary
  4. //
  5. // Created by Alexi on 14-11-17.
  6. // Copyright (c) 2014年 Alexi Chen. All rights reserved.
  7. //
  8. #import "MKMapView+ZoomLevel.h"
  9. #import <objc/runtime.h>
  10. @implementation MKMapView (ZoomLevel)
  11. #define MERCATOR_OFFSET 268435456
  12. #define MERCATOR_RADIUS 85445659.44705395
  13. #pragma mark -
  14. #pragma mark Map conversion methods
  15. - (double)longitudeToPixelSpaceX:(double)longitude
  16. {
  17. return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
  18. }
  19. - (double)latitudeToPixelSpaceY:(double)latitude
  20. {
  21. return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
  22. }
  23. - (double)pixelSpaceXToLongitude:(double)pixelX
  24. {
  25. return ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
  26. }
  27. - (double)pixelSpaceYToLatitude:(double)pixelY
  28. {
  29. return (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
  30. }
  31. #pragma mark -
  32. #pragma mark Helper methods
  33. - (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView
  34. centerCoordinate:(CLLocationCoordinate2D)centerCoordinate
  35. andZoomLevel:(NSUInteger)zoomLevel
  36. {
  37. // convert center coordiate to pixel space
  38. double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude];
  39. double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude];
  40. // determine the scale value from the zoom level
  41. NSInteger zoomExponent = 20 - zoomLevel;
  42. double zoomScale = pow(2, zoomExponent);
  43. // scale the map’s size in pixel space
  44. CGSize mapSizeInPixels = mapView.bounds.size;
  45. double scaledMapWidth = mapSizeInPixels.width * zoomScale;
  46. double scaledMapHeight = mapSizeInPixels.height * zoomScale;
  47. // figure out the position of the top-left pixel
  48. double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
  49. double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
  50. // find delta between left and right longitudes
  51. CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX];
  52. CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth];
  53. CLLocationDegrees longitudeDelta = maxLng - minLng;
  54. // find delta between top and bottom latitudes
  55. CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY];
  56. CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight];
  57. CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat);
  58. // create and return the lat/lng span
  59. MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
  60. return span;
  61. }
  62. #pragma mark -
  63. #pragma mark Public methods
  64. - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate
  65. zoomLevel:(NSUInteger)zoomLevel
  66. animated:(BOOL)animated
  67. {
  68. return;
  69. // clamp large numbers to 28
  70. zoomLevel = MIN(zoomLevel, kMKMapViewMaxZoomLevel);
  71. zoomLevel = MAX(kMKMapViewMinZoomLevel, zoomLevel);
  72. // use the zoom level to compute the region
  73. MKCoordinateSpan span = [self coordinateSpanWithMapView:self centerCoordinate:centerCoordinate andZoomLevel:zoomLevel];
  74. MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
  75. MKCoordinateRegion regf = [self regionThatFits:region];
  76. [self setRegion:regf animated:animated];
  77. }
  78. - (void)setZoomLevel:(NSUInteger)zoomLevel animated:(BOOL)animated
  79. {
  80. CLLocationCoordinate2D center = [self centerCoordinate];
  81. [self setCenterCoordinate:center zoomLevel:zoomLevel animated:animated];
  82. }
  83. - (void)setZoomLevel:(NSUInteger)zoomLevel
  84. {
  85. [self setZoomLevel:zoomLevel animated:YES];
  86. }
  87. @end