Leaflet使用多面(MultiPolygon)进行遥感影像掩膜报错解决之道

目录

前言

一、问题初诊断

1、山重水复

2、柳暗花明

3、庖丁解牛

4、问题定位

二、解决多面掩膜问题

1、尝试数据修复

2、实际修复

3、最终效果

 三、总结


前言

        之前一篇讲解遥感影像掩膜实现:基于SpringBoot和Leaflet的行政区划地图掩膜效果实战,在这边博客中,详细说明了在Leaflet中进行行政区划地图掩膜效果的实现。同时也展示了一些升级行政区的掩膜效果,确实效果也出来了。但是有小伙伴给博主私信留言,说是在展示一些省份的时候出现了无法进行正确掩膜的效果。没有达到预期的目的,行政边界外的遥感影像还是正常展示,实际效果看起来就是只是像做了一个行政区划定位而已。

        最开始,这位小伙伴在提出这个展示问题的时候。一度以为是代码实现的姿势不对。一样的代码执行效果一定是一样的,代码是最遵守规则的,不会出现不同的执行效果的情况。因此半信半疑,在刚开始排查的时候,把方向放在了查找代码的实现方式差异上。有一句话叫“方向不对,选择全废”。确实是如此,在最开始排查问题的方向上,就犯了致命问题。差点与解决办法擦肩而过。真的是“纸上得来终觉浅,绝知此事要躬行”。

        本文将深刻剖析在Leaflet中,对于面(Polygon)和多面(MultiPolygon)在影像掩膜实战过程的正确展示方法,分析了问题产生的原因以及如何解决多面(MultiPolygon)进行影像掩膜实现。如果电脑前的你也有同样的问题,或者存在多面(MultiPolygon)展示不出来的问题。不妨来看看这篇博客,或许能解决你的疑问。

一、问题初诊断

        本节重点描述怎么排查问题,有的时候,排查问题比解决问题耗时更长,也更费脑筋。这就是软件修复bug的时候,为什么定位bug比修改bug的时间长的原因了。虽然入行多年,依然没有找到好的解决之道,未来依然要修炼这种寻找问题所在,提升高效寻找bug之道。

1、山重水复

        在经历了最开始的代码对比排查之后,刚开始是没有找到问题的所在。像无头苍蝇一样(还是着急了),所以下次再遇到问题,一定要冷静和理智。先让自己冷静下来,只有冷静下来才会冷静,才能慢慢的寻找方向。在经过几次的错误排查之后,然后与小伙伴的一个交流中捕获一点信息。这位小伙伴说,他的研究区域在沿海,比如浙江或者江苏等,与常规的内陆省份不一样。这些省份通常会有很多岛屿,而这些岛屿大大小小,星罗棋布,因此这部分省份一点就有问题。

2、柳暗花明

        确实可以用“山重水复疑无路,柳暗花明又一村”来形容寻找问题的过程。在上面的交流过程中,发现小伙伴对沿海区域感兴趣,基本都是选择的沿海的省份进行掩膜。而我在测试时,选择的恰好都是内陆省份,都是单面的。由此猜测,是否是因为多面导致的。于是在自己的系统中也选择一个沿海城市,比如江苏为例,来看看是否能会出现同样的问题。

        于是我们在之前的系统中,找到江苏省,点击分析按钮,看到了以下的效果。

        再切换一个省份,换成浙江来看看是否也是这个问题,先来看看效果: 

         连着两个省份都出现这个问题,说明我们已经复现了bug。那么既然掩膜效果没有实现,究竟问题是出在哪里呢?遇到问题不着急,不妨先来看看浏览器的控制台有没有什么异常,通过以上去找问题,距离真相又更近一步。

3、庖丁解牛

        打开浏览器的调试窗口,然后再界面中点击“定位”按钮,然后在控制台中发现了一些蛛丝马迹。果然是报错了,看到错误不要怕,解决错误就是获取经验的过程。先来看看具体是报了什么错误,对错误信息进行基本分析。

        具体的报错信息如下:

LatLng.js:32 Uncaught Error: Invalid LatLng object: (121.4037488,32.52239686, 121.40616219,32.522424195)
    at new v (LatLng.js:32:9)
    at w (LatLng.js:131:10)
    at e._convertLatLngs (Polyline.js:160:17)
    at e._convertLatLngs (Polygon.js:75:51)
    at e._setLatLngs (Polyline.js:146:24)
    at e._setLatLngs (Polygon.js:86:34)
    at e.initialize (Polyline.js:65:8)
    at new e (Class.js:24:20)
    at t.polygon (Polygon.js:158:9)
    at showMask (province:287:26)

        此时看到这红色的报错信息,是否觉得它竟然是如此可爱呢。因为报错是指引我们达到问题彼岸的一座桥梁,这么一想确实值得高兴。 聪明的您,是否根据上面的信息猜到了什么呢?这是格式错误的经纬度信息。

        在之前的内容中,曾经提过,像浙江省这样的多岛屿省份,一定会存在于大陆不相连的地方。而这就是问题的所在,因为大陆省份一般都是一个面(Polygon),而浙江是多面(MultiPolygon),这就是问题的根本。

