OpenLayers中的球面墨卡托投影
最近看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代码将在地图中用到。
1 <html>
2 <head>
3 <title>OpenLayers Example</title>
4 <script src='http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1'></script>
5 <script src="http://openlayers.org/api/OpenLayers.js%22%3E%3C/script>
6 </head>
7 <body>
8 <div style="width:100%; height:100%" id="map"></div>
9 <script defer='defer' type='text/javascript'>
10 // Code goes here
11 </script>
12 </body>
13 </html>
就下来添加Virtual Earth图层作为地图的基础图层
1 var map = new OpenLayers.Map('map');
2 var layer = new OpenLayers.Layer.VirtualEarth("Virtual Earth",
3 {
4 sphericalMercator: true,
5 maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)
6 });
7 map.addLayer(layer);
8 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': new OpenLayers.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添加到地图上即可。
自定义瓦片地图
另一个使用球面墨卡托投影的场合是加载自定义的瓦片地图。很多瓦片使用和Google Maps一样的投影,而且是使用同样的z/x/y语法来访问瓦片。
如果你的瓦片是依照Google的瓦片编码规则(从世界的左上角开始,按照x,y,z编码),通过简单的修改get_url函数,就可以用TMS图层来加载这些瓦片。
首先定义getURL函数:允许接受bounds作为参数,然后按照以下方法编写:
function get_my_url (bounds) {
var res = this.map.getResolution();
var x = Math.round ((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
var y = Math.round ((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
var z = this.map.getZoom();
var path = z + "/" + x + "/" + y + "." + this.type;
var url = this.url;
if (url instanceof Array) {
url = this.selectUrl(path, url);
}
return url + path;
}
然后,创建TMS图层,传入一个选项告诉图层自定义瓦片的加载函数是什么:
new OpenLayers.Layer.TMS("Name",
"http://example.com/",
{ 'type':'png', 'getURL':get_my_url });
自己编写的函数将覆盖getURL函数,请求自己的瓦片来代替标准的TMS瓦片。
这样做,你的地图选项还需要包含和Google Maps一样的maxExtent和maxResolution。
new OpenLayers.Map("map", {
maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
numZoomLevels:18,
maxResolution:156543.0339,
units:'m',
projection: "EPSG:900913",
displayProjection: new OpenLayers.Projection("EPSG:4326")
});
球面墨卡托投影和EPSG的其他命名
球面墨卡托投影在OpenLayers中使用代码EPSG:900913,很多其他的服务比如OpenStreetMap, Bing和Yahoo也用同样的投影,但并不一定要用EPSG:900913代码,一些其他的代码比如EPSG:3857 和EPSG:102113也在使用。现在官方统一规定了代码EPSG:3857来代替EPSG:900913(http://www.epsg-registry.org/export.htm?gml=urn:ogc:def:crs:EPSG::3857)。因此,如果你想合并OpenLayers球面墨卡托投影的叠加图层,不管该图层使用的是其他代码还是官方的代码,你必须确保OpenLayers请求的是EPSG:3857或者别的代码而不是EPSG:900913。在加载一个图层到地图上之前,重写图层的投影来完成这些工作。代码如下:
// set transformation functions from/to alias projection
OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:3857", OpenLayers.Layer.SphericalMercator.projectForward);
OpenLayers.Projection.addTransform("EPSG:3857", "EPSG:4326", OpenLayers.Layer.SphericalMercator.projectInverse); // create sphericalmercator layers
var googleLayer = new OpenLayers.Layer.Google("Google", {"sphericalMercator": true});
var osmLayer = new OpenLayers.Layer.OSM("OpenStreetMap"); // override default epsg code
aliasproj = new OpenLayers.Projection("EPSG:3857");
googleLayer.projection = osmLayer.projection = aliasproj; //add baselayers to map
map.addLayers([googleLayer, osmLayer]);
这样,叠加图层(例如WMS图层)将使用3857代码,并在4326和3857之间完成坐标变换。
OpenLayers中的球面墨卡托投影的更多相关文章
- OpenLayers中的图层
OpenLayers有多个不同的图层类,每一个都可以连接到不同的地图服务器.例如通过Layer.WMS类可以连接到WMS地图服务器,通过Layer.Google类可以连接到谷歌地图服务器.OpenLa ...
- OpenLayers中地图缩放级别的设置方法
来源于:http://www.cnblogs.com/sailheart/archive/2011/03/15/1984519.html 一.概述 在OpenLayers中,地图必须具有一个缩放级别的 ...
- OpenLayers中的Layer概念和实践--Openlayers调用WMS服务
整理转自:http://hi.baidu.com/lixuweiok/item/c406a4e6a6d390e7fa42ba4b 本章我认为是这本书的真正开端,终于开始讲一些有意思的东西了.. 在这一 ...
- OpenLayers中的图层(转载)
作者:田念明出处:http://www.cnblogs.com/nianming/本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法 ...
- openlayers中单击获取要素
openlayers中单击获取要素 分类专栏: GIS 总结 OpenLayers 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接: ...
- openlayers中的自定制工具栏,包含画点、线、面
先是在projectquantan-master这个项目中有一个EditingPanel这个工具条,也挺好的,功能挺全的,但是有一点就是只有画多边形的一个按钮,没有point和path俩个的,所以就想 ...
- Openlayers中layer介绍
1.base layers & overlay layers base layer:最底层的layer,其它的图层是在他之上,最先增加的图层默认作为base layer. overlay la ...
- openlayers中实现点的拖拽(modify),在layer中增加修改删除point。
最近忙着整地图,都忘记了总结来沉淀自己,自我检讨一下. 总结一下最近使用openlayer时学习的内容,先说下我的业务逻辑吧,在室内地图中 1,点击新增在地图上新增一个可以拖拽的点,拖拽完成后确定位置 ...
- openLayers中WMTS结合GeoServer呈现瓦片地图
首先看openlayers官网中wmts模块,https://openlayers.org/en/latest/apidoc/module-ol_source_WMTS-WMTS.html,里面的参数 ...
随机推荐
- 【Alpha版本】冲刺阶段——Day7
[Alpha版本]冲刺阶段--Day7 阅读目录 今日进展 今日贡献量 贡献量汇总 TODOList 及项目燃尽图 [今日进展] 将项目源文件打成jar包,并运行测试 完成答辩ppt 项目运行情况 主 ...
- Subversion1.8源码安装流程
为了解决svnamin:Unrecognized record type in stream的问题,决定将Subversion1.7升级为Subversion1.8 Subversion1.8的源码安 ...
- Linux基础命令---显示登录用户logname
logname 显示当前登录的用户名称.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 logname 2 ...
- 51Nod 1256 乘法逆元
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1256 给出2个数M和N(M < N),且M与N互质,找 ...
- centos6使用yum安装python3和pip3
在安装了epel源的情况下,直接yum就可以安装python3.4 #yum install python34 -y# python3 --versionPython 3.4.5 没有自带pip3,需 ...
- LINUX搭建PySpider爬虫服务
1.环境搭建 yum update -y yum install gcc gcc-c++ -y yum install python-pip python-devel python-distribut ...
- 4-20mA电流环路发送器入门(转)
4-20mA电流环路发送器入门 作者:Collin Wells, 德州仪器精密模拟应用工程师 在现代工业控制系统中,4-20 mA电流环路发送器一直是在控制中心和现场传感器/执行器之间进行数据传输最为 ...
- Percona Server 5.6 安装TokuDB
系统:Red Hat Enterprise Linux Server release 6.3 (Santiago) 数据库:Percona-Server-5.6.29-rel76.2-Linux.x8 ...
- PyCharm配置MySQL
有时候电脑没有安装Navicat,也想要操作数据库,那么PyCharm也能实现Navicat的一些功能.下面演示,用PyCharm如何连接数据库并执行操作: 1. 打开PyCharm,在右侧边栏打开D ...
- kafka学习指南(总结版)
版本介绍 从使用上来看,以0.9为分界线,0.9开始不再区分高级/低级消费者API. 从兼容性上来看,以0.8.x为分界线,0.8.x不兼容以前的版本. 总体拓扑架构 从上可知: 1.生产者不需要访问 ...