【Arcpy学习实践教程】wgs84坐标系和火星坐标系的转换中demo的对与错

2024-03-19 19:30

本文主要是介绍【Arcpy学习实践教程】wgs84坐标系和火星坐标系的转换中demo的对与错,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

度娘和谷哥已经变成了我们学习工作生活中必不可少的工具。

更有甚者,甚至已经不用输入法来搜索,而直接通过语音识别来搜索。但是我们搜索的结果真的可靠?我们在找到我们想要的资源之后是否有认真检验一下,我们找到的代码,找到的资料是否正确。当没有思考力和鉴别力的搬运工进入大众视野时,我们就需要谨慎起来了。

最近,因为工作的原因需要对高德坐标(即火星坐标)和wgs84坐标系实现互转。一直记得有位大神曾经在网上发布过相关的代码,和大家一样,第一步做的也是搜索,信息铺天盖地,随便找几个阅读量大的原创文章,给大家展示一下代码吧。

1.在《博客园》找到了一篇文章《GCJ-02火星坐标系和WGS-84坐标系转换关系》(ps:一般喜欢在博客园里面找代码,因为这边的文章相对专业一些,附上链接,下面是上面贴的code,python哈)

# -*- coding: utf-8 -*-
import json
import mathx_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626  # π
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 扁率def wgs84togcj02(lng, lat):"""WGS84转GCJ02(火星坐标系):param lng:WGS84坐标系的经度:param lat:WGS84坐标系的纬度:return:"""if out_of_china(lng, lat):  # 判断是否在国内return lng, latdlat = transformlat(lng - 105.0, lat - 35.0)dlng = transformlng(lng - 105.0, lat - 35.0)radlat = lat / 180.0 * pimagic = math.sin(radlat)magic = 1 - ee * magic * magicsqrtmagic = math.sqrt(magic)dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)mglat = lat + dlatmglng = lng + dlngreturn [mglng, mglat]def gcj02towgs84(lng, lat):"""GCJ02(火星坐标系)转GPS84:param lng:火星坐标系的经度:param lat:火星坐标系纬度:return:"""if out_of_china(lng, lat):return lng, latdlat = transformlat(lng - 105.0, lat - 35.0)dlng = transformlng(lng - 105.0, lat - 35.0)radlat = lat / 180.0 * pimagic = math.sin(radlat)magic = 1 - ee * magic * magicsqrtmagic = math.sqrt(magic)dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)mglat = lat + dlatmglng = lng + dlngreturn [lng * 2 - mglng, lat * 2 - mglat]def transformlat(lng, lat):ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *math.sin(2.0 * lng * pi)) * 2.0 / 3.0ret += (20.0 * math.sin(lat * pi) + 40.0 *math.sin(lat / 3.0 * pi)) * 2.0 / 3.0ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *math.sin(lat * pi / 30.0)) * 2.0 / 3.0return retdef transformlng(lng, lat):ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *math.sin(2.0 * lng * pi)) * 2.0 / 3.0ret += (20.0 * math.sin(lng * pi) + 40.0 *math.sin(lng / 3.0 * pi)) * 2.0 / 3.0ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *math.sin(lng / 30.0 * pi)) * 2.0 / 3.0return retdef out_of_china(lng, lat):"""判断是否在国内,不在国内不做偏移:param lng::param lat::return:"""if lng < 72.004 or lng > 137.8347:return Trueif lat < 0.8293 or lat > 55.8271:return Truereturn Falseif __name__ == '__main__':[lng,lat]=[114.061202,22.529388][dstlng, dstlat] = gcj02towgs84(lng, lat)print(dstlng, dstlat)

2.在csdn中找到一篇2017年的文章,阅读量大概过万了吧,反正应该还是比较权威的吧,或者是说比较早的---《火星坐标、百度坐标、WGS84坐标转换代码(JS、python版)》,连接不可少,哈哈。代码也是不能少的,这个是必须的

