距离测量功能实现流程:
1.鼠标左键点击地图开始绘制,连续点击生成区域范围的角点,使用红色圆圈表示;
2.鼠标右键点击完成绘制并计算区域面积;
3.将计算结果标记在最后一个点的位置,并解绑绘制功能。
一、代码如下所示:
// 面积距离
function calDrawLines(viewer) {
let activeShapePoints = [];
let activeShape;
let floatingPoint;
var poi = [];
var points2 = [];
viewer.screenSpaceEventHandler.setInputAction(function (event) {
const ray = viewer.camera.getPickRay(event.position);
const earthPosition = viewer.scene.globe.pick(ray, viewer.scene);
poi.push(Cesium.Cartographic.fromCartesian(earthPosition));
points2.push(earthPosition);
if (Cesium.defined(earthPosition)) {
if (activeShapePoints.length === 0) {
floatingPoint = createPoint(earthPosition, activeShapePoints);
activeShapePoints.push(earthPosition);
const dynamicPositions = new Cesium.CallbackProperty(function () {
return new Cesium.PolygonHierarchy(activeShapePoints);
}, false);
activeShape = drawShape(dynamicPositions);
}
activeShapePoints.push(earthPosition);
createPoint(earthPosition, activeShapePoints);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.screenSpaceEventHandler.setInputAction(function (event) {
if (Cesium.defined(floatingPoint)) {
const ray = viewer.camera.getPickRay(event.endPosition);
const newPosition = viewer.scene.globe.pick(ray, viewer.scene);
if (Cesium.defined(newPosition)) {
floatingPoint.position.setValue(newPosition);
activeShapePoints.pop();
activeShapePoints.push(newPosition);
}
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
);
// 鼠标右击移除
viewer.screenSpaceEventHandler.setInputAction(function (event) {
const areas = getArea(points2); //计算面积
var p = Cesium.Cartesian3.fromRadians(
poi[poi.length - 1].longitude,
poi[poi.length - 1].latitude,
poi[poi.length - 1].height
)
viewer.entities.add({
position: p,
label: {
text: areas + "平方米",
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -20),
font: '20px monospace',
showBackground: true,
backgroundColor: Cesium.Color.BLACK.withAlpha(1),
backgroundPadding: new Cesium.Cartesian2(17, 10),
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
});
terminateShape();
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
function terminateShape() {
activeShapePoints.pop();
drawShape(activeShapePoints);
viewer.entities.remove(floatingPoint);
viewer.entities.remove(activeShape);
floatingPoint = undefined;
activeShape = undefined;
activeShapePoints = [];
poi = [];
points2 = [];
}
function createPoint(worldPosition) {
var point = viewer.entities.add({
position: worldPosition,
point: {
color: Cesium.Color.RED,
pixelSize: 10,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
}
});
return point;
}
function drawShape(positionData) {
var shape = viewer.entities.add({
polygon: {
hierarchy: positionData,
material: new Cesium.ColorMaterialProperty(
Cesium.Color.BLUE.withAlpha(0.5)
),
},
});
return shape;
}
// 计算面积
function getArea(points1) {
var res = 0;
for (var i = 0; i < points1.length - 2; i++) {
var j = (i + 1) % points1.length; //相邻3个点中的第二个点
var k = (i + 2) % points1.length; //相邻3个点中的第3个点
var totalAngle = getAngle(points1[i], points1[j], points1[k]).toFixed();
var dis_temp1 = getDistance(poi[i], poi[j]);
var dis_temp2 = getDistance(poi[j], poi[k]);
res += dis_temp1 * dis_temp2 * Math.abs(Math.round(Math.sin((totalAngle * Math.PI / 180)) * 1000000) / 1000000);
}
return res.toFixed(2); //单位:平方米
}
// 计算三个点-两条线连成的夹角
function getAngle(p1, p2, p3) {
var b1 = getBearing(p2, p1);
var b2 = getBearing(p2, p3);
var angle = b1 - b2;
if (angle < 0) {
angle += 360
}
return angle
}
// 计算相邻两点的空间距离
function getDistance(point1, point2) {
var geodesic = new Cesium.EllipsoidGeodesic();
geodesic.setEndPoints(point1, point2);
var s = geodesic.surfaceDistance; //两点之间的水平距离
s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2.height - point1.height, 2)) //勾股定理
return s
}
// 计算两点连成线的朝向
function getBearing(from, to) {
var radiansPerDegree = Math.PI / 180.0; //角度转化为弧度
var degreesPerRadian = 180.0 / Math.PI; //弧度转化为角度
var from = Cesium.Cartographic.fromCartesian(from);
var to = Cesium.Cartographic.fromCartesian(to);
//角度转化弧度
var fromLat = from.latitude * radiansPerDegree;
var fromLon = from.longitude * radiansPerDegree;
var toLat = to.latitude * radiansPerDegree;
var toLon = to.longitude * radiansPerDegree;
var angle = -Math.atan2(
Math.sin(fromLon - toLon) * Math.cos(toLat), Math.cos(fromLat) * Math.sin(toLat) - Math.sin(fromLat) * Math.cos(toLat) * Math.cos(fromLon - toLon)
)
if (angle < 0) {
angle += Math.PI * 2.0;
}
// 弧度转换角度
angle = angle * degreesPerRadian;
return angle
}
}
二、源码下载:附带cesium框架,一键运行
https://download.csdn.net/download/qq_27814951/88041578?spm=1001.2014.3001.5501