地图投影
对于接触互联网地图的同学来说,最开始接触的恐怕就是坐标转换的过程了。由于地球是个近似椭球的形状,有各种各样的椭球模型来模拟地球,最著名的也就是GPS系统使用的WGS84椭球了。但是这些椭球体的坐标使用的是经纬度,单位是角度。目前我们的地图大多是二维平面上展示,使用角度为基础来计算多有不便,所以有众多数学家提出各种不同的转换方式来将经纬度表示的位置转换成平面坐标,这个转换过程地图学上成为投影。投影的方式多种多样,对我们做互联网地图的来说,最重要的就是墨卡托投影的变体——Web墨卡托投影。我们先来看一下墨卡托投影的转换过程
(以赤道本初子午线为原点)
投影完毕后的结果就是:
先不要头疼数学公式,已经有很多类库做好了代码实现,比如leaflet:
L.Projection.Mercator ={
R:6378137,
R_MINOR:6356752.314245179,
bounds: L.bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),
project:function(latlng) {var d = Math.PI / 180,
r= this.R,
y= latlng.lat *d,
tmp= this.R_MINOR /r,
e= Math.sqrt(1 - tmp *tmp),
con= e *Math.sin(y);var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);
y= -r * Math.log(Math.max(ts, 1E-10));return new L.Point(latlng.lng * d *r, y);
},
unproject:function(point) {var d = 180 /Math.PI,
r= this.R,
tmp= this.R_MINOR /r,
e= Math.sqrt(1 - tmp *tmp),
ts= Math.exp(-point.y /r),
phi= Math.PI / 2 - 2 *Math.atan(ts);for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {
con= e *Math.sin(phi);
con= Math.pow((1 - con) / (1 + con), e / 2);
dphi= Math.PI / 2 - 2 * Math.atan(ts * con) -phi;
phi+=dphi;
}return new L.LatLng(phi * d, point.x * d /r);
}
};
接下来我们说一下互联网地图真正使用的投影——Web墨卡托或者也叫球形墨卡托。一般来说按照传统地图学的要求,一个投影坐标系都要有一个对应的椭球体,比如从WGS84的坐标转换成国内腾讯地图或者百度地图的坐标,都是要经过一步椭球体转换成gcj02椭球下的经纬度然后才能打点。所以有没有小伙伴在开发中使用Geolocation接口获取的经纬度直接传入上面地图api中打点发现误差很大?就是因为没有转成gcj02椭球下的经纬度。但是web墨卡托这个投影其实并不符合地图学的要求,它没有对应的椭球体,它是谷歌自己造出来的(因为简单),也可以说对任何椭球体都适用,但这种时候我们在表达一个位置信息时严格来说应当这样表达:***椭球下的Web墨卡托投影坐标是***。
好了现在来说一下web墨卡托的转换方式:
/** @namespace Projection
* @projection L.Projection.SphericalMercator
*
* Spherical Mercator projection — the most common projection for online maps,
* used by almost all free and commercial tile providers. Assumes that Earth is
* a sphere. Used by the `EPSG:3857` CRS.*/L.Projection.SphericalMercator={
R:6378137,
MAX_LATITUDE:85.0511287798,
project:function(latlng) {var d = Math.PI / 180,
max= this.MAX_LATITUDE,
lat= Math.max(Math.min(max, latlng.lat), -max),
sin= Math.sin(lat *d);return newL.Point(this.R * latlng.lng *d,this.R * Math.log((1 + sin) / (1 - sin)) / 2);
},
unproject:function(point) {var d = 180 /Math.PI;return newL.LatLng(
(2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) *d,
point.x* d / this.R);
},
bounds: (function() {var d = 6378137 *Math.PI;return L.bounds([-d, -d], [d, d]);
})()
};
相对来说这个计算方法简单一些,但是这种投影有一些缺点,比如维度投影范围只能在-85~85之间,一般来说没什么关系,反正一般人不会闲的没事跑南北极去。同时由于南北极特殊的位置,通常有一些专门的地图来表达。
地图的组织方式
可以观察一下腾讯地图在展示时,通常是一个正方形一个正方形的出现,这些正方形地图上成为瓦片