最近看OpenLayers,研究到地图投影时找到官方的文档,就翻译了一下,由于英文能力差,翻译不好的地方,请看原文
原文地址: http://docs.openlayers.org/library/spherical_mercator.html

球面墨卡托投影 该文档说明了什么是球面墨卡托投影以及何时使用该投影。文档中包含一些必要的背景知识、商用图层的代码演示、添加WMS图层以及使用OpenLayers进行投影变换的内容。要求读者对投影变换和OpenLayers有一个基本的了解。

  • 什么是球面墨卡托投影?

球面墨卡托投影在OpenLayers community版本和其他OSG community版本中都有使用。Google Maps,微软Virtual Earth,Yahoo Maps和其他商业地图API的提供者都使用该投影。
该投影是将地球当作一个球体而不是椭球体,然后应用墨卡托投影的方法,将地图投影到一个地图平面上。
为了正确的在商业地图API上叠加地图数据,就必须使用该投影。最基本的是在商业地图API上显示栅格瓦片地图——例如TMS,WMS以及其他类似的瓦片。
为了更好的使用商业地图API,基于Google Maps的数据生成人员也需要使用该投影。最基本的例如OpenStreetMap,栅格地图瓦片都是使用的“球面墨卡托投影”。
GIS中,通常用“EPSG”的代码来表示一种地图投影。最常用的“EPSG:4326”,在地图上将经纬度直接当作X /Y对待。球面墨卡托投影在官方指定的代码为EPSG:3785。但是在官方发布之前,很多软件已经使用了EPSG:900931代码来表示该投影,OpenLayers仍然使用这个非官方的代码。看到“EPSG:4326”字符,就是经纬度坐标的描述,看到“EPSG:900931”则是用“米”做单位的x/y坐标的描述。

  • 创建地图

首先我们创建一个使用球面墨卡托投影的地图。在这里我们使用基于微软Virtual Earth API的地图。以下的HTML代码将在地图中用到。

<html><head><title>OpenLayers Example</title><script src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1'></script><script src="http://openlayers.org/api/OpenLayers.js%22%3E%3C/script></head>
<body><div style="width:100%; height:100%" id="map"></div><script defer='defer' type='text/javascript'>// Code goes here</script></body></html>

就下来添加Virtual Earth图层作为地图的基础图层

var map = new OpenLayers.Map('map');
var layer = new OpenLayers.Layer.VirtualEarth("Virtual Earth", {sphericalMercator: true,maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)});map.addLayer(layer);map.zoomToMaxExtent();

这样就创建了一副地图。像这样的地图,应该着重注意:setCenter不能再使用经纬度坐标,而应该是投影以后以“米”为单位的坐标。你可以拖动该地图,但是如果你不理解球面墨卡托投影,接下来做任何功能都将非常困难。
该地图的maxResolution根据一些默认值进行计算,通常球面墨卡托投影的地图范围是经度-180~180,纬度-85.0511~85.0511,这是因为墨卡托投影两极将变形到无穷远处,必须排除掉北极和南极区域,剩下的区域投影后正好是一个正方形,投影后的范围是从 -20037508.34到20037508.34。
地图的maxResolution默认值的计算方法是:将该范围匹配在边长为256像素的图片上,结果maxResolution的值就是156543.0339。在图层中默认的就是该值,不需要通过图层options来设置了。
如果将球面墨卡托投影的WMS或者TMS图层作为一个单独的图层,需要指定图层的maxResolution属性,另外还需要定义该图层的maxExtent。

  • 使用投影坐标

OpenLayers提供了在客户端进行投影变换的工具,可以将经纬度坐标转换为球面墨卡托坐标。文档中首先在setCenter或者其他函数中需要使用坐标转换,接着演示如何通过使用map的displayProjection选项来将地图的坐标系显示为其他的投影坐标。

  • Points,Bounds投影变换

首先创建一个投影对象作为默认的投影,标准的经纬度投影的字符串是“EPSG:4326”——基于WGS84的参考椭球面(如果你的数据和Google Maps匹配很准,就是这种投影)。
接着创建一个对象保存你的坐标,然后转换
var proj = new OpenLayers.Projection("EPSG:4326" );
var point = new OpenLayers.LonLat(-71, 42 );
point.transform(proj, map.getProjectionObject());

该点已经转换为球面墨卡托投影坐标,你可以传递给map的setCenter方法:
map.setCenter(point);

也可以直接在setCenter中调用:
var proj = new OpenLayers.Projection("EPSG:4326" );
var point = new OpenLayers.LonLat(-71, 42 );
map.setCenter(point.transform(proj, map.getProjectionObject()));

通过这种方法,可以使用经纬度坐标来设置地图中心。
还可以使用相同的方法来投影变换OpenLayers.Bounds对象:同样用Bounds对象的transfrom方法:
var bounds = new OpenLayers.Bounds(-74.047185, 40.679648, -73.907005, 40.882078 )
bounds.transform(proj, map.getProjectionObject());

