使用Leaflet进行船舶航行警告区域绘制实战

news2024/9/20 9:20:58

目录

前言

一、坐标格式转换

1、数据初认识

2、将区域分割成多个点

3、数据转换

4、数据转换调用

二、WebGIS展示空间位置信息

1、定义底图

2、Polygon的可视化

3、实际效果

三、总结


前言

        通常而言,海事部门如海事局,通常会在所述的管辖区域内进行航行管控。比如会在海面上进行采砂作业、或者是拖带作业、人员落水、沉船碍航等作业需求。这些消息通常会先由各海域属地的海事局进行消息的发布,可以在他们的官方网站上看到,如以下的信息:

闽航警34/24  台湾海峡

2024年7月15日至2024年10月15日,每日24小时,在以下四点连线范围内的安全作业区进行采砂作业,24-12.27N  118-24.04E ,24-10.25N  118-26.30E ,24-08.17N  118-24.05E ,

24-10.19N  118-21.78E 。无关船舶禁止驶入。

福建海事局。

        在图上的信息中, 其实就包含一些很重要的时空信息,比如预警的时间是2024年7月15日到10月15日,中间差不多有三个月的时间,在这三个月的时间内,是不允许其它的船舶驶入上述的区域内的。作为GIS开发者,我们除了重点关注预警的时间范围,更关心的是空间范围。如果假定是一些商用船舶,我们就可以提取这些空间数据,在进行航线规划的时候,绕开这些作业区域,不仅能保证航行安全,也是加快作业效率。关注新闻的朋友一定知道,一些重要的行动需要对某一些区域进行管控的,也是会经过地方海事局进行公开位置,然后在规定的时间内进行。而这些区域不仅仅是一块区域,而是多个区域同时进行,从而锤炼不同的队伍的实战能力。如下图发布的航行警告中就包括6个区域(即面数据)。

        本文即以Leaflet为例,重点讲解如何将上述的空间信息转换为可以在地图上浏览的位置信息。首先使用Java语言将上面的涉及的空间坐标(度分秒)调整为常见的经纬度坐标。然后根据不同的点连接成多个面,最后将这些Polygon面数据叠加到Leaflet中,从而实现航行警告中的相关区域和地图的融合。通过本文,您可以掌握怎么使用Java把度分秒坐标转为标准格式,还可以掌握在Leaflet当中如何把这些Polygon进行空间叠加。

一、坐标格式转换

        其实度分秒这种格式的坐标在日常生活中也是非常常见的,读起来也比较顺畅。但是通常,我们在WebGIS上进行位置展示时,还是习惯于使用经纬度格式的坐标。因此这里主要讲解如何将度分秒的坐标转为标准经纬度信息。转换它的方法其实很简单,本人比较熟悉Java语言,因此后台的转换方法均使用Java编写,除了使用Java来开发这个功能,其他的编程语言同样可以实现。

1、数据初认识

        要想实现格式的转换,首先我们要对原文中的格式进行解释。可以看到在原文中的,它的具体内容中包含位置面信息内容如下:

区域一为下列4点连线水域:     25°15′26"N/120°29′20"E,24°50′30"N/120°05′45"E,     25°04′32"N/119°51′22"E,25°28′12"N/120°14′30"E。   
区域二为下列4点连线水域:     26°07′00"N/121°57′00"E,25°30′00"N/121°57′00"E,     25°30′00"N/121°28′00"E,26°07′00"N/121°28′00"E。    
区域三为下列4点连线水域:     25°34′00"N/122°50′00"E,25°03′00"N/122°50′00"E,     25°03′00"N/122°11′00"E,25°34′00"N/122°11′00"E。   
区域四为下列4点连线水域:     22°56′00"N/122°40′00"E,23°38′00"N/122°51′00"E,     23°38′00"N/123°23′00"E,22°56′00"N/123°09′00"E。    
区域五为下列4点连线水域:     21°14′00"N/121°33′00"E,21°33′00"N/121°18′00"E,     21°07′00"N/120°43′00"E,20°48′00"N/120°59′00"E。     
区域六为下列4点连线水域:     22°43′00"N/119°14′00"E,22°10′00"N/119°06′00"E,     21°33′00"N/120°29′00"E,22°09′00"N/120°32′00"E。   

        每个区域的都是这种形式的数据,这也为我们进行统一转换提供了有效的数据格式的基础。可以看到,每个区域都是一条数据,不同的点位(point)之间用逗号分隔,而坐标点内部使用/来分割。因此我们要想识别每一个区域的信息,其实也很简单。首先将字符串按逗号分隔,这样就可以形成多个点位的度分秒字符串。然后再分割/字符串,从而得到度分秒的位置。

