前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >大地经纬度坐标系与Web墨卡托坐标系的转换

大地经纬度坐标系与Web墨卡托坐标系的转换

作者头像
charlee44
发布于 2021-10-26 03:20:39
发布于 2021-10-26 03:20:39
3.8K00
代码可运行
举报
文章被收录于专栏:代码编写世界代码编写世界
运行总次数:0
代码可运行

目录

1. 概述

我在《大地经纬度坐标与地心地固坐标的的转换》这篇文章中已经论述了大地坐标系/地理坐标系的概念,简单来说就是由经度、纬度以及高程(BLH)确定的坐标系,它是一种曲面坐标。

然而,在实际使用过程中我们用的最多的还是平面坐标,并且单位最好与常用的长度单位(米)一致。所以就产生了从曲面到平面的转换,这个过程也叫做投影,转换的结果也就是投影平面坐标系。我在《GDAL坐标转换》这篇文章中详细论述了我们国内常用的三种投影平面坐标系:横轴墨卡托投影,高斯-克吕格投影和UTM投影。本质上来说,高斯-克吕格投影和UTM投影其实都是横轴墨卡托投影,横轴墨卡托投影也是用的最为广泛的地图投影方式。

但是在GIS,尤其是WebGIS领域中,横轴墨卡托投影的使用远没有Web墨卡托投影方式用的多。最重要的原因是Web墨卡托投影的转换算法比横轴墨卡托投影要简单很多,符合Web的轻量化的特点。

2. 实现

Web墨卡托投影是横轴墨卡托投影的特化版,要完全搞清楚Web墨卡托投影就必须得先搞清楚横轴墨卡托投影,不过横轴墨卡托投影实在太复杂了,但是我们可以定性地去理解。它的计算过程大概可以这样理解:

在X方向上,为了保证投影到平面后经线和纬线仍然垂直,那么每条纬线都会按照赤道周长展开,也就是

2*PI*r = 2*20037508.3427892

。由于原点位于平面中心,那么可以算得X轴的取值范围:-20037508.3427892,20037508.3427892。经度与投影后X长是简单的线性关系。

在Y方向上,则需要借助于墨卡托投影公式。为了保证投影的结果是正方形,那么就把Y轴的取值范围也取值成-20037508.3427892,20037508.3427892之间。这样做没什么道理,纯粹是为了希望投影的结果是正方形,便于切片。最后,通过墨卡托投影公式进行反算,得到的经纬度范围就是-85.05112877980659,85.05112877980659。也就是这种投影方式,大于这个范围是失效的。

参考Cesium的具体实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <iostream>
//#include <eigen3/Eigen/Eigen>

//#include <osgEarth/GeoData>

using namespace std;

const double epsilon = 0.000000000000001;
const double pi = 3.14159265358979323846;
const double d2r = pi / 180;
const double r2d = 180 / pi;

const double a = 6378137.0;		//椭球长半轴
const double f_inverse = 298.257223563;			//扁率倒数
const double b = a - a / f_inverse;
//const double b = 6356752.314245;			//椭球短半轴

const double e = sqrt(a * a - b * b) / a;

//墨卡托范围[-PI, PI]->大地纬度范围[-PI/2, PI/2]
static double mercatorAngleToGeodeticLatitude(double mercatorAngle)
{
	return pi / 2.0 - (2.0 * atan(exp(-mercatorAngle)));
	//return 2.0 * atan(exp(mercatorAngle)) - pi / 2.0;
}

//Web墨卡托投影所支持的最大纬度(北和南)
static double maximumLatitude = mercatorAngleToGeodeticLatitude(pi);

//大地纬度范围[-PI/2, PI/2]->墨卡托范围[-PI, PI]
static double geodeticLatitudeToMercatorAngle(double latitude)
{
	// Clamp the latitude coordinate to the valid Mercator bounds.
	if (latitude > maximumLatitude)
	{
		latitude = maximumLatitude;
	}
	else if (latitude < -maximumLatitude)
	{
		latitude = -maximumLatitude;
	}
	double sinLatitude = sin(latitude);
	return 0.5 * log((1.0 + sinLatitude) / (1.0 - sinLatitude));
} 

