基于Java后台实现百度、高德和WGS84坐标的转换实战

举报
夜郎king 发表于 2024/11/28 12:53:22 2024/11/28
【摘要】 本文旨在探讨如何使用Java后台技术实现百度、高德和WGS84坐标之间的转换。我们将深入分析这些坐标系统的特点,以及它们之间的转换逻辑和算法。通过实战案例,我们将展示如何在Java环境中编写高效、可靠的坐标转换代码,以满足不同业务场景的需求。

 目录


前言

一、需求的缘由

1、百度坐标拾取

2、高德坐标拾取 

3、不同地图的坐标展示

二、后端坐标偏移转换处理

1、相关类库介绍

2、coordtransorm类图介绍

3、后台实际转换

三、总结 



前言

        在当今数字化时代,地理位置信息的精确性和实时性对于各种应用至关重要。其实在之前的博客中,我们曾将提到过高德AOI的位置偏移,也讲过如何来解决这些位置偏移带来的问题,基于Leaflet的高德AOI数据在天地图底图可视化纠偏实践。无论是地图导航、物流配送还是社交网络,都依赖于精确的地理坐标系统来提供服务。然而,不同的地图服务提供商,如百度地图、高德地图和国际上广泛使用的WGS84坐标系统,它们之间存在着坐标系的差异。这种差异给开发者在实现跨平台、跨服务的地理信息服务时带来了挑战。因此,掌握如何在这些不同的坐标系统之间进行转换,成为了后端开发人员的一项必备技能。在下图中详细演示了这种场景,以天地图底图为例,右边两个位置分别是百度和高德的位置,紫色的位置是正确的原始位置。

        本文旨在探讨如何使用Java后台技术实现百度、高德和WGS84坐标之间的转换。我们将深入分析这些坐标系统的特点,以及它们之间的转换逻辑和算法。通过实战案例,我们将展示如何在Java环境中编写高效、可靠的坐标转换代码,以满足不同业务场景的需求。

        首先,我们需要了解不同的坐标系统下,比如百度、高德的具体位置展示。然后在技术实现上,我们将探讨如何利用java来简化开发过程,提高开发效率。此外,本文还将分享一些在实际开发中遇到的常见问题及其解决方案,比如如何处理坐标转换中的精度问题、如何优化大规模坐标转换的性能等。通过这些实战经验的分享,我们希望能够帮助开发者在面对复杂的地理信息服务时,能够更加从容不迫。最后,随着技术的不断进步,坐标转换的方法和工具也在不断更新。本文将提供一个持续学习和探索的平台,鼓励开发者关注最新的技术动态,不断优化和升级自己的坐标转换解决方案,以适应不断变化的市场需求。

一、需求的缘由

        说起一个在刚开始接触GIS时一位老同志讲的故事,虽然现在听起来有点不可思议。但是当时,说不定你也是抱有同样的疑问。故事的起因是这样,某公司要求一名工程师通过手机去采集车辆的轨迹信息,然后将轨迹信息放到地图中去展示。需求很简单,没什么复杂的。手机嘛,一般都是用的GPS的信息,底图有点意思。当时用户没有自己的离线地图,因此就尝试用高德地图作为他们的离线地图服务器。三下五除二,把坐标导出来,然后连接成一条线,接着二三并作五,再把生成的线叠加到地图上。本来以为手到擒来,可以汇报结果。可当一群人看到地图上的曲线傻眼了。明明自己只是过了一座桥,怎么在地图上跑河里去了。于是大家你一言,我一语的说。张三说,这是有人搞破坏,我们的数据被篡改了。有的说,发生了不可描述的事情,大家被带偏了。一时没有了主义。于是找到了一个大牛,将情况跟大佬说了一下。大佬听到了高德地图,眼神闪过一丝亮光,似乎有了答案,又卖了一个关子。

        相信以上场景,对于半路出家的GISER同学来说,确实有点悬,明明是好的。来的时候明明走的陆地,怎么到这里却飞了呢?不是走的河里,就是穿墙而过。当你在这一行有了一定的经验后,一定会会心的一笑。那么我们先来使用地图来情景再现一下。当然,这里我们只是模拟,通过现象看本质。为了起到对比的作用,这里分别选用百度地图和高德地图的坐标拾取器来对同一个标志物(长沙市橘子洲景区的橘市文创店)进行拾取,然后将两者的坐标叠加到天地图中。来看看是在山上还是河里?

