基于Leaflet和天地图的细直箭头和突击方向标绘实战

news2024/10/1 15:45:34

目录

前言

一、细直箭头和突击方向的类设计

1、总体类图

2、对象区别

二、标绘绘制的具体实现

 1、绘制时序图

2、相关点的具体绘制

3、最终的成果

三、总结


前言

        今天是10月1日国庆节,迎来我们伟大祖国75周年的华诞。有国才有家,在这里首先祝我们伟大的祖国繁荣昌盛。放眼这个世界,俄乌战争时至今日,尚未结束,中东战场现在火药味浓烈,简直就是一个巨大的火药桶。国际局势很紧张,感恩在华夏,可以安心放假休假。祝各位小伙伴们假期愉快。

        在之前的博客中分享了一次关于如何在Leaflet中进行直箭头的对象标绘。在实际的标绘过程中,我们需要展示一定宽度的箭头,基于Leaflet和天地图的直箭头标绘实战-源码分析。如下面的图片展示的效果:

        在上图中,有两种类型的标绘对象,第一个是细直箭头;第二个是突击方向。这两类对象其实是差不多的,在后面的讲解过程中,你就会发现。突击方向是细直箭头的子类,具体内容在后续的章节中进行介绍。

        本文将重点讲解在Leaflet中如何进行细直箭头和突击方向的绘制,首先使用面向对象的方法对细直箭头和突击方向的属性和方法进行介绍,然后重点介绍在绘制细直箭头和突击方向对象的各个绘制点的计算过程,最后给出一个实例过程。如果您对这两种标绘对象的绘制有兴趣,不妨来看看。

一、细直箭头和突击方向的类设计

        在前面的内容中,我们介绍了细直箭头和突击方向这两种标绘对象。突击方向是细直箭头的子类,为了更详细展示两者的区别和联系。我们使用面向对象的方式来简单介绍一下。

1、总体类图

        根据源代码,我们把这两个对象的总体类图绘制如下,供大家参考:

        通过以上的图中,我们可以看到,L.PlotUtils是公共的绘制对象,提供了很多的计算方法,比如:把地理坐标和平面坐标的互相转换,计算贝塞尔曲线,计算相关点等方法。这些方法在进行相应的对象绘制时非常重要。

2、对象区别

        L.Plot是所有标绘对象的基类,包含了各个点的信息,包括控制点信息。基于L.Plot对象,扩展两个箭头对象,细直箭头和突击方向。

/**
 * 突击方向
 */
L.Plot.AssaultDirection = L.Plot.FineArrow.extend({
    options: {
        tailWidthFactor: 0.2,
        neckWidthFactor: 0.25,
        headWidthFactor: 0.3,
        headAngle: Math.PI / 4,
        neckAngle: Math.PI * 0.17741,
        fixPointCount: 2
    },
    initialize: function (latlngs, options) {
        L.setOptions(this, options);
        this.type = L.PlotTypes.ASSAULT_DIRECTION;
        this.setPoints(latlngs)
    }
});

L.Plot.assaultDirection = function (latlngs, options) {
    return new L.Plot.AssaultDirection(latlngs, options);
};

        以上简单介绍细直箭头和突击方向的类继承关系。了解继承关系对于理解对象和构造有很大的作用。通过上面的类定义可以看到,细直箭头与突击方向的最大区别就是箭头对象的宽度和角度有一定的区别。当然,大家可以通过参数传入的方式来进行属性的控制。两者的区别就是:

options: {
        tailWidthFactor: 0.15,//尾部宽度倍数
        neckWidthFactor: 0.2,//颈部宽度倍数
        headWidthFactor: 0.25,//头部宽度倍数
        headAngle: Math.PI / 8.5,//头部角度
        neckAngle: Math.PI / 13,//颈部角度
        fixPointCount: 2
    }

