基于Leaflet和天地图的直箭头标绘实战-源码分析

目录

前言

一、Leaflet的特种标绘库

1、特种标绘对象的定义

2、Plot基类定义

3、直线箭头的设计与实现

二、在天地图中进行对象绘制

1、引入天地图资源

2、标绘对象的调用时序

3、实际调用过程

三、总结


前言

        在博客中介绍过geoman标绘的具体实现,使用Leaflet GeoMan结合天地图进行自由标绘实战,基于GeoMan的标绘只能包含了常见的点、线、面、矩形的空间对象的标绘。在一些面向特种行业的应用中,我们会遇到特种标绘。比如用来表示敌我双方态势的战斗标绘,比如在一场战斗中的敌我接敌,各方的支援力量的介入,战斗的结果等等过程需要进行集中的标绘。如下图所示:

        以上对象的绘制比之前的基于Geoman的点、线、面等信息的生成稍微要复杂一些。当然您使用一些开源库进行系统的构建,这样能加快开发的速度。但是如果我们想实现自由业务的封装,就需要进行相应的改造才可以,比如我们需要定义箭头的偏转角,控制斜率,生成集结地等曲面时更加的平滑等等,这些功能的实现都是需要进行自己的定制和改造的。因此我们有必要在Leaflet中实现上述的功能,同时掌握如何来进行自定义的绘制。

        一般的态势标绘的类型可以包含以下几种:直箭头、细直箭头、突击方向、进攻方向、进攻方向(尾)、分队战斗行动、分队战斗行动(尾)、钳击、聚集地等。不同的图形绘制过程不一样,根据绘制算法的不同,计算过程也不尽相同。后续会依据不同的标绘对来进行绘制过程解析。本文主要以直线箭头的绘制重点讲解在Leaflet中对上述对象的封装,相关类的功能介绍等,首先介绍一个基于Leaflet的标绘基础库,其次介绍这个库的基本结构,相关类属性和方法的定义,然后基于时序图来介绍相关API的调用,最后生成一个直线箭头的实例。如果对标绘感兴趣的朋友,可以不妨看过来。

一、Leaflet的特种标绘库

        目前基于Leaflet的特种标绘库开源的不多,但是有一个基础的开源库可以提供标绘对象的生成服务,leaflet_plot,大家可以下载相关的源代码进行学习。它的开源代码主要包含两个文件,一个是Plots.js和PlotUtil.js,其中PlotUtil.js主要用于相关坐标点的绘制,Plots.js主要用于绘制和展示不同的对象。

1、特种标绘对象的定义

        首先,我们来看一下Plots.js,在这个类中,定义了所有的标绘对象,由于对象种类较多,这里仅以直线箭头为例,重点讲解标绘类的设计与实现,其它的对象绘制过程比较复杂,后续再慢慢进行讲解。Plots.js主要包含类型定义、对象工厂的创建、具体对象实现的创建。下面将详细介绍。

        在这里,通过javascript代码定义出所有的对象类型,具体有下列几种:

序号类型说明
1STRAIGHT_ARROW"straightarrow",//直箭头
2ASSAULT_DIRECTION"assaultdirection",//突击方向
3ATTACK_ARROW"attackarrow",//进攻方向
4TAILED_ATTACK_ARROW"tailedattackarrow",//进攻方向(尾)
5SQUAD_COMBAT"squadcombat",//分队战斗行动
6TAILED_SQUAD_COMBAT"tailedsquadcombat",//分队战斗行动(尾)
7FINE_ARROW"finearrow",//细直箭头
8DOUBLE_ARROW"doublearrow", //钳击 
9 GATHERING_PLACE"gatheringplace",//聚集地  

2、Plot基类定义

        按照后端面向对象的方式将对象的公共父类抽象出来,形成公共的基类。用于基础属性的设置与渲染。其它对象可以在此基础之上进行扩展即可。

L.Plot = {isPlot: function () {return true;},getBaseType: function () {let geojson = this.toGeoJSON()let type = geojson.geometry.typeif (type == 'MultiLineString' || type == 'LineString') {type = 'Polyline'}return type},//设置绘制图形需要的点setPoints: function (latlngs) {this._bounds = new L.LatLngBounds();this._setLatLngs([])this._points = this._convertLatLngs(latlngs) || [];this._proPoints = L.PlotUtils.proPoints(this._points);if (this.getPointCount() >= 1)this.generate();},//设置投影点并更新对应的坐标点setProPoints: function (proPts) {var latlngs = L.PlotUtils.unProPoints(proPts);this.setPoints(latlngs);},//获取控制点坐标getCtrlPoints: function() {let ctrlPts = []switch (this.type) {case L.PlotTypes.SECTOR:case L.PlotTypes.ARC:ctrlPts = this.getPoints();if (ctrlPts.length < 3) {ctrlPts = this._ctrlPnts;}break;case L.PlotTypes.CIRCLE:ctrlPts = this.getPoints();if (ctrlPts.length < 2) {ctrlPts = this._ctrlPnts;}break;default:ctrlPts = this.getPoints();}return ctrlPts;},//获取输入点getPoints: function () {return this._points;},//获取输入点对应的投影点getProPoints: function () {return this._proPoints;},//获取输入的点个数getPointCount: function () {return this._proPoints.length || 0;},toPlotJSON: function () {let setting = {type: this.type,points: this.getPoints(),options: this.options,}return setting},//结束绘制finishDrawing: function () {}
}

        Plos类的方法列表如下:

序号方法说明
1isPlot是否特殊标绘,默认true
2getBaseType获取基础类型,如:Polyline
3setPoints设置绘制图形需要的点
4setProPoints 设置投影点并更新对应的坐标点
5getCtrlPoints获取控制点坐标
6getPoints获取输入点
7getProPoints获取输入点对应的投影点
8getPointCount获取输入的点个数
9toPlotJSON转成标绘json
10finishDrawing标绘结束事件

3、直线箭头的设计与实现

        在特种标绘的工厂方法中,有生成直线箭头的方法,为简单起见,将其它的方法进行隐藏说明,关键代码如下所示:。

L.PlotFactory = {};
L.PlotFactory.createPlot = function (type, points, options) {switch (type) {case L.PlotTypes.STRAIGHT_ARROW:return new L.Plot.StraightArrow(points, options);case L.PlotTypes.ASSAULT_DIRECTION:return new L.Plot.AssaultDirection(points, options);}return null;
}

        其次我们来看下具体的直线箭头的具体实现:

/*** 直箭头*/
L.Plot.StraightArrow = L.Polyline.extend({includes: L.Plot,options: {fixPointCount: 2,maxArrowLength: 3000000,arrowLengthScale: 8},initialize: function (latlngs, options) {L.setOptions(this, options);this.type = L.PlotTypes.STRAIGHT_ARROW;this.setPoints(latlngs)},//生成图形generate: function () {if (this.getPointCount() < 2) {return;}var pnts = this._proPoints;var pnt1 = pnts[0];var pnt2 = pnts[1];var distance = L.PlotUtils.distance(pnt1, pnt2);var len = distance / this.options.arrowLengthScale;len = len > this.options.maxArrowLength ? this.options.maxArrowLength : len;var leftPnt = L.PlotUtils.getThirdPoint(pnt1, pnt2, Math.PI / 8, len, false);var rightPnt = L.PlotUtils.getThirdPoint(pnt1, pnt2, Math.PI / 8, len, true);let proPts = [pnt1, pnt2, leftPnt, pnt2, rightPnt]this._setLatLngs(L.PlotUtils.unProPoints(proPts));this.redraw();}
});
L.Plot.straightArrow = function (latlngs, options) {return new L.Plot.StraightArrow(latlngs, options);
};

        通过代码大家可以看到,在StraightArrow这个类中,其是通过继承Polyline来实现对象的扩展的,在extends扩展实现中,扩展了两个属性和两个方法。

序号参数说明
1includes: L.Plot,表示基类包含Plot对象
2options当前对象扩展属性,包含对象独有的箭头倾角等
3initialize初始化方法
4generate最主要的图形绘制,包括各种角度的计算

        以上就是特种标绘对象的方法和属性的具体介绍。下面将结合天地来重点讲解如何进行标绘对象的静态标绘,即根据指定坐标来动态绘制。

二、在天地图中进行对象绘制

        这里将重点讲解如何在天地图中进行特种对象的标绘。通过具体代码的实现和调用过程的重现,让大家对如何进行标绘有更详细的讲解。

1、引入天地图资源

        在地图的展示界面中,引入天地图的在线图源非常重要,在加载影像注记的时候,需要请大家注意替换相应的参数。关键代码如下:

<!DOCTYPE >
<html lang="zh"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1" /><title>Leaflet plot绘制</title><link rel="stylesheet" href="./lib/leaflet.css"/><style>.hello {position: relative;}#mapContainer {width: 100%;height: 600px;background-color: #eee;z-index: 0;}#toolbar {position: absolute;left: 10px;bottom: 10px;list-style: none;margin: 0;padding: 10px;box-shadow: 2px 2px 5px;background-color: rgb(34 34 34 / 50%);border-radius: 0 5px 5px 0;}#toolbar li {line-height: 28px;}</style></head><body><div class="hello"><h1>Leaflet的plot标绘</h1><div id="mapContainer"></div><ul id="toolbar"><li><button onclick="addStraightArrow();">直箭头</button></li><hr><li><button onclick="clearPlots();">清空</button></li></ul></div><script src="./lib/leaflet.js"></script><!-- // 计算工具 --><script src="./lib/PlotUtil.js"></script><!-- // 绘制工具 --><script src="./lib/Plots.js"></script><script>var tdt_client_key = "xxx";//天地图客户端的key//影像底图const tiles = 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:'&copy; <a href="https://www.tianditu.gov.cn/">在线图源使用国家天地图</a> contributors',});var plotLayer;var map = L.map('mapContainer').setView([28.170086, 112.957993], 13).addLayer(tiles);//影像注记const label_tiles = L.tileLayer('http://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + tdt_client_key, {maxZoom: 18});map.addLayer(label_tiles);plotLayer = L.featureGroup().addTo(map);function clearPlots() {this.plotLayer && this.plotLayer.clearLayers()}// 直箭头function addStraightArrow() {L.Plot.straightArrow([[28.17629, 112.923746],[28.188471, 112.948208]]).addTo(this.plotLayer);}</script></body>
</html>

        这里需要注意的是,在引入影像注记的时候,需要根据天地图的规范进行相应图层的替换,这里需要注意的点就是:

http://t0.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=

        需要注意上述字符串中的cia_w和后面的cia,cia表示图层的名字,这里一定注意,否则地图不能正确加载。

2、标绘对象的调用时序

        这里我们使用时序图来进行调用时序的讲解,让大家对标绘对象的绘制和加载过程有更深入的讲解,以下是简单的时序调用视图。

3、实际调用过程

        这里以静态标绘为例,未来需要根据绘制事件来进行绘制坐标的获取来进行对象的生成。

         绘制对象的关键点生成,这个距离在后面的倾角的计算有很大的作用。

        第三点(即倾角坐标点的计算)

         最终得到的空间对象如下所示:

        最后在在上面的结果中对标注关键参数进行说明。

         通过以上四点的计算即完成直线箭头的绘制,将绘制的对象添加到地图即可。

三、总结

        以上就是本文的主要内容,本文主要以直线箭头的绘制重点讲解在Leaflet中对上述对象的封装,相关类的功能介绍等,首先介绍一个基于Leaflet的标绘基础库,其次介绍这个库的基本结构,相关类属性和方法的定义,然后基于时序图来介绍相关API的调用,最后生成一个直线箭头的实例。行文仓促,定有不足之处,还请各位专家博友不吝指教,不胜感激。

        参考资料:

        1、基于Leaflet实现标绘——直箭头。

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

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

相关文章

Window Server 2019+ 安装 Docker

刚刚在等待下载的时候&#xff0c;发了篇文&#xff0c;然后发现直接下载docker用不了&#xff0c;看了官网说明发现&#xff1a;Docker 不支持Window Server!!!不要直接下载官网那里的安装包。 那个链接点进去了windows的指南&#xff0c;发现也有问题&#xff0c;给的脚本地…

数据结构:(OJ141)环形列表

给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;…

【数据类型】映射map

小明正在备考英语四级考试&#xff0c;但他的词典太厚了&#xff0c;他记不住哪个单词在哪里。 于是他准备开发一个可以直接找某单词在某页的应用。 但是&#xff0c;他不会做&#xff0c;整天十分烦恼。 好啦&#xff0c;进入正题&#xff0c;大家好&#xff0c;我是学霸小羊…

Kubernetes从零到精通(12-Ingress、Gateway API)

Ingress和Gateway API都是Kubernetes中用于管理外部访问集群服务的机制&#xff0c;但它们有不同的设计理念和适用场景。它们的基本原理是通过配置规则&#xff0c;将来自外部的网络流量路由到Kubernetes集群内部的服务上。 Ingress/Gateway API和Service Ingress/Gateway API…

Django后台管理复杂模型

【图书介绍】《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》_django 5企业级web应用开发实战(视频教学版)-CSDN博客 《Django 5企业级Web应用开发实战&#xff08;视频教学版&#xff09;》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) Django框架…

ZLMediaKit Windows编译以及使用

1.运行ZLMediaKit 2.通过ffmpeg把视频源推流给ZLMediaKit 执行以下命令&#xff0c;将本地视频通过RTSP协议推流给ZLMediaKit。 ffmpeg -re -stream_loop -1 -i "D:\workplace\armgb\public\1.fileh264" -vcodec h264 -f rtsp rtsp://127.0.0.1/live/test 若想将本…

统信服务器操作系统【d版系统上Ansible工具】配置方法

在统信服务器操作系统d版本上进行安装Ansible工具的方法以及配置方法。 文章目录 准备环境功能描述安装与配置一、 安装ansible工具1. 直接 命令安装2. 验证安装结果3. 配置ssh免密登录二、Ansible使用1. 主机清单配置2. ansible命令3. ansible模块三、 playbook配置文件1. 执行…

Java 发布jar包到maven中央仓库(2024年9月保姆级教程)