void Blh2Wmc(double &x, double &y, double &z)
{
	x = x * d2r * a;
	y = geodeticLatitudeToMercatorAngle(y * d2r) * a;
}

void Wmc2Blh(double &x, double &y, double &z)
{
	//var oneOverEarthSemimajorAxis = this._oneOverSemimajorAxis;
	x = x / a * r2d;
	y = mercatorAngleToGeodeticLatitude(y / a) * r2d;	
}

int main()
{
	double x = 113.6;
	double y = 38.8;
	double z = 100;	   

	printf("%.10lf\n", maximumLatitude * r2d);

	printf("原大地经纬度坐标:%.10lf\t%.10lf\t%.10lf\n", x, y, z);
	Blh2Wmc(x, y, z);
	printf("Web墨卡托坐标:%.10lf\t%.10lf\t%.10lf\n", x, y, z);
	Wmc2Blh(x, y, z);
	printf("转回大地经纬度坐标:%.10lf\t%.10lf\t%.10lf\n", x, y, z);
}

最终运行的结果:

通过GlobalMapper中的坐标转换工具对照的结果如下:

两者结果基本一致。

3. 参考

  1. Web Mercator 公开的小秘密
  2. GIS——各大地图厂商为什么偏爱web墨卡托投影
  3. 墨卡托及Web墨卡托投影
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
ES6函数参数的默认值设置
在ES6(ECMAScript 2015)中,我们可以为函数参数设置默认值,这使得函数在调用时可以接受一部分或全部参数的默认值。默认参数值的设置提供了更灵活和方便的函数使用方式。
堕落飞鸟
2023/05/22
1.6K0
你真的了解ES6函数特性么?
hello大家好,又见面了。 假期转瞬即逝,年后开工的第一天,早上是真的不想起床吖,为了不迟到闭着眼睛就穿衣服。 好啦好啦,步入正题啦,打起精神哦!
JowayYoung
2021/04/30
4770
「译」ES6:参数默认值的实现细节
在这篇文章中我们会介绍另一个 ES6 的特性,带默认值的函数参数。正如我们将看到的,有一些微妙的案例。
Chor
2019/11/07
5190
【译】《Understanding ECMAScript6》- 第二章-函数
函数在任何一门编程语言中都是很重要的一个环节。JavaScript至今已有多年的历史,但是它的函数仍然停留在很初级的阶段。函数问题的大量堆积,以及某些函数非常微妙的功能差异,很容易产生错误,并且有时候一个很简单的功能往往需要通过大量的代码来实现。 ES6吸取了多年来JavaScript开发者的反馈,在ES5函数的基础上进行了大量的改进,令JavaScript程序更加健壮并且减少了错误发生率。 默认参数 JavaScript函数的特性之一,便是接受传入的参数可以与函数定义的参数数量不同。利用这种特性,函数可以
寒月十八
2018/01/30
1.4K0
ES6 函数的扩展
ES6 引入 rest 参数(形式为…变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
全栈程序员站长
2022/07/21
3320
JS Advance --- ES6语法(二)
在ES6之前,如果我们想要将字符串和一些动态的变量(标识符)拼接到一起,是非常麻烦和丑陋的
玖柒的小窝
2021/10/09
1.2K0
ES6--对象、函数的扩展
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
奋飛
2019/08/15
5240
ES6 函数参数(默认参数、结构)
重来没有系统的学过es6,感觉语法和swift 、java、python等语言差不多,今天给我上了一课。 缘起 ---- 今天看了一个函数,愣是看的有点蒙。 clone ({ zindex = this.commonStyle.zindex + 1 } = {}) { } 最后终于弄明白了,写点总结 ES6函数参数 ---- 1、默认值 这个没什么说的,就是传入undefine 的时候使用默认值,注意null不行。 function esFn(name = 'zzy') { console.lo
星宇大前端
2021/04/30
8870
ES6——函数
只有在未传递参数,或者参数为 undefined 时,才会使用默认参数,null 值被认为是有效的值传递。
羊羽shine
2019/07/03
4090
ES6新增语法(二)——函数和参数
箭头函数:将原来函数的function关键字和函数名都删掉,并使用”=>”连接参数列表和函数体。
呆呆
2021/09/29
3050
js默认参数和rest参数
在JavaScript中,ES6(ECMAScript 2015)引入了默认参数(Default Parameters)和rest参数(Rest Parameters)这两个新特性,它们为函数参数的处理提供了更多的灵活性。
jack.yang
2025/04/05
2140
JavaScript 设计模式学习第四篇-ES6 中可能遇到的知识点
ES6(ECMAScript 6,ES2015)原来指的是 ECMA 组织在 2015 年发布的 ECMAScript 2015 标准,以后发布的 ECMAScript 2016 对应 ES7,依此类推。今年发布的 ECMAScript 2019 标准对应的就是 ES10。相比于之后发布的这些版本,ES6 的改变幅度非常大,因此我们通常说的 ES6 广义上也包括 ES5 之后的所有更新。
越陌度阡
2020/11/26
4920
JavaScript 设计模式学习第四篇-ES6 中可能遇到的知识点
JavaScript ES6  让我们写得少,做得多
JavaScript ES6 带来了新的语法和新的强大功能,使您的代码更现代,更易读。它允许您编写更少的代码并执行更多操作。 ES6 向我们介绍了许多强大的功能,如箭头函数,模板字符串,对象结构,模块等,让我们来看看。
桃翁
2018/10/18
8520
ES6
在cmd命令窗口初始化项目-y代表全部默认同意,就不用一次次按回车了。命令执行完成后,会在项目根目录下生产package.json文件。
楠楠
2018/09/11
2.8K0
每天3分钟,重学ES6-ES12(四)函数的补充 展开语法
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
虎妞先生
2022/10/27
2410
带你入门 JavaScript ES6 (一)
ES6: 是 ECMA国际组织于 2015 年 6 月 17 日发布的 ECMAScript 第六版,正式名为 ECMAScript 2015,通常被成为 ES6 或 ECMAScript 6。
柳公子
2018/09/17
5750
前端基础进阶(十六):ES6常用基础合集
与 var 不同,新的变量声明方式带来了一些不一样的特性,其中最重要的两个特性就是提供了块级作用域与不再具备变量提升。通过 2 个简单的例子来说明这两点。
唐志远
2022/10/27
2300
前端基础进阶(十六):ES6常用基础合集
ES6
ES6引入了let和const关键字,可以在块级作用域中声明变量,解决了以前使用var声明变量可能导致的问题。在ES6之前,JavaScript中的变量声明使用var关键字,它具有函数作用域而不是块级作用域。这意味着使用var声明的变量可以在其所在的函数内部任何位置访问,而不仅仅是在声明的块级作用域内。
用户11124947
2024/05/16
1300
1.2w字 | 初中级前端 JavaScript 自测清单 - 1
前言 最近与部门老大一起面试了许多前端求职者,其中想换个学习氛围较好的人占多数,但良好的学习氛围也是需要一点点营造出来的🌺。 为此我们组建了我们团队内部的“现代 JavaScript 突击队”,第一期学习内容为《现代 JavaScript 教程》系列,帮助小组成员系统地进行学习巩固,并让大家养成系统性学习和输出学习总结的学习方式。 本文作为我输出的第一部分学习总结,希望作为一份自测清单,帮助大家巩固知识,温故知新。 这里也下面分享我们学习小组的“押金制度”和“押金记录表”🍀 [“押金制度”和“押金记录表”]
pingan8787
2020/07/04
1.2K0
十六、半小时掌握ES6常用知识,覆盖80%实践场景
在实际开发中,ES6已经非常普及了。掌握ES6的知识变成了一种必须。尽管我们在使用时仍然需要经过babel编译。
用户6901603
2020/07/27
6940
十六、半小时掌握ES6常用知识,覆盖80%实践场景
推荐阅读
相关推荐
ES6函数参数的默认值设置
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档