2、将区域分割成多个点

按照前面介绍得分割方法,首先根据逗号,将目标区域字符串分割成多个点。关键的代码如下:

/**
 * 	将四个点的字符串统一解析为经纬度数组
 * @param bboxString
 */
private static void str2Point(String bboxString) {
	//将经纬度单位中的分改为英文状态下的分
	bboxString = bboxString.replaceAll("′", "\'");
	String [] points = bboxString.split(",");
	for (String str : points) {
		String [] latLon = str2LatLon(str);
		System.out.println(str + " = (" + latLon[0] + "," +latLon[1] + ")");
	}
}

        将经纬度单位中的分改为英文状态下的分是为了在后续的解析中进行数据容错。

3、数据转换

        将点从区域点字符串提取出来之后,我们需要将数据进行提取和转换两个步骤。提取是按照/将字符进行分割,而转换是将度分秒的数据转换为标准的经纬度数据。关键代码如下:

/**
* 	将单个度分秒坐标转经纬度坐标数组
* @param latLonStr
* @return
*/
private static String [] str2LatLon(String latLonStr) {
	String lat = latLonStr.split("\\/")[0];
    String lon = latLonStr.split("\\/")[1];
    String latSuffix = lat.substring(lat.length() -1 );//取出纬度后缀N,S	
    String lonSuffix = lon.substring(lon.length() -1 );//取出纬度后缀W,E
    String newLat =String.valueOf(LatLngUtil.dfm2LatLng(lat.substring(0,lat.length()-1)));
    String newLon =String.valueOf(LatLngUtil.dfm2LatLng(lon.substring(0,lon.length()-1)));
    newLat = latSuffix.equalsIgnoreCase("S") ?  "-" + newLat : newLat;
    newLon = lonSuffix.equalsIgnoreCase("W") ?  "-" + newLon : newLon;
    return new String[]{newLat,newLon};
}

        这里还是将经纬度转换的方法提供出来,防止大家在第一次看的时候有所迷糊。

/**
 * 度分秒转经纬度
 *
 * @param dms 116°25'7.85"
 * @return 116.418847
 */
public static double dfm2LatLng(String dms) {
    if (dms == null) return 0;
    try {
        dms = dms.replace(" ", "");
        String[] str2 = dms.split("°");
        if (str2.length < 2) return 0;
        int d = Integer.parseInt(str2[0]);
        String[] str3 = str2[1].split("\'");
        if (str3.length < 2) return 0;
        int f = Integer.parseInt(str3[0]);
        String str4 = str3[1].substring(0, str3[1].length() - 1);
        double m = Double.parseDouble(str4);

        double fen = f + (m / 60);
        double du = (fen / 60) + Math.abs(d);
        if (d < 0) du = -du;
         return Double.parseDouble(String.format("%.7f", du));
      } catch (Exception e) {
          e.printStackTrace();
      }
    return 0;
}

4、数据转换调用

        调用的函数比较简单,这里采用test的测试用例调用为例进行讲解,当然这里不限于使用何种方法。