二、标绘绘制的具体实现

        我们仔细来看细直箭头,可以发现。在绘制过程中,我们只需要确定两个点,即开始位置和结束位置,下图中的pnt1和pnt2。而构成整体面的点为不包括pnt1以外的所有点。绘制原理如下:

直箭头是有两个点组成的,左下角为起点(pnt1),右上角为终点(pnt2)。那么,这个直箭头是如何来的?其实,这个直箭头就是通过起止两个点计算得到的一个由七个点连成的多边形Polygon。

        通过两个点创建标绘对象的方法可以使用以下公式来表达:

其中:polygon(pnt1,pnt2)表示求解根据起始位置构建箭头对象;

        tailLeft表示尾部左边点坐标,neckLeft表示颈部左边点位置,headLeft表示头部左边点位置,pnt2表示结束点位置,headRight 表示头部右边点位置,neckRight表示颈部右边点位置,tailRight表示尾部右边点位置。从尾部左边点位置开始,按照顺时针的顺序连接这7个点即完成一个面的构建。然后把平面左边转为地理左边面,最后叠加在地图上展示。突击方向除了箭头的方向扁平程度与细直箭头有所区别,绘制方式是一样的。后续内容中以细直箭头绘制为例。

 1、绘制时序图

        为了让大家对标绘对象的绘制时序有一个基本的了解,因此这里结合一些关键步骤来讲解相关类的调用过程。

        在上图中清晰的展示了在界面中各个对象如何进行调用。涉及的对象有PlotUtils和具体的箭头对象。 那么具体细直箭头是如何根据两个点来生成另外的七个点的过程,我们将在后续的内容中进行详细介绍。

2、相关点的具体绘制

        了解了绘制时序及相关的对象之后,我们来具体看一下如何使用两个点生成面的七个关键点。其它的辅助代码再此不再赘述,重点叙述7个点的计算过程。计算方法源码如下所示:

//生成图形
generate: function () {
  if (this.getPointCount() < 2) {
      this._setLatLngs([])
      return;
  }
  var pnts = this._proPoints;
  var pnt1 = pnts[0];
  var pnt2 = pnts[1];
  var len = L.PlotUtils.getBaseLength(pnts);//pnt1和pnt2的距离的0.99次幂
  var tailWidth = len * this.options.tailWidthFactor;//尾部的宽度
  var neckWidth = len * this.options.neckWidthFactor;//颈部宽度
  var headWidth = len * this.options.headWidthFactor;//头部宽度
  var tailLeft = L.PlotUtils.getThirdPoint(pnt2, pnt1, L.PlotConstants.HALF_PI, tailWidth, true);
  var tailRight = L.PlotUtils.getThirdPoint(pnt2, pnt1, L.PlotConstants.HALF_PI, tailWidth, false);
  var headLeft = L.PlotUtils.getThirdPoint(pnt1, pnt2, this.options.headAngle, headWidth, false);
  var headRight = L.PlotUtils.getThirdPoint(pnt1, pnt2, this.options.headAngle, headWidth, true);
  var neckLeft = L.PlotUtils.getThirdPoint(pnt1, pnt2, this.options.neckAngle, neckWidth, false);
  var neckRight = L.PlotUtils.getThirdPoint(pnt1, pnt2, this.options.neckAngle, neckWidth, true);
  var pList = [tailLeft, neckLeft, headLeft, pnt2, headRight, neckRight, tailRight];
  this._setLatLngs([L.PlotUtils.unProPoints(pList)]);
  this.redraw();
}

        第一步:计算尾部左右两个坐标点位置。想要计算尾部两个坐标的位置,首先我们需要根据pnt1、和pnt2来计算两个点的长度,这样整体箭头的长度大致就确定了。然后根据细直箭头的尾部宽度的配置,在源码中可以看到设置的比例是0.15,具体是前面计算长度的0.15。最后计算获取第三点(起点到终点的连线上,以终点为轴,旋转angle后,距离终点distance的点)。

 var len = L.PlotUtils.getBaseLength(pnts);//pnt1和pnt2的距离的0.99次幂

        根据长度和设置的尾部宽度的系数可以得到尾部的宽度一个值,然后代入到计算第三个点的计算公式中,即可:

var tailLeft = L.PlotUtils.getThirdPoint(pnt2, pnt1, L.PlotConstants.HALF_PI, tailWidth, true);

        计算第三个点的坐标位置具体方法如下,这个方法在后续的过程中经常用到。

//获取第三点(起点到终点的连线上,以终点为轴,旋转angle后,距离终点distance的点)
L.PlotUtils.getThirdPoint = function (startPnt, endPnt, angle, distance, clockWise) {
  var azimuth = L.PlotUtils.getAzimuth(startPnt, endPnt);//获取终点相对于起点的方位角
  var alpha = clockWise ? azimuth + angle : azimuth - angle;
  var dx = distance * Math.cos(alpha);
  var dy = distance * Math.sin(alpha);
  return [endPnt[0] + dx, endPnt[1] + dy];
};

        下面结合图形来讲解tailLeft和tailRight的具体计算过程。对trailLeft这个点来说,就是pnt1沿着pnt2的方向逆时针旋转90度(\pi /2)的方向上,距离pnt1有trailWidth远的点。反方向上距离pnt2有trailWidth远的点就是trailRight。

        通过以上步骤即可获得尾部的两个点的坐标信息,然后我们依次来计算neck和head的两个点的位置信息。

        第二步:计算headLeft和headRight两个点。而head的两个坐标点的计算则反过来,以pnt2为起点按照逆时针和顺时针来进行坐标点的计算。偏转的角度为:Math.PI / 8.5,//头部角度。

        第三步:获取neckLeft和neckRight两个点的绘制与前两个点的绘制过程类似,这里不再进行赘述。主要步骤分两个,第一个是计算neckWidth,然后根据设置的neck的偏转角,这里取: 

neckAngle: Math.PI / 13,//颈部角度,大家可以根据实际情况来进行相应情况的设置。

        最后,根据计算获得的这7个点,连成一个Polygon面,然后叠加到地图上即可实现一个细直箭头。同理突击方向的箭头绘制也是一样的处理方法。

3、最终的成果

        为了展示细直箭头和突击方向的最终成果,我们结合天地图,使用Leaflet来进行一个两个结合的综合展示功能开发。动态绘制的代码如下:

// 直箭头
function addStraightArrow() {
	L.Plot.straightArrow([[28.17629, 112.923746],[28.188471, 112.948208]])
	.addTo(this.plotLayer);
}
		
// 细直箭头
function addFineArrow() {
	L.Plot.fineArrow([[28.167286, 112.969236],[28.180224, 112.976618]])
	.addTo(this.plotLayer);
	L.Plot.fineArrow([[28.19248, 112.983398],[28.173415, 113.006058]])
	.addTo(this.plotLayer);
}

// 突击方向
function addAssaultDirection() {
	L.Plot.assaultDirection([[28.180981, 112.901001],[28.200045, 112.937222]])
	.addTo(this.plotLayer);
		  
	L.Plot.assaultDirection([[28.143903, 112.964344],[28.179165, 112.94117]])
	.addTo(this.plotLayer);
		  
	L.Plot.assaultDirection([[28.211995, 112.984772],[28.202163, 112.962284]])
	.addTo(this.plotLayer);
}

        最终执行的效果如下图所示:

三、总结

        以上就是本文的主要内容,本文将重点讲解在Leaflet中如何进行细直箭头和突击方向的绘制,首先使用面向对象的方法对细直箭头和突击方向的属性和方法进行介绍,然后重点介绍在绘制细直箭头和突击方向对象的各个绘制点的计算过程,最后给出一个实例过程。行文仓促,难免有许多不足之处,如有不足,还请各位专家和博主在评论区中留下真知烁见,不才定当感激不尽。

        博文编写过程中,参考了下列内容(但本文做了更详细的介绍)在此表示感谢:

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

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

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

