最近看OpenLayers,研究到地图投影时找到官方的文档,就翻译了一下,由于英文能力差,翻译不好的地方,请看原文

球面墨卡托投影

该文档说明了什么是球面墨卡托投影以及何时使用该投影。文档中包含一些必要的背景知识、商用图层的代码演示、添加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 2

3 OpenLayers Example4 5 6 7 8 12 13

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

1 varmap=newOpenLayers.Map('map');2 varlayer=newOpenLayers.Layer.VirtualEarth("Virtual Earth",3 {4 sphericalMercator:true,5 maxExtent:newOpenLayers.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匹配很准,就是这种投影)。

接着创建一个对象保存你的坐标,然后转换

varproj=newOpenLayers.Projection("EPSG:4326");varpoint=newOpenLayers.LonLat(-71,42);

point.transform(proj, map.getProjectionObject());

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

map.setCenter(point);

也可以直接在setCenter中调用:

varproj=newOpenLayers.Projection("EPSG:4326");varpoint=newOpenLayers.LonLat(-71,42);

map.setCenter(point.transform(proj, map.getProjectionObject()));

通过这种方法,可以使用经纬度坐标来设置地图中心。

还可以使用相同的方法来投影变换OpenLayers.Bounds对象:同样用Bounds对象的transfrom方法:

varbounds=newOpenLayers.Bounds(-74.047185,40.679648,-73.907005,40.882078)

bounds.transform(proj, map.getProjectionObject());

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

Geometries的投影变换

Geometry对象和LonLat与Bounds对象一样拥有坐标转换方法。在你的应用程序代码中创建的geometry对象添加到图层上之前,应该先进行坐标转换,同样从图层获取得到的geometry对象在别的地方使用,也需要坐标转换。

由于所有的坐标转换都是更新对象自身,所以想添加一个geometry到图层上,不应该直接调用转换方法,而是克隆一个geometry对象后再调用:

varfeature=vector_layer.features[0];vargeometry=feature.geometry.clone();

geometry.transform(layerProj, targetProj);

矢量数据的投影变换

创建一副带投影的地图后,很可能需要将矢量数据进行投影变换然后添加到基础地图上,完成这个工作,只需要简单的设置好矢量数据的投影,并确定地图的投影就可以了。

varmap=newOpenLayers.Map("map", {

projection:newOpenLayers.Projection("EPSG:900913")

});varmyBaseLayer=newOpenLayers.Layer.Google("Google",

{'sphericalMercator':true,'maxExtent':newOpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)

});

map.addLayer(myBaseLayer);varmyGML=newOpenLayers.Layer.GML("GML","mygml.gml", {

projection:newOpenLayers.Projection("EPSG:4326")

});

map.addLayer(myGML);

可以使用该方法加载任何OpenLayers支持格式的矢量数据,包括WKT,GeoJSON,KML和其他一些格式,在GML图层上指定format选项。

vargeojson=newOpenLayers.Layer.GML("GeoJSON","geo.json", {

projection:newOpenLayers.Projection("EPSG:4326"),

format: OpenLayers.Format.GeoJSON

});

map.addLayer(geojson);

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

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

OpenLayers中矢量数据序列化的方法是将矢量图层上获取数据集合传递给格式化类写数据。在一个具有投影的地图中,我们获取到的数据是已经投影变换过的,为了进行数据转换,需要使用内部投影和外部投影两个参数给格式化类,然后再用格式化类序列化数据。

varformat=newOpenLayers.Format.GeoJSON({'internalProjection':newOpenLayers.Projection("EPSG:900913"),'externalProjection':newOpenLayers.Projection("EPSG:4326")

});varjsonstring=format.write(vector_layer.features);

在控件中显示投影坐标