# -*- coding: utf-8 -*-
import json
import requests
import mathkey = 'your key here'  # 这里填写你的百度开放平台的key
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626  # π
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 扁率def geocode(address):"""利用百度geocoding服务解析地址获取位置坐标:param address:需要解析的地址:return:"""geocoding = {'s': 'rsv3','key': key,'city': '全国','address': address}res = requests.get("http://restapi.amap.com/v3/geocode/geo", params=geocoding)if res.status_code == 200:json = res.json()status = json.get('status')count = json.get('count')if status == '1' and int(count) >= 1:geocodes = json.get('geocodes')[0]lng = float(geocodes.get('location').split(',')[0])lat = float(geocodes.get('location').split(',')[1])return [lng, lat]else:return Noneelse:return Nonedef gcj02tobd09(lng, lat):"""火星坐标系(GCJ-02)转百度坐标系(BD-09)谷歌、高德——>百度:param lng:火星坐标经度:param lat:火星坐标纬度:return:"""z = math.sqrt(lng * lng + lat * lat) + 0.00002 * math.sin(lat * x_pi)theta = math.atan2(lat, lng) + 0.000003 * math.cos(lng * x_pi)bd_lng = z * math.cos(theta) + 0.0065bd_lat = z * math.sin(theta) + 0.006return [bd_lng, bd_lat]def bd09togcj02(bd_lon, bd_lat):"""百度坐标系(BD-09)转火星坐标系(GCJ-02)百度——>谷歌、高德:param bd_lat:百度坐标纬度:param bd_lon:百度坐标经度:return:转换后的坐标列表形式"""x = bd_lon - 0.0065y = bd_lat - 0.006z = math.sqrt(x * x + y * y) - 0.00002 * math.sin(y * x_pi)theta = math.atan2(y, x) - 0.000003 * math.cos(x * x_pi)gg_lng = z * math.cos(theta)gg_lat = z * math.sin(theta)return [gg_lng, gg_lat]def wgs84togcj02(lng, lat):"""WGS84转GCJ02(火星坐标系):param lng:WGS84坐标系的经度:param lat:WGS84坐标系的纬度:return:"""if out_of_china(lng, lat):  # 判断是否在国内return lng, latdlat = transformlat(lng - 105.0, lat - 35.0)dlng = transformlng(lng - 105.0, lat - 35.0)radlat = lat / 180.0 * pimagic = math.sin(radlat)magic = 1 - ee * magic * magicsqrtmagic = math.sqrt(magic)dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)mglat = lat + dlatmglng = lng + dlngreturn [mglng, mglat]def gcj02towgs84(lng, lat):"""GCJ02(火星坐标系)转GPS84:param lng:火星坐标系的经度:param lat:火星坐标系纬度:return:"""if out_of_china(lng, lat):return lng, latdlat = transformlat(lng - 105.0, lat - 35.0)dlng = transformlng(lng - 105.0, lat - 35.0)radlat = lat / 180.0 * pimagic = math.sin(radlat)magic = 1 - ee * magic * magicsqrtmagic = math.sqrt(magic)dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)mglat = lat + dlatmglng = lng + dlngreturn [lng * 2 - mglng, lat * 2 - mglat]def transformlat(lng, lat):ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *math.sin(2.0 * lng * pi)) * 2.0 / 3.0ret += (20.0 * math.sin(lat * pi) + 40.0 *math.sin(lat / 3.0 * pi)) * 2.0 / 3.0ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *math.sin(lat * pi / 30.0)) * 2.0 / 3.0return retdef transformlng(lng, lat):ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *math.sin(2.0 * lng * pi)) * 2.0 / 3.0ret += (20.0 * math.sin(lng * pi) + 40.0 *math.sin(lng / 3.0 * pi)) * 2.0 / 3.0ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *math.sin(lng / 30.0 * pi)) * 2.0 / 3.0return retdef out_of_china(lng, lat):"""判断是否在国内,不在国内不做偏移:param lng::param lat::return:"""if lng < 72.004 or lng > 137.8347:return Trueif lat < 0.8293 or lat > 55.8271:return Truereturn Falseif __name__ == '__main__':lng = 128.543lat = 37.065result1 = gcj02tobd09(lng, lat)result2 = bd09togcj02(lng, lat)result3 = wgs84togcj02(lng, lat)result4 = gcj02towgs84(lng, lat)result5 = geocode('北京市朝阳区朝阳公园')print result1, result2, result3, result4, result5