文章目录 前言一、账号准备1. 注册登录账号2. 新建命名空间3. 验证命名空间4. 生成令牌5. 为 maven 设置令牌二、GPG准备1. 下载GPG2. 发布证书2.1 新建证书2.2 发布证书到服务器2.3 验证发布三、发布jar包到中央仓库1. 编辑项目pom文件2. 打包上传3. 发布jar包4. 搜索我们的ja…

【机器学习】任务五:葡萄酒和鸢尾花数据集分类任务

目录 1.实验基础知识 1.1 集成学习 &#xff08;1&#xff09;随机森林 &#xff08;2&#xff09;梯度提升决策树&#xff08;GBDT&#xff09; &#xff08;3&#xff09;XGBoost &#xff08;4&#xff09;LightGBM 1.2 参数优化 &#xff08;1&#xff09;网格搜索…

Java面试篇基础部分-Java线程池工作原理

线程池的出现,主要是用来管理一组线程的工作运行状态,这样可以方便JVM更好的利用CPU资源。 Java线程池的工作原理:JVM先根据用户的参数创建一定数量的可运行的线程任务,并且将这些任务放入到队列中,在线程创建之后,启动这些任务。 如果当线程数超过最大线程数,这个线程数…

WIFI路由器的套杆天线简谈

❝本次推文简单介绍下WIFI路由器的套杆天线。 路由器天线 路由器在这个万物互联的时代&#xff0c;想必大家对其都不陌生。随着科技的发展&#xff0c;常用的路由器上的天线也越来越多&#xff0c;那么问题来了&#xff1a;天线越多&#xff0c;信号越好吗&#xff1f;路由器…

视频转文字工具:开启视频内容深度挖掘的钥匙

图片里到文字要提取出来&#xff0c;现在有很多的工具&#xff0c;但是视频里的文字要提取出来&#xff0c;是不是就不那么好操作呢&#xff1f;并不是的&#xff0c;现在也有不少支持视频转文字的工具&#xff0c;这次我们就来介绍一些可以提高我们视频文字提取效率的工具吧。…

【CSS in Depth 2 精译_033】5.4 Grid 网格布局的显示网格与隐式网格(中)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

[Redis][环境配置]详细讲解

目录 1.安装 && 简单配置2.文件目录说明3.客户端 1.安装 && 简单配置 Ubuntu下&#xff0c;直接使用sudo apt install redis -y即可支持远程连接&#xff1a;修改/etc/redis/redis.conf 将bind 127.0.0.1改为bing 0.0.0.0作为学习用途&#xff0c;可以将prote…

代码——IMX6UL烧录工具及其使用

一、简介 在此感谢正点原子官方提供的IMX6UL烧录代码&#xff0c;本篇是在正点原子给的代码基础上修改的&#xff0c;增加了些许功能&#xff0c;可根据自己的需求更改。此外代码难免有疏漏之处&#xff0c;还望见谅 二、源代码的使用 1,库和工具的安装 安装库和工具前&#x…

Datawhale X 南瓜书 task01学习笔记

机器学习三观 机器学习工程领先理论 what:什么是机器学习? 机器学习定义&#xff1a;研究关于“学习算法”(一类能从数据中学习出其背后潜在规律的算法)的一门学科PS:深度学习指的是&#xff1a;神经网络那一类学习算法&#xff0c;因此是机器学习的子集把深度学习单列出来…

idea连接docker 自动化部署

进入Linux服务器 vim /lib/systemd/system/docker.service将 ExecStart/usr/bin/dockerd -H fd:// --containerd/run/containerd/containerd.sock 替换为 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock新建文件 Dockerfile配置Dockerfile文…

Linux下rpm方式部署mysql(国产化生产环境无联网服务器部署实操)

请放心观看&#xff0c;已在正式环境部署验证&#xff0c;流程无问题&#xff01; 所用系统为国产化麒麟银河 aarch64系统&#xff0c;部署时间2024年9月份&#xff01; #查看服务器信息 #涉及生产服务器&#xff0c;所以输出信息隐藏了一部分[rootecs-xxxxx hdata]# uname -…

Java 中常用的排序算法

Java 中常用的排序算法有很多&#xff0c;每种算法的时间复杂度和适用场景都不同。以下是几种常见的排序算法及其 Java 实现和讲解&#xff1a; 1. 冒泡排序 (Bubble Sort) 算法思路&#xff1a; 重复地遍历数组&#xff0c;每次比较相邻两个元素。如果前一个比后一个大&…

性能测试笔记

一、性能测试介绍 1.概述 性能测试时通过工具/代码模拟正常/峰值/异常的负载条件&#xff0c;对系统的各项性能指标进行测试和评估的过程 本阶段的学习范围是服务端的性能测试&#xff0c;不包括客户端性能 测试目的 评估当前系统能力&#xff0c;如&#xff1a;新出的手机都…