参考链接:
https://www.cnblogs.com/onsummer/p/7451128.html
https://cnodejs.org/topic/564c0a27e4766d487f6fe38d
前言:GIS跟几何关系十分密切,能有丰富的空间想象能力,将有助你更好的理解接下来的知识~
一、经纬度和地理坐标系(GCS)
1、地球
- 为了能让地球出现在数学家的公式里,我们曾经走过了2个阶段:用平静的海面描述地球——用虚拟的旋转椭球面描述地球表面。
- “假设地球表面都是水,当海平面风平浪静没有波澜起伏时,这个面就是大地水准面。”
- 注意区分椭球面和旋转椭球面这两个数学概念,在GCS中都是旋转椭球面
- 旋转椭球面的标准方程:(x2+y2)/a2+z2/b2=1
- 由此我们可以下定义,GIS坐标系中的椭球,如果加上高程系,在其内涵上就是GCS(地理坐标系统)。其度量单位就是度分秒。
2、参心坐标系、地心坐标系
- 物体均有其质心,处处密度相等的物体的质心在其几何中心
- 由地球的唯一性和客观存在,以地球质心为旋转椭球面的中心的坐标系,叫地心坐标系(协议地球坐标系)
- GPS中的坐标系叫瞬时地球坐标系
- 人为的把地球的质心“移走”,将局部的表面“贴到”该国的国土,使之高程误差尽量减小到最小。就出现了所谓的“参心坐标系”。即椭球中心不在地球质心的坐标系。
- 我国常用的参心系及对应椭球
北京54坐标系:克拉索夫斯基椭球体
西安80坐标系:IAG75椭球体
- 我国常用的地心系及对应椭球:
WGS84坐标系:WGS84椭球体(GPS星历的坐标系,全球统一使用,最新版于2002年修正)
CGCS2000坐标系:CGCS2000椭球体(事实上,CGCS2000椭球和WGS84椭球极为相似,偏差仅有0.11mm,完全可以兼容使用)
3、我国常见GCS
此处不介绍具体来历,需要了解的童鞋自行百度,Google
3.1北京54坐标系(参心)
- 椭球体:Krasovsky椭球(克拉索夫斯基椭球)
- 极半径b=6 356 863.0187730473 m
- 赤道半径a=6 378 245m
- 扁率=1/298.3
- 高程系:56黄海系
3.2西安80坐标系(参心)
- 椭球体:IAG椭球
- 极半径b=6 356 755m
- 赤道半径a=6 378 140m
- 扁率=1/298.25722101
- 高程系:85黄海系
- 大地原点设在我国中部的陕西省泾阳县永乐镇
3.3WGS84坐标系(地心)
- 解决GPS定位而产生的全球统一的一个坐标系
- 椭球体:WGS84椭球
- 极半径b=6 356 752.314 245 179 5m
- 赤道半径a=6 378 137 m
- 扁率=1/298.257223563
- 高程系:根据国家需求定
3.4CGCS2000坐标系(地心)
- 全球地心坐标系在我国的具体体现
- 椭球体:CGCS2000坐标系
- 极半径b=6 356 752.314 140 355 8m
- 赤道半径a=6 378 137m
- 扁率=1/298.257222101
- 高程系:85黄海系
【注】CGCS2000的定义与WGS84实质一样。采用的参考椭球非常接近。扁率差异引起椭球面上的纬度和高度变化最大达0.1mm。当前测量精度范围内,可以忽略这点差异。可以说两者相容至cm级水平
EPSG对世界的每一个地方都制定了地图,但是由于座标系不同,所以地图也各不相同。
所有的EPSG均可查到的神奇网站~~https://epsg.io/
二、平面坐标和投影坐标系(PCS)
1、提出问题
- 如何用经纬度表达一块地的面积?
- 如何建立一个新的坐标系使得地图分析、空间分析得以定量计算?
2、什么是投影
- 光线打到物体上,使得物体产生的阴影形状,就叫它的投影
- 地图:把投影的平面改为曲面,产生了不同的投影,比如投射到一个圆锥面上,一个圆柱面上,一个平面上...等等
- PCS是基于存在的GCS的。即:PCS=GCS+投影方式
3、我国常用的投影方式
- 高斯克吕格(Gauss Kruger)投影=横轴墨卡托(Transverse Mercator)投影
- 墨卡托(Mercator)投影
- 通用横轴墨卡托(UTM)投影
- Lambert投影
- Albers投影
- Web Mercator(网络墨卡托)投影
3.1高斯克吕格投影/横轴墨卡托投影
- 投影面是椭圆柱面
- 假设椭圆柱躺着,和地轴垂直,而且投影面与之相切,就是横轴墨卡托了
- 等角/横/切椭圆柱/投影
- 投影合适用于导航
- 适用比例尺:1:2.5万--1:100万等使用6度分带法;1:5000--1:10000使用3度分带法
a、中央那条黑线就是投影中心线,与椭圆柱面相切
b、这条线逢360°的因数就可以取,一般多用3度带(120个)、6度带(60个)
c、Y方向(赤道方向)前需要加投影带号
3.2墨卡托投影
- 正轴等角切/割圆柱投影
- 高斯克吕格的圆柱面竖起来
3.3通用横轴墨卡托投影(UTM投影)
- 横轴等角割圆柱投影
- UTM投影=0.9996高斯投影
- 高斯克吕格的投影面是与椭球面相切的,这货与椭球面相割
- 大地测量和地形测量的投影基础
- 我国各种遥感影像的常用投影
3.4Lambert投影(兰伯特投影)
- 我国地形图常用投影,比如1:400万基础数据
- 自定义投影
- 等角圆锥投影
- 圆锥的方向和地轴的方向:正轴、横轴、斜轴
3.5Albers投影(阿伯斯投影)
- 正轴等积割圆锥投影
- 我国各省市的投影
- 与Lambert投影的区别就在前者是等角,后者是等积
3.6Web墨卡托(WebMercator投影)
- 由Google提出的、为了自家GoogleMap而专门定义的一种投影,属于墨卡托投影
- 经常被百度地图等网络地图采用
三、GCS与PCS相互转化(三参数、七参数)(包含SuperMap iDesktop转换)
1、GCS转GCS
- 进行平移、旋转、缩放三步,可以无序进行
1.1利用SuperMap iDesktop转换(WGS84转西安80)
a、打开某数据源,其中具有地理坐标系为WGS84的数据集
具有地理坐标系为WGS84的数据集.png
b、重设坐标系信息
重设坐标系.png
c、重新打开数据集即可查看
西安80坐标系.png
d、相关坐标系参数可在重设弹窗中查看,WGS84转西安80,是属于7参数转换(地心转参心),在SuperMap iDesktop中是默认的,也可根据数据情况来进行坐标系参数的修改
2、GCS进行投影
- 重设投影坐标系即可
- 如果所需投影系没有自己需要的GCS,就新建一个
3、PCS转PCS(重投影)
- 三参数即可
4、根据ArcGIS总结如下(网扒图。。)
坐标系转换.png四、火星坐标系
- 火星坐标这个东西很常见,出现在互联网地图上。例如百度、腾讯、谷歌等地图。
- 出于保密等政治因素,地图的GCS坐标值,会被一种特殊的数学函数加密一次,会偏离真实坐标数百米的距离,但是反馈到用户端的却是正确的位置信息(也就是说你拿到GCS坐标也没用,拿GPS到实地跑跟拿着地图定位,可能会偏出几十米甚至一百米的距离)。
1、火星坐标 (GCJ-02)也叫国测局坐标系
- 中国标准,从国行移动设备中定位获取的坐标数据使用这个坐标系
- 国家规定: 国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。
2、百度坐标 (BD-09)
- 百度标准,百度 SDK,百度地图,Geocoding 使用
- 百度又在火星坐标上来个二次加密
3、coordtransform 坐标转换
- Github地址:https://github.com/wandergis/coordtransform
- npm地址:https://www.npmjs.com/package/coordtransform
3.1安装(install)
npm install coordtransform
3.2示例用法(Example&Usage)
3.2.1 NodeJs用法
//国测局坐标(火星坐标,比如高德地图在用),百度坐标,wgs84坐标(谷歌国外以及绝大部分国外在线地图使用的坐标)
var coordtransform=require('coordtransform');
//百度经纬度坐标转国测局坐标
var bd09togcj02=coordtransform.bd09togcj02(116.404, 39.915);
//国测局坐标转百度经纬度坐标
var gcj02tobd09=coordtransform.gcj02tobd09(116.404, 39.915);
//wgs84转国测局坐标
var wgs84togcj02=coordtransform.wgs84togcj02(116.404, 39.915);
//国测局坐标转wgs84坐标
var gcj02towgs84=coordtransform.gcj02towgs84(116.404, 39.915);
console.log(bd09togcj02);
console.log(gcj02tobd09);
console.log(wgs84togcj02);
console.log(gcj02towgs84);
//result
//bd09togcj02: [ 116.39762729119315, 39.90865673957631 ]
//gcj02tobd09: [ 116.41036949371029, 39.92133699351021 ]
//wgs84togcj02: [ 116.41024449916938, 39.91640428150164 ]
//gcj02towgs84: [ 116.39775550083061, 39.91359571849836 ]
3.2.2 浏览器用法
直接引用目录内的index.js,会有一个coordtransform的全局对象暴露出来,也支持用AMD加载器加载
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>coordTransform</title>
</head>
<body>
<h1>请按F12打开控制台查看结果</h1>
<script src="index.js"></script>
<script>
//国测局坐标(火星坐标,比如高德地图在用),百度坐标,wgs84坐标(谷歌国外以及绝大部分国外在线地图使用的坐标)
//百度经纬度坐标转国测局坐标
var bd09togcj02 = coordtransform.bd09togcj02(116.404, 39.915);
//国测局坐标转百度经纬度坐标
var gcj02tobd09 = coordtransform.gcj02tobd09(116.404, 39.915);
//wgs84转国测局坐标
var wgs84togcj02 = coordtransform.wgs84togcj02(116.404, 39.915);
//国测局坐标转wgs84坐标
var gcj02towgs84 = coordtransform.gcj02towgs84(116.404, 39.915);
console.log(bd09togcj02);
console.log(gcj02tobd09);
console.log(wgs84togcj02);
console.log(gcj02towgs84);
//result
//bd09togcj02: [ 116.39762729119315, 39.90865673957631 ]
//gcj02tobd09: [ 116.41036949371029, 39.92133699351021 ]
//wgs84togcj02: [ 116.41024449916938, 39.91640428150164 ]
//gcj02towgs84: [ 116.39775550083061, 39.91359571849836 ]
</script>
</body>
</html>
五、JavaScript封装方法转换坐标
【注】参数设置正常即可
var GPS = {
PI: 3.14159265358979324,
x_pi: 3.14159265358979324 * 3000.0 / 180.0,
delta: function (lat, lon) {
// Krasovsky 1940
//
// a = 6378245.0, 1/f = 298.3
// b = a * (1 - f)
// ee = (a^2 - b^2) / a^2;
var a = 6378245.0;
var ee = 0.00669342162296594323;
var dLat = this.transformLat(lon - 105.0, lat - 35.0);
var dLon = this.transformLon(lon - 105.0, lat - 35.0);
var radLat = lat / 180.0 * this.PI;
var magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
var sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
return { 'lat': dLat, 'lon': dLon };
},
//WGS-84 to GCJ-02
gcj_encrypt: function (wgsLat, wgsLon) {
if (this.outOfChina(wgsLat, wgsLon))
return new TYLngLat(wgsLon, wgsLat);
var d = this.delta(wgsLat, wgsLon);
return new TYLngLat(wgsLon + d.lon, wgsLat + d.lat);
},
//GCJ-02 to WGS-84
gcj_decrypt: function (gcjLat, gcjLon) {
if (this.outOfChina(gcjLat, gcjLon))
return { 'lat': gcjLat, 'lon': gcjLon };
var d = this.delta(gcjLat, gcjLon);
return new TYLngLat(gcjLon - d.lon, gcjLat - d.lat);
},
//GCJ-02 to WGS-84 exactly
gcj_decrypt_exact: function (gcjLat, gcjLon) {
var initDelta = 0.01;
var threshold = 0.000000001;
var dLat = initDelta, dLon = initDelta;
var mLat = gcjLat - dLat, mLon = gcjLon - dLon;
var pLat = gcjLat + dLat, pLon = gcjLon + dLon;
var wgsLat, wgsLon, i = 0;
while (1) {
wgsLat = (mLat + pLat) / 2;
wgsLon = (mLon + pLon) / 2;
var tmp = this.gcj_encrypt(wgsLat, wgsLon)
dLat = tmp.lat - gcjLat;
dLon = tmp.lon - gcjLon;
if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))
break;
if (dLat > 0) pLat = wgsLat; else mLat = wgsLat;
if (dLon > 0) pLon = wgsLon; else mLon = wgsLon;
if (++i > 10000) break;
}
//console.log(i);
return new TYLngLat(wgsLon, wgsLat);
},
//GCJ-02 to BD-09
bd_encrypt: function (gcjLat, gcjLon) {
var x = gcjLon, y = gcjLat;
var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);
var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);
bdLon = z * Math.cos(theta) + 0.0065;
bdLat = z * Math.sin(theta) + 0.006;
return { 'lat': bdLat, 'lon': bdLon };
},
//BD-09 to GCJ-02
bd_decrypt: function (bdLat, bdLon) {
var x = bdLon - 0.0065, y = bdLat - 0.006;
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);
var gcjLon = z * Math.cos(theta);
var gcjLat = z * Math.sin(theta);
return { 'lat': gcjLat, 'lon': gcjLon };
},
distance: function (latA, logA, latB, logB) {
var earthR = 6371000;
var x = Math.cos(latA * Math.PI / 180) * Math.cos(latB * Math.PI / 180) * Math.cos((logA - logB) * Math.PI / 180);
var y = Math.sin(latA * Math.PI / 180) * Math.sin(latB * Math.PI / 180);
var s = x + y;
if (s > 1)
s = 1;
if (s < -1)
s = -1;
var alpha = Math.acos(s);
var distance = alpha * earthR;
return distance;
},
outOfChina: function (lat, lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
},
transformLat: function (x, y) {
var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
return ret;
},
transformLon: function (x, y) {
var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
return ret;
}
};
网友评论