@Test
public void testBoundaryConvert() {
	/*
	区域一为下列4点连线水域:   25°15′26"N/120°29′20"E,24°50′30"N/120°05′45"E,25°04′32"N/119°51′22"E,25°28′12"N/120°14′30"E
	区域二为下列4点连线水域:     26°07′00"N/121°57′00"E,25°30′00"N/121°57′00"E,25°30′00"N/121°28′00"E,26°07′00"N/121°28′00"E  
	区域三为下列4点连线水域:     25°34′00"N/122°50′00"E,25°03′00"N/122°50′00"E,25°03′00"N/122°11′00"E,25°34′00"N/122°11′00"E   
	区域四为下列4点连线水域:     22°56′00"N/122°40′00"E,23°38′00"N/122°51′00"E,23°38′00"N/123°23′00"E,22°56′00"N/123°09′00"E    
	区域五为下列4点连线水域:     21°14′00"N/121°33′00"E,21°33′00"N/121°18′00"E,21°07′00"N/120°43′00"E,20°48′00"N/120°59′00"E     
	区域六为下列4点连线水域:     22°43′00"N/119°14′00"E,22°10′00"N/119°06′00"E,21°33′00"N/120°29′00"E,22°09′00"N/120°32′00"E   
	*/
	List<String> bboxList = new ArrayList<String>();
		bboxList.add("25°15′26\"N/120°29′20\"E,24°50′30\"N/120°05′45\"E,25°04′32\"N/119°51′22\"E,25°28′12\"N/120°14′30\"E");//区域一
		bboxList.add("26°07′00\"N/121°57′00\"E,25°30′00\"N/121°57′00\"E,25°30′00\"N/121°28′00\"E,26°07′00\"N/121°28′00\"E");//区域二
		bboxList.add("25°34′00\"N/122°50′00\"E,25°03′00\"N/122°50′00\"E,25°03′00\"N/122°11′00\"E,25°34′00\"N/122°11′00\"E");//区域三
		bboxList.add("22°56′00\"N/122°40′00\"E,23°38′00\"N/122°51′00\"E,23°38′00\"N/123°23′00\"E,22°56′00\"N/123°09′00\"E");//区域四
		bboxList.add("21°14′00\"N/121°33′00\"E,21°33′00\"N/121°18′00\"E,21°07′00\"N/120°43′00\"E,20°48′00\"N/120°59′00\"E");//区域五
		bboxList.add("22°43′00\"N/119°14′00\"E,22°10′00\"N/119°06′00\"E,21°33′00\"N/120°29′00\"E,22°09′00\"N/120°32′00\"E");//区域六
		int index = 1;
		for(String bbox : bboxList) {
			System.out.println("区域"+index+"位置字符串:" + bbox);
			str2Point(bbox);
			System.out.println("--------------------------------------------------------------");
			index ++;
		}
	}

        在控制台中执行上述代码之后,可以看到以下结果,说明执行成功,同时数据均已成功的转换。

        解析的数据内容如下(取其中的一个点为例):

区域1位置字符串:25°15′26"N/120°29′20"E,24°50′30"N/120°05′45"E,25°04′32"N/119°51′22"E,25°28′12"N/120°14′30"E
25°15'26"N/120°29'20"E = (25.2572222,120.4888889)
24°50'30"N/120°05'45"E = (24.8416667,120.0958333)
25°04'32"N/119°51'22"E = (25.0755556,119.8561111)
25°28'12"N/120°14'30"E = (25.47,120.2416667)

         在经过上述的方法将度分秒坐标转换为标准经纬度坐标后,我们就可以将坐标叠加到Leaflet当中进行空间展示,下一节来深入阐述。

二、WebGIS展示空间位置信息

        当我们得到了经过转换过的空间标准经纬度坐标信息后,我们就可以将这些空间数据转换为面数据或者点数据,然后使用WebGIS框架,比如Leaflet等进行信息的几种展示。

1、定义底图

        定义定图的方法非常简单,这里我们直接给出在应用程序中使用天地图的方法,请注意如果在拷贝这里的代码时,一定要注意替换这里的令牌。

var map = L.map('mapid').setView([23.785345, 120.948486], 7);
	
var tdt_client_key = "473af7dc18cafb6b993616a0ce8e1ead";//天地图客户端的key

L.tileLayer('http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' +tdt_client_key, {
		maxZoom: 18,
		attribution: 'Map data &copy; <a href="http://www.tianditu.gov.cn/">TianDiTu</a>, <a href="http://www.esri.com/">Esri</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'
}).addTo(map);
	
//标签 
L.tileLayer('http://t1.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk='+ tdt_client_key, {maxZoom: 18
}).addTo(map);

2、Polygon的可视化

        在定义的基础的底图之后,下面将第一节转换好的所有的坐标进行Polygon空间展示。关键代码如下:

var style = {"color":"red","fillColor":"red","weight":2};
	
	L.polygon([
		[25.2572222,120.4888889],
		[24.8416667,120.0958333],
		[25.0755556,119.8561111],
		[25.47,120.2416667]
	],style).addTo(map).bindPopup("区域一.");
	
	L.polygon([
		[26.1166667,121.95],
		[25.5,121.95],
		[25.5,121.4666667],
		[26.1166667,121.4666667]
	],style).addTo(map).bindPopup("区域二.");
	
	L.polygon([
		[25.5666667,122.8333333],
		[25.05,122.8333333],
		[25.05,122.1833333],
		[25.5666667,122.1833333]
	],style).addTo(map).bindPopup("区域三.");
	
	L.polygon([
		[22.9333333,122.6666667],
		[23.6333333,122.85],
		[23.6333333,123.3833333],
		[22.9333333,123.15]
	],style).addTo(map).bindPopup("区域四.");
	
	L.polygon([
		[21.2333333,121.55],
		[21.55,121.3],
		[21.1166667,120.7166667],
		[20.8,120.9833333]
	],style).addTo(map).bindPopup("区域五.");
	
	L.polygon([
		[22.7166667,119.2333333],
		[22.1666667,119.1],
		[21.55,120.4833333],
		[22.15,120.5333333]
	],style).addTo(map).bindPopup("区域六.");

        请注意,在上述的例子中,我们使用一个统一的样式选型,style,它表示展示的Polygon面的颜色和填充颜色都是红色,如果您想设置自己喜欢的颜色也是可以的。

