目录
前言
一、投影的相关知识
1、经纬度投影
2、Web墨卡托投影
二、经纬度投影下的空间信息展示
1、空间信息展示
2、效果展示
3、经纬度投影下的圆修正
三、Web墨卡托投影下空间信息展示
1、底图引用
2、自定义生成圆
总结
前言
在GIS的知识海洋中,对于地理信息科班出身的同学来说,WGS84 Web墨卡托投影(以下简称Web墨卡托投影)和WGS84 经纬度投影(以下简称经纬度投影)以及他们的区别应该非常了解。但是对于一些开发的同学,尤其是从计算机转向GIS的开发同学来说,就未必对两者的区别有这么详细的了解。但是如果对两种投影方式不了解的话,在实际开发过程当中就会遇到一些有趣的问题,有的空间对象在经纬度投影下的空间信息形变比较严重,而在Web墨卡托的投影方式下是展示比较良好的。因此有必要将这两种常见的投影类型以及一些实际的空间对象的展示,结合两种投影来进行讲解。
本文就是在以下的问题背景下产生,首先地图采用的是WGS84经纬度投影的方式,在地图上我们根据需要进行缓冲区分析,展示出来的效果就是一个圆。通过代码实践,我们发现,本来是是正常的一个圆,在不同纬度位置上表现出来的效果居然是不一样的。如下图所示:
同样的圆,在地图上展示的效果是完全不一样的,接近赤道的地区基本是正常的图形,随着纬度的增加,到了中高纬度地区,圆慢慢被拉平,变成了一个椭圆形,到了接近极地的地区,变平度更大,长轴与短轴的比接近2:1。为什么会出现以上的现象,出现了以上的现象,如何在开发的时候进行修正呢?
本文主要讲解GIS中的两种投影方式和区别,结合空间对象信息的展示里讲述不同投影方式下图形的形变问题,然后通过代码讲解如果遇到形变问题的对应解决办法。希望对遇到这种问题的朋友有一定的帮助。
一、投影的相关知识
地图投影,是指按照一定的数学法则将地球椭球面上的经纬网转换到平面上,使地面的地理坐标与平面直角坐标建立起函数关系。这是绘制地图的数学基础之一。由于地球是一个不可展的球体,使用物理方法将其展平会引起褶皱、拉伸和断裂,因此要使用地图投影实现由曲面向平面的转化。关于地球的投影,有很多种不同的处理方式,通常我们采用WebGIS的开发方式,比较常用的投影类型就是WGS84下的经纬度投影和Web墨卡托投影两种。因此本节主要简单介绍这两种投影的相关知识,其它的投影方式请各位朋友查询相关资料了解相关知识,不在本文中赘述。
1、经纬度投影
当全球影像显示为如下图所示的矩形时,该地图投影一般为 WGS84 经纬度投影。该投影下的经度范围为-180度到180度,纬度范围为-90度到90度,因此该投影下的全球影像矩形的长度刚好是宽度的2倍。在这请注意,随着纬度的增加,采用经纬度投影的地图,在中高纬度地区的变形会变得很严重,而在接近赤道地区是正常的。在了解它的投影原理之后是比较好理解的。
经纬度投影下全球影像展示示意图
2、Web墨卡托投影
当全球影像显示为如下图所示的正矩形时,该地图投影一般为 WGS84 Web 墨卡托投影。由于赤道半径为6378137米,则赤道周长为2×PI×R=20037508.3427892米。因此,X轴的取值范围在(-20037508.3427892和20037508.3427892)之间。当纬度接近两极,即90°时,Y值趋向于无穷,在该投影下通常将Y轴的取值范围限定在(-20037508.3427892,20037508.3427892)之间。最后可以得出,在 WGS84 Web 墨卡托投影坐标系下,左下角的投影坐标为(-20037508.3427892, -20037508.3427892),右上角的投影坐标为(20037508.3427892, 20037508.3427892),需要注意是这里的单位不再是度,而是米。
采用Web墨卡托投影方式时,空间图形的变形很小。在高纬度地区有较好的展示能力。
Web墨卡托投影下全球影像展示示意图
通过上述的这种简单的办法就可以区分Web墨卡托投影和经纬度投影这两种方式。你也看看目前你的系统中使用的是什么投影方式。
二、经纬度投影下的空间信息展示
本节主要讲解在经纬度投影下如何进行空间信息展示,以圆为例,经常遇到的问题可能是什么?以及遇到了这些问题如何去解决。
1、空间信息展示
考虑到经纬度投影下的变形是随着纬度的增加而加重的,空间圆的展示采用从赤道到北纬地区逐渐延伸的方式,构建了不同纬度下的圆信息展示,让大家对不同纬度下的空间信息展示有一个直观的认识和理解。在GIS中展示空间圆的关键代码如下:
经纬度投影的底图定义:
//以下采用经纬度投影方式
L.CRS.CustomEPSG4326 = L.extend({}, L.CRS.Earth, {
code: 'EPSG:4326',
projection: L.Projection.LonLat,
transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5),
scale: function (zoom) {
return 256 * Math.pow(2, zoom - 1);
}
});
var mymap = L.map('mapid',{crs:L.CRS.CustomEPSG4326}).setView([29.052934, 104.0625], 5);
L.tileLayer('http://localhost:8086/data/basemap_nowater/1_10_tms/{z}/{x}/{y}.jpg', {
maxZoom: 16,
attribution: 'yelangkingMap data © <a href="/">本地瓦片加载</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 256,
zoomOffset: -1
}).addTo(mymap);
//标签
L.tileLayer('http://localhost:8086/data/basemap_nowater/1-10label/{z}/{x}/{y}.png', {maxZoom: 10,minZoom:3,
id: 'mapbox/label',tileSize: 256,zoomOffset: -1
}).addTo(mymap);
根据纬度的不同创建不同的圆空间对象,关键代码如下:
L.circle([0.175781, 111.445313], 399000, {
color: '#960e00',
fillColor: '#960e00',
fillOpacity: 0.5,
}).addTo(mymap).bindPopup("靠近赤道地区的马来西亚某地.");
L.circle([12.612305, 110.830078], 399000, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
}).addTo(mymap).bindPopup("南海某地.");
L.circle([29.649869, 120.146484], 399000, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
}).addTo(mymap).bindPopup("我是一个圆.");
L.circle([50.097656, 111.09375], 399000, {
color: 'blue',
fillColor: 'blue',
fillOpacity: 0.5
}).addTo(mymap).bindPopup("我是第二个圆.");
L.circle([22.851563, 109.248047], 399000, {
color: '#550096',
fillColor: '#550096',
fillOpacity: 0.5
}).addTo(mymap).bindPopup("我是第三个圆.");
L.circle([66.884766, 108.017578], 399000, {
color: '#006696',
fillColor: '#006696',
fillOpacity: 0.5
}).addTo(mymap).bindPopup("我变形最严重.");
2、效果展示
将上述代码部署至静态服务器或者直接在浏览器中运行,可以看到以下的空间可视化效果。
赤道及低纬度地区圆展示示意图
通过观察可以看到,从赤道地区到两极的扩展过程当中,在 这个纬度区间内,圆的整体展示效果还是比较好的,变形的情况不严重。下面来看中高纬度下,圆的空间展示情况是什么样子的。
中高纬度地区圆可视化效果
通过上图可以很直观的看到,随着纬度的增加,中高纬度地区的圆逐渐开始了形变,而在极地地区达到了最大。而变形也是跟着经纬度投影的原理一致。赤道最小,而两极最大。
3、经纬度投影下的圆修正
如果当前系统已经是采用了经纬度投影的方式,又不能一下子改变底图的投影方式。这种情况下该如何解决这种问题呢?这里参考了一个朋友分享的解决思路。大致的思路就是,在中高纬度地区,对于圆的生成不采用Leaflet等自己的原生api的创建方式,而是通过多边形近似计算的方式,通过自己计算选点,生成一个接近圆的多边形,以此来避免在经纬度投影下的图形变形的问题。具体的算法代码如下:
function buildCirclePolygon(lat,lng,color){
//这里采用自定义生成
var radius = 4;
//点集
var parts = [];
//计算圆的边缘所有点
for (var i = 0; i < 360; i++) {
var radians = (i + 1) * Math.PI / 180;
var circlePoint = [Math.cos(radians) * radius + lat, Math.sin(radians) * radius + lng];
parts[i] = circlePoint;
}
//生成面,近似圆
var polygon = L.polygon(parts, {
color: color
});
return polygon;
}
在需要生成圆的地方调用以上的方法,请注意,这里的方法中,第一个参数表示纬度,第二个参数表示经度。
buildCirclePolygon(34,108,'blue').addTo(mymap);
buildCirclePolygon(66.884766,108.017578,'blue').addTo(mymap);
来看一下经过自主模拟的圆生成的图形叠加到地图后,在高纬度的效果是怎么样的?
修正圆在中高纬度的可视化效果
在上面的效果图中可以看到,黄色标色修正圆,蓝色表示原始的圆。可以很直观的看到,修正圆已经很好的可视化效果。
三、Web墨卡托投影下空间信息展示
本节主要讲解在Web墨卡托投影下如何进行空间信息展示,以圆为例,是否会遇到在经纬度投影下碰到的问题。
1、底图引用
由于要调整使用Web墨卡托的投影方式,因此这里需要重新定义底图。定义的方式如下所示:
var mymap = L.map('mapid').setView([29.052934, 104.0625], 5);
L.tileLayer('http://localhost:8086/data/basemap_water/{z}/{x}/{y}.png', {
maxZoom: 16,
attribution: 'Map data © <a href="">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}).addTo(mymap);
圆的空间信息添加方式不变,来看一下实际的效果:
墨卡托投影下圆可视化示意图
通过观察上述的效果可以看到,当地图采用Web墨卡托投影时,在地图上展示圆几乎是没有变形的。在中高纬度地区也是正常的。
2、自定义生成圆
虽然在墨卡托投影下,圆没有发生变更,但是我们依然想了解下,如果进行修正数据叠加后会是什么效果。
中高纬度修正圆展示示意图
可以看到,在web墨卡托投影下,经过修正的圆反而会有变形。通过图形的对比相信大家对两种不同的投影规则下的图形展示已经有了比较直观的认识。
总结
通过上述两种不同投影类型中对圆的加载和修正展示。相信大家对空间对象的展示已经比较清楚了。如果是经纬度投影,在中高纬度地区,空间信息会变形,如果需要按原始图形展示,需要自己修正。而采用Web墨卡托投影,则不需要做任何处理。
以上就是本文的主要内容,本文主要讲解GIS中的两种投影方式和区别,结合空间对象信息的展示里讲述不同投影方式下图形的形变问题,然后通过代码讲解如果遇到形变问题的对应解决办法。希望对遇到这种问题的朋友有一定的帮助。行文仓促,定有不足之处,如有任何问题或者不当之处,欢迎各位朋友专家在评论区批评指出,不深感谢。
博文在编写过程中参考了相关文章,站在巨人的肩膀上才能看得更远,在此表示感谢。
1、GIS基础一: GIS中的WGS84地理坐标系和墨卡托投影坐标系。
2、【gis技术】web墨卡托投影和经纬度直投的差别。
3、不得不说的地图投影那些事儿。