百度墨卡托坐标转化笔记
一、墨卡托坐标转化
调研了python和java多种实现方式的转换,发现有的不符合需求,原因还没找到。
我是用百度地图返回的poi边界(返回的是墨卡托坐标)
转换的原理没有深入研究,直接拿来用的,测试可行,非常感谢https://blog.csdn.net/qq_33734315/article/details/121071650
挺好奇MCBAND,MC2LL 这两个变量是从哪里找到的,还是自己研究出来的,太厉害了。
下面两种实现转换后的经纬度均为百度坐标系
调研的java代码实现
package utils;import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 百度geo返回的结果转换* 墨卡托坐标转成百度坐标*/
public class MocatorConvert {private static final Double[] MCBAND = {12890594.86, 8362377.87, 5591021d, 3481989.83, 1678043.12, 0d};private static final Double[][] MC2LL = {{1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2}, {-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86}, {-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37}, {-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06}, {3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4}, {2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5}};public static void main(String[] args) {String geo = "4|13139481.25,2796369.48;13139944.08,2796651.95|1-13139481.25,2796439.55,13139533.24,2796369.48,13139572.31,2796398.44,13139925.51,2796431.39,13139944.08,2796444.84,13139801.3,2796651.95,13139481.25,2796439.55;";String ss = mc2jw(geo);System.out.println(ss);Double x = 13139533.24;Double y = 2796369.48;Map<String, Double> rs = convertMC2LL(x, y);System.out.println(rs.values());}/*** 墨卡托坐标转成百度坐标 返回的百度坐标* @param geo* @return*/public static String mc2jw(String geo) {//String geo = "4|13517816.2,3597097.8;13527673.6,3607970.0|1-13520242.7,3597248.8,13520242.7,3597399.8,13519636.1,3597399.8,13519636.1,3598607.8,13519484.4,3598607.8,13519484.4,3598758.8,13519029.5,3598758.8,13519029.5,3599060.8,13518574.5,3599060.8,13518574.5,3599211.8,13518271.2,3599211.8,13518271.2,3599815.9,13517816.2,3599815.9,13517816.2,3600268.9,13518119.6,3600268.9,13518119.6,3600570.9,13518271.2,3600570.9,13518271.2,3600872.9,13518574.5,3600872.9,13518574.5,3601023.9,13519181.1,3601023.9,13519181.1,3602533.9,13518877.8,3602533.9,13518877.8,3602986.9,13519332.8,3602986.9,13519332.8,3605100.9,13518574.5,3605100.9,13518574.5,3606611.0,13518422.8,3606611.0,13518422.8,3607064.0,13518574.5,3607064.0,13518574.5,3607366.0,13518877.8,3607366.0,13518877.8,3607819.0,13519332.8,3607819.0,13519332.8,3607970.0,13519787.7,3607970.0,13519787.7,3607064.0,13521152.6,3607064.0,13521152.6,3606460.0,13522062.5,3606460.0,13522062.5,3605856.0,13521910.8,3605856.0,13521910.8,3604345.9,13522669.1,3604345.9,13522669.1,3603288.9,13523730.7,3603288.9,13523730.7,3602533.9,13524185.6,3602533.9,13524185.6,3601023.9,13524337.3,3601023.9,13524337.3,3600721.9,13526157.1,3600721.9,13526157.1,3601174.9,13527218.6,3601174.9,13527218.6,3600419.9,13527370.3,3600419.9,13527370.3,3599513.9,13527673.6,3599513.9,13527673.6,3598758.8,13527218.6,3598758.8,13527218.6,3598305.8,13526612.0,3598305.8,13526612.0,3597097.8,13524943.9,3597097.8,13524943.9,3597550.8,13524792.2,3597550.8,13524792.2,3598154.8,13522517.4,3598154.8,13522517.4,3597701.8,13522214.1,3597701.8,13522214.1,3597550.8,13520697.6,3597550.8,13520697.6,3597097.8,13520242.7,3597097.8;";List<String> mocatorList = new ArrayList<String>();if (geo.length() <= 71) {//没有边界,解析该点坐标mocatorList = parseJeoPoint(geo);} else {//有边界mocatorList = parseJeo(geo);}// 封装板块边界StringBuilder sb = new StringBuilder();for (int i = 0; i < mocatorList.size(); i++) {String[] coordinate = mocatorList.get(i).split("\\#");// 墨卡托坐标转换为百度经纬度坐标Map<String, Double> location = convertMC2LL(Double.parseDouble(coordinate[0]), Double.parseDouble(coordinate[1]));Double lng = location.get("lng");Double lat = location.get("lat");String coord = lng + "," + lat;sb.append(coord);if (i < mocatorList.size() - 1) {sb.append(";");}}return sb.toString();}/*** 解析Jeo数据** @param mocator*/public static List<String> parseJeo(String mocator) {List<String> mocatorList = new ArrayList<String>();if (null == mocator) return null;/* 拆分数据 */String[] geos = mocator.split("\\|");int n = Integer.parseInt(geos[0]);String center = geos[1];String polylineMoca = geos[2]; //墨卡托坐标if (n == 2) {polylineMoca = "1-" + polylineMoca;String[] plm = polylineMoca.split("\\;");String plmstr = "";for (String str : plm) {plmstr += str;}plm = new String[1];plm[0] = plmstr;}String[] plm = polylineMoca.split("\\;");/* 获取墨卡托边界 */String geo = null;if (n == 4 || n == 2) {for (int i = 0; i < plm.length; i++) {String[] geoPaths = plm[i].split("\\-");if (geoPaths[0].equals("1")) {geo = geoPaths[1];}}}// 墨卡托坐标解析String[] geoPolyline = new String[9999];try {geoPolyline = geo.split("\\,");} catch (Exception e) {System.out.println(e.getMessage());}for (int i = 0; i < geoPolyline.length; i += 2) {mocatorList.add(geoPolyline[i] + "#" + geoPolyline[i + 1]);}return mocatorList;}/*** 解析Jeo坐标点的数据** @param mocatorpoint*/public static List<String> parseJeoPoint(String mocatorpoint) {List<String> mocatorList = new ArrayList<String>();if (null == mocatorpoint) return null;String str = mocatorpoint.substring(0, mocatorpoint.lastIndexOf("|"));String str1 = mocatorpoint.substring(str.length() + 1, mocatorpoint.length() - 1);/* 拆分数据 */// 墨卡托坐标解析String[] geoPolyline = str1.split("\\,");for (int i = 0; i < geoPolyline.length; i += 2) {mocatorList.add(geoPolyline[i] + "#" + geoPolyline[i + 1]);}return mocatorList;}/*** 墨卡托坐标转经纬度坐标** @param x* @param y* @return*/public static Map<String, Double> convertMC2LL(Double x, Double y) {Double[] cF = null;x = Math.abs(x);y = Math.abs(y);for (int cE = 0; cE < MCBAND.length; cE++) {if (y >= MCBAND[cE]) {cF = MC2LL[cE];break;}}Map<String, Double> location = converter(x, y, cF);location.put("lng", location.get("x"));location.remove("x");location.put("lat", location.get("y"));location.remove("y");return location;}private static Map<String, Double> converter(Double x, Double y, Double[] cE) {Double xTemp = cE[0] + cE[1] * Math.abs(x);Double cC = Math.abs(y) / cE[9];Double yTemp = cE[2] + cE[3] * cC + cE[4] * cC * cC + cE[5] * cC * cC * cC + cE[6] * cC * cC * cC * cC + cE[7] * cC * cC * cC * cC * cC + cE[8] * cC * cC * cC * cC * cC * cC;xTemp *= (x < 0 ? -1 : 1);yTemp *= (y < 0 ? -1 : 1);Map<String, Double> location = new HashMap<String, Double>();location.put("x", xTemp);location.put("y", yTemp);return location;}}
调研的python实现
MCBAND = [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0]LLBAND = [75, 60, 45, 30, 15, 0]MC2LL = [[1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547,91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2],[-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826,-59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86],[-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871,-25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37],[-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277,-4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06],[3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511,-0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4],[2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994,-0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5]]LL2MC = [[-0.0015702102444, 111320.7020616939, 1704480524535203, -10338987376042340, 26112667856603880, -35149669176653700,26595700718403920, -10725012454188240, 1800819912950474, 82.5],[0.0008277824516172526, 111320.7020463578, 647795574.6671607, -4082003173.641316, 10774905663.51142,-15171875531.51559, 12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5],[0.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662, 79682215.47186455, -115964993.2797253,97236711.15602145, -43661946.33752821, 8477230.501135234, 52.5],[0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287,1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5],[-0.0003441963504368392, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378,54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5],[-0.0003218135878613132, 111320.7020701615, 0.00369383431289, 823725.6402795718, 0.46104986909093,2351.343141331292, 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45]]def location_mokatuo(lng, lat): # 百度坐标转百度墨卡托坐标cE = Nonelng = get_loop(lng, -180, 180)lat = get_range(lat, -74, 74)for i in range(len(LLBAND)):if lat >= LLBAND[i]:cE = LL2MC[i]breakif cE:for i in range(len(LLBAND) - 1, 0, -1):if lat <= -LLBAND[i]:cE = LL2MC[i]breakreturn converter(lng, lat, cE)def converter(lng, lat, cE):lngTemp = cE[0] + cE[1] * abs(lng)cC = abs(lat) / cE[9]latTemp = cE[2] + cE[3] * cC + cE[4] * cC * cC + cE[5] * cC * cC * cC + cE[6] * cC * cC * cC * cC + cE[7] * cC * cC * cC * cC * cC + cE[8] * cC * cC * cC * cC * cC * cClngTemp *= (-1 if lng < 0 else 1)latTemp *= (-1 if lat < 0 else 1)return [lngTemp, latTemp]def get_loop(lng, min1, max1):while lng > max1:lng -= max1 - min1while lng < min1:lng += max1 - min1return lngdef get_range(lat, min1, max1):if min1:lat = max(lat, min1)if max1:lat = min(lat, max1)return latdef mokatuo_location(lng,lat): # 百度墨卡托转换百度坐标cF = Nonelng = abs(lng)lat = abs(lat)for i in range(len(MCBAND)):if lat >= MCBAND[i]:cF = MC2LL[i]breakreturn converter(lng, lat, cF)if __name__ == '__main__':print(location_mokatuo(118.03315104440664, 24.498307986743058)) # 经纬度转墨卡托print(mokatuo_location(13139533.24,2796369.48)) # 墨卡托转经纬度
二、坐标测试用例
墨卡托坐标: 13139533.24,2796369.48
百度: 118.03315104440664, 24.498307986743058
GPS: 118.02167877581007, 24.495393563196547
高德: 118.02657021322973, 24.492638370577403
三、调研资料
http://www.site-digger.com/tools/mct2latlng.html
这个工具里面测试了一下返回的经纬度坐标是百度的坐标系
https://www.cnblogs.com/feffery/p/11023673.html
这个实现用上面的测试用例测试没有通过,不知道是不是墨卡托用到的标准不同导致的?
https://blog.csdn.net/qq_33734315/article/details/121071650
主要是用到了这个大佬的思路和实现,非常感谢
相关文章:
百度墨卡托坐标转化笔记
一、墨卡托坐标转化 调研了python和java多种实现方式的转换,发现有的不符合需求,原因还没找到。 我是用百度地图返回的poi边界(返回的是墨卡托坐标) 转换的原理没有深入研究,直接拿来用的,测试可行&…...
每日学术速递4.12
CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.HC 随着新的“生成代理”论文的发布,LLM刚刚达到了一个重要的里程碑——通过使用 LLM,生成代理能够在受《模拟人生》启发的交互式沙箱中模拟类人行为。代理架构扩展…...
HarmonyOS/OpenHarmony公司级技术开发团队硬件基本配置清单
有朋友公司咨询进入HarmonyOS/OpenHarmony领域,组建技术团队,硬件设备的基本配置应该是怎么样的比较合适?这个是进入鸿蒙开发领域相关配置的第一步,我们以一个基本的团队配置为例说明,供想进入的团队参考。 HarmonyOS/…...
新一代信息技术赋能,安科瑞搭建智慧水务体系的新思路
随着新时期治水方针的逐步落实,水利现代化、智能化建设已开启,物联网、图像识别、数字孪生等新技术的成熟,也为智慧水务体系的搭建提供了技术保障,新时代治水新思路正逐步得到落实。本文对智慧水务的总体架构与包含的建设内容进行…...
37岁测试工程师被裁,120天没找到工作,无奈...
从短期来看,程序员的确算是个不错的工作,薪水也比一般岗位高很多,但是从长远来看,程序员的中年危机会比其他岗位来的更早,很多程序员只有到了35岁左右,才能真正认清楚互联网行业,尤其是被裁之后…...
Java容器使用注意点
前置:问题 判空集合转map集合遍历集合去重集合转数组数组转集合 一:集合判空 《阿里巴巴 Java 开发手册》的描述如下: 判断所有集合内部的元素是否为空,使用 isEmpty() 方法,而不是 size()0 的方式。 我们在开发中也…...
密文题解(图论+字典树)
题目大意 有一段长度为nnn的密文,密文的每一位都可以用一个非负整数来描述,并且每一位都有一个权值aia_iai。你可以操作任意多次,每次操作可以选择任意一段密文,花费选择的所有位上权值的异或和的代价获得这段密文每一位的异或…...
Baumer工业相机堡盟工业相机如何通过BGAPISDK里的工具函数来计算工业相机的实时帧率(C#)
Baumer工业相机堡盟工业相机如何通过BGAPISDK里函数来计算相机的实时帧率(C#)Baumer工业相机Baumer工业相机的帧率的技术背景Baumer工业相机的帧率计算方式在BufferEvent声明显示FrameID设计显示帧率的函数Baumer工业相机通过BGAPI SDK计算帧率的优势B…...
数据结构与常量(Java)
目录 1.字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 补充:变量 int long short double和float char boolean byte 4.类型转换 类型提升小结 5. 字符串类型 1. int 转成 String 2. String 转成 int 1.字面常量 类似System.Out.p…...
【LeetCode】剑指 Offer 54. 二叉搜索树的第k大节点 p269 -- Java Version
题目链接:https://leetcode.cn/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/ 1. 题目介绍( 54. 二叉搜索树的第k大节点) 给定一棵二叉搜索树,请找出其中第 k 大的节点的值。 【测试用例】: 示例 1: 示例2&…...
[工具类] post请求 获取request对象, 获取request的请求体(body)参数
目录 引言: 1. 获取request对象的几种常用方式 -> 1.1 获取请求对象 通过请求上下文对象 获取信息[推荐] -> 1.2 在controller层直接获取[不推荐 侵害性太强] -> 1.3 interceptor中获取[部分业务中使用] -> 1.4 request常用api简介 2. 获取request的body的工具…...
Golang 多版本安装小工具G
voidint制作的Golang版本安装管理,非常好用。想装就装,想换版本就换版本 除了一些使用go install的场景可能有不兼容,主要是安装了工具有时候不能直接用。 GitHub - voidint/g: Golang Version Manager 使用方式很简单&a…...
day29—选择题
文章目录1.HashSet子类依靠什么方法区分重复元素(C)2.以下代码在编译和运行过程中会出现什么情况(A)3.有这么一段程序,执行的结果是(C)1.HashSet子类依靠什么方法区分重复元素(C&…...
day8 互斥锁/读写锁的概念及使用、死锁的避免
目录 互斥锁的概念和使用 线程通信 - 互斥 互斥锁的创建和销毁 互斥锁的创建 互斥锁的销毁 互斥锁的使用 申请锁 释放锁 互斥锁的概念和使用 线程通信 - 互斥 临界资源: 一次只允许一个任务(进程、线程)访问的共享资源;…...
2023-04-13 monetdb-str类型变长存储-分析
摘要: monetdb的列的基本抽象是BAT,但是对于列数据的存储方式, 对于固定长度和不固定长度,使用了不同的存储方式。 固定长度的数据比如int,int64之类的, 直接存储在了数据tail文件。 但是对于不固定长度比如string, 则使用另外一个独立的theap文件存储, tail文件仅保留对于…...
011:Mapbox GL两种方式隐藏logo和版权,个性化版权的声明
第011个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中用两种方式隐藏logo和版权,并个性化版权的声明 。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共91行)相关API参考:专栏目标示例效果 配置方式…...
结合PCA降维的DBSCAN聚类方法(附Python代码)
目录 前言介绍: 1、PCA降维: (1)概念解释: (2)实现步骤: (3)优劣相关: 2、DBSCAN聚类: (1)概念解释&a…...
限流:计数器、漏桶、令牌桶 三大算法的原理与实战(史上最全)
限流 限流是面试中的常见的面试题(尤其是大厂面试、高P面试) 注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请到文末《技术自由圈》公号获取 为什么要限流 简单来说: 限流在很多场景中用来…...
Redis用于全局ID生成器、分布式锁的解决方案
全局ID生成器 每个店铺都可以发布优惠卷 当用户抢购时,就会生成订单并保存到tb_voucher_order这张表中,而订单表如果使用数据库自增id就存在一些问题: 1.id的规律性太明显 2.受单表数据量的限制 全局ID生成器,是一种在分布式系…...
OpenTex 企业内容管理平台
OpenText 企业内容管理平台 将内容服务与领先应用程序集成,弥合内容孤岛、加快信息流并扩大治理 什么是内容服务集成? 内容服务集成通过将内容管理平台与处于流程核心的独立应用程序和系统连接起来,支持并扩展了 ECM 的传统优势。 最好的内…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...
