地图的失真

有时候,看地图会误判,地图上俄罗斯过大(6400公里),非洲过小(7200公里)。

x6Rol9.png

这并不是地图画错了,而是地球为球形,投影成平面地图会失真,高纬度地区被拉长了。

1. 地理坐标系

地理坐标系统(Geographic Coordinate System),是一种球面坐标,是使用三维球面来定义地球表面位置,以实现通过经纬度对地球表面点位引用的坐标系。表示单位为度;常规叫为东经、西经、南纬、北纬。目前国际上最通用的标准是WGS84坐标系,我国当前最新的标准是国家大地坐标系(CSCS2000),CSCS2000与WGS84相差几厘米,对于一般的工程测量,可以认为两者是一致的。

x6RISJ.png

2. 投影坐标系

投影坐标系统(Projection Coordinate System),是一种平面坐标。利用一定数学法则把地球表面的经、纬线转换到平面上投影坐标系使用;基于X,Y值的坐标系统来描述地球上某个点所处的位置。这个坐标系是从地球的近似椭球体投影得到的;表示单位为米。

x6R4W4.png

3. web墨卡托投影

Web Mercator(墨卡托)是以整个世界范围,赤道作为标准纬线,本初子午线作为中央经线,两者交点为坐标原点,向东北为正,向西南为负。在投影过程中,将表示地球的参考椭球体近似的作为正球体处理(正球体半径R = 椭球体半长轴a)。由于墨卡托投影当纬度接近两级时,y值趋向于无穷大,为了方便,就把Y轴的取值范围也限定在X轴相同范围, 形成正方形地图,即Web Mercator投影。
目前互联网上大部分全国公众地图网站均采用web墨卡托投影,因为目前webGIS中前端应用的投影坐标系基本都为web墨卡托投影。所以俄罗斯看起来比非洲要大,这是地图的失真。

4. WGS 84坐标转web墨卡托坐标

转换公式:

x = lon*20037508.34/180

y = log(tan((90+lat)*PI/360))/(PI/360)*20037508.34/180

注:lon为经度,lat为纬度,PI为π。

5. WGS84坐标与web墨卡托投影的转换(JavaScript)

/*
经纬度转墨卡托
@params
lonlat     转换前经纬度坐标的对象
*/
export function lonlat2mercator(lonlat) {
	var mercator = {
		x: 0,
		y: 0
	};
	var x = lonlat.x * 20037508.34 / 180;
	var y = Math.log(Math.tan((90 + lonlat.y) * Math.PI / 360)) / (Math.PI / 180);
	y = y * 20037508.34 / 180;
	mercator.x = x;
	mercator.y = y;
	return mercator;
}
 
/*
墨卡托转经纬度
@params
lonlat     转换前墨卡托坐标的对象
*/
export function mercator2lonlat(mercator) {
	var lonlat = {
		x: 0,
		y: 0
	};
	var x = mercator.x / 20037508.34 * 180;
	var y = mercator.y / 20037508.34 * 180;
	y = 180 / Math.PI * (2 * Math.atan(Math.exp(y * Math.PI / 180)) - Math.PI / 2);
	lonlat.x = x;
	lonlat.y = y;
	return lonlat;
}

6. WGS84坐标与web墨卡托投影的转换(Python)

#!/usr/bin/python
# -*- coding: utf-8 -*-
#wgs84-WebMercator
import math
def wgs84toWebMercator(lon,lat):
    x =  lon*20037508.342789/180
    y =math.log(math.tan((90+lat)*math.pi/360))/(math.pi/180)
    y = y *20037508.34789/180
    return x,y
#WebMercator-wgs84
def webMercator2wgs84(x,y):
    lon = x/20037508.34*180
    lat = y/20037508.34*180
    lat= 180/math.pi*(2*math.atan(math.exp(lat*math.pi/180))-math.pi/2)
    return lon,lat
 
if __name__=="__main__":
    xylist = [12980914.6304,4912134.49832]
    transform1 = webMercator2wgs84( xylist[0], xylist[1])
    print('WebMercator坐标:',xylist[0], xylist[1])
    print('转换后WGS84坐标:',transform1[0],transform1[1])
    lonlatlist = [116.650155437,40.377151862]
    transform2 = wgs84toWebMercator(lonlatlist[0], lonlatlist[1])
    print('WGS84坐标:',lonlatlist[0], lonlatlist[1] )
    print('转换后WebMercator坐标:',transform2[0],transform2[1] )

7.小结

用以°为单位表示,是地理坐标。

用以米为单位表示,是投影坐标。

它们之间可以互转。下图是地理坐标与投影坐标的各个国家面积对比,深色是WGS84,浅色是墨卡托投影。

x6RTyR.png

打广告:个人公众号:《remote sensing》,关注点赞不吃亏呀,嘻嘻。