4、问题定位

        根据上面的猜想,我们通过数据来验证我们的猜想是否是正确的。在我们的后台接口中,我们将省份的空间范围数据以GeoJSON的格式进行返回的。

package com.yelang.project.extend.earthquake.mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yelang.project.extend.earthquake.domain.Province;
/**
 * 省级行政区划数据接口
 * @author wuzuhu
 *
 */
public interface ProvinceMapper extends BaseMapper<Province>{
	static final String FIND_GEOJSON_SQL="<script>"
			+ "select st_asgeojson(geom) as geomJson from biz_province "
			+ "where id = #{id} "
			+ "<if test='null != name'>and name like concat('%', #{name}, '%')</if>"
			+ "</script>";
	@Select(FIND_GEOJSON_SQL)
	Province findGeoJsonById(@Param("id")Long id,@Param("name")String name);
}

        这里明确通过st_asgeojson(geom)函数将空间对象转变成了geojson对象。然后在前端看一下实际的返回的数据。

        上面这是返回多面的空间范围数据,确实是返回了多面。再来看看单面的情况:

        到这里,基本已经定位了问题的所在。根本原因就是因为空间数据的不同导致的掩膜效果不正常。因此博文刚开始遇到的问题找到原因,定位了bug。

二、解决多面掩膜问题

        既然知道了根本的问题,就可以针对问题来寻找解决办法。通过上节的问题定位,我们已经将问题锁定在返回的数据源上,因此只要解决这个数据的问题即可。本节重点描述如何通过数据源的修复来解决多面掩膜的问题。

1、尝试数据修复

        在寻找问题解决方案的过程中,也遇到了一个问题。就是是解决问题数据源的问题还是解决可视化的问题。因为polygon是完全正常的,刚开始想着是否可以把MultiPolygon转为polygon,在数据层解决。这种思路是有问题的,因为MultiPolygon是有现实的空间意义的。毕竟想海上的岛屿,我们在空间矢量范围数据管理时,通常会按照多面来处理。所以,数据修复的道路不通。既然在原始数据源上无法进行修复。那只能在拿到数据后进行处理。

2、实际修复

        在放弃了最原始的数据修复后,我们决定采用数据二次加工的办法。把多个面拆成单面集合。然后按照这些单面进行掩膜,也就是化零为整的做法,把一个一个的面组合起来,不也是实现了我们的目的吗。想到这个思路,是看到有网友介绍了多面转单面的思路。这里也采用这种思路来解决问题。

        首先对多面转成单面,关键的核心代码如下,将多面对象传入:

function multiPolygon2polygons (multiPolygon){
	 if(multiPolygon.type !== 'MultiPolygon'){
	       return
	 }
	 var polygons = [];
	 multiPolygon.coordinates.forEach((item)=>{
	      var polygon = {
	            type: "Polygon",
	            coordinates: []
	      };
	      polygon.coordinates = item;
	      polygons.push(polygon)
	  });
	  return polygons;
}

        然后对从后台回传的geojson数据进行分开处理。

function showMask(geojson){
	    	var showPolygons = [];
    	    if(geojson.type == "Polygon"){
    	    	var pArray = [];
    	    	for (var i = 0; i < geojson.coordinates.length; i++) {
    	            var points = [];
    	            $.each(geojson.coordinates[i],function(k,v){
    	                points.push({lat:v[1],lng:v[0]});
    	            });
    	            //将闭合区域加到遮蔽层上,每次添加完后要再加一次西北角作为下次添加的起点和最后一次的终点
    	            pArray = pArray.concat(points);
    	            pArray.push(pArray[0]);
    	        }
    	    	var polygon = L.polygon(pArray, { color: 'green' });
    	    	showPolygons.push(polygon);
    	    }
    	    if(geojson.type == "MultiPolygon"){
    	    	var polygons = multiPolygon2polygons(geojson);
    	    	for (var i = 0; i < polygons.length; i++) {
    	    		var pArray = [];
        	    	for (var j = 0; j < polygons[i].coordinates.length; j++) {
        	            var points = [];
        	            $.each(polygons[i].coordinates[j],function(k,v){
        	                points.push({lat:v[1],lng:v[0]});
        	            });
        	            //将闭合区域加到遮蔽层上,每次添加完后要再加一次西北角作为下次添加的起点和最后一次的终点
        	            pArray = pArray.concat(points);
        	            pArray.push(pArray[0]);
        	        }
        	    	var polygon = L.polygon(pArray, { color: 'green' });
        	    	showPolygons.push(polygon);
    	        }
    	    }
	      	var mask = L.mask({
	            showPolygons: showPolygons,
	            color: '#C0C0C0',
	            fillOpacity: 1,
	            renderer: L.canvas({ padding: 1 })  //解决遮罩层拖拽与缩放显示不全的Bug
	        });
	      	showLayerGroup.addLayer(mask);
	    }

