Leaflet在WGS84 Web墨卡托投影与WGS84经纬度投影下空间信息变形问题及修正-以圆为例

目录

前言

一、投影的相关知识

1、经纬度投影

2、Web墨卡托投影 

二、经纬度投影下的空间信息展示

1、空间信息展示

2、效果展示

3、经纬度投影下的圆修正

三、Web墨卡托投影下空间信息展示

1、底图引用

2、自定义生成圆

 总结  


前言

        在GIS的知识海洋中,对于地理信息科班出身的同学来说,WGS84 Web墨卡托投影(以下简称Web墨卡托投影)和WGS84 经纬度投影(以下简称经纬度投影)以及他们的区别应该非常了解。但是对于一些开发的同学,尤其是从计算机转向GIS的开发同学来说,就未必对两者的区别有这么详细的了解。但是如果对两种投影方式不了解的话,在实际开发过程当中就会遇到一些有趣的问题,有的空间对象在经纬度投影下的空间信息形变比较严重,而在Web墨卡托的投影方式下是展示比较良好的。因此有必要将这两种常见的投影类型以及一些实际的空间对象的展示,结合两种投影来进行讲解。

        本文就是在以下的问题背景下产生,首先地图采用的是WGS84经纬度投影的方式,在地图上我们根据需要进行缓冲区分析,展示出来的效果就是一个圆。通过代码实践,我们发现,本来是是正常的一个圆,在不同纬度位置上表现出来的效果居然是不一样的。如下图所示:

         同样的圆,在地图上展示的效果是完全不一样的,接近赤道的地区基本是正常的图形,随着纬度的增加,到了中高纬度地区,圆慢慢被拉平,变成了一个椭圆形,到了接近极地的地区,变平度更大,长轴与短轴的比接近2:1。为什么会出现以上的现象,出现了以上的现象,如何在开发的时候进行修正呢?

        本文主要讲解GIS中的两种投影方式和区别,结合空间对象信息的展示里讲述不同投影方式下图形的形变问题,然后通过代码讲解如果遇到形变问题的对应解决办法。希望对遇到这种问题的朋友有一定的帮助。

一、投影的相关知识

        地图投影,是指按照一定的数学法则将地球椭球面上的经纬网转换到平面上,使地面的地理坐标与平面直角坐标建立起函数关系。这是绘制地图的数学基础之一。由于地球是一个不可展的球体,使用物理方法将其展平会引起褶皱、拉伸和断裂,因此要使用地图投影实现由曲面向平面的转化。关于地球的投影,有很多种不同的处理方式,通常我们采用WebGIS的开发方式,比较常用的投影类型就是WGS84下的经纬度投影和Web墨卡托投影两种。因此本节主要简单介绍这两种投影的相关知识,其它的投影方式请各位朋友查询相关资料了解相关知识,不在本文中赘述。

1、经纬度投影

        当全球影像显示为如下图所示的矩形时,该地图投影一般为 WGS84 经纬度投影。该投影下的经度范围为-180度到180度,纬度范围为-90度到90度,因此该投影下的全球影像矩形的长度刚好是宽度的2倍。在这请注意,随着纬度的增加,采用经纬度投影的地图,在中高纬度地区的变形会变得很严重,而在接近赤道地区是正常的。在了解它的投影原理之后是比较好理解的。

经纬度投影下全球影像展示示意图

2、Web墨卡托投影 

        当全球影像显示为如下图所示的正矩形时,该地图投影一般为 WGS84 Web 墨卡托投影。由于赤道半径为6378137米,则赤道周长为2×PI×R=20037508.3427892米。因此,X轴的取值范围在(-20037508.3427892和20037508.3427892)之间。当纬度接近两极,即90°时,Y值趋向于无穷,在该投影下通常将Y轴的取值范围限定在(-20037508.3427892,20037508.3427892)之间。最后可以得出,在 WGS84 Web 墨卡托投影坐标系下,左下角的投影坐标为(-20037508.3427892, -20037508.3427892),右上角的投影坐标为(20037508.3427892, 20037508.3427892),需要注意是这里的单位不再是度,而是米。

        采用Web墨卡托投影方式时,空间图形的变形很小。在高纬度地区有较好的展示能力。

 Web墨卡托投影下全球影像展示示意图

        通过上述的这种简单的办法就可以区分Web墨卡托投影和经纬度投影这两种方式。你也看看目前你的系统中使用的是什么投影方式。