3、实际效果

        经过上述的两个步骤,我们已经实现了地图对象的定义和绑定,同时我们将转换好的坐标信息进行赋值,让6个面在地图上进行可视化。

        以上的红色区域就是我们转换的六个区域,不知道大家看了这六个区域,有没有勾起点啥记忆呢。 这里不多说,大家可以去相关网站搜索这个区域之前发生过什么就大致清楚了。

三、总结

        以上就是本文的主要内容,本文即以Leaflet为例,重点讲解如何将上述的空间信息转换为可以在地图上浏览的位置信息。首先使用Java语言将上面的涉及的空间坐标(度分秒)调整为常见的经纬度坐标。然后根据不同的点连接成多个面,最后将这些Polygon面数据叠加到Leaflet中,从而实现航行警告中的相关区域和地图的融合。通过本文,您可以掌握怎么使用Java把度分秒坐标转为标准格式,还可以掌握在Leaflet当中如何把这些Polygon进行空间叠加。行文仓促,定有不足之处,真诚期待各位专家朋友在评论区批评指正,不甚感激。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java从入门到精通(十五) ~ IO流

晚上好&#xff0c;愿这深深的夜色给你带来安宁&#xff0c;让温馨的夜晚抚平你一天的疲惫&#xff0c;美好的梦想在这个寂静的夜晚悄悄成长。 目录 前言 什么是IO流&#xff1f; IO流的作用&#xff1a; 一、基础流 1. 字节流 1.1 字节输入流 FileInputStream 1.2 字节…

找到第一个满足条件的格值

表格第1列是科目&#xff0c;之后几列是每次的考试成绩&#xff0c;顺序排列。 ABCDE1Art03.676.27.82History3.786.217.29.83Maths5.66.36.68.9 要求根据指定的科目和成绩&#xff0c;找到该科目中大于等于该成绩的第1个格值&#xff0c;比如参数是Maths、6.5时&#xff0c;…

element-ui简单入门1.0.0

第一篇&#xff1a;table标签速用 总结&#xff1a;建楼前&#xff0c;先打地基<el-table></el-table>&#xff0c;打完地基看高度&#xff0c;一层楼4米&#xff0c;80米20个<el-table-column></el-table-column>&#xff0c;每次楼的名字是label 第…

[翻译] Asset Administration Shells

关于资产管理外壳 (AAS) 资产管理外壳 (AAS) 是工业4.0中的关键概念&#xff0c;为产品、资源&#xff08;如设备&#xff09;和过程提供信息隐藏和更高层次的抽象。AAS 是技术和设备无关的机器可读描述&#xff0c;提供访问资产属性和功能的统一接口。与现有解决方案不同&…

C# 下的限定符运算详解(全部,任意,包含)与示例

文章目录 1.限定符概述2. 全部限定符运算&#xff08;All&#xff09;3. 任意限定符运算&#xff08;Any&#xff09;4. 包含限定符运算&#xff08;Contains&#xff09;总结 当我们在C#编程中需要进行条件判断或集合操作时&#xff0c;限定符&#xff08;qualifiers&#xff…

Vue项目启动ESLint报错no-unused-vars解决办法

目录 原因分析解决方法 Vue项目启动时报错如下 ✘ http://eslint.org/docs/rules/no-unused-vars index is assigned a value but never usedsrc\views\friend\list.vue:206:17const index this.tableList.indexOf(v)^原因分析 ESLint是一个在JavaScript代码中识别和报告问…

【传知代码】辅助任务改进社交帖子多模态分类(论文复现)

在当今数字化社交时代&#xff0c;社交媒体平台如同人们生活的一部分&#xff0c;每天数以亿计的帖子在网络上涌现。这些帖子不仅仅是信息的载体&#xff0c;更是人们思想、情感和行为的折射。然而&#xff0c;要准确理解和分析这些多样化的社交帖子&#xff0c;仅依靠文本内容…

请问如何做好软件测试工作呢?

一、明确测试目标和范围 理解测试目的&#xff1a;在开始测试之前&#xff0c;首先要明确测试的目标和范围&#xff0c;确保测试计划 与需求相匹配。这有助于测试人员聚焦在关键功能上&#xff0c;避免浪费时间和资源。制定详细的测试计划&#xff1a;根据项目需求&#xff0…