对比了一下,虽然写法有些许不一样,但是算法核心都是一样的。看到这么多的代码都是一样的,我当然也一样照做了。和第一个方法一样,我也做了定位,在高德地图上面发现了一个小问题,其实转出来的结果和实际有非常小的偏差。根据转出的结果,又用代码转回到wgs84,做投影,神奇的事情发生了,相差2m多。

(转回去之后的wgs84投影差别2m)

 

这个时候意识到一个问题,一定是这个算法存在问题。网上继续检索查找,大神浮出水面,geohey大神。用了qgis上他开发的转化工具之后,逆转换没有任何问题,这个时候正常的人也只会做一个事了,趴代码。代码趴到手,这里我也做一下搬运工吧。

# -*- coding: utf-8 -*-
##########################################################################################
"""
/***************************************************************************OffsetWGS84CoreA QGIS pluginClass with methods for geometry and attributes processing-------------------begin                : 2016-10-11git sha              : $Format:%H$copyright            : (C) 2017 by sshuairemail                : sshuair@gmail.com***************************************************************************//****************************************************************************                                                                         **   This program is free software; you can redistribute it and/or modify  **   it under the terms of the GNU General Public License as published by  **   the Free Software Foundation; either version 2 of the License, or     **   (at your option) any later version.                                   **                                                                         ****************************************************************************/
"""
from __future__ import print_function
##########################################################################################
from builtins import zip
import math
from math import sin, cos, sqrt, fabs, atan2
from math import pi as PI
# from numba import jit# =================================================sshuair=============================================================
# define ellipsoid
a = 6378245.0
f = 1 / 298.3
b = a * (1 - f)
ee = 1 - (b * b) / (a * a)# check if the point in china
def outOfChina(lng, lat):return not (72.004 <= lng <= 137.8347 and 0.8293 <= lat <= 55.8271)# @jit
def geohey_transformLat(x, y):ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x))ret = ret + (20.0 * sin(6.0 * x * PI) + 20.0 * sin(2.0 * x * PI)) * 2.0 / 3.0ret = ret + (20.0 * sin(y * PI) + 40.0 * sin(y / 3.0 * PI)) * 2.0 / 3.0ret = ret + (160.0 * sin(y / 12.0 * PI) + 320.0 * sin(y * PI / 30.0)) * 2.0 / 3.0return ret# @jit
def geohey_transformLon(x, y):ret = 300.0 + x + 2.0 * y + 0.1 * x * x +  0.1 * x * y + 0.1 * sqrt(fabs(x))ret = ret + (20.0 * sin(6.0 * x * PI) + 20.0 * sin(2.0 * x * PI)) * 2.0 / 3.0ret = ret + (20.0 * sin(x * PI) + 40.0 * sin(x / 3.0 * PI)) * 2.0 / 3.0ret = ret + (150.0 * sin(x / 12.0 * PI) + 300.0 * sin(x * PI / 30.0)) * 2.0 / 3.0return ret# @jit
def wgs2gcj(wgsLon, wgsLat):if outOfChina(wgsLon, wgsLat):return wgsLon, wgsLatdLat = geohey_transformLat(wgsLon - 105.0, wgsLat - 35.0)dLon = geohey_transformLon(wgsLon - 105.0, wgsLat - 35.0)radLat = wgsLat / 180.0 * PImagic = math.sin(radLat)magic = 1 - ee * magic * magicsqrtMagic = sqrt(magic)dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * PI)gcjLat = wgsLat + dLatgcjLon = wgsLon + dLonreturn (gcjLon, gcjLat)def gcj2wgs(gcjLon, gcjLat):g0 = (gcjLon, gcjLat)w0 = g0g1 = wgs2gcj(w0[0], w0[1])# w1 = w0 - (g1 - g0)w1 = tuple([x[0]-(x[1]-x[2]) for x in zip(w0,g1,g0)])  # delta = w1 - w0delta = tuple([x[0] - x[1] for x in zip(w1, w0)])while (abs(delta[0]) >= 1e-6 or abs(delta[1]) >= 1e-6):w0 = w1g1 = wgs2gcj(w0[0], w0[1])# w1 = w0 - (g1 - g0)w1 = tuple([x[0]-(x[1]-x[2]) for x in zip(w0,g1,g0)])# delta = w1 - w0delta = tuple([x[0] - x[1] for x in zip(w1, w0)])return w1def gcj2bd(gcjLon, gcjLat):z = sqrt(gcjLon * gcjLon + gcjLat * gcjLat) + 0.00002 * sin(gcjLat * PI * 3000.0 / 180.0)theta = atan2(gcjLat, gcjLon) + 0.000003 * cos(gcjLon * PI * 3000.0 / 180.0)bdLon = z * cos(theta) + 0.0065bdLat = z * sin(theta) + 0.006return (bdLon, bdLat)def bd2gcj(bdLon, bdLat):x = bdLon - 0.0065y = bdLat - 0.006z = sqrt(x * x + y * y) - 0.00002 * sin(y * PI * 3000.0 / 180.0)theta = atan2(y, x) - 0.000003 * cos(x * PI * 3000.0 / 180.0)gcjLon = z * cos(theta)gcjLat = z * sin(theta)return (gcjLon, gcjLat)def wgs2bd(wgsLon, wgsLat):gcj = wgs2gcj(wgsLon, wgsLat)return gcj2bd(gcj[0], gcj[1])def bd2wgs(bdLon, bdLat):gcj = bd2gcj(bdLon, bdLat)return gcj2wgs(gcj[0], gcj[1])if __name__ == '__main__':# wgs2gcj# coord = (112, 40)# trans = WGS2GCJ()print(wgs2gcj(112, 40))print(gcj2wgs(112.00678230985764, 40.00112245823686))# gcj2wgs