二、经纬度投影下的空间信息展示

        本节主要讲解在经纬度投影下如何进行空间信息展示,以圆为例,经常遇到的问题可能是什么?以及遇到了这些问题如何去解决。

1、空间信息展示

        考虑到经纬度投影下的变形是随着纬度的增加而加重的,空间圆的展示采用从赤道到北纬地区逐渐延伸的方式,构建了不同纬度下的圆信息展示,让大家对不同纬度下的空间信息展示有一个直观的认识和理解。在GIS中展示空间圆的关键代码如下:

        经纬度投影的底图定义:

 //以下采用经纬度投影方式
 L.CRS.CustomEPSG4326 = L.extend({}, L.CRS.Earth, {
		code: 'EPSG:4326',
		projection: L.Projection.LonLat,
		transformation: new L.Transformation(1 / 180, 1, -1 / 180, 0.5),
		scale: function (zoom) {
			return 256 * Math.pow(2, zoom - 1);
		}
});
	
var mymap = L.map('mapid',{crs:L.CRS.CustomEPSG4326}).setView([29.052934, 104.0625], 5);

L.tileLayer('http://localhost:8086/data/basemap_nowater/1_10_tms/{z}/{x}/{y}.jpg', {
	maxZoom: 16,
	attribution: 'yelangkingMap data &copy; <a href="/">本地瓦片加载</a> contributors, ' +
			'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
			'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
		id: 'mapbox/streets-v11',
		tileSize: 256,
		zoomOffset: -1
}).addTo(mymap);

//标签
L.tileLayer('http://localhost:8086/data/basemap_nowater/1-10label/{z}/{x}/{y}.png', {maxZoom: 10,minZoom:3,
		id: 'mapbox/label',tileSize: 256,zoomOffset: -1
}).addTo(mymap);

        根据纬度的不同创建不同的圆空间对象,关键代码如下:

L.circle([0.175781, 111.445313], 399000, {
	color: '#960e00',
	fillColor: '#960e00',
	fillOpacity: 0.5,
}).addTo(mymap).bindPopup("靠近赤道地区的马来西亚某地.");
	
L.circle([12.612305, 110.830078], 399000, {
	color: 'red',
	fillColor: '#f03',
	fillOpacity: 0.5
}).addTo(mymap).bindPopup("南海某地.");

L.circle([29.649869, 120.146484], 399000, {
	color: 'red',
	fillColor: '#f03',
	fillOpacity: 0.5
}).addTo(mymap).bindPopup("我是一个圆.");
	
L.circle([50.097656, 111.09375], 399000, {
	color: 'blue',
	fillColor: 'blue',
	fillOpacity: 0.5
}).addTo(mymap).bindPopup("我是第二个圆.");
	
L.circle([22.851563, 109.248047], 399000, {
	color: '#550096',
	fillColor: '#550096',
	fillOpacity: 0.5
}).addTo(mymap).bindPopup("我是第三个圆.");
	
L.circle([66.884766, 108.017578], 399000, {
	color: '#006696',
	fillColor: '#006696',
	fillOpacity: 0.5
}).addTo(mymap).bindPopup("我变形最严重.");

2、效果展示

        将上述代码部署至静态服务器或者直接在浏览器中运行,可以看到以下的空间可视化效果。

赤道及低纬度地区圆展示示意图

        通过观察可以看到,从赤道地区到两极的扩展过程当中,在 这个纬度区间内,圆的整体展示效果还是比较好的,变形的情况不严重。下面来看中高纬度下,圆的空间展示情况是什么样子的。

