【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

相关文章

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但... 目录MyBATis-Plus 中nested()与and()方法详解一、核心区别对比二、方法详解1.and()

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

MySQL 中 ROW_NUMBER() 函数最佳实践

《MySQL中ROW_NUMBER()函数最佳实践》MySQL中ROW_NUMBER()函数,作为窗口函数为每行分配唯一连续序号,区别于RANK()和DENSE_RANK(),特别适合分页、去重... 目录mysql 中 ROW_NUMBER() 函数详解一、基础语法二、核心特点三、典型应用场景1. 数据分

深度解析Spring AOP @Aspect 原理、实战与最佳实践教程

《深度解析SpringAOP@Aspect原理、实战与最佳实践教程》文章系统讲解了SpringAOP核心概念、实现方式及原理,涵盖横切关注点分离、代理机制(JDK/CGLIB)、切入点类型、性能... 目录1. @ASPect 核心概念1.1 AOP 编程范式1.2 @Aspect 关键特性2. 完整代码实

利用Python脚本实现批量将图片转换为WebP格式

《利用Python脚本实现批量将图片转换为WebP格式》Python语言的简洁语法和库支持使其成为图像处理的理想选择,本文将介绍如何利用Python实现批量将图片转换为WebP格式的脚本,WebP作为... 目录简介1. python在图像处理中的应用2. WebP格式的原理和优势2.1 WebP格式与传统

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.