3、最终效果

        至此,经过上述的代码处理。可以解决多面(MultiPolygon)的掩膜无法展示的问题。照例,来看一下多面的展示效果,这里特意选择数据是多面的情况进行展示。

江苏省掩膜效果示意图 

浙江省掩膜效果示意图 

福建省掩膜效果示意图

广东省掩膜效果示意图 

 三、总结

        以上就是本文的主要内容,文章详细分析了遇到问题的应对之道,怎么去面对问题,遇到了问题怎么去问题排查。对于我本文也是一次较大考验,因为刚开始确实走了不少弯路,因为方向不对,在以后开发的道路中,一定更加科学严谨,引以为戒。

        本文将深刻剖析在Leaflet中,对于面(Polygon)和多面(MultiPolygon)在影像掩膜实战过程的正确展示方法,分析了问题产生的原因以及如何解决多面(MultiPolygon)进行影像掩膜实现。如果电脑前的你也有同样的问题,或者存在多面(MultiPolygon)展示不出来的问题。不妨来看看这篇博客,或许能解决你的疑问。行文仓促,多有不当之处,欢迎各位前辈和专家批评指正。

        在博客的编写过程中,参考了以下前辈的知识,在此致谢:

1、Leaflet.draw 无法编辑multipolygon类型多边形 解决方法。

2、GIS操作:Mutipolygon与Polygon的转换。

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

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

相关文章

CleanMyMac X中文---让Mac焕发新生,Mac优化与清理的终极利器

CleanMyMac X是一款专为Mac用户设计的综合性系统优化工具。通过智能扫描&#xff0c;它能够快速识别并清理Mac磁盘上的垃圾文件、重复文件、无用语言安装包、iTunes缓存、邮件附件等&#xff0c;有效释放磁盘空间&#xff0c;提升Mac电脑的运行速度。此外&#xff0c;CleanMyMa…

【初阶数据结构】——160. 相交链表

文章目录 1. 题目介绍2. 思路1&#xff1a;暴力求解算法思想代码实现 3. 思路2&#xff1a;快慢指针算法思想代码实现 1. 题目介绍 链接: link 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&…

Flutter 全局控制底部导航栏和自定义导航栏的方法

1. 介绍 导航栏在移动应用中扮演着至关重要的角色&#xff0c;它是用户与应用之间进行导航和交互的核心组件之一。无论是简单的页面切换&#xff0c;还是复杂的应用导航&#xff0c;导航栏都能够帮助用户快速找到所需内容&#xff0c;提升用户体验和应用的易用性。 在移动应用…

chatgpt用pygame根据重心坐标 填充三角形

pygame.Surface.set_at(screen, (int(w), int(h)), (int(255zhongxina),int(255zhongxinb),int(255zhongxinc))) 颜色是由三个重心坐标权重abc255求出的 import pygame from pygame.locals import * import sys import mathpygame.init()width, height 800, 600 screen pyga…

关于 C/C++ 1Z(17)开源项目 openppp2 协同程式切换工作流

下述为开源项目 openppp2&#xff08;github&#xff09;构建工作在 C/C 17 的 stackful 有栈协同程式的工作流切换示意图&#xff1a; 在 openppp2 之中采用人工手动方式管理协同程式之间的切换&#xff0c;每个中断过程只是保存线程栈信息&#xff08;如寄存器、当前#PC EIP&…

魔改一个过游戏保护的CE

csdn审核不通过 网易云课堂有配套的免费视频 int0x3 - 主页 文章都传到github了 Notes/外挂/魔改CE at master MrXiao7/Notes GitHub 为什么要编译自己的CE 在游戏逆向的过程中&#xff0c;很多游戏有保护&#xff0c;我们运行原版CE的时候会被检测到 比如我们开着CE运…

C语言——内存函数

前言&#xff1a; C语言中除了字符串函数和字符函数外&#xff0c;还有一些函数可以直接对内存进行操作&#xff0c;这些函数被称为内存函数&#xff0c;这些函数与字符串函数都属于<string.h>这个头文件中。 一.memcpy&#xff08;&#xff09;函数 memcpy是C语言中的…

【OpenGL】(1) 环境搭建:运行简单的 OpenGL 教学示例程序