很明显在火星坐标系转wgs84坐标系过程中的算法存在较大的差异,这是之前误差2m的绝对原因。

希望以后大家在搬运代码的时候回过去验证一下,做一个有判断力和有辨识力的搬运工,我们虽然可以不重复生产轮子,但是我们不能够把别人的方轮子拿来用吧!!!!

 

本文由元凿坊独创,如需转载,请获得作者的授权。如发现问题,请及时告知作者,

欢迎前来探讨交流!!!!

发布于 17:28

这篇关于【Arcpy学习实践教程】wgs84坐标系和火星坐标系的转换中demo的对与错的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/827016

相关文章

MySQL8.2.0安装教程分享

《MySQL8.2.0安装教程分享》这篇文章详细介绍了如何在Windows系统上安装MySQL数据库软件,包括下载、安装、配置和设置环境变量的步骤... 目录mysql的安装图文1.python访问网址2javascript.点击3.进入Downloads向下滑动4.选择Community Server5.

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

Python实现视频转换为音频的方法详解

《Python实现视频转换为音频的方法详解》这篇文章主要为大家详细Python如何将视频转换为音频并将音频文件保存到特定文件夹下,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5. 注意事项

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

使用Python实现图片和base64转换工具

《使用Python实现图片和base64转换工具》这篇文章主要为大家详细介绍了如何使用Python中的base64模块编写一个工具,可以实现图片和Base64编码之间的转换,感兴趣的小伙伴可以了解下... 简介使用python的base64模块来实现图片和Base64编码之间的转换。可以将图片转换为Bas

MySql9.1.0安装详细教程(最新推荐)

《MySql9.1.0安装详细教程(最新推荐)》MySQL是一个流行的关系型数据库管理系统,支持多线程和多种数据库连接途径,能够处理上千万条记录的大型数据库,本文介绍MySql9.1.0安装详细教程,... 目录mysql介绍:一、下载 Mysql 安装文件二、Mysql 安装教程三、环境配置1.右击此电脑