1、百度坐标拾取

        首先我们打开百度地图的坐标拾取器地址百度地图坐标拾取器,然后缩放到我们的目标地点。如下所示:

        首先当我们在地图上找到我们的目标点,即橘市文创店。然后点击鼠标的左键。在界面的右上角就有生成的当前选择地点的坐标位置。可以点击按钮实现复制。当前的坐标信息如下:

(112.967397, 28.172314)

        在获取了百度的坐标之后,接下来我们尝试在高德地图上获取同一个位置的坐标。

2、高德坐标拾取 

        与百度地图一样,高德地图也提供的坐标拾取的功能,它的官方地址是:高德坐标拾取器。依然选择缩放到橘市文创店附近,如下图所示:

        最终得到的高德坐标为: 

        到这里,可能您并不觉得他们有什么问题,因为我们还没有把他们放到一起来进行展示。是骡子是马,是该拉出来溜溜。因此下面我们统一将他们放到天地图中进行展示。

3、不同地图的坐标展示

        为了解决工作量,也为了有统一展示的效果。我们将采集到的百度坐标和高德坐标进行统一展示。展示组件依然选用Leaflet。Leaflet展示点的关键代码如下:

// 待标绘的点
var dataJson = [
	{lat:28.172314,lon:112.967397,name:"橘市文创店-百度坐标(转换前)",color:"#aba021"},
	{lat:28.166447,lon:112.960922,name:"橘市文创店-高德坐标(转换前)",color:"#21abab"}
];
	
for(var i=0;i<dataJson.length;i++){
	L.marker([dataJson[i].lat, dataJson[i].lon], {
		icon: L.divIcon({
			iconSize: null,
			className: '',
			popupAnchor:[5,5],
			shadowAnchor:[5,5],
			html: "<div class='marsBlackPanel'  animation-spaceInDown style='background:"+dataJson[i].color+"'>"+
					"<div class='marsBlackPanel-text' style=''>"+dataJson[i].name+"</div>"+
					"<div class='marsBlackPanel-text' style=''>经度:"+dataJson[i].lon+"</div>"+
					"<div class='marsBlackPanel-text' style=''>经度:"+dataJson[i].lat+"</div>"+
					"</div>"
		})
	}).addTo(map);
}

        首先来看一下这时的效果:

        是不是符合你的预期呢?将百度的坐标和高德的坐标叠加在天地图的底图上,你会惊奇的发现。点居然跑了。不在我们预期的橘子洲头的位置。而且,百度的坐标偏的更厉害。这也就解释了什么事二次偏移。在高德的偏移上还加了自己的偏移。 到这里,能理解为什么GPS的信息,可能到了高德这里,会跑到河里了吧。

        遇到问题不可怕,下面我们来解决问题。之前我们曾经分享过了如何在Javascript前端来解决,下面我们来介绍如何使用后端的方式来进行处理。

二、后端坐标偏移转换处理

        在之前的博客中,我们介绍了使用JavaScript前端的方式来进行坐标的转换。这种方式在前端使用普遍,而且能很好的与前端开发语言进行结合。但是缺点也同样的明显,很多场景中,我们需要在后台进行数据的处理,比如某接口调用的是百度或者高德的地图的API接口。通过这些API接口得到的坐标都是对应平台的。通过前面的博客可以得知,其坐标在不同的平台有不同的偏移。因此急需在后台来进行相应的坐标转换。同时,我们还可以在后台以接口的形式提供对外服务,提供坐标转换的服务。因此本节来具体介绍如何在后台,以java语言为例,详细介绍如何进行坐标偏移转换。

1、相关类库介绍

        这里提供一个开源的java坐标转换组件。不再进行重复造轮子。为了让大家熟悉相关的组件和方法,这里还是对组件进行简单的介绍。coordtransform java实现

        这个组件主要提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换的工具模块 (参考wandergis的python版coordtransform的Java版实现)。也是我们在后台进行坐标转换的主要方法。