有些控件可以将地图坐标显示给用户,有的直接显示,有的包含在超链接中。MousePosition和Permalink控件(包括ArgParser控件)都是用地图所使用地图投影坐标——也就是球面墨卡托坐标。为了避免用户混淆不清,OpenLayers可以通过displayProjection设置控件的坐标系,将地图坐标系转换为显示坐标系。

要使用这一功能,在创建地图时需要指定projection和displayProjection选项,控件将自动选择这些选项的设置。

varmap=newOpenLayers.Map("map", {

projection:newOpenLayers.Projection("EPSG:900913"),

displayProjection:newOpenLayers.Projection("EPSG:4326")

});

map.addControl(newOpenLayers.Control.Permalink());

map.addControl(newOpenLayers.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"endend#Layers go hereend

这样就可以通过MapServer的WMS服务请求使用球面墨卡托投影的瓦片地图,通过OpenLayers很好的和商业数据匹配。

varoptions={

projection:newOpenLayers.Projection("EPSG:900913"),

units:"m",

maxResolution:156543.0339,

maxExtent:newOpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)

};

map=newOpenLayers.Map('map', options);//create Google Mercator layersvargmap=newOpenLayers.Layer.Google("Google Streets",

{'sphericalMercator':true,'maxExtent':newOpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34)

}

);//create WMS layervarwms=newOpenLayers.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作为参数,然后按照以下方法编写:

functionget_my_url (bounds) {varres=this.map.getResolution();varx=Math.round ((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));vary=Math.round ((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));varz=this.map.getZoom();varpath=z+"/"+x+"/"+y+"."+this.type;varurl=this.url;if(urlinstanceofArray) {

url=this.selectUrl(path, url);

}returnurl+path;

}

然后,创建TMS图层,传入一个选项告诉图层自定义瓦片的加载函数是什么:

newOpenLayers.Layer.TMS("Name","http://example.com/",

{'type':'png','getURL':get_my_url });

自己编写的函数将覆盖getURL函数,请求自己的瓦片来代替标准的TMS瓦片。

这样做,你的地图选项还需要包含和Google Maps一样的maxExtent和maxResolution。

