GIS小知识-由对GCJ-02问题引出的坐标系相关概念
坐标系
在介绍GCJ-在02之前,让我们先了解一下坐标系的常见术语
直角坐标系
直角坐标系,又称笛卡尔坐标系,通过一对数字坐标在平面上唯一指定每个点。坐标系是两个固定的垂直和向线点的符号距离,由相同长度的单位测量。
平面坐标系
表示点的平面位置。我国一般采用高斯-克吕格平面直角坐标系,以高斯-克吕格投影分带的中央子午线为纵轴和赤道投影为横轴,简称高斯平面坐标系。坐标纵轴为x,从原点向北为正;坐标横轴为y,从原点向东为正。点的平面坐标是(x,y)。选择任何子午线为坐标纵轴和高斯投影面的坐标系,或选择高斯-克吕格投影带的中央子午线为纵轴和任何高程坐标系,属于当地(矿区)平面坐标系。如果选择坐标原点和x轴方向,则称为独立平面坐标系。
大地坐标系
地球不是标准球,而是南北两极略扁赤道略胖的胖子。
:用平静的海面描述地球就是假设地球表面都是水,且风平浪静。
:椭球表面在每个坐标平面上的投影是椭圆,你可以用它的方程来验证。旋转椭球表面可以用椭圆绕对称轴旋转,因此其在坐标平面上的投影是椭圆。
:旋转椭球面的中心坐标系,又称协议地球坐标系,是唯一的。
:也就是说,椭球中心不在地球纹理的坐标系。(地图为人民服务,每个国家都希望地图尽可能准确地描述国家的地形,所以一些国家移除纹理,让当地表面粘贴国家的土地,尽量减少高误差)
:(Geodetic coordinate System)以椭球面为基准面的坐标基准面的坐标,地面点P的位置采用地面经度L、地球纬度B和地球高H表示。地心坐标系和参心坐标系是地球坐标系的一种。
大地坐标系在中国很常见
2000国家大地坐标系
2000国家大地坐标系,是我国当前最新的国家大地坐标系,英文名称为China Geodetic Coordinate System 英文缩写为2000英文CGCS2000。2000国家地球坐标系的原点是整个地球的质量中心,包括海洋和大气;2000国家地球坐标系的Z轴从原点指向历元2万.0地球参考极的方向,由国际时间局给出的历元指向1984.0的初始方向计算,定向时间进化保证了与地壳相比没有残余的全球旋转,X格林尼治参考子午线和地球赤道面,轴由原点指向.0)的交点,Y轴与Z轴、X轴构成右手正交坐标系。
西安80坐标系
西安80坐标系是指1980年西安坐标系,又称西安大地原点。坐标系位于陕西省泾阳县永乐镇县永乐镇,位于西安西北约60公里,故称1980年西安坐标系,又称西安原点。基准面采用1952-1979年确定的黄海平均水面(即1985年国家高程基准)。西安80坐标系为参心坐标系,长轴6378140m,短轴6356755,扁率1/298.25722101。
北京54坐标系
北京54坐标系(BJZ54)是指北京54坐标系为参心大地坐标系,大地上的一点可用经度L54、纬度M54和大地高H54定位,是基于克拉索夫斯基椭球,局部平差后产生的坐标系。1954年,北京坐标系可以看作是1942年前苏联坐标系的延伸。它的起源不是北京,而是普尔科沃,前苏联。
WGS84坐标系
WGS84:World Geodetic System 1984,是为GPS使用全球定位系统建立的坐标系统。第一次通过世界各地卫星观测站观测到的坐标建立WGS84的精度为1-2m,1994年1月2日,通过10个观测站GPS改正了测量方法,得到了改正WGS84(G730),G表示由GPS730表示测量GPS第730周。1996年,National Imagery and Mapping Agency (NIMA) 美国国防部 (U.S.Departemt of Defense, DoD)制作新的坐标系统。这样实现了新的WGS版本:WGS(G873)。因为加入USNO改正站和北京站,东部方向增加31-39cm 的改正。所有其他坐标都在1分米内修正。第三次精化:WGS84(G1150)于2002年1月20日启用。
投影坐标系
PCS(Projection Coordinate System)
地球坐标系中不能准确计算面积,因为不同纬度的弧长不同,赤道附近最长,两极附近最短。
人们想到了投影坐标系,以建立坐标系,使地图分析和空间分析能够定量计算。
地球是一个球面,地图必须是一个平面,所以地球的表面必然会产生,曲面必须采用一定的数学方法展成平面,变形较小,这需要一定的数学方法来实现。
投影变换(地图投影)
投影变换(projection transformation)它是将一个地图投影点的坐标转换为另一个地图投影点的坐标的过程。研究投影点坐标转换的理论和方法。在地图投影过程中,将球上的元素(距离、角度、图形)投影到平面上,与原始距离、角度和图形不同,即。
投影变形形式:。
地图投影:
- 等角投影-投影前后角度相等,但长度和面积变形;
- 等距投影-投影前后长度相等,但角度和面积变形;
- 等积投影-投影前后面积相等,但角度和长度变形。
因此可以认为:
投影方式就是上面说的数学方法,不同的投影有不同的用途,也就有了不同的名字。
投影坐标系的基础是,没有地理坐标系,就没有所谓的投影坐标系。投影坐标系是地理坐标系中地物投射到特定投影表面的结果。
墨卡托投影
其投影面为垂直椭圆柱面,投影面与地轴方向一致,也称为正轴等角切割/切割圆柱投影。
意思是可以切割圆柱,即球体和椭圆柱面相切;也可以切割圆柱,即球体和椭圆柱面相切。
百度地图和Google Maps墨卡托投影采用投影方法。
高斯-克吕格投影 19日,德国数学家、物理学家、天文学家高斯投影 世纪20 德国大地测量学家克吕格于1912年制定后 2000年补充了投影公式,因此被称为高斯-克吕格投影。其投影面为椭圆柱面。假设椭圆柱垂直于地轴,投影面与之相切,即横轴墨卡托,也可称为等角横轴切椭圆柱投影。
垂直有三条线,中间是投影中心线,根据不同的方法,可分为3度带和6度带。
3度带和6度带的起算经线不同。
6°分带法:从格林威治零度经线开始,每6次°全球分为60条投影带。
3°分带法:从东经1°30′起,每3°将世界划分为120个投影带。
高斯-克吕格投影有三个主要特点:
- 投影后的地图,角度不变,面积不变。离中央经线越远,面积变化越大。该投影适用于导航。
- 投影椭圆柱面水平;
- 椭圆柱面与椭球体相切。
我国1:2.5万1:50万地形图采用6度分带法;1:50001:10000地形图采用3度分带法。
通用横轴墨卡托投影
你也应该听说过它的江湖别称:UTM投影,它与高斯克吕格投影特别相似,但它是一个切割柱,即球体和椭圆柱表面。因此,它也被称为横轴和其他角切割柱投影。
中国的遥感图像通常被使用UTM投影。
坐标系转换
坐标转换是空间实体的位置描述,是从一个坐标系统到另一个坐标系统的过程。通过建立两个坐标系统之间的对应关系来实现。它是建立地图数学基础的基本步骤。当两个或两个以上的坐标转换时,维度空间由极坐标的相对参考来确定。
七参数
当两个不同的三维空间直角坐标系(投影坐标系)转换时,通常使用七个参数模型(数学方程组),其中有七个未知参数。两个椭球间的坐标转换一般采用七参数布尔莎模型,即 X 平移, Y 平移, Z 平移, X 旋转(WX), Y 旋转(WY), Z 旋转(WZ),尺度变化(DM )。需要在一个地区获得七个参数 3 以上已知点。如果区域范围不大,最远点之间的距离不大于30Km( 经验值 ) ,这可以用三参数,即 X 平移, Y 平移, Z 平移,而将 X 旋转, Y 旋转, Z 旋转,尺度变化面DM视为 0 。
火星坐标GCJ-02
了解了前置的坐标系知识后,这里我们终于可以开始讨论GCJ-02,又称火星坐标
火星坐标系,也叫,正式名称为「」。是由中国国家测绘局2002年制订的地理信息系统的坐标系统。
我国规定国内出版的各种地图系统(包括电子形式),必须至少采用“GCJ02”对地理位置进行首次加密。
所以在中国所有的地图必须使用“GCJ02”对地理位置进行首次加密。比如谷歌中国、高德、腾讯都在用这个坐标系。
它主要目的不是对GPS定位进行偏移,而是对高精度地图进行偏移,降低其精度。定位信息不是重中之重,高精度地图则是国家机密。而对定位进行偏移只不过是为了与脱密后的地图保持同步性,从而不影响导航等公开领域的应用。
目标是通过保密处理,对高精度数据进行偏移,使其成为低精度数据,从而降低国外导弹精准打击的准度,以保护我国、我军的重要基础设施。
GCJ-02坐标系 / 火星坐标系的存在没有现时意义,因为火星坐标系对内(测绘领域内部),偏移距离过大,导致某些数据产生的成果都是错的,也就;对外,由于现阶段公式已被破解,实际上已。
扩展文档
java版坐标转换方法
WGS84、GCJ02、BD09坐标之间的转换方法
/** * * 坐标系转换工具类 */
public class GPSUtil {
public static double pi = 3.1415926535897932384626;
public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
public static double a = 6378245.0;
public static double ee = 0.00669342162296594323;
public static double transformLat(double x, double y) {
double 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 * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
public static double transformLon(double x, double y) {
double 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 * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
public static double[] transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[] {
lat, lon };
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[] {
mgLat, mgLon };
}
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
if (lat < 0.8293 || lat > 55.8271)
return true;
return false;
}
/** * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System * * @param lat * @param lon * @return */
public static double[] gps84_To_Gcj02(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new double[] {
lat, lon };
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 105.0, lat - 35.0);
double radLat = lat / 180.0 * pi;
double magic = Math.sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = Math.sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new double[] {
mgLat, mgLon };
}
/** * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return * */
public static double[] gcj02_To_Gps84(double lat, double lon) {
double[] gps = transform(lat, lon);
double lontitude = lon * 2 - gps[1];
double latitude = lat * 2 - gps[0];
return new double[] {
latitude, lontitude };
}
/** * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标 * * @param lat * @param lon */
public static double[] gcj02_To_Bd09(double lat, double lon) {
double x = lon, y = lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta) + 0.0065;
double tempLat = z * Math.sin(theta) + 0.006;
double[] gps = {
tempLat, tempLon };
return gps;
}
/** * * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param * bd_lat * @param bd_lon * @return */
public static double[] bd09_To_Gcj02(double lat, double lon) {
double x = lon - 0.0065, y = lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
double tempLon = z * Math.cos(theta);
double tempLat = z * Math.sin(theta);
double[] gps = {
tempLat, tempLon };
return gps;
}
/** * 将gps84转为bd09 * * @param lat * @param lon * @return */
public static double[] gps84_To_bd09(double lat, double lon) {
double[] gcj02 = gps84_To_Gcj02(lat, lon);
double[] bd09 = gcj02_To_Bd09(gcj02[0], gcj02[1]);
return bd09;
}
public static double[] bd09_To_gps84(double lat, double lon) {
double[] gcj02 = bd09_To_Gcj02(lat, lon);
double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
// 保留小数点后六位
gps84[0] = retain6(gps84[0]);
gps84[1] = retain6(gps84[1]);
return gps84;
}
/** * 保留小数点后六位 * * @param num * @return */
private static double retain6(double num) {
String result = String.format("%.6f", num);
return Double.valueOf(result);
}
public static void main(String[] args) {
String str = "113.2362898,21.9053547;113.2353993,21.9076491;113.2352312,21.9079071;113.2345464,21.9086146;113.2342782,21.9089879;113.2341989,21.9093424;113.2342173,21.9101219;113.2345064,21.9118989";
String[] arr = str.split(";");
String res = "";
for(String s : arr) {
String[] lntlat = s.split(",");
Double lnt = Double.parseDouble(lntlat[0]);
Double lat = Double.parseDouble(lntlat[1]);
double[] bd09 = gps84_To_bd09(lnt, lat);
res += bd09[0] + "," + bd09[1] + ";";
}
res = res.substring(0, res.lastIndexOf(";"));
System.out.println(res);
}
}