2、coordtransorm类图介绍

        左边转换的类比较简单,这里采用面向对象的方法对它的类图进行介绍,让大家对转换组件有一个详细的认识。类图结构如下所示:

        属性列表:

序号 参数 参数说明
1 x_pi 3.14159265358979324 * 3000.0 / 180.0
2 π 3.1415926535897932384626
3 a 长半轴,6378245.0
4 ee 扁率,0.00669342162296594323

        方法列表:

序号 方法名 方法说明 参数说明
1 bd09towgs84 百度坐标系(BD-09)转WGS坐标 百度坐标经纬度
2 wgs84tobd09 WGS坐标转百度坐标系(BD-09) WGS84坐标系的经纬度
3 gcj02tobd09 火星坐标系(GCJ-02)转百度坐标系(BD-09) 火星坐标系经纬度
4 bd09togcj02 百度坐标系(BD-09)转火星坐标系(GCJ-02) 百度坐标系经纬度
5 wgs84togcj02 WGS84转GCJ02(火星坐标系) WGS84坐标系的经纬度
6 gcj02towgs84 GCJ02(火星坐标系)转GPS84 火星坐标系经纬度
7 transformlat 纬度转换
8 transformlng 经度转换
9 out_of_china 判断是否在国内,不在国内不做偏移

        在掌握了以上的参数和方法之后,下面我们使用Java开发语言在后台来进行相关坐标的转换与转换。

3、后台实际转换

        下面根据第一章中采集的百度和高德坐标,在后台分别进行相应的转换。变成我们需要的WGS84坐标后,然后我们在天地图中进行WebGIS展示。

public static void main(String[] args) {
    double [] bd284 = CoordinateTransformUtil.bd09towgs84(112.967397D, 28.172314D);
    System.out.println("百度坐标转wgs84坐标" + bd284[0] + "=" + bd284[1]);
	
    double [] gcj284 = CoordinateTransformUtil.gcj02towgs84(112.960922D, 28.166447D);
    System.out.println("高德坐标转wgs84坐标" + gcj284[0] + "=" + gcj284[1]);
}

        在控制台中看到以下的转换结果,如下所示:

百度坐标转wgs84坐标112.95536764126244=28.16996238135615
高德坐标转wgs84坐标112.95541908168103=28.16990747088316

        单从转换后的结果可以看到,两个坐标的值是非常接近的。稍微有点偏差,这可能与我们在实际拾取坐标时有一定的偏差。将转换后的坐标在Leaflet中进行展示。关键代码如下:

// 待标绘的点
var dataJson = [
	{lat:28.172314,lon:112.967397,name:"橘市文创店-百度坐标(转换前)",color:"#aba021"},
	{lat:28.166447,lon:112.960922,name:"橘市文创店-高德坐标(转换前)",color:"#21abab"},
	{lat:28.16996238135615,lon:112.95536764126244,name:"橘市文创店-百度坐标(转换后)",color:"#b91980"},
	{lat:28.16990747088316,lon:112.95541908168103,name:"橘市文创店-高德坐标(转换后)",color:"#b91980"}
];

        最后来看一下经过转换后的坐标在天地图中的位置展示如下:

        可以看到,经过纠偏后的坐标基本实现了还原,有一点的误差,大概率是我们在拾取时可能手抖了导致的。忽略这个误差,说明我们的转换结果符合我们的需求。至此,基于后台来进行相关坐标的转换就已经实现。

三、总结 

        以上就是本文的主要内容,本文旨在探讨如何使用Java后台技术实现百度、高德和WGS84坐标之间的转换。我们将深入分析这些坐标系统的特点,以及它们之间的转换逻辑和算法。通过实战案例,我们将展示如何在Java环境中编写高效、可靠的坐标转换代码,以满足不同业务场景的需求。行文藏度,定有诸多不足之处,如有不足,还恳请各位专家朋友在评论区批评指出,不胜感激。文章重点在讲解偏移的出现场景,通过场景的还原让大家了解不同的坐标展示效果,同时为下一步进行转换奠定基础。关于java的转换代码,完全是开源的,大家可以根据需要集成到自己的gis系统当中。

        参考地址:coordtransform java转换

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。