【Cesium】距离量测和面积量测

article/2025/9/21 11:27:21

1 、空间量测

        空间量测是在三维空间中测量距离、角度、面积等内容。实现方法为在屏幕中拾取对应点的位置,然后将屏幕坐标转换为地理坐标,再根据地球椭球参数,进行几何解算,获取地理空间距离、面积等。

1.1、 距离量测

        两点之间的距离量测,核心代码:

function distanceCal(point1,point2){var cartographic1 = Cesium.Cartographic.fromCartesian(point1); var cartographic2 = Cesium.Cartographic.fromCartesian(point2); console.log(cartographic1);console.log(cartographic2);var geodesic = new Cesium.EllipsoidGeodesic();geodesic.setEndPoints(cartogrartographic2);//两点的贴地线距离(不计算高度差)var s =geodesic.surfaceDistance;return s;
}

思路是先获取两点的屏幕坐标,将其转为笛卡尔空间直角坐标,然后转成WGS-84。利用WGS-84椭球体得出两点的距离。

1.2、 面积量测

//计算多边形面积, S=[(x1*y2-y1*x2)+(x2*y3-y2*x3)+.....+(xn*y1*x1)]/2,
function getArea(points) {let s = 0;let p1 = 0;let p2 = 0;for (let i = 0; i < points.length; ++i){ p1 = points[i];let j = (i + 1) % points.length;p2 = points[j];s += p1.x * p2.y;s -= p2.x * p1.y;}return Math.abs(s/2/1000000.0).toFixed(6);
}

根据官网案例

https://sandcastle.cesium.com/?src=Drawing%20on%20Terrain.html

改造完成距离和面积测量功能,效果如下:
距离量测:
距离量测

面积量测:
面积量测
完整代码如下:

