【Cesium】绘制区域面积测量

距离测量功能实现流程:

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼遇雨愈愉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值