相关文章

【vs code(cursor) ssh连不上服务器(2)】但是 Terminal 可以连上,问题解决 ✅

【vs code(cursor) ssh连不上服务器】但是 Terminal 可以连上&#xff0c;问题解决 ✅ 对于类似的问题&#xff0c;之前的解决方法是清洗配置文件再重新连接。当重新连接不起作用时&#xff0c;可以再试下本文的方法。 问题描述&#xff1a;SSH 超时错误 vs code 连不上 ssh…

解决方案:机器学习中,回归及分类常用的模型评估指标有哪些

文章目录 一、现象二、解决方案回归任务的评价指标&#xff1a;均方误差 (MSE):平均绝对误差 (MAE): 分类任务的评价指标&#xff1a;准确率 (Accuracy):混淆矩阵 (Confusion Matrix):精确度 (Precision):召回率 (Recall):F1分数 (F1 Score):ROC曲线 (Receiver Operating Chara…

Qt的互斥量用法

目的 互斥量的概念 互斥量是一个可以处于两态之一的变量:解锁和加锁。这样&#xff0c;只需要一个二进制位表示它&#xff0c;不过实际上&#xff0c;常常使用一个整型量&#xff0c;0表示解锁&#xff0c;而其他所有的值则表示加锁。互斥量使用两个过程。当一个线程(或进程)…

ubuntu 24.04如何分配内存

24版与之前有一点不同&#xff0c;这里记录一下我的经历&#xff0c;希望有帮助 1.进入ubuntu直接试用&#xff0c;没有之前的安装向导&#xff08;如图&#xff09;&#xff0c;在屏幕的左上角会找到安装Ubuntu 2.分配内存 24的手动分配内存&#xff0c;不需要分配系统内存&…

IOT平台颜值天花板?延凡科技物联网平台让人惊叹不已

IOT平台颜值天花板&#xff1f;延凡科技物联网平台让人惊叹不已 在物联网的时代&#xff0c;AIOT平台凭借智能化的管理和决策能力&#xff0c;为多个行业带来了巨大的提升。本文将为大家介绍AIOT物联网平台的核心功能、应用场景以及它是如何改变我们的生活的。 平台简介 AIOT物…

二维环境下的TDOA测距定位的MATLAB代码,带中文注释

TDOA测距定位程序介绍 概述 本MATLAB程序实现了基于时间差到达&#xff08;TDOA&#xff09;技术的二维测距定位&#xff0c;能够处理4个或任意数量&#xff08;大于3个&#xff09;的锚节点。在无线定位和导航系统中&#xff0c;TDOA是一种常用的定位方法&#xff0c;通过测量…

一款免费开源的接口测试工具——ApiFox详细教程

前言 APIfox是一种功能强大的接口测试工具&#xff0c;它可以帮助用户轻松地进行REST API的自动化测试和文档编写。本文将从以下几个方面介绍APIfox的基本使用方法、特点和优势。 一、什么是APIfox&#xff1f; APIfox是一款基于Web的REST API测试工具&#xff0c;通过创建测…

论文笔记:LAFF 文本到视频检索的新基准

整理了ECCV2022 Lightweight Attentional Feature Fusion: A New Baseline for Text-to-Video Retrieval 论文的阅读笔记 背景模型问题定义LAFF(Lightweight Attention Feature Fusion)LAFF Block 实验消融实验可视化对比试验 这篇文章提出了一种新颖灵活的特征融合方式&#x…

初步认识产品经理

产品经理 思考问题的维度 1️⃣为什么要抓住核心用户&#xff1f; 所有和产品有关系的群体就是用户&#xff0c;存在共性和差异了解用户的付费点&#xff0c;更好的优化产品是否使用&#xff1a;&#xff08;目标用户-已使用产品&#xff1a;种子用户-尝鲜&#xff1b;核心用…