中高纬度地区圆可视化效果

        通过上图可以很直观的看到,随着纬度的增加,中高纬度地区的圆逐渐开始了形变,而在极地地区达到了最大。而变形也是跟着经纬度投影的原理一致。赤道最小,而两极最大。

3、经纬度投影下的圆修正

        如果当前系统已经是采用了经纬度投影的方式,又不能一下子改变底图的投影方式。这种情况下该如何解决这种问题呢?这里参考了一个朋友分享的解决思路。大致的思路就是,在中高纬度地区,对于圆的生成不采用Leaflet等自己的原生api的创建方式,而是通过多边形近似计算的方式,通过自己计算选点,生成一个接近圆的多边形,以此来避免在经纬度投影下的图形变形的问题。具体的算法代码如下:

function buildCirclePolygon(lat,lng,color){
	//这里采用自定义生成
	var radius = 4;
	//点集
	var parts = [];
	//计算圆的边缘所有点
	for (var i = 0; i < 360; i++) {
		var radians = (i + 1) * Math.PI / 180;
	    var circlePoint = [Math.cos(radians) * radius + lat, Math.sin(radians) * radius + lng];
		parts[i] = circlePoint;
	}
	//生成面,近似圆
	var polygon = L.polygon(parts, {
		color: color
	});
		
	return  polygon;
}

        在需要生成圆的地方调用以上的方法,请注意,这里的方法中,第一个参数表示纬度,第二个参数表示经度。

buildCirclePolygon(34,108,'blue').addTo(mymap);
	
buildCirclePolygon(66.884766,108.017578,'blue').addTo(mymap);

        来看一下经过自主模拟的圆生成的图形叠加到地图后,在高纬度的效果是怎么样的?

        修正圆在中高纬度的可视化效果

        在上面的效果图中可以看到,黄色标色修正圆,蓝色表示原始的圆。可以很直观的看到,修正圆已经很好的可视化效果。

三、Web墨卡托投影下空间信息展示

        本节主要讲解在Web墨卡托投影下如何进行空间信息展示,以圆为例,是否会遇到在经纬度投影下碰到的问题。

1、底图引用

        由于要调整使用Web墨卡托的投影方式,因此这里需要重新定义底图。定义的方式如下所示:

var mymap = L.map('mapid').setView([29.052934, 104.0625], 5);

L.tileLayer('http://localhost:8086/data/basemap_water/{z}/{x}/{y}.png', {
	maxZoom: 16,
	attribution: 'Map data &copy; <a href="">OpenStreetMap</a> contributors, ' +
			'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
			'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
	id: 'mapbox/streets-v11',
	tileSize: 512,
	zoomOffset: -1
}).addTo(mymap);

        圆的空间信息添加方式不变,来看一下实际的效果:

墨卡托投影下圆可视化示意图

        通过观察上述的效果可以看到,当地图采用Web墨卡托投影时,在地图上展示圆几乎是没有变形的。在中高纬度地区也是正常的。

2、自定义生成圆

        虽然在墨卡托投影下,圆没有发生变更,但是我们依然想了解下,如果进行修正数据叠加后会是什么效果。

 中高纬度修正圆展示示意图

        可以看到,在web墨卡托投影下,经过修正的圆反而会有变形。通过图形的对比相信大家对两种不同的投影规则下的图形展示已经有了比较直观的认识。

 总结  

        通过上述两种不同投影类型中对圆的加载和修正展示。相信大家对空间对象的展示已经比较清楚了。如果是经纬度投影,在中高纬度地区,空间信息会变形,如果需要按原始图形展示,需要自己修正。而采用Web墨卡托投影,则不需要做任何处理。

        以上就是本文的主要内容,本文主要讲解GIS中的两种投影方式和区别,结合空间对象信息的展示里讲述不同投影方式下图形的形变问题,然后通过代码讲解如果遇到形变问题的对应解决办法。希望对遇到这种问题的朋友有一定的帮助。行文仓促,定有不足之处,如有任何问题或者不当之处,欢迎各位朋友专家在评论区批评指出,不深感谢。

        博文在编写过程中参考了相关文章,站在巨人的肩膀上才能看得更远,在此表示感谢。