<div id="container"></div>
<div id="toolbar" style="display: inline;"><select id="spatial_cal" class="cesium-button"><option value="distance">距离量算</option><option value="area">面积量算</option></select><button id="calculate" class="cesium-button" onclick="cal();">计算</button><button id="clear" class="cesium-button" onclick="clearCal();">清空</button>
</div>
//创建点
function createPoint(windowPosition){var point = new Cesium.Entity({position: windowPosition, point:{pixelSize: 10, //点的大小color : Cesium.Color.WHITE,//点的颜色heightReference : Cesium.HeightReference.NONE, //高度参考,NONE表示绝对高程}
})viewer.entities.add(point);return point;
}var drawingMode = "polyline";
var activeShapePoints = []; //参与画图的点集合
var activeShape;  //正在绘制的图形
var floatingPoint;  //绘制图形时的跟踪点
var calPoints = [];
var calEntity;
var floatingPoints = [];
var label;
//监听下拉框的变化
var selectForm = document.getElementById("spatial_cal");
selectForm.addEventListener('change',function(){let select_val = selectForm.options[selectForm.selectedIndex].value;if(select_val == "distance"){drawingMode = "polyline";}else if(select_val == "area"){drawingMode = "polygon";}
});const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
//添加鼠标左键处理事件(在鼠标右键终止绘制后,将会禁用该事件) 
function setBuildShapeHandler(flag){if(flag){handler.setInputAction(function (event) {const earthPosition = viewer.scene.pickPosition(event.position);// `earthPosition` will be undefined if our mouse is not over the globe.if (Cesium.defined(earthPosition)) {if (activeShapePoints.length === 0) {floatingPoint = createPoint(earthPosition);floatingPoints.push(floatingPoint);activeShapePoints.push(earthPosition);const dynamicPositions = new Cesium.CallbackProperty(function () {if (drawingMode === "polygon") {return new Cesium.PolygonHierarchy(activeShapePoints);}return activeShapePoints;}, false);activeShape = drawShape(dynamicPositions);}activeShapePoints.push(earthPosition);floatingPoint = createPoint(earthPosition);floatingPoints.push(floatingPoint);}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);//添加鼠标移动处理事件handler.setInputAction(function (event) {if (Cesium.defined(floatingPoint)) {const newPosition = viewer.scene.pickPosition(event.endPosition);if (Cesium.defined(newPosition)) {floatingPoint.position.setValue(newPosition);activeShapePoints.pop();activeShapePoints.push(newPosition);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);}else{handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);}
}
//默认开启
setBuildShapeHandler(true);//绘制图形
function drawShape(positionData)
{let shape;if(drawingMode === "polyline"){shape = viewer.entities.add({polyline: {positions: positionData,width: 5,material: Cesium.Color.RED,heightReference : Cesium.HeightReference.NONE,depthFailMaterial: Cesium.Color.RED, //被地形遮挡部分的颜色},});}else if(drawingMode === "polygon"){shape = viewer.entities.add({polygon: {hierarchy: positionData,material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7)),},});}return shape;
}
// Redraw the shape so it's not dynamic and remove the dynamic shape.
function terminateShape() {activeShapePoints.pop();calEntity = drawShape(activeShapePoints);calPoints = activeShapePoints;viewer.entities.remove(floatingPoint);viewer.entities.remove(activeShape);floatingPoint = undefined;activeShape = undefined;activeShapePoints = [];//绘制完一个图形后,移除鼠标左键和移动的监听事件,防止再次绘制。setBuildShapeHandler(false);
}
handler.setInputAction(function (event) {terminateShape();
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);//计算距离、面积、角度
window.cal = function(){let result = 0;if(drawingMode == "polyline"){result = distanceCal(calPoints);let text = "距离:"+result+"km";label = createLabel(calPoints[calPoints.length-1],text);}else{result = getArea(calPoints);let text = "面积:"+result+"km²";label = createLabel(calPoints[calPoints.length-1],text);}
}
//清空,注意viewer.scene.requestRenderMode为true时,不会立刻显示清空后的样子,只有当鼠标中键滚动或鼠标左键拖拽时才会渲染!!!
function clearCalculate()
{viewer.entities.remove(calEntity);viewer.entities.remove(label);for(let i=0;i<floatingPoints.length;++i){viewer.entities.remove(floatingPoints[i]);}floatingPoint = undefined;floatingPoints = [];activeShape = undefined;activeShapePoints = [];calEntity = undefined;calPoints = [];label = undefined;//清空后,再次添加鼠标左键和移动的监听事件,以便下一次测量。setBuildShapeHandler(true);
}
window.clearCal = function(){clearCalculate();
}function createLabel(position,text){const label = viewer.entities.add({position: position,label : {text : text,font : '20px sans-serif',style : Cesium.LabelStyle.FILL,backgroundColor : Cesium.Color.GRAY.withAlpha(0.3),showBackground : true,fillColor : Cesium.Color.YELLOW,heightReference : Cesium.HeightReference.CLAMP_GROUND, //高度参考,NONE表示绝对高程,horizontalOrigin : Cesium.HorizontalOrigin.LEFT,verticalOrigin : Cesium.VerticalOrigin.TOP,disableDepthTestDistance: Number.POSITIVE_INFINITY //解决了label被地形建筑遮挡的问题!}})return label;
}
//计算多边形面积, 微元法求面积,S=[(x1*y2-y1*x2)+(x2*y3-y2*x3)+.....+(xn*y1-yn*x1)]/2,
//但是结果不除以2才是真实面积,不知道为什么!
function getArea(points) {let s = 0;let p1 = 0;let p2 = 0;for (let i = 0; i < points.length; ++i){ p1 = points[i];let j = (i + 1) % points.length;p2 = points[j];s += p1.x * p2.y;s -= p2.x * p1.y;}return Math.abs(s/1000000.0).toFixed(6);
}
//计算两点之间的距离
function distanceBetweenTwoPoints(point1,point2){let cartographic1 = Cesium.Cartographic.fromCartesian(point1); let cartographic2 = Cesium.Cartographic.fromCartesian(point2); let geodesic = new Cesium.EllipsoidGeodesic();geodesic.setEndPoints(cartographic1,cartographic2);//这里得出来的是两个点的测地线距离let s =geodesic.surfaceDistance;return s;
}
//计算总长度
function distanceCal(points){let res = 0;for(let i=0;i<points.length-1;++i){res += distanceBetweenTwoPoints(points[i],points[i+1]);}return (res/1000.0).toFixed(3);
}

http://chatgpt.dhexx.cn/article/aM6hdXnn.shtml

相关文章

百度地图API画多边型,测面积

效果&#xff1a; 脚本&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv"Content-Type" c…

cad面积计算机,AutoCAD如何测面积 AutoCAD面积计算方法

在AutoCAD运用的实例中&#xff0c;我们常常需要测量所画图形的尺寸面积&#xff0c;如果通过手算的方式总会觉得特别麻烦&#xff0c;还容易出错&#xff0c;为此小编特意为大家准备了最全面的CAD面积计算方法&#xff0c;教你如何巧妙的使用AutoCAD完成面积运算。 AutoCAD面积…

cesium工具-测距和测面-原理和代码

测距分为&#xff1a;空间距离和贴地距离&#xff1b; 测面积分为&#xff1a;水平面积和贴地面积。 下面讲解这4个工具的相关思路和代码&#xff1a; 1、空间距离 思路&#xff1a; Cesium.Cartesian3.distance()计算出两点之间的距离 一条线上的所有点&#xff0c;每2个点依次…

高德地图面积测量小工具

由于项目的需要&#xff0c;需要用到高德地图的测量面积功能&#xff0c;其实高德地图官方已经提供了测量面积的工具&#xff0c;但是感觉有点不太方便&#xff0c;于是在原来的测量面积工具的基础上进行一点补充&#xff0c;由于时间的原因&#xff0c;写的比较粗糙&#xff0…

国土面积测量问题

国土面积测量问题 如图所示一个国家的地图边界线&#xff0c;有关方面需确认国家的国土面积的数值。现在将地图放入平面直角坐标系中&#xff0c;以由西向东方向为 x 轴&#xff0c;由南向北方向为 y 轴&#xff0c;在边界上选取若干 点测出个点对应的坐标数据&#xff08;?,…

cesium面积测量

使用方法新建一个文件measureArea.js将下面代码贴上去 // DrawPolygon /* 绘制面(面积测量)*/class measureArea {constructor(arg) {this.objId Number(new Date().getTime() "" Number(Math.random() * 1000).toFixed(0));this.viewer arg.viewer;this.Cesium…

CAD快速测量面积与周长

这篇来教大家如何用CAD梦想画图快速测出规则图形与不规则图形的面积&#xff0c;首先这些图形都需要是封闭图形。 操作工具 操作系统&#xff1a;Windows10 CAD软件&#xff1a;CAD梦想画图 步骤 1.首先我们画一个规则的矩形与一个用多边形绘制的不规则封闭图形&#xff0…

openlayers测距和测面积

初次使用openlayers地图进行开发各种地图功能,测距和测面积使用的是官方例子并进行了一些简单的修改,官方示例在测量一次之后不能停止,修改后,每点击测量,只会测量一次。 而且需要注意的是,官方例子测距测面积使用的投影坐标系是3857。 js文件:measure.js import Draw…

手机测量面积的软件哪个好用?这些软件你值得收藏

相信大家在日常生活中总会遇到测量的问题&#xff0c;如果身边有测量工具还好&#xff0c;就怕恰好身边没有测量的工具&#xff0c;那就麻烦了。那有没有什么快捷的方法能够让我们迅速获得测量数据呢&#xff1f; 其实&#xff0c;现在市面上有很多面积测量软件&#xff0c;能…

cesium 实现测距离测面积 (划线画面 跟随鼠标位置 )

效果图 方法一&#xff1a;使用插件 cesium_measure.js 下载地址&#xff1a;https://github.com/zhangti0708/cesium-measure/blob/master/src/cesium-measure.js <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"&g…

平方面积怎么测量?教你快速学会这个方法

平方面积怎么测量&#xff1f;我们平常可能很少会需要测量平方面积的&#xff0c;但是当我们装修屋子的时候&#xff0c;不可避免地需要计算各种物品的面积。只有精准的计算&#xff0c;才能减少不必要的浪费。我们可以手工测量&#xff0c;然后进行计算。我们也可以借助手机上…

QML QtLocation地图应用学习-3:实现面积测量

1.实现思路 参照网上的测面积功能&#xff0c;界面效果和测距差不多&#xff0c;在点和线的基础上多了一个填充区域。 点和线参照上一篇博客&#xff1a;https://blog.csdn.net/gongjianbo1992/article/details/103674047 填充区域使用 MapPolygon &#xff0c;但是这个类接口…

手机怎么测量物品面积?测试原理是什么?

在我们的日常生活中&#xff0c;我们常常需要测量物品的面积&#xff0c;比如房间的面积、墙壁的面积、家具的面积等等。传统的测量方法需要使用量尺或计算公式&#xff0c;不仅繁琐而且容易出现误差。而现在&#xff0c;我们可以利用手机的功能来快速、准确地测量物品的面积。…

NMF(非负矩阵分解)

NMF 1.算法概述2. 损失函数python代码 1.算法概述 NMF(Non-negative matrix factorization)&#xff0c;即对于任意给定的一个非负矩阵V&#xff0c;其能够寻找到一个非负矩阵W和一个非负矩阵H&#xff0c;满足条件VW*H,从而将一个非负的矩阵分解为左右两个非负矩阵的乘积。 …

CAUCHY NMF FOR HYPERSPECTRAL UNMIXING

J. Peng, F. Jiang, W. Sun and Y. Zhou, "Cauchy NMF for Hyperspectral Unmixing," IGARSS 2020 - 2020 IEEE International Geoscience and Remote Sensing Symposium, 2020, pp. 2384-2387, doi: 10.1109/IGARSS39084.2020.9323950. 摘要&#xff1a; 非负矩阵…

【降维之NMF】NMF(非负矩阵分解)实例

数据介绍&#xff1a;NMF人脸数据特征提取目标&#xff1a;已知 Olivetti 人脸数据共400个&#xff0c;每个数据是 64*64 大小。由于NMF分解得到的 W 矩阵相当于从原始矩阵中提取的特征&#xff0c;那么就可以使用NMF对400个人脸数据进行特征提取。 NMF 非负矩阵分解是在矩阵中…

ADMM求解优化NMF

本文拟对文章&#xff1a;“An Alternating Direction Algorithm for Matrix Completion with Nonnegative Factors”中利用ADMM进行非负矩阵分解部分进行推导。 他的 augmented Lagrangian 可写成如下形式&#xff1a; (1) (1)优化W (2)优化H: &#xff08;3&#xff09;优化…

NMF降维算法与聚类模型的综合运用

NMF降维算法与聚类模型的综合运用 前言一&#xff1a;NMF算法二&#xff1a;NMF算法的使用三&#xff1a;NMF算法与层次聚类的综合使用四&#xff1a;总结 前言 这一章&#xff0c;我们讨论下另一个比较有效的降维手段&#xff1a;NMF&#xff08;非负矩阵分解&#xff09;。N…

NMF(非负矩阵分解)分子分型

<~生~信~交~流~与~合~作~请~关~注~公~众~号生信探索> Non-Negative Matrix Factorization (NMF). Find two non-negative matrices, i.e. matrices with all non-negative elements, (W, H) whose product approximates the non-negative matrix X. This factorization c…

LSA、pLSA、LDA、NMF、BERTopic、Top2Vec进行主题建模

在自然语言处理(NLP)中,主题建模是一种技术,用于从文本数据中发现隐藏的语义主题(或主题)。这是一个无监督机器学习问题,即在没有标签或标签的情况下学习模式。主题建模的应用非常广泛,可用于搜索引擎、情感分析、新闻聚类和摘要生成等许多任务。 在这里将探讨主题建模…