&#x1f4ad; 写在前面&#xff1a;我们尽可能地让大家以 最简单粗暴且无脑的方式&#xff0c;带大家配置好 OpenGL 环境&#xff0c;并跑出我们第一个示例程序。再次声明&#xff0c;本专栏所有教学都是基于 Windows上使用 VS2022 (X64) 的。本专栏主要内容是关于 3D 计算机图…

用数组模拟单链表、双链表、栈、单调栈、队列、循环队列、单调队列

本文用于记录个人算法竞赛学习&#xff0c;仅供参考 目录 一.模拟单链表 二.双链表 三.栈 四.单调栈 五.队列 六.循环队列 七.单调队列 为什么要用数组模拟而不用现成的STL&#xff0c;因为用数组模拟效率会快一点&#xff0c;比如用结构体指针的方式创建链表&#xff0…

C++ 二叉树OJ题

&#x1f493;博主CSDN主页:麻辣韭菜-CSDN博客&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 前言 C二叉搜索树 这篇讲解了搜索二叉…

动态规划1

动态规划问题的五步操作&#xff1a; 动态规划就是把dp表填满&#xff0c;则最终一定有一个数据是我们所需要的数据 下面以一道简单的题目进行讲解 本题其实就是斐波那契数列的一个plus版 &#xff0c;就是利用递推关系求值的过程 1.前期准备&#xff1a;创建dp表(使用一维…

GRE和MGRE

思维导图 综合实验 配置IP地址 R1&#xff1a; [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]ip add 192.168.1.1 24 [R1-GigabitEthernet0/0/0]int s3/0/0 [R1-Serial3/0/0]ip add 15.1.1.1 24 R2: [R2]int g 0/0/0 [R2-GigabitEthernet0/0/0]ip ad 192.168.2.2 24 [R2-G…

基于四足机器人和机械臂的运动控制系统(二)

文章目录 前言一、四足步态二、视觉抓取三、远程遥控 谢绝转载&#xff0c;无作者许可不可用做其他用途&#xff08;如教育展示产品、课程设计或毕业设计等&#xff09; 前言 衔接上一篇文章&#xff0c;这篇文章主要来介绍项目的初步实现 一、四足步态 可以知道&#xff0…

常用的几种排序算法小结

目录 1.冒泡排序 2.堆排序 2.1堆的基础知识和特性 2.2向上调整算法和向下调整算法 2.3堆排序实现 3.插入排序 4.希尔排序 5.选择排序 5.1选择排序递归版 5.2选择排序非递归版 6.快速排序 6.1 Hoare版本之递归 6.1.1普通版 6.1.2随机数版 6.1.3三数取中版 6.1.4小区间优化…

前端虚拟滚动列表 vue虚拟列表

前端虚拟滚动列表 在大型的企业级项目中经常要渲染大量的数据&#xff0c;这种长列表是一个很普遍的场景&#xff0c;当列表内容越来越多就会导致页面滑动卡顿、白屏、数据渲染较慢的问题&#xff1b;大数据量列表性能优化&#xff0c;减少真实dom的渲染 看图&#xff1a;绿色…

安装最新的wxPython和Python3并保证二者兼容

要安装最新的wxPython和Python3并保证二者兼容&#xff0c;你可以按照以下步骤进行操作&#xff1a; 安装Python3&#xff1a; 访问Python官方网站下载适合你操作系统的最新版Python3安装包。运行安装程序&#xff0c;确保在安装过程中将Python添加到系统环境变量中。安装完成…

【Java】:static成员和代码块

目录 1.static成员 1.1再谈学生类 1.2static修饰成员变量 1.3static修饰成员方法 1.4static成员变量初始化 1.4.1就地初始化 1.4.2静态代码块初始化 2.代码块 2.1代码块概念以及分类 2.2普通代码块 2.3构造代码块 2.4静态代码块 1.static成员 1.1再谈学生类 使用类…

MATLAB 点云随机渲染赋色(51)

MATLAB 点云随机渲染赋色(51) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 为点云中的每个点随机赋予一种颜色,步骤和效果如图: 1、读取点云 (ply格式) 2、随机为每个点的RGB颜色字段赋值 3、保存结果 (ply格式) 二、算法实现 1.代码 代码如下(示例):…

gin基础学习笔记--参数验证

用gin框架的数据验证&#xff0c;可以不用解析数据&#xff0c;减少if else&#xff0c;会简洁许多。 package mainimport ("fmt""time""github.com/gin-gonic/gin""github.com/gorilla/sessions" )// 初始化一个cookie存储对象 // s…

基于STM32的武警哨位联动报警系统设计,支持以太网和WIFI通信

1.功能 本文提出的武警报警信息系统终端&#xff0c;可实现报警和联动响应&#xff0c;支持以太网和WIFI两种通信模式&#xff0c;可实现移动哨位报警和固定哨位报警&#xff0c;语音和显示报警信息用户可自行定制。 本终端主要由STM32F103处理器模块和C8051F340处理器模块构…