问题形容
当我的项目须要对接 GIS 图层时,发现它的坐标系为 EPSG:4490,而 mapbox 反对的坐标系是 EPSG:3857。mapbox 对接 wms 时 bbox 截取的地图块的经纬度范畴,在对接时可将其 EPSG:3857 通过拦挡申请转换为 EPSG:4490 的坐标系,获取失去 GIS 对应的图层瓦片。
- EPSG:4326
大地坐标系,WGS84- EPSG:4490
大地坐标系,cgcs2000- EPSG:3857
投影坐标系,墨卡托投影
形式 1: 通过全局拦挡 fetch 申请的形式
function injectFetch() {const newFetch = Object.getOwnPropertyDescriptor(window, 'fetch');
Object.defineProperty(window, 'fetch', {value(a, b) {if (a instanceof Request && a.url.includes('/GISServices/')) {const u = new URL(a.url);
// 解析 bbox 参数
const bbox = u.searchParams.get('bbox') ?? '';
const [lon1, lat1, lon2, lat2] = bbox.split(',');
// 坐标系转换:墨卡托 ->GPS
const p1 = mercator2LonLat([Number(lon1), Number(lat1)]);
const p2 = mercator2LonLat([Number(lon2), Number(lat2)]);
const newBBOX = p1.concat(p2).join(',');
u.searchParams.set('bbox', newBBOX);
Object.defineProperty(a, 'url', {value: decodeURIComponent(u.toString()),
});
}
return newFetch.value.apply(this, [a, b]);
},
});
}
代理拦挡申请的形式
- 可通过 node 写一个代理服务,拦挡瓦片申请服务。参考 webpack 的配置代理服务的形式,通过
http-proxy-middleware
来实现,而后可通过把 node 服务打包为 exe 后部署服务器来实现。
坐标系简介
通常有两种坐标系 天文坐标系(geographic coordinate systems)和 投影坐标系(projected coordinate systems)
天文坐标系
坐标系 | 简介 |
---|---|
WGS-84 坐标系 | 地心坐标系,GPS 原始坐标体系 |
GCJ-02 坐标系 | 国测局坐标,火星坐标系,应用:高德、腾讯、Google 中国地图 |
CGCS2000 坐标系 | 国家大地坐标系 |
BD-09 坐标系 | 百度地图所采纳的坐标系,由 GCJ-02 进行进一步的偏移算法失去 |
投影坐标系(Projected coordinate systems)
天文坐标系是三维的,咱们要在地图或者屏幕上显示就须要转化为二维,这被称为投影(Map projection)。不言而喻的是,从三维到二维的转化,必然会导致变形和失真,失真是不可避免的,然而不同投影下会有不同的失真,这让咱们能够有得抉择。罕用的投影有等矩矩形投影(Platte Carre)和墨卡托投影(Mercator)
- 墨卡托投影: 投影后依然是圆形,然而在高纬度时物体被重大放大了
- 等距投影: 物体的大小变动不是那么显著,然而图像被拉长了
墨卡托坐标系与 GPS 坐标系转换工具办法
// 墨卡托坐标转 GPS 坐标
function mercator2LonLat(mercator) {const x = (mercator[0] / 20037508.34) * 180;
let y = (mercator[1] / 20037508.34) * 180;
y = (180 / Math.PI) * (2 * Math.atan(Math.exp((y * Math.PI) / 180)) - Math.PI / 2);
return [x, y];
}
// GPS 坐标转墨卡托坐标
function lonLat2Mercator(lonlat) {const x = (lonlat[0] * 20037508.34) / 180;
let y = Math.log(Math.tan(((90 + lonlat[1]) * Math.PI) / 360)) / (Math.PI / 180);
y = (y * 20037508.34) / 180;
return [x, y];
}