newOpenLayers.Map("map", {

maxExtent:newOpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),

numZoomLevels:18,

maxResolution:156543.0339,

units:'m',

projection:"EPSG:900913",

displayProjection:newOpenLayers.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 projectionOpenLayers.Projection.addTransform("EPSG:4326","EPSG:3857", OpenLayers.Layer.SphericalMercator.projectForward);

OpenLayers.Projection.addTransform("EPSG:3857","EPSG:4326", OpenLayers.Layer.SphericalMercator.projectInverse);//create sphericalmercator layersvargoogleLayer=newOpenLayers.Layer.Google("Google", {"sphericalMercator":true});varosmLayer=newOpenLayers.Layer.OSM("OpenStreetMap");//override default epsg codealiasproj=newOpenLayers.Projection("EPSG:3857");

googleLayer.projection=osmLayer.projection=aliasproj;//add baselayers to mapmap.addLayers([googleLayer, osmLayer]);

这样,叠加图层(例如WMS图层)将使用3857代码,并在4326和3857之间完成坐标变换。

图像坐标球面投影_OpenLayers中的球面墨卡托投影相关推荐

  1. OpenLayers中的球面墨卡托投影

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

  2. 图像坐标球面投影_坐标系统及投影概述

    什么是坐标系? 初中学得直面直角坐标系,是为了精确描述平面上的点的位置.GIS中的坐标系的目的就是为了精确描述地球上的点的位置.有了坐标系,我们就能描述地球上的点了,比如(经度,纬度) (36.12, ...

  3. 图像坐标球面投影_地图开发知识之-投影坐标

    地球投影 由于地球是一个赤道略宽两极略扁的不规则的梨形球体,表面是一个不可展平的曲面,而地图通常是二维平面,因此在地图制图时首先要考虑把曲面转化成平面.然而,从几何意义上来说,球面是不可展平的曲面.要 ...

  4. 图像坐标球面投影_比较常用的坐标几种投影

    只谈比较常用的几种: " 墨卡托投影 " . " 高斯 - 克吕格投影 " . "UTM 投影 " . " 兰勃特 等角投影 &q ...

  5. 图像坐标:我想和世界坐标谈谈(B)

    二.图像坐标:我想和世界坐标谈谈(B) 玉米将在这篇博文中,对图像坐标与世界坐标的这场对话中涉及的第二个问题:谈话方式,进行总结.世界坐标是怎样变换进摄像机,投影成图像坐标的呢? 玉米做了一个简单的图 ...

  6. 图像坐标:我想和世界坐标谈谈(A) 【计算机视觉学习笔记--双目视觉几何框架系列】

    玉米竭力用轻松具体的描述来讲述双目三维重建中的一些数学问题.希望这样的方式让大家以一个轻松的心态阅读玉米的<计算机视觉学习笔记>双目视觉数学架构系列博客.这个系列博客旨在捋顺一下已标定的双 ...

  7. 张正友标定Opencv实现、标定流程以及图像坐标转为世界坐标

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/xiaomifanhxx/article/details/79560693 使用相机以前,首先要进行相 ...

  8. matlab 相机焦距,世界坐标、相机坐标、图像坐标、像素坐标的原理、关系,并用matlab仿真...

    照相机是日常生活中最常见的.它能把三维的空间图片等比例缩小投影在照片上,称为一个二维图像. 以下我们就讲一讲原理,并相应的进行matlab仿真. 在学之前,先要了解几个概念: 什么是世界坐标? 也就是 ...

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

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

  10. 图像坐标空间变换:透视变换(Perspective Transformation),或称为单应性(Homography)变换

    文章目录 透视变换简介 预备知识 透视变换公式推导 投影 二维坐标向齐次坐标的变换 公式求解 例子:A4纸视角校正 原始图片和坐标变换模板 计算程序 结果 透视变换的限制 前向映射与后向映射矩阵不互逆 ...

最新文章

  1. 阿里开源的缓存框架JetCache,实现spring二级缓存
  2. Altera FPGA配置过程
  3. webpack is not defined
  4. getopt()简介
  5. Arm学习总结之 32位和64位寄存器
  6. 在线开关MySQL5.7 GTID_MySQL5.7 GTID在线开启与关闭【转】
  7. 计算机算法设计与分析 N后问题
  8. 送6个Gmail邀请!
  9. JavaScript语言概况(一)
  10. 《BUG创造队》第九次团队作业:Beta冲刺与验收准备
  11. 你我贷CTO冯炯:互联网金融的P2P+O2O怎么做?
  12. Mysql支持的数据类型
  13. mac怎么设置锁屏壁纸,锁屏壁纸和屏幕壁纸不同
  14. 多Excel文件内容查询工具
  15. 目标客户画像_如何定义目标客户和用户画像
  16. magicbook java开发,买前必看,荣耀MagicBook和华为MateBook D(2018版)哪个更适合你?
  17. 红帽linux员工数,红帽企业 Linux Atomic Host 管理
  18. [转]Apache Ignite——新一代数据库缓存系统
  19. OCA/OCP Oracle 数据库12c考试指南读书笔记:第11章: Subqueries and Set Operators
  20. 时序预测方法——指数平滑法(Holt-Winters)

热门文章

  1. 小米手机访问电脑共享文件_小米手机如何与电脑共享文件
  2. flink 时间语义、水位线(Watermark)、生成水位线、水位线的传递
  3. 单片机定时器程序c语言,单片机定时器程序
  4. java实现表白动图
  5. STM32+ADS1110
  6. latex关于的报错问题及表格排版问题
  7. Python之XML解析
  8. word文档如何设置四级标题
  9. 解决360浏览器兼容模式不兼容,极速模式兼容问题
  10. android 多个 前台 挂机,安卓手机如何进行多开挂机?