1、GIS基础一: GIS中的WGS84地理坐标系和墨卡托投影坐标系。

2、【gis技术】web墨卡托投影和经纬度直投的差别。

3、不得不说的地图投影那些事儿。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/604525.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis集群分片

什么是集群 集群是由多个复制集组成的,能提供在多个redis节点间共享数据的程序集 简而言之就是将原来的单master主机拆分为多个master主机,将整个数据集分配到各主机上 集群的作用 集群中可以存在多个master,而每个master可以挂载多个slave自带哨兵的故障转移机制,不需要再去…

【Android】源码解析Activity的结构分析

源码解析Activity的结构分析 目录 1、Activity、View、Window有什么关联&#xff1f;2、Activity的结构构建流程3 源码解析Activity的构成 3.1 Activity的Attach方法3.2 Activity的OnCreate 4、WindowManager与View的关系总结 1、一个Activity对应几个WindowManage&#xff0…

【论文阅读笔记】关于“二进制函数相似性检测”的调研(Security 22)

个人博客链接 注&#xff1a;部分内容参考自GPT生成的内容 [Security 22] 关于”二进制函数相似性检测“的调研&#xff08;个人阅读笔记&#xff09; 论文&#xff1a;《How Machine Learning Is Solving the Binary Function Similarity Problem》&#xff08;Usenix Securi…

C++ 模拟实现 priority_queue(优先队列)

目录 一&#xff0c;优先队列简介 二&#xff0c;priority_queue 的内部实现原理 三&#xff0c;模拟实现 priority_queue 1&#xff0c;模板参数与数据结构 2&#xff0c;构造 3&#xff0c;辅助功能&#xff08;堆的有序化&#xff0c;建立堆&#xff09; 4&#xff0…

嵌入式学习69-C++(Opencv)

知识零碎&#xff1a; QT的两种编译模式 1.debug 调试模式 …

springboot整合rabbitmq的不同工作模式详解

前提是已经安装并启动了rabbitmq&#xff0c;并且项目已经引入rabbitmq&#xff0c;完成了配置。 不同模式所需参数不同&#xff0c;生产者可以根据参数不同使用重载的convertAndSend方法。而消费者均是直接监听某个队列。 不同的交换机是实现不同工作模式的关键组件.每种交换…

泛微E9开发 选择项目类型,自动带出该类项目的预计金额(即下拉框联动浮点型数据)

1、功能背景 在用户进行项目类型选择时&#xff0c;自动带出其余的标准数据&#xff08;样例中的预计金额&#xff09;&#xff0c;如对员工进行表彰奖励时&#xff0c;不同的表彰有不同的奖励金额&#xff0c;那么我们就可以使用以下的方式来进行操作。 2、展示效果 3、实现…

WiFine通信与Wi-sun通信对比

调制速率 WiFine通信&#xff1a;(G)FSK 50Kbps~500Kbps &#xff1b;LoRa 5Kbps~37.5Kbps Wi-Sun通信&#xff1a;(G)FSK 50Kbps~300Kbps &#xff1b;QPSK/OFDM 计划中… 2、协议简介 WiFine通信&#xff1a;为低成本、低功耗、移动设备倾力打造 的轻量级、分布式无线移动…

英语新概念2-回译法-lesson13

The Greenwood Boys 绿林少年是一组流行歌手们。现在他们正在参观城市里的所有公园&#xff0c;他们明天就要到这。他们将坐火车到并且大多数小镇上的年轻人将要欢迎他们&#xff0c;明天晚上他们将要在工人俱乐部唱歌。绿林少年将在这待五天&#xff0c;在这期间&#xff0c;…

