WGS84、GCJ-02、BD-09、图吧坐标简介及坐标转换实现(java版)

2023-05-16

1.定位系统及如何定位

        现在全球有四个卫星定位系统:美国的全球定位系统GPS(Global Positioning System),俄罗斯的格洛纳斯GIONASS, 欧盟的伽利略系统,我国的北斗。

       每个系统都有几个部分:星载部分、控制部分、以及用户部分。每个卫星在运行中,发送电磁波信息、包含时间、位置等等,用户部分根据定位装置接收信号,然后进行方程解算,由于要更多的解因子,所以GPS系统下,一般三颗卫星信号锁定后才能计算三差解,也就是粗略定位结果了。

2.定位坐标系

       地理坐标系(GeographicCoordinate System):是使用三维球面来定义地球表面位置,以实现通过经纬度对地球表面点位引用的坐标系。一个地理坐标系包括角度测量单位、本初子午线和参考椭球体三部分。在球面系统中,水平线是等纬度线或纬线。垂直线是等经度线或经线。是以经纬度来表示地面点的一种球面坐标系,用度做单位;

       投影坐标系(ProjectedCoordinate System):投影坐标系在二维平面中进行定义。与地理坐标系不同,在二维空间范围内,投影坐标系的长度、角度和面积恒定。投影坐标系始终基于地理坐标系,而后者则是基于球体或旋转椭球体的。在投影坐标系中,通过格网上的 x,y 坐标来标识位置,其原点位于格网中心。每个位置均具有两个值,这两个值是相对于该中心位置的坐标。一个指定其水平位置,另一个指定其垂直位置。这两个值称为 x 坐标和 y 坐标。采用此标记法,原点坐标是 x = 0 和 y = 0,常用m、km做单位;

       地图投影(Map Projection):无论将地球视为球体还是旋转椭球体,都必须变换其三维曲面以创建平面地图图幅(即,按照一定的数学法则将地球椭球面上点的经维度坐标转换到平面上的直角坐标表示的一个过程,将地理坐标系通过地图投影就可以得到对应的投影坐标系)。此数学变换通常称作地图投影。理解地图投影如何改变空间属性的一种简便方法就是观察光穿过地球投射到表面(称为投影曲面)上。想像一下,地球表面是透明的,其上绘有经纬网。用一张纸包裹地球。位于地心处的光会将经纬网投影到一张纸上。现在,可以展开这张纸并将其铺平。纸张上的经纬网形状与地球上的形状不同。地图投影使经纬网发生了变形。地图投影使用数学公式将地球上的球面坐标与平面坐标关联起来。常见的投影方法有:等角投影、等积投影、等距投影以及真方向投影。

 

3.不同地图服务商的坐标系

       出于国家安全考虑不同的国家在规定地图服务提供商在提供地图服务的时候需要将地图数据进行加密。现在比较流行的坐标系有WGS84、GCJ-02、BD-09,且各个坐标之间存在偏差。

        WGS84:World Geodetic System 1984,是为GPS全球定位系统使用而建立的坐标系统。通过遍布世界的卫星观测站观测到的坐标建立,其初次WGS84的精度为1-2m,在1994年1月2号,通过10个观测站在GPS测量方法上改正,得到了WGS84(G730),G表示由GPS测量得到,730表示为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日启用。

        GCJ-02(官方称地形图非线性保密处理算法,俗称火星坐标系、国测局坐标):是一种基于WGS-84制定的大地测量系统,由中国国家测绘地理信息局制定,国家科学技术进步奖一等奖得主李成名开发。此坐标系所采用的混淆算法会在经纬度中加入看似随机的偏移,号称可以促进国家安全。使用GCJ-02记录下的地点在GCJ-02的地图中会显示在正确的位置,然而换成WGS-84的地图或地点记录就可能造成100-700米不等的偏移。

        BD-09:是百度地图使用的地理坐标系,其在GCJ-02上多增加了一次变换,号称“有助保护用户隐私”。

        图吧坐标:图吧是百度坐标乘以10000的结果。

        搜狗坐标:在GCJ-02上进行了加密

4.不同地图服务提供商的坐标系

地图服务

坐标系

坐标系名称

百度地图

百度坐标

BD09

腾讯搜搜地图

火星坐标

GCJ02

搜狐搜狗地图

搜狗坐标*

 

