MKMapView and Zoom Levels: A Visual Guide
原帖:http://troybrant.net/blog/2010/01/mkmapview-and-zoom-levels-a-visual-guide/
So, how exactly does the code provided in the previous post work? What follows is a visual explanation of Google Maps, zoom levels, and how you go about adding support for zoom levels to the MKMapView class.
Round to Flat
This is planet Earth:

As you may know, it is round.
To create a map of the Earth, the curved surface must be projected onto a flat surface. There are many map projections that attempt to flatten the Earth. There are distortions inherent to every projection, but each map projection aims to preserve at least one quality from the original curved representation.
Some projections preserve area, such as the Mollweide projection:

Equirectangluar projections preserve distance between the meridians:

The Mercator projection stretches out the poles in order to preserve locally measured angles:

Google uses the Mercator projection to render Google Maps:

Mercator Math
The Mercator projection converts latitude (φ) and longitude (λ) coordinates to pixel values. It uses math:

You don’t have to understand the math; just know that it converts latitudes and longitudes to pixels.
But, where are these pixels? Well, it depends on your zoom level.
Zoom Levels
At zoom level 0, Google displays the world in a single 256 pixel by 256 pixel tile:

At zoom level 1, Google doubles the area of the map while keeping the tile size constant. So, the map grows to 512 pixels by 512 pixels and uses four tiles:

At zoom level 2, Google doubles the area again. The map grows to 1024 pixels by 1024 pixels and uses sixteen tiles:

The pixel area continues to double at each zoom level, and when zoom level 20 is reached, the map is 536,870,912 pixels by 536,870,912 pixels. It has so many tiles we won’t bother to count them:

Latitudes and Longitudes to Pixels
As part of the PHP Static Maps project, Mike Tuupola wrote some code that converts latitudes and longitudes to pixels at zoom level 20. The code is easily ported to Objective-C:
#define MERCATOR_OFFSET 268435456 /* (total pixels at zoom level 20) / 2 */
#define MERCATOR_RADIUS 85445659.44705395 /* MERCATOR_OFFSET / pi */
x = round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI / 180.0);
y = round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI / 180.0)) / (1 - sinf(latitude * M_PI / 180.0))) / 2.0);
To be honest, I haven’t taken the time to wrap my head around how this code works. But, knowing that it does
 work, we can now take any latitude and longitude and figure out its
pixel coordinates at zoom level 20. For instance, here are the pixel
coordinates of several cities around the world:

Add an iPhone
Say we place an iPhone on top of Anchorage, Alaska at zoom level 20:

In the iPhone shown above, the map size is 320 pixels by 460 pixels.
Since we know the map dimensions and center coordinate in pixels, we can
 easily compute the pixel coordinates of the top-left corner relative to
 the center pixel coordinate:

We can find the relative position of the top-right and bottom-left pixel coordinates as well:

The PHP Static Maps code also provides code to go from pixels at zoom level 20 to latitudes and longitudes:
latitude = (M_PI / 2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET) / MERCATOR_RADIUS))) * 180.0 / M_PI;
longitude = ((round(pixelX) - MERCATOR_OFFSET) / MERCATOR_RADIUS) * 180.0 / M_PI;
We can use this code to convert the corners from pixel coordinates to latitudes and longitudes:

As shown above, using the corner coordinates, we can compute the
latitudinal and longitudinal distances. These distances are exactly what
 we need to construct an MKCoordinateSpan. That span, in turn, is used to initialize the region property of an MKMapView:
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span);
[mapView setRegion:region animated:NO];
And you’re done!…That is, if you want to see zoom level 20. What do
you do when your user wants to see the map at zoom level 19 instead of
20?
Scaling using Zoom Levels
Relative to zoom level 20, zooming out one level doubles the area visible on the map.
For example, consider the image below. On the left is Anchorage at
zoom level 19, and on the right are the 4 iPhones at zoom level 20 it
would take to display the same amount of area:

If we move up another level, the area doubles again. Consider the
following image. On the left is Anchorage at zoom level 18, and on the
right are the 16 iPhones at zoom level 20 it would take to display the
same amount of area:

Since the area doubles at each zoom level, we can define the
following exponential relationship between the zoom level and the area
covered by the map:
NSInteger zoomExponent = 20 - zoomLevel;
double zoomScale = pow(2, zoomExponent);
double scaledMapWidth = mapSizeInPixels.width * zoomScale;
double scaledMapHeight = mapSizeInPixels.height * zoomScale;
For instance, here is Anchorage at zoom levels 20, 19, and 18. The map’s width and height in pixels are unaltered:

After computing the zoom scale factor, we can apply it to each map to determine its dimensions at zoom level 20:

After we compute these new dimensions, we plug them into the algorithm for finding the coordinates of the map corners.
An Example: Zoom Level 18
For instance, say we take the map at zoom level 18:

Let’s drop the matrix of phones but keep the scaled width and height:

We find the top-left corner just like we did before, except now we use the scaled width and height:

Similarly, we use the scaled width and height for finding the top-right and bottom-left corners as well:

Using the pixel and latitude and pixel and longitude helper methods,
we can compute the coordinates of the corners and the distance between
them:

These delta values are used to initialize the map’s region property, and the map zooms to the level you specify.
That’s a Wrap
Be sure to check out the previous post for the full code that adds support for zoom levels to MKMapView.
If you are interested in learning more from someone much smarter than I am, check out these posts from Charlie Savage, a programmer and cartographer extraordinaire:
Much of what I know about maps is from these articles, and I highly
recommended checking them out if you want to learn more about how Google
 Maps works under the hood.
MKMapView and Zoom Levels: A Visual Guide的更多相关文章
- [Forward]Visual Guide: Setting up My Sites in SharePoint 2013
		from http://blog.sharedove.com/adisjugo/index.php/2012/07/25/visual-guide-setting-up-my-sites-in-sh ... 
- A SIMPLE LIBRARY TO BUILD A DEEP ZOOM IMAGE
		My current project requires a lot of work with Deep Zoom images. We recently received some very high ... 
- leaflet地图库
		an open-source JavaScript libraryfor mobile-friendly interactive maps Overview Tutorials Docs Downlo ... 
- Android Weekly Notes Issue #221
		Android Weekly Issue #221 September 4th, 2016 Android Weekly Issue #221 ARTICLES & TUTORIALS And ... 
- less 基础+ flex
		1.less 中的变量 @ 符号 引入 /*普通变量*/ @color:pinker; .styles{ color:@color; } /*选择器变量*/ @I:img; @{I}{ width: ... 
- Flex 布局教程:语法篇
		作者: 阮一峰 网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便 ... 
- TileJSON
		TileJSON TileJSON is an open standard for representing map metadata. License The text of this specif ... 
- MBTiles
		MBTiles Specification MBTiles is a specification for storing tiled map data in SQLite databases for ... 
- 【转】Flex 布局语法教程
		网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂直居中 ... 
随机推荐
- 源代码解读Cas实现单点登出(single sign out)功能实现原理--转
			关于Cas实现单点登入(single sing on)功能的文章在网上介绍的比较多,想必大家多多少少都已经有所了解,在此就不再做具体介绍.如果不清楚的,那只能等我把single sign on这块整理 ... 
- 为什么要配置path环境变量?
			一:关于path环境变量--为了在任意目录下,使用javac/java命令 第一种配置方法: 通过配置path环境变量,我们可以使某个程序,比如javac.exe,在任意目录下都可以运行,而不用跑到j ... 
- git pull 代码很慢的问题
			办公环境调整,之前开发机是和自己的电脑放同一网段内的,现在开发机放至到本地其他网段内,造成pull 代码很慢的问题,在网上查了一下 以下是原文,链接为 http://blog.sina.com.cn/ ... 
- MFC 中的 “printf” 函数
			怀念C语言的我,MFC没法使用的C语言printf函数,于是: int MFCprintf(const char* m_data, ...){ CString str; char printf_buf ... 
- 在Github上面搭建Hexo博客(一):部署到Github
			什么是Hexo Hexo是一个基于Node.js的静态博客程序,可以方便的生成静态网页托管在Github和Heroku上.并且有很多人为其制作了很多优秀的主题(theme),你可以根据自己的喜好进行设 ... 
- php function_name($type=0,$order_ids='',$flag=2)
			$order_ids='',表示$order_ids是字符串,不是数组 foreach ($order_ids as $key=>$order_id){ //TODO} 这 ... 
- 打jar包的方法
			打jar包的方法是什么? java打jar包,引用其他.jar文件 java项目打jar包 将java源码打成jar包 maven打jar例子 打war包的方法是什么? Eclipse->项目右 ... 
- .Net程序员 Solr-5.3之旅 (三)Solr 从MSSQ导入索引数据
			阅读目录 引言 准备工作 data-config.xml schema.xml 导入数据 结尾 附件下载 引言 Other men live to eat, while I eat to live.- ... 
- phpmyadmin登陆提示#2002 无法登录 MySQL 服务器和设置自增
			看看mysql启动没有,结果是mysql服务没有启动,找了半天,是这个原因,那就右键计算机->管理->服务->启动mysql服务 设置自增:在显示出来的一行字段定义中把浏览器的滚动条 ... 
- jquery中的this 到底是什么意思? $(this)
			如果你学过面向对象语言的话,例如JAVA,你应该明白这个this在JAVA里的意思,简单的说,谁在调用它,它就代表文谁. 那么,用到这个jquery里,也算是蛮简单的.举两个例子,一个是单个对象,一个 ... 