【Golang】深入解读Go语言中的错误(error)与异常(panic)

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【Pyecharts】时间线柱状图x轴坐标重复出现并重叠

问题描述 如图右侧显示多的一列坐标 解决方案 降低pyecharts版本&#xff1a;pip install pyecharts2.0.5

ChatGPT与R语言融合技术在生态环境数据统计分析、绘图(回归和混合效应模型、多元统计分析)

自2022年GPT&#xff08;Generative Pre-trained Transformer&#xff09;大语言模型的发布以来&#xff0c;它以其卓越的自然语言处理能力和广泛的应用潜力&#xff0c;在学术界和工业界掀起了一场革命。在短短一年多的时间里&#xff0c;GPT已经在多个领域展现出其独特的价值…

vue2接入高德地图实现折线绘制、起始点标记和轨迹打点的完整功能(提供Gitee源码)

目录 一、申请密钥 二、安装element-ui 三、安装高德地图依赖 四、完整代码 五、运行截图 六、官方文档 七、Gitee源码 一、申请密钥 登录高德开放平台&#xff0c;点击我的应用&#xff0c;先添加新应用&#xff0c;然后再添加Key。 ​ 如图所示填写对应的信息&…

第十九章(自定义类型:结构体)

1. 结构体类型的声明 2. 结构体变量的创建和初始化 3. 结构成员访问操作符 4. 结构体内存对⻬ 5. 结构体传参 一、结构体类型的声明 1.1结构体的声明 struct student {int age;int id[10];char name[10]; };1.2 结构体变量的初始化 struct student {int age;char id[10…

YOLOv1代码复现(论文复现)

YOLOv1代码复现&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 YOLOv1代码复现&#xff08;论文复现&#xff09;论文介绍主要内容实验部分卷积网络结构计算损失核心代码 缺点 论文介绍 该论文就是YOLOv1&#xff0c;YOLOv1是YOLO系列目…

大模型部署——NVIDIA NIM 和 LangChain 如何彻底改变 AI 集成和性能

DigiOps与人工智能 人工智能已经从一个未来主义的想法变成了改变全球行业的强大力量。人工智能驱动的解决方案正在改变医疗保健、金融、制造和零售等行业的企业运营方式。它们不仅提高了效率和准确性&#xff0c;还增强了决策能力。人工智能的价值不断增长&#xff0c;这从它处…

Ubuntu网卡配置

一、低阶版本配置网卡步骤:(如Ubuntu 16.04.2 LTS) 编辑配置文件interfaces,添加网卡配置信息 我这边以root用户登录进服务器,就不需要普通用户每次在命令前添加sudo vim /etc/network/interfaces 1.动态获取ip设置: auto ens3 # 网卡设备名称ens3 iface ens3 ine…

Tdesign TreeSelect 树形选择 多选

这里写自定义目录标题 小程序原生开发 Tdesign TreeSelect 树形选择 多选可以选择不同一级分类下的数据 小程序原生开发 Tdesign TreeSelect 树形选择 多选可以选择不同一级分类下的数据 TreeSelect 树形选择 在原demo基础上修改 const chineseNumber 一二三四五六七八九十.…

音视频入门基础:FLV专题(9)——Script Tag简介

一、SCRIPTDATA 根据《video_file_format_spec_v10_1.pdf》第75页到76页&#xff0c;如果某个Tag的Tag header中的TagType值为18&#xff0c;表示该Tag为Script Tag&#xff08;脚本Tag&#xff0c;又称Data Tag、SCRIPTDATA tag&#xff09;。这时如果Filter的值不为1表示未加…

昇思MindSpore进阶教程--使能图算融合

大家好&#xff0c;我是刘明&#xff0c;明志科技创始人&#xff0c;华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享&#xff0c;如果你也喜欢我的文章&#xff0c;就点个关注吧 正文开始 图算融合是MindSpore特有的网络…