阿里云地图

火星坐标

GCJ02

图吧MapBar地图

图吧坐标

图吧

高德MapABC地图

火星坐标

GCJ02

灵图51ditu地图

火星坐标

GCJ02

Google中国地图

火星坐标

GCJ02

Google(除中国)

大地坐标

WGS84

GPS芯片或者北斗芯片

大地坐标

WGS84

5.不同坐标之间转换java实现

具体实现请参考:https://github.com/pengcao/dc.toolkit.loc.jar/blob/master/src/main/java/dc/toolkit/lbs/util/CoorUtil.java

package dc.toolkit.lbs.util;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import dc.toolkit.lbs.base.entity.Point;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class CoorUtil {
	// radius --- 地球赤道半径
	// x_pi   --- 百度与gcj坐标系之间进行转换的参数
	// a      --- 克拉索夫斯基椭球参数长半轴  
	// ee     --- 克拉索夫斯基椭球参数第一偏心率平方  (a^2 - b^2) / a^2
	private static double radius = 6378.137, x_pi = Math.PI * 3000.0 / 180.0,
			a = 6378245.0, ee = 0.00669342162296594323;
	
	private 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 * Math.PI) + 20.0 * Math.sin(2.0 * x
				* Math.PI)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0
				* Math.PI)) * 2.0 / 3.0;
		ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y
				* Math.PI / 30.0)) * 2.0 / 3.0;
		return ret;
	}

	private 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 * Math.PI) + 20.0 * Math.sin(2.0 * x
				* Math.PI)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0
				* Math.PI)) * 2.0 / 3.0;
		ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x
				/ 30.0 * Math.PI)) * 2.0 / 3.0;
		return ret;
	}



	public static JSONObject delta(double lat, double lng) {
		JSONObject jsonObject = new JSONObject();
		double dLat = transformLat(lng - 105.0, lat - 35.0);
		double dLng = transformLon(lng - 105.0, lat - 35.0);
		double radLat = lat / 180.0 * Math.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) * Math.PI);
		dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI);
		jsonObject.put("lat", dLat);
		jsonObject.put("lng", dLng);
		return jsonObject;
	}	
	
	/**
	 * 
	 * Description: 将google(除中国)坐标转换为高德坐标
	 * Creation time: 2016年8月2日 上午12:08:18
	 *
	 * @param wgsLat
	 * @param wgsLng
	 * @return
	 */
	public static JSONObject wgs2gcj(double wgsLat, double wgsLng) {
		JSONObject jsonObject = new JSONObject();
		JSONObject d = delta(wgsLat, wgsLng);
		jsonObject.put("lat", wgsLat + d.getDouble("lat"));
		jsonObject.put("lng", wgsLng + d.getDouble("lng"));
		return jsonObject;
	}

	/**
	 * 
	 * Description: 将高德坐标转换为google(除中国)坐标
	 * Creation time: 2016年8月2日 上午12:09:11
	 *
	 * @param gcjLat
	 * @param gcjLng
	 * @return
	 */
	public static JSONObject gcj2wgs(double gcjLat, double gcjLng) {
		JSONObject jsonObject = new JSONObject();
		JSONObject d = delta(gcjLat, gcjLng);

		jsonObject.put("lat", gcjLat - d.getDouble("lat"));
		jsonObject.put("lng", gcjLng - d.getDouble("lng"));
		return jsonObject;
	}

	/**
	 * 
	 * Description: 将高德坐标转换为百度坐标
	 * Creation time: 2016年8月2日 上午12:10:18
	 *
	 * @param lat
	 * @param lng
	 * @return
	 */
	public static JSONObject gcj2bd(double lat, double lng) {
		JSONObject jsonObject = new JSONObject();
		double z = Math.sqrt(lng * lng + lat * lat) + 0.00002
				* Math.sin(lat * x_pi);
		double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi);
		double bd_lon = z * Math.cos(theta) + 0.0065;
		double bd_lat = z * Math.sin(theta) + 0.006;
		jsonObject.put("lat", bd_lat);
		jsonObject.put("lng", bd_lon);
		return jsonObject;
	}

	/**
	 * 
	 * Description: 将百度坐标转换为高德坐标
	 * Creation time: 2016年8月2日 上午12:10:40
	 *
	 * @param bd_lat
	 * @param bd_lon
	 * @return
	 */
	public static JSONObject bd2gcj(double bd_lat, double bd_lon) {
		JSONObject jsonObject = new JSONObject();
		double x = bd_lon - 0.0065, y = bd_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 gg_lon = z * Math.cos(theta);
		double gg_lat = z * Math.sin(theta);

		jsonObject.put("lat", gg_lat);
		jsonObject.put("lng", gg_lon);
		return jsonObject;
	}

	// 图吧坐标转换成wgs坐标
	public static JSONObject mapBar2WGS84(double sbar_lng, double sbar_lat) {
		JSONObject jsonObject = new JSONObject();
		
		float bar_lng = ((float)sbar_lng) * 100000 % 36000000;
		float bar_lat = (float)sbar_lat * 100000 % 36000000;
		int lng1 = (int) (-(((Math.cos(bar_lat / 100000)) * (bar_lng / 18000)) + ((Math.sin(bar_lng / 100000)) * (bar_lat / 9000))) + bar_lng);
		int lat1 = (int) (-(((Math.sin(bar_lat / 100000)) * (bar_lng / 18000)) + ((Math.cos(bar_lng / 100000)) * (bar_lat / 9000))) + bar_lat);
		int lng2 = (int) (-(((Math.cos(lat1 / 100000)) * (lng1 / 18000)) + ((Math.sin(lng1 / 100000)) * (lat1 / 9000))) + bar_lng + ((bar_lng > 0) ? 1: -1));
		int lat2 = (int) (-(((Math.sin(lat1 / 100000)) * (lng1 / 18000)) + ((Math.cos(lng1 / 100000)) * (lat1 / 9000))) + bar_lat + ((bar_lat > 0) ? 1: -1));
		double endLat=lat2/100000.0;
		double endLng=lng2/100000.0;
		jsonObject.put("lat", endLat);
		jsonObject.put("lng", endLng);
		return jsonObject;
	}

	// 图吧坐标转换成gcj坐标
	public static JSONObject mapBar2gcj(double bar_lng, double bar_lat) {
		JSONObject wgs = mapBar2WGS84(bar_lng, bar_lat);
		return wgs2gcj(wgs.getDouble("lat"), wgs.getDouble("lng"));
	}

	// 图吧坐标转换成gcj坐标
	public static JSONObject mapBar2bd(double bar_lng, double bar_lat) {
		JSONObject wgs = mapBar2WGS84(bar_lng, bar_lat);
		return wgs2bd(wgs.getDouble("lat"), wgs.getDouble("lng"));
	}
}

