cesium学习记录08-鼠标绘制多边形
上一篇学习了实体的一些基础知识,这一篇来学习鼠标绘制实体多边形的实现
一、方法一:
1,结果显示
贴地:

不贴地:

2,方法全部代码:
主方法:
/*** 绘制多边形* @param {Object} option* @param {Boolean} option.ground 是否贴地*/ DrawPolygon(option) {var allPoints=[]// 设置返回值return new Promise((resolve, reject) => {// 1. 获取Cesium Viewerlet viewer = this.viewer;// 2. 创建一个用于存储多边形顶点的数组let polygonPoints = [];// 3. 创建一个用于显示当前绘制中的多边形的实体let drawingPolygon = viewer.entities.add({id: "drawingPolygon",name: "画多边形",polygon: {hierarchy: new Cesium.CallbackProperty(() => {return new Cesium.PolygonHierarchy(polygonPoints);}, false),material: Cesium.Color.BLUE.withAlpha(0.2),perPositionHeight: (option&&option.ground)||false // true:不贴地/false:贴地},});// 4. 创建一个用于显示当前绘制中的线的实体let drawingLine = viewer.entities.add({id: "drawingLine",name: "画线",polyline: {positions: new Cesium.CallbackProperty(() => {return polygonPoints;}, false),width: 3,material: Cesium.Color.GREEN}});// 5. 监听鼠标点击事件,将点击的点添加到顶点数组中,并添加点实体let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);handler.setInputAction(event => {var cartesian = this.getCatesian3FromPX(event.position);if (cartesian) {// 将点坐标添加到数组中polygonPoints.push(cartesian.clone());// 在第一次点击时,添加一个克隆的点到数组中,用于动态更新if (polygonPoints.length === 1) {polygonPoints.push(cartesian.clone());}// 添加点实体viewer.entities.add({position: cartesian,point: {color: Cesium.Color.RED,pixelSize: 10}});//将三维笛卡尔坐标系点转为经纬度坐标点,并保存到点数组中let cartesian3 = cartesian.clone()// 使用Cesium.Cartographic.fromCartesian将Cartesian3对象转换为Cartographic对象let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);allPoints.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height]);}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 6. 监听鼠标移动事件,动态更新多边形和线的形状handler.setInputAction(event => {var cartesian = this.getCatesian3FromPX(event.endPosition);if (polygonPoints.length >= 2) {if (cartesian && cartesian.x) {polygonPoints.pop();polygonPoints.push(cartesian);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 7. 监听鼠标右键点击事件,结束绘制handler.setInputAction(() => {var cartesian=polygonPoints[polygonPoints.length-1]// 添加点实体viewer.entities.add({position: cartesian,point: {color: Cesium.Color.RED,pixelSize: 10}});polygonPoints.push(polygonPoints[0]);handler.destroy(); // 关闭鼠标事件监听,结束绘制resolve(allPoints);}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);})},
调用进行位置拾取和转换的方法(此处三个方法来自测量插件):
/*** 拾取位置点* @param {Object} px 屏幕坐标* @return {Object} Cartesian3 三维坐标*/getCatesian3FromPX: function(px) {if (this.viewer && px) {var picks = this.viewer.scene.drillPick(px);var cartesian = null;var isOn3dtiles = false,isOnTerrain = false;// drillPickfor (let i in picks) {let pick = picks[i];if ((pick && pick.primitive instanceof Cesium.Cesium3DTileFeature) ||(pick && pick.primitive instanceof Cesium.Cesium3DTileset) ||(pick && pick.primitive instanceof Cesium.Model)) {//模型上拾取isOn3dtiles = true;}// 3dtilsetif (isOn3dtiles) {this.viewer.scene.pick(px); // pickcartesian = this.viewer.scene.pickPosition(px);if (cartesian) {let cartographic = Cesium.Cartographic.fromCartesian(cartesian);if (cartographic.height < 0) cartographic.height = 0;let lon = Cesium.Math.toDegrees(cartographic.longitude),lat = Cesium.Math.toDegrees(cartographic.latitude),height = cartographic.height;cartesian = this.transformWGS84ToCartesian({lng: lon,lat: lat,alt: height});}}}// 地形let boolTerrain =this.viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider;// Terrainif (!isOn3dtiles && !boolTerrain) {var ray = this.viewer.scene.camera.getPickRay(px);if (!ray) return null;cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);isOnTerrain = true;}// 地球if (!isOn3dtiles && !isOnTerrain && boolTerrain) {cartesian = this.viewer.scene.camera.pickEllipsoid(px,this.viewer.scene.globe.ellipsoid);}if (cartesian) {let position = this.transformCartesianToWGS84(cartesian);if (position.alt < 0) {cartesian = this.transformWGS84ToCartesian(position, 0.1);}return cartesian;}return false;}},/**** 坐标转换 84转笛卡尔* @param {Object} {lng,lat,alt} 地理坐标* @return {Object} Cartesian3 三维位置坐标*/transformWGS84ToCartesian: function(position, alt) {if (this.viewer) {return position? Cesium.Cartesian3.fromDegrees(position.lng || position.lon,position.lat,(position.alt = alt || position.alt),Cesium.Ellipsoid.WGS84): Cesium.Cartesian3.ZERO;}},/**** 坐标转换 笛卡尔转84* @param {Object} Cartesian3 三维位置坐标* @return {Object} {lng,lat,alt} 地理坐标*/transformCartesianToWGS84: function(cartesian) {if (this.viewer && cartesian) {var ellipsoid = Cesium.Ellipsoid.WGS84;var cartographic = ellipsoid.cartesianToCartographic(cartesian);return {lng: Cesium.Math.toDegrees(cartographic.longitude),lat: Cesium.Math.toDegrees(cartographic.latitude),alt: cartographic.height};}},
3,调用方法:
let option = {ground: true //true:不贴地/false:贴地 };
DrawPolygon(option).then(allPoints => {// 在这里,allPoints是结束绘制后的点坐标数组var resultPoints=allPoints})
4,DrawPolygon方法说明:
1,定义返回结果的方式:
var allPoints=[]
return new Promise((resolve, reject) => {
......
}
在这个方法开始时,定义了一个allPoints数组,用于存储绘制的多边形的所有顶点,并且返回一个Promise,允许在绘制结束后将这些点的坐标返回。
2,获取Cesium Viewer:
let viewer = this.viewer;
获取Cesium的Viewer实例
3,创建一个实体以显示绘制中的多边形:
let drawingPolygon = viewer.entities.add({ ... });
这段代码通过Cesium的entities.add方法创建一个新的实体,并将它添加到地图上。这个实体用于实时显示用户绘制的多边形。
4,创建一个实体以显示绘制中的线:
let drawingLine = viewer.entities.add({ ... });
创建一个实体来实时显示用户绘制的线。
5,设置鼠标点击事件的监听:
let handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(event => { ... }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
这段代码创建一个新的ScreenSpaceEventHandler实例来监听鼠标和触摸事件。然后设置一个函数来监听左键点击事件。每当用户点击鼠标左键时,这个函数就会被调用,并将点击的位置添加到polygonPoints数组(即多边形的顶点)和allPoints数组。
需要说明的是这一段代码:
//将三维笛卡尔坐标系点转为经纬度坐标点,并保存到点数组中let cartesian3 = cartesian.clone()// 使用Cesium.Cartographic.fromCartesian将Cartesian3对象转换为Cartographic对象let cartographic = Cesium.Cartographic.fromCartesian(cartesian3);allPoints.push([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height]);
加上这一段只是因为,如果要对获取的点数组进行进一步使用,我更习惯使用经纬度坐标
6,设置鼠标移动事件的监听:
handler.setInputAction(event => { ... }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
当用户移动鼠标时,这个函数会被调用。它用于实时更新正在绘制的多边形和线的形状。
7,设置鼠标双击事件的监听:
handler.setInputAction(() => { ... }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
这个函数监听鼠标左键双击事件。当用户双击鼠标左键时,这个函数会被调用,表示用户完成了多边形的绘制。此时,它会添加最后一个点实体,关闭鼠标事件监听,结束绘制,并通过resolve(allPoints)将绘制的点坐标返回。
8,总说明:
这个方法允许用户通过点击和移动鼠标在Cesium地图上绘制一个多边形。在用户完成绘制(通过双击鼠标左键)后,这个方法通过Promise的resolve函数将绘制的点坐标数组allPoints返回,供其他部分的代码使用。
(比如进行填挖方的计算,将上面的点数组传到地形填挖方计算的方法,用来生成三角网)

5,getCatesian3FromPX方法说明:
该方法根据给定的屏幕坐标px,计算出对应的三维世界坐标。该三维世界坐标可以代表一个具体的点在地图上的位置。
使用drillPick方法来获取屏幕坐标点上所有的对象。如果该点上有一个或多个对象,方法会尝试从3D模型上拾取坐标。
如果拾取不在3D模型上,并且地形存在,则从地形上拾取坐标。
如果既不在3D模型上也不在地形上,则从地球椭球体上拾取坐标。
最后返回这个点的三维世界坐标,或者在无法确定时返回false。
6,transformWGS84ToCartesian方法说明:
该方法根据给定的地理坐标(WGS84格式)计算出相应的三维世界坐标(笛卡尔坐标)。
使用Cesium的Cartesian3.fromDegrees方法从给定的经纬度和高度计算出三维坐标。
7,transformCartesianToWGS84方法说明:
该方法根据给定的三维世界坐标(笛卡尔坐标)计算出相应的地理坐标(WGS84格式)。
使用Cesium的Ellipsoid.WGS84和cartesianToCartographic方法将三维世界坐标转换为地理坐标。
8,后续学习记录文章说明:
将火星科技(Mars3D)的一些例子,自己用Cesium来实现
相关文章:
cesium学习记录08-鼠标绘制多边形
上一篇学习了实体的一些基础知识,这一篇来学习鼠标绘制实体多边形的实现 一、方法一: 1,结果显示 贴地: 不贴地: 2,方法全部代码: 主方法: /*** 绘制多边形* param {Object} op…...
rocketMq启动broker报错找不到或无法加载主类 Files\Java\jdk1.8.0_171\lib\dt.jar;C:\Program]
假如弹出提示框提示‘错误: 找不到或无法加载主类 xxxxxx’。 1.打开runbroker.cmd 将"%CLASSPATH%"加上英文双引号,切勿别加中文双引号 2.打开runserver.cmd 同理 将"%CLASSPATH%"加上英文双引号,切勿别加中文双引号 3.正常执行即…...
Linux touch 命令指南大全
1. 概述 在本教程中,我们将学习touch命令。简而言之,这个命令允许我们更新文件或目录的最后修改时间和最后访问时间。 因此,我们将重点关注如何使用该命令及其各种选项。 请注意,我们使用 Bash 测试了此处显示的所有命令;但是,它们应该与任何兼容 POSIX 的 shell 一起使…...
华为网络篇 RIPv2的基础配置-25
难度 1复杂度1 目录 一、实验原理 1.1 RIP的版本 1.2 RIP的路由更新方式 1.3 RIP的计时器 1.4 RIP的防环机制 二、实验拓扑 三、实验步骤 四、实验过程 总结 一、实验原理 RIP(Routing Information Protocol,路由信息协议)&am…...
fastadmin 下拉多级分类
要实现下图效果 一、先创建数据表 二、在目标的controll中引入use fast\Tree; public function _initialize() {parent::_initialize();$this->model new \app\admin\model\zxdc\Categorys;$tree Tree::instance();$tree->init(collection($this->model->order(…...
时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)
时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价) 目录 时序预测 | MATLAB实现基于CNN-LSTM卷积长短期记忆神经网络的时间序列预测-递归预测未来(多指标评价)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 MATLAB实现基…...
RabbitMQ工作流程详解
1 生产者发送消息的流程 (1)生产者连接RabbitMQ,建立TCP连接(Connection),开启信道(Channel) (2)生产者声明一个Exchange (交换器),并设置相关属性,比如交换器类型、是否持久化等 (3)生产者声明一个队列井设置相关属性…...
LabVIEW使用图像处理进行交通控制性能分析
LabVIEW使用图像处理进行交通控制性能分析 采用普雷维特、拉普拉斯、索贝尔和任意的空间域方法对存储的图像进行边缘检测,并获取实时图像。然而,对四种不同空间域边缘检测方法的核的性能分析。 以前,空路图像存储在数据库中,道路…...
CentOS 7 下 Keepalived + Nginx 实现双机高可用
CentOS 7 下 Keepalived Nginx 实现双机高可用 文章目录 CentOS 7 下 Keepalived Nginx 实现双机高可用服务器准备服务信息服务架构 服务安装nginxKeepalived 服务配置nginxKeepalived 启动服务nginxkeepalived 服务验证查看 VIP 状态CURL 命令访问浏览器访问 高可用验证停止…...
【Linux】IO多路转接——select接口
目录 I/O多路转接之select select初识 select函数 socket就绪条件 select基本工作流程 select服务器 select的优点 select的缺点 select的适用场景 I/O多路转接之select select初识 select是系统提供的一个多路转接接口。 select系统调用可以让我们的程序同时监视多…...
error_Network Error
此页面为订单列表,是混合开发(页面嵌入在客户端中) 此页面为订单列表,此需求在开发时后端先将代码发布在测试环境,我在本地调试时调用的后端接口进行联调没有任何问题。 此后我将代码发布在测试环境,在app中打开页面,…...
Python爱心光波
文章目录 前言Turtle入门简单案例入门函数 爱心光波程序设计程序分析 尾声 前言 七夕要来啦,博主在闲暇之余创作了一个爱心光波,感兴趣的小伙伴们快来看看吧! Turtle入门 Turtle 是一个简单而直观的绘图工具,它可以帮助你通过简…...
【分布式】Viewstamped Replication Revisited
篇前感悟: 阅读分布式系统文章的意义其实并不在于你个人真正地去开发这样一个基于这种协议的系统,因为真正去开发一个高可用的分布式系统实在是太难了(对我来说…)更多的还是汲取其中的思想,包括设计思路,优…...
微服务07-分布式缓存
前提: 单机的Redis存在四大问题: 解决办法:基于Redis集群解决单机Redis存在的问题 1、Redis持久化 Redis 具有持久化功能,其会按照设置以 快照 或 操作日志 的形式将数据持久化到磁盘。 Redis有两种持久化方案: RDB持久化AOF持久化注意: RDB 是默认持久化方式,但 Red…...
QGraphicsView放大时,paint有时不被调用,导致图像绘制不出来(2)
此前(1)解决的是在QGraphicsItem::boundingRect不变的情况下造成不绘制。这次解决的是QGraphicsItem::boundingRect随时都发生变化导致的不绘制。 这问题是我在不继承QGraphicsLineItem(调用setLine),而是继承QGraphic…...
深入理解设计模式-创建型之建造者模式(与工厂区别)
什么是建造者设计模式?和工厂设计模式有什么区别 建造者设计模式(Builder Design Pattern)和工厂设计模式(Factory Design Pattern)都是面向对象设计中的创建型模式,但它们解决的问题和应用场景有所不同。…...
Centos7多台服务器免密登录
准备四台服务器: docker0 docker1 docker2 docker3 在docker0服务器上生成公钥和私钥 [rootwww ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created directory /root/.ssh. Enter passp…...
C语言实现哈希搜索算法
一、哈希搜索算法原理 哈希搜索,也叫散列查找,是一种通过哈希表(散列表)实现快速查找目标元素的算法。哈希搜索算法通常适用于需要快速查找一组数据中是否存在某个元素的场景,其时间复杂度最高为 O(1),而平…...
MySQL卸载并重装指定版本
MySQL卸载并重装制定版本 学习新的项目,发现之前的Navicat已经失去了与现有MySQL的链接,而且版本也不适合,为了少走弯路,准备直接重装相应版本的MySQL 卸载现有MySQL 停止windows的MySQL服务,【windowsR】打开运行框…...
文件IO编程 1 2
头文件包含路径 linux 操作系统分为两大空间:用户空间和内核空间 这样划分,是为了保护内核的核心组件,不被轻易访问和修改 系统调用:安全的访问内核空间 其核心是:函数API(API:用户编程接口&…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
Caliper 负载(Workload)详细解析
Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...
Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...
