zoukankan      html  css  js  c++  java
  • Cesium 绘制点、线、面和测距

      本文基于ES6,采用React+Cesium的Webgis前端开发框架,目前threejs和cesium的结合正在研究中。此段代码采用原生javascript,可能过程中用到了es6的扁平化语法,如()=>{},list.map方法。

    废话不多说了,直接上代码。

    import Cesium from 'cesium/Source/Cesium';
    import monitor from '../style/images/monitor.jpeg';
    
    const ECesium = {
        version: '0.1',
        description: '自定义cesium组件',
        copyright: '2018-enbo'
    };
    
    ECesium.Tools = function (viewer, callback) {
        this.viewer = viewer;
        this.init();
    };
    
    ECesium.Tools.prototype.init = function (back) {
        //初始化事件
        const viewer = this.viewer;
        const scene = viewer.scene;
        this.drawingMode = null;
        this.measureMode = null;
        this.geodesic = new Cesium.EllipsoidGeodesic();
        this.handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
    
        this.dataSource = new Cesium.CustomDataSource('test1');
        viewer.dataSources.add(this.dataSource);
        console.log(viewer.dataSources.indexOf(this.dataSource));
    };
    
    ECesium.Tools.prototype.draw = function (type) {
        if (!this.viewer) return console.error('this.viewer 未定义');
        this.deactivate();
        this.drawingMode = type;
        switch (type) {
            case this.DRAW_TYPE.Point:
                this.DrawPoint();
                break;
            case this.DRAW_TYPE.PolyLine:
            case this.DRAW_TYPE.Polygon:
                this.DrawGraphics();
                break;
            default:
                break;
        }
    };
    
    ECesium.Tools.prototype.DrawPoint = function (callback) {
        const viewer = this.viewer;
        const this_ = this;
        this.drawingMode = "point";
        this.handler.setInputAction(function (evt) {
            const ray = viewer.camera.getPickRay(evt.position);
            const mapPosition = this_.getMapPoint(ray);
            if (!mapPosition) return;
            this_.dataSource.entities.add({
                id: '云台' + Math.random(),
                name: '林火监测点',
                position: Cesium.Cartesian3.fromDegrees(mapPosition.x, mapPosition.y, mapPosition.z),
                point: new Cesium.PointGraphics({
                    color: Cesium.Color.SKYBLUE,
                    pixelSize: 10,
                    outlineColor: Cesium.Color.YELLOW,
                    outlineWidth: 3,
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
                }),
                description: `<img style="height: 200px;" src=${monitor}>`
            });
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    };
    
    ECesium.Tools.prototype.DrawGraphics = function (callback) {
        const viewer = this.viewer;
        const this_ = this;
        let activeShapePoints = [];
        let activeShape, floatingPoint;
        this.handler.setInputAction(function (event) {
            if (!Cesium.Entity.supportsPolylinesOnTerrain(viewer.scene)) {
                return console.log('This browser does not support polylines on terrain.');
            }
            const ray = viewer.camera.getPickRay(event.position);
            const earthPosition = viewer.scene.globe.pick(ray, viewer.scene);
            if (Cesium.defined(earthPosition)) {
                if (activeShapePoints.length === 0) {
                    floatingPoint = this_.createPoint(earthPosition);
                    activeShapePoints.push(earthPosition);
                    const dynamicPositions = new Cesium.CallbackProperty(function () {
                        return activeShapePoints;
                    }, false);
                    activeShape = this_.drawShape(dynamicPositions);
                }
    
                activeShapePoints.push(earthPosition);
                this_.createPoint(earthPosition);
            }
    
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    
        this.handler.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);
    
        this.handler.setInputAction(function () {
            terminateShape();
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    
        function terminateShape() {
            activeShapePoints.pop();
            this_.drawShape(activeShapePoints);
            this.dataSource.entities.remove(floatingPoint);
            this.dataSource.entities.remove(activeShape);
            floatingPoint = undefined;
            activeShape = undefined;
            activeShapePoints = [];
        }
    };
    
    ECesium.Tools.prototype.getMapPoint = function (ray) {
        const viewer = this.viewer;
        const cartesian = viewer.scene.globe.pick(ray, viewer.scene);
        if (!cartesian) {
            return null;
        }
    
        const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        const lng = Cesium.Math.toDegrees(cartographic.longitude);//经度值
        const lat = Cesium.Math.toDegrees(cartographic.latitude);//纬度值
        //cartographic.height的值为地形高度。
        return {x: lng, y: lat, z: cartographic.height};
    };
    
    ECesium.Tools.prototype.createPoint = function (worldPosition) {
        return this.dataSource.entities.add({
            position: worldPosition,
            point: {
                color: Cesium.Color.WHITE,
                pixelSize: 5,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
            }
        });
    };
    
    ECesium.Tools.prototype.drawShape = function (positionData) {
        switch (this.drawingMode) {
            case this.DRAW_TYPE.PolyLine:
                return this.dataSource.entities.add({
                    polyline: {
                        positions: positionData,
                        clampToGround: true,
                         3
                    }
                });
            case this.DRAW_TYPE.Polygon:
                return this.dataSource.entities.add({
                    polygon: {
                        hierarchy: positionData,
                        material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7))
                    }
                });
            default:
                return;
        }
    };
    
    ECesium.Tools.prototype.measure = function (type) {
        this.deactivate();
        this.measureMode = type;
        this.DrawMeasureGraphics();
    };
    
    ECesium.Tools.prototype.DrawMeasureGraphics = function () {
        const viewer = this.viewer;
        const this_ = this;
        let activeShapePoints = [];
        let activeShape, floatingPoint;
        let measureDistance = 0, floatDistance = 0;
        this.handler.setInputAction(function (event) {
            if (!Cesium.Entity.supportsPolylinesOnTerrain(viewer.scene)) {
                return console.log('This browser does not support polylines on terrain.');
            }
            const ray = viewer.camera.getPickRay(event.position);
            const earthPosition = viewer.scene.globe.pick(ray, viewer.scene);
            if (Cesium.defined(earthPosition)) {
                if (activeShapePoints.length === 0) {
                    floatingPoint = this_.createMeasurePoint(earthPosition);
                    if (this_.measureMode === this_.MEASURE_TYPE.MEASURE_DISTANCE) {
                        floatingPoint.label = {
                            text: new Cesium.CallbackProperty(function (time) {
                                let distance = floatDistance = this_.getLatestLength(activeShapePoints);
                                return ((distance + measureDistance) / 1000).toFixed(2) + ' km';
                            }, false),
                            showBackground: true,
                            backgroundColor: new Cesium.Color(0, 0, 0, 0.5),
                            backgroundPadding: new Cesium.Cartesian2(7, 5),
                            font: '16px sans-serif',
                        };
    
                        this_.createLabel(earthPosition, '起点')
                    }
                    activeShapePoints.push(earthPosition);
                    const dynamicPositions = new Cesium.CallbackProperty(function () {
                        return activeShapePoints;
                    }, false);
                    activeShape = this_.drawMeasureShape(dynamicPositions);
                }
    
                if (activeShapePoints.length > 1 && this_.measureMode === this_.MEASURE_TYPE.MEASURE_DISTANCE) {
                    measureDistance += floatDistance;
                    this_.createLabel(earthPosition, (measureDistance / 1000).toFixed(2) + ' km');
                }
    
                activeShapePoints.push(earthPosition);
                this_.createMeasurePoint(earthPosition);
            }
    
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    
        this.handler.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);
    
        this.handler.setInputAction(function () {
            terminateShape();
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
    
        function terminateShape() {
            activeShapePoints.pop();
            this_.drawMeasureShape(activeShapePoints);
            this_.dataSource.entities.remove(floatingPoint);
            this_.dataSource.entities.remove(activeShape);
            floatingPoint = undefined;
            activeShape = undefined;
            activeShapePoints = [];
            measureDistance = 0;
        }
    };
    
    ECesium.Tools.prototype.drawMeasureShape = function (positionData, callback) {
        console.log("draw shape");
        switch (this.measureMode) {
            case this.MEASURE_TYPE.MEASURE_DISTANCE:
                return this.dataSource.entities.add({
                    polyline: {
                        positions: positionData,
                        clampToGround: true,
                         3
                    }
                });
            case this.MEASURE_TYPE.MEASURE_AREA:
                return this.dataSource.entities.add({
                    polygon: {
                        hierarchy: positionData,
                        material: new Cesium.ColorMaterialProperty(Cesium.Color.WHITE.withAlpha(0.7))
                    }
                });
            default:
                return;
        }
    };
    
    ECesium.Tools.prototype.getLatestLength = function (activeShapePoints) {
        const length = activeShapePoints.length;
        const endPoint = activeShapePoints[length - 1];
        const startPoint = activeShapePoints[length - 2];
        const startCartographic = Cesium.Cartographic.fromCartesian(startPoint);
        const endCartographic = Cesium.Cartographic.fromCartesian(endPoint);
        this.geodesic.setEndPoints(startCartographic, endCartographic);
        return Math.round(this.geodesic.surfaceDistance);
    };
    
    ECesium.Tools.prototype.createMeasurePoint = function (worldPosition, callback) {
        return this.dataSource.entities.add({
            position: worldPosition,
            point: {
                color: Cesium.Color.WHITE,
                pixelSize: 8,
                outlineColor: Cesium.Color.RED,
                outlineWidth: 3,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                scaleByDistance: new Cesium.NearFarScalar(0, 0, 1, 1)
            }
        });
    };
    
    ECesium.Tools.prototype.createLabel = function (worldPosition, text) {
        return this.dataSource.entities.add({
            position: worldPosition,
            label: {
                text: text,
                showBackground: true,
                backgroundColor: new Cesium.Color(1, 1, 1, 0.7),
                backgroundPadding: new Cesium.Cartesian2(7, 5),
                font: '16px sans-serif',
                fillColor: Cesium.Color.BLACK,
                outlineColor: Cesium.Color.BLACK,
                pixelOffset: new Cesium.Cartesian2(-15, -15)
            }
        });
    };
    
    ECesium.Tools.prototype.deactivate = function () {
        if (this.handler) {
            this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        }
    
        this.drawingMode = null;
    };
    
    ECesium.Tools.prototype.DRAW_TYPE = {
        Point: 'Point',
        PolyLine: 'PolyLine',
        Polygon: 'Polygon'
    };
    
    ECesium.Tools.prototype.MEASURE_TYPE = {
        MEASURE_DISTANCE: 'MeasureTerrainDistance',
        MEASURE_AREA: 'MeasureTerrainArea'
    };
    export default ECesium;
    

       使用时直接实例化ECesium

    this.tool = new ECesium.Tools(this.viewer);
    

       绘制图形

    this.tool.draw('Point/PolyLine/Polygon');

       测距

    this.tool.measure(MeasureTerrainDistance);

    Tips*面积测量没有添加计算方法,后期会加上。

  • 相关阅读:
    Win10 rocketmq 安装
    Vulnhub DC7
    Vulnhub DC6
    Vulnhub DC5
    Vulnhub DC4
    Vulnhub DC3
    一文带你学会CSRF漏洞
    Shiro反序列化漏洞复现与实战
    DataPipeline CPO 陈雷:实时数据融合之法:便捷可管理
    DataPipeline合伙人 & CPO 陈雷:企业实时数据管理问题与实践 | 附PPT下载
  • 原文地址:https://www.cnblogs.com/zfygiser/p/10169312.html
Copyright © 2011-2022 走看看