6.坐标系坐标转换开源api

1.https://tool.lu/coordinate/

2.http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition

3.https://lbs.amap.com/api/webservice/guide/api/convert

7.参考

1.http://desktop.arcgis.com/zh-cn/arcmap/10.3/guide-books/map-projections/about-map-projections.htm

2.https://www.biaodianfu.com/coordinate-system.html

3.https://www.zhihu.com/question/277520588

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WGS84、GCJ-02、BD-09、图吧坐标简介及坐标转换实现(java版) 的相关文章

随机推荐

  • Pixhawk解锁常见错误

    这个我看写得还挺不错的 xff0c 终于有人比较全地总结一下了 摘自 xff1a http www paopaola com m news notice 3571899352 html Pixhawk解锁常见错误 2019 06 08 09
  • T265的线似乎就是普通移动硬盘的线

    T265的线似乎就是普通移动硬盘的线 所以应该不用怕线坏了没处买什么的 xff0c 本身你搜T265的线也搜不到 觉得T265的线太硬了应该也可以自己换个软点的线 还可以看看我最近的这篇 xff0c 也是最近的发现 xff1a https
  • 推荐用这种螺母

    也是之前无名给我配的螺母 xff0c 我之前还没有完全清楚它为什么这么设计 xff0c 现在清楚 xff01 xff01 xff01 xff01 确实非常便捷 xff0c 这样你只需要拧诺斯一端就可以了 xff0c 而不用一边拧螺丝一边用老
  • 时间不多了,在准备找工作上面,我们就像考研后期一样,多刷真题吧,而不是依旧抱着书看了。

    时间不多了 xff0c 在准备找工作上面 xff0c 我们就像考研后期一样 xff0c 多刷真题吧 xff0c 而不是依旧抱着书看了 免得效果不好 别再一个劲追求系统看书 xff0c 来不及了
  • 你会发现C++现在去做笔试题根本动不了笔

    你会发现C 43 43 现在去做笔试题根本动不了笔 这就是你一直看不不做题的下场 xff0c 和你第一次考研多么相像 xff0c 看来几个月 xff0c 去做真题 xff0c 也是很多动不了笔吧 xff1f 还想着把书看懂了那些题就自然会做
  • 笔试就重在刷题

    你以前不是害怕笔试么 xff0c 现在可以告诉你 xff0c 笔试就重在刷题 类似于考研数学 把题做通 刷题刷出feel 刷出感觉 刷出规律 越刷越爽
  • 刷了下七月在线的C++笔试题和看了下《程序员面试笔记》我发现他们很多考点,知识点都是相似的

    刷了下七月在线的C 43 43 笔试题和看了下 程序员面试笔记 我发现他们很多考点 xff0c 知识点都是相似的 xff0c 你像我都做到了内联函数 xff0c sizeof对于结构体 真的可能C 43 43 的笔试题做多了就是通了 xff
  • 腾讯课堂的C++ STL听课笔记

    https ke qq com course 303640 platform 61 1 amp pay succ 61 1 term id 61 100525847 amp pf 61 midas group pay 1000 pc 100
  • 深度学习中的隐私保护技术综述

    摘要 xff1a 如今机器学习以及深度学习在各个领域广泛应用 xff0c 包括医疗领域 金融领域 网络安全领域等等 深度学习的首要任务在于数据收集 xff0c 然而在数据收集的过程中就可能产生隐私泄露的风险 xff0c 而隐私泄露将导致用户
  • STL运用的三个档次

    STL运用的三个档次 拍自 Linux多线程服务端编程 使用muduo C 43 43 网络库
  • b站有不少STL的教学视频

    我甚至还看到了讲C 43 43 primer的视频 xff0c 如果真的有视频讲解的话 xff0c 我看你就不用抱着那本厚书啃了 而且看他们的STL视频的目录 xff0c 大体框架内容应该是差不多的 xff0c 这样就可以对STL有个大体的
  • 刷leetcode究竟要不要使用库函数

    这个很不错 xff0c 解答了我的一些疑问 xff0c 我之前惊喜faxiNgSTL是数据结构和算法的时候有这种想法 xff0c 现在发现 xff0c 你还是得老老实实自己用C实现 摘自 xff1a https github com you
  • LeetCode 刷题攻略

    摘自 xff1a https github com youngyangyang04 leetcode master 目录 xff1a 算法面试思维导图算法文章精选LeetCode 刷题攻略算法模板LeetCode 最强题解关于作者 算法面试
  • 一线互联网公司技术面试的流程以及注意事项

    摘自 xff1a https mp weixin qq com s 1VMvQ 6HbVpEn85CNilTiw 一线互联网公司技术面试的流程以及注意事项 原创 CarlSun 代码随想录 3月31日 企业一般通过几轮技术面试来考察大家的各
  • 现代C++语言可以看作是三部分组成

    现代C 43 43 语言可以看作是三部分组成 拍自 C 43 43 primer 前言
  • 别人推荐的一些C++书籍

    在 Linux多线程服务端编程 使用muduo C 43 43 网络库 里面 xff0c 陈硕推荐了几本 xff0c 依次是 xff1a C 43 43 primer Effective C 43 43 中文版 泛型编程与STL C 43
  • 两种乐趣

    一种是你以前的激情 xff0c 做高大上的东西 xff0c 你以前图书馆那种大量的看书也是这种乐趣 喜欢定宏伟的目标 xff0c 做大的事情 不追求学会一个东西 xff0c 只求各种办法能把功能实现就好 我现在做SLAM无人机也是的 xff
  • 《C++ primer》第五版习题答案

    C 43 43 primer 第五版习题答案 https www zhihu com question 37908263 answer 74051428 https github com Mooophy Cpp Primer
  • 木桨震动小

    木桨震动小
  • WGS84、GCJ-02、BD-09、图吧坐标简介及坐标转换实现(java版)

    1 定位系统及如何定位 现在全球有四个卫星定位系统 xff1a 美国的全球定位系统GPS xff08 Global Positioning System xff09 俄罗斯的格洛纳斯GIONASS 欧盟的伽利略系统 xff0c 我国的北斗