坐标变换后替换掉原来的对象,因此不需要重新定义一个变量。

  • Geometries的投影变换

Geometry对象和LonLat与Bounds对象一样拥有坐标转换方法。在你的应用程序代码中创建的geometry对象添加到图层上之前,应该先进行坐标转换,同样从图层获取得到的geometry对象在别的地方使用,也需要坐标转换。
由于所有的坐标转换都是更新对象自身,所以想添加一个geometry到图层上,不应该直接调用转换方法,而是克隆一个geometry对象后再调用:
var feature = vector_layer.features[0 ];
var geometry =  feature.geometry.clone();
geometry.transform(layerProj, targetProj);

  • 矢量数据的投影变换

创建一副带投影的地图后,很可能需要将矢量数据进行投影变换然后添加到基础地图上,完成这个工作,只需要简单的设置好矢量数据的投影,并确定地图的投影就可以了。
var map = new OpenLayers.Map("map" , {
  projection: new OpenLayers.Projection("EPSG:900913" )
});
var myBaseLayer = new OpenLayers.Layer.Google("Google" ,
              {'sphericalMercator': true ,
               'maxExtent':newOpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34 )
              });
map.addLayer(myBaseLayer);
var myGML = new OpenLayers.Layer.GML("GML", "mygml.gml" , {
  projection: new OpenLayers.Projection("EPSG:4326" )
});
map.addLayer(myGML);

可以使用该方法加载任何OpenLayers支持格式的矢量数据,包括WKT,GeoJSON,KML和其他一些格式,在GML图层上指定format选项。
var geojson = new OpenLayers.Layer.GML("GeoJSON", "geo.json" , {
  projection: new OpenLayers.Projection("EPSG:4326" ),
  format: OpenLayers.Format.GeoJSON
});
map.addLayer(geojson);

设置了图层的投影属性后,如果手动添加features到图层上(比如调用layer.addFeatures),在添加到图层上之前必须进行坐标转换。

  • 投影变换后的数据的序列化

OpenLayers中矢量数据序列化的方法是将矢量图层上获取数据集合传递给格式化类写数据。在一个具有投影的地图中,我们获取到的数据是已经投影变换过的,为了进行数据转换,需要使用内部投影和外部投影两个参数给格式化类,然后再用格式化类序列化数据。
var format = new  OpenLayers.Format.GeoJSON({
  'internalProjection': new OpenLayers.Projection("EPSG:900913" ),
  'externalProjection': new OpenLayers.Projection("EPSG:4326" )
});
var jsonstring = format.write(vector_layer.features);

  • 在控件中显示投影坐标

有些控件可以将地图坐标显示给用户,有的直接显示,有的包含在超链接中。MousePosition和Permalink控件(包括ArgParser控件)都是用地图所使用地图投影坐标——也就是球面墨卡托坐标。为了避免用户混淆不清,OpenLayers可以通过displayProjection设置控件的坐标系,将地图坐标系转换为显示坐标系。
要使用这一功能,在创建地图时需要指定projection和displayProjection选项,控件将自动选择这些选项的设置。
var map = new OpenLayers.Map("map" , {
  projection: new OpenLayers.Projection("EPSG:900913" ),
  displayProjection: new OpenLayers.Projection("EPSG:4326" )
});
map.addControl(new  OpenLayers.Control.Permalink());
map.addControl(new OpenLayers.Control.MousePosition());

这样你就可以正常加载地图了。

  • 创建球面墨卡托投影栅格图片

球面墨卡托投影如此重要的一个原因是只有这种投影能让你将图片地图正确的叠加到类似于Google Maps这样的商业图层上。在浏览器是使用栅格地图,在一个瘦GIS客户端是不可能对图片进行重新投影,只能是所有的图片使用同样的投影。
如何生成球面墨卡托投影的瓦片地图取决于你使用什么软件来创建地图图片。MapServer的使用包含在此文档中。

  • MapServer

MapServer采用proj.4来支持地图投影。为了转换为球面墨卡托投影,需要在proj.4的data目录下添加投影定义。
Linux环境下,打开/usr/share/proj/epsg文件,在文件尾部添加一行:
<900913> +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null  +no_defs
然后在地图文件中添加投影在wms_srs元数据中:
map
  web
    metadata
      wms_srs "EPSG:4326 EPSG:900913"
     end
   end
   #  Layers go here
end

这样就可以通过MapServer的WMS服务请求使用球面墨卡托投影的瓦片地图,通过OpenLayers很好的和商业数据匹配。
var options =  {
    projection: new OpenLayers.Projection("EPSG:900913" ),
    units: "m" ,
    maxResolution: 156543.0339 ,
    maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34 ,
                                     20037508.34, 20037508.34 )
};

map = new OpenLayers.Map('map' , options);

// create Google Mercator layers
var gmap = new  OpenLayers.Layer.Google(
    "Google Streets" ,
    {'sphericalMercator': true ,
     'maxExtent': new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34 )
    }
);