【Python】爬取网易新闻今日热点列表数据并导出

1. 需求 从网易新闻的科技模块爬取今日热点的列表数据&#xff0c;其中包括标题、图片、标签、发表时间、路径、详细文本内容&#xff0c;最后导出这些列表数据到Excel中。 网易科技新闻网址&#xff1a;https://tech.163.com 2. 解决步骤 2.1 前期准备 爬虫脚本中需要引用…

Visio新手安装及超全快捷指令合集

Microsoft Visio是一款专业的流程图和图表绘制软件&#xff0c;是微软旗下的一款图表和矢量图形应用程序&#xff0c;属于Microsoft 365系列的一部分。但Visio需要单独安装&#xff0c;安装完成之后可与Word联用。 一、Visio软件介绍 Visio 是一款用途多样的绘图工具&#xff…

全球氢钎焊市场规划预测:未来六年CAGR为3.4%

随着全球制造业的持续发展和消费者对高质量产品的需求增加&#xff0c;氢钎焊作为一种高效的焊接技术&#xff0c;正逐渐受到市场的广泛关注。本文旨在通过深度分析氢钎焊行业的各个维度&#xff0c;揭示行业发展趋势和潜在机会。 【市场趋势的演变】 1. 市场规模与增长&#…

【uniapp】集成第三方插件示例

文章目录 uniapp芯套Android壳app目录下/libs目录导入全部aar工程目录下导入rewriter文件夹 uniapp芯套Android壳 https://blog.csdn.net/xzzteach/article/details/140800350 app目录下/libs目录导入全部aar工程目录下导入rewriter文件夹 本地引入包内容 在 project 级别的…

解决com.alibaba.csp.sentinel.slots.block.flow.FlowException: null

springboot项目配置sentinel&#xff0c;能限流成功但是不能限流方法 原因 名字没对应上

token和embedding

1. token 2. embedding 1.token token&#xff1a;词元/令牌/词 tokenization&#xff1a;分词 tokenizer&#xff1a;分词器 token是最小语义单元&#xff0c;通常可以是&#xff0c;一个字母、一个词、一个数字、一个汉字或任何其他有意义的字符组合&#xff0c;取决于文本处…

免费【2024】springboot 大学生心理健康诊断专家系统设计与开发

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

R语言统计分析——点图

参考资料&#xff1a;R语言实战【第2版】 点图提供了一种在简单水平刻度上绘制大量有标签值得方法。我们可以使用dotchart()函数创建点图&#xff0c;格式为&#xff1a; dotchart(x,labels) 其中&#xff0c;x是一个数值向量&#xff0c;而labels则是由每个点的标签组成的向量…

【Linux系统编程】:进程地址空间1

1.引出进程地址空间 因为str指向的是字符串首字母的地址&#xff0c;首字母是字符常量“h”&#xff0c;地址存储在字符常量区&#xff0c;无法修改&#xff0c;故报错。 Linux进程地址空间与进程内存布局详解 - 知乎 (zhihu.com) 我们编写一段代码&#xff0c;来认识一下存储…

C++ const、constexpr与consteval作用与区别

C const、constexpr与consteval作用与区别 在C 常量表达式和编译时优化中&#xff0c;我们已经提到了常量、编译时常量与运行时常量的概念。为了加深理解&#xff0c;我们再重新明晰一下这三者的概念。 常量&#xff1a;初始化之后便不可修改的量。在c中使用const修饰的“变量”…

开源Spring Boot版本WebSSH:轻松在浏览器中管理SSH和FTP

介绍 WebSSH 是一个轻量级的开源ssh工具&#xff0c;只需安装在服务端&#xff0c;就可以通过浏览器访问SSH和FTP。它支持文件和日志高亮显示&#xff0c;Vim 和 Top 命令&#xff0c;实时查看日志&#xff0c;并且操作体验与标准的 Shell 基本相同。WebSSH 支持多会话、文件上…

“艺启创作 智绘未来”AI漫画创意大赛,燃动国漫新纪元!

8月2日&#xff0c;百度文库宣布携手玄机科技举办国内首个「AI漫画大赛」&#xff0c;用户可以直接尝试用AI创作漫画&#xff0c;并在未来为用户独家提供AI小说、AI漫画分镜等行业领先的跨模态AI创作能力。 跨界融合&#xff0c;创新无限 本次大赛&#xff0c;不仅是创意的碰撞…