我独自升级崛起加速器推荐 我独自升级免费加速器

近期&#xff0c;《我独自升级》这部动画凭借爆棚的人气&#xff0c;在各大平台上掀起了一阵观看热潮&#xff0c;其影响力不容小觑。借此时机&#xff0c;韩国游戏巨头网石集团敏捷响应&#xff0c;顺势推出了同名游戏《我独自升级&#xff1a;ARISE》&#xff0c;为粉丝们搭建…

如何让vim支持python3

首先删除旧的vim。 sudo apt-get remove vim //输入re按下tab直接显示remove sudo apt-get remove vim-runtime sudo apt-get remove vim -tiny sudo apt-get remove vim-common 然后下载vim8源码&#xff1a; git clone https://github.com/vim/vim.git 进行编译安装…

鸿蒙开发全攻略:华为应用系统如何携手嵌入式技术开启新篇章~

鸿蒙操作系统是华为自主创新的成果&#xff0c;打破了传统操作系统的局限。通过结合嵌入式技术&#xff0c;鸿蒙实现了跨平台、跨设备的高度融合&#xff0c;提供了流畅、智能的体验。华为应用系统与嵌入式技术的结合&#xff0c;提升了性能&#xff0c;丰富了用户体验。鸿蒙与…

【stm-4】PWM驱动LED呼吸灯 PWM驱动舵机PWM驱动直流电机

1.PWM驱动LED呼吸灯 void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); //结构体初始化输出比较单元 void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef*…

RabbitMQ的五种模式

一、简单模式 简单模式&#xff08;Simple&#xff09;&#xff1a;一个生产者&#xff0c;一个消费者 package com.qiangesoft.rabbitmq.mode.simple;import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.Queue; import org.springframe…

mysql集群cluster引擎在写入数据时报错 (1114, “The table ‘ads‘ is full“)

问题描述&#xff1a;mysql集群在写入数据时&#xff0c;出现上述报错 问题原因&#xff1a;表数据已满&#xff0c;一般是在集群的管理节点设置里面datamemory的值太小&#xff0c;当数据量超过该值时就会出现该问题 解决方案&#xff1a; 修改集群管理节点的config.ini里面…

JUC下的ScheduledThreadPoolExecutor详解

ScheduledThreadPoolExecutor是Java并发编程框架中一个强大且灵活的线程池实现&#xff0c;专为定时与周期性任务而设计。作为ThreadPoolExecutor的子类&#xff0c;它不仅继承了线程池管理的高效与灵活性&#xff0c;还内置了基于优先级队列的延迟任务调度机制&#xff0c;支持…

商务分析方法与工具(五):Python的趣味快捷-文件和文件夹操作自动化

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

pytest教程-41-钩子函数-pytest_runtest_teardown

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了pytest_runtest_call钩子函数的使用方法&#xff0c;本小节我们讲解一下pytest_runtest_teardown钩子函数的使用方法。 pytest_runtest_teardown 钩子函数在每个测试用例执行完成后被调用&…

游戏辅助 -- 三种分析角色坐标方法(CE、xdbg、龙龙遍历工具)

所用工具下载地址&#xff1a; https://pan.quark.cn/s/d54e7cdc55e6 在上次课程中&#xff0c;我们成功获取了人物对象的基址&#xff1a;[[[0xd75db8]1C]28]&#xff0c;而人物血量的地址则是基址再加上偏移量278。 接下来&#xff0c;我们需要执行以下步骤来进一步操作&a…

JSP技术讲解

目录 1、JSP简介 2、JSP体验 3、JSP运行原理 4、JSP基本语法 5、JSP指令 6、JSP内置九大对象 7、JSP标签 8、JSP配置 9、JSP排错 10、总结 在前面的Servlet学习中发现Servlet本质是一个java程序&#xff0c;因此Servlet更加擅长编写程序的业务逻辑&#xff0c;而如果要…
最新文章