// create WMS layer
var wms = new  OpenLayers.Layer.WMS(
    "World Map" ,
    "http://vmap0.tiles.osgeo.org/wms/vmap0" ,
    {'layers': 'basic', 'transparent': true }
);

map.addLayers(gmap, wms);

WMS图层自动继承地图基础图层的投影,所以不需要在图层中设置投影选项。

  • GeoServer

最新版的GeoServer已经支持EPSG:900913,因此不需要额外添加投影。把GeoServer的图层作为WMS添加到地图上即可。

OpenLayers中的球面墨卡托投影相关推荐

  1. OpenLayers 6 如何优雅的使用天地图WMTS服务“经纬度投影(CGCS2000)”和“球面墨卡托投影(EPSG:3857)”

    最近google.com卫星图和bing卫星图相继有重大变动,常规方式已经没办法使用XYZ方式加载在线图了,于是我把目光转向了天地图.之前以为天地图是GCJ02加偏的资源,直到看到官网上这么一句话: ...

  2. 《水经注地图服务》发布的卫星影像数据在OpenLayers中调用

    (本文首发于"水经注GIS"公号,关注公号免费领取地图数据) OpenLayers是一个用于开发WebGIS客户端的JavaScript包. OpenLayers 支持的地图来源包 ...

  3. 读书笔记(2) OpenLayers中的图层

    OpenLayers有多个不同的图层类,每一个都可以连接到不同的地图服务器.例如通过Layer.WMS类可以连接到WMS地图服务器,通过Layer.Google类可以连接到谷歌地图服务器.OpenLa ...

  4. Openlayers中使用Overlay实现点击要素显示html内容弹窗并且动态更改弹窗内容

    场景 Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动: Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动_BADAO_LIUMANG_QIZHI的博客 ...

  5. Openlayers中加载Geoserver切割的EPSG:900913离线瓦片图层组

    场景 Openlayers中加载Geoserver切割的EPSG:900913离线瓦片地图并显示: Openlayers中加载Geoserver切割的EPSG:900913离线瓦片地图并显示_BADA ...

  6. Openlayers中使用Overlay实现点击要素弹窗并且弹窗随之移动

    场景 Vue+Openlayer使用overlay实现弹窗弹出显示与关闭: Vue+Openlayer使用overlay实现弹窗弹出显示与关闭_BADAO_LIUMANG_QIZHI的博客-CSDN博 ...

  7. Openlayers中使用Cluster+Overlay实现点击单个要素和聚合要素时显示不同弹窗

    场景 Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合: Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合_BADAO_LIUMANG_QIZHI的博客 ...

  8. Openlayers中使用Cluster实现点位元素重合时动态聚合与取消聚合

    场景 Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合: Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合_BADAO_LIUMANG_QIZHI的博客 ...

  9. Openlayers中使用Cluster实现缩放地图时图层聚合与取消聚合

    场景 Openlayers中实现地图上打点并显示图标和文字: Openlayers中实现地图上打点并显示图标和文字_BADAO_LIUMANG_QIZHI的博客-CSDN博客_openlayers 打 ...

最新文章

  1. python3.6小程序_python3.6小程序
  2. android系统电量优化,基于Android系统网络耗电量优化方法的.pdf
  3. 深入浅出统计学 第一章 数据的可视化
  4. Python 网络爬虫笔记5 -- Beautiful Soup库实战
  5. C++ 标准库类型 string
  6. Exchange2003-2010迁移系列之九,创建DAG组
  7. 看似简单的hashCode和equals面试题,竟然有这么多坑!
  8. Anguar 使用interceptor拦截器设置请求头传入jwt token
  9. 【CF gym 103260】40th Petrozavodsk Programming Camp, Day 5,2021.2.3 水题2题
  10. 微信小程序云开发教程-JavaScript入门(2)-变量定义
  11. Gerald and Giant Chess
  12. 一个优化好的、成熟的代购网站需要哪些功能,操作流程又是怎么样的?
  13. 几款比较有名的刷流量软件
  14. 通证与区块链:前台经济+后台技术
  15. 上传Excel文件进度条原理
  16. 自动化测试 - 如何自动提取手机短信验证码
  17. Windows版本,OS内核版本,Windows SDK之间的关系(附 :Windows纯净系统下载以及更新)
  18. 手机网站——移动互联网新趋势
  19. 对当下AI的一些思考
  20. Linux内核4.14版本——Nand子系统(1)——hisi504_nand.c分析

热门文章

  1. 绘画系统(04):【类】QPaintDevice[官翻]
  2. python自学入门要多久,新手学python需要多久
  3. 从头造一个SSD网络(1):理论篇
  4. php 女生生理计算,女性的安全期怎么算_世界避孕日官方网站
  5. 五种方式释放你的压力!
  6. Java的常用输入输出语句
  7. (二十二)岁月无声 - 1
  8. 详细解答Java中抽象类和接口的区别问题!
  9. 设计模式——单例模式、工厂模式
  10. Unity打包Android的apk文件时有关Json的注意事项