1. 程式人生 > >cesium的量測外掛(支援有無地形)

cesium的量測外掛(支援有無地形)

import * as turf from '@turf/turf'

export default class MeasureDistance {
    constructor(viewer, isTerrain, style,callback) {
        this.viewer = viewer;
        this.isTerrain = isTerrain;
        this.style = style

        this.handler = null
        this.tempEntities = [];
        this.lineEntities = []
        this.labelEntities = null
        this.linePositionList = [];
        this.labelPosition = {
            x: 1,
            y: 1,
            z: 1
        };
        this.countDis = "";
        this.tempPoints = []
        this.textDivs = []
        this.distance = 0

        this.callback = callback
        this._addDisListener()
    }
    _addDisListener() {
        let viewer = this.viewer
        let scene = viewer.scene;
        let linePositionList = this.linePositionList
        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(GV.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        this.handler = new GV.ScreenSpaceEventHandler(scene.canvas);
        this._drawLine(linePositionList);
        this._drawDis()
        let isDraw = false
        let reDraw = false
        this.handler.setInputAction((movement) => {
            if (reDraw) {
                 this._reDraw()
                reDraw = false
            }
            let pickedObject = scene.pick(movement.position);
            console.log(pickedObject)
            if (!GV.defined(pickedObject) || pickedObject.primitive instanceof GV.Polyline || pickedObject.primitive instanceof GV.Primitive) {
                let cartesian = this.isTerrain === true ? scene.pickPosition(movement.position) : viewer.camera.pickEllipsoid(movement.position, scene.globe.ellipsoid);
                if (cartesian) {
                    this.tempPoints.push(this._car3ToLatLon(cartesian));
                    linePositionList.push(cartesian);
                    this._drawPoint(this.tempPoints[this.tempPoints.length - 1]);
                }
                isDraw = true
            }
        }, GV.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.setInputAction((movement) => {
            if (isDraw) {
                let cartesian = this.isTerrain === true ? scene.pickPosition(movement.endPosition) : viewer.camera.pickEllipsoid(movement.endPosition, scene.globe.ellipsoid);
                if (cartesian) {
                    var tempPoints = this.tempPoints
                    if (linePositionList.length > 1) {
                        linePositionList.pop();
                        linePositionList.push(cartesian);
                        this.labelPosition = cartesian
                    }
                    if (linePositionList.length === 1) {
                        linePositionList.push(cartesian);
                    }
                    if (tempPoints.length>1) {
                        tempPoints.pop()
                        tempPoints.push(this._car3ToLatLon(cartesian));
                    }
                    if(tempPoints.length===1){
                        tempPoints.push(this._car3ToLatLon(cartesian));
                    }
                    var distance = this._getFlatternDistance(tempPoints)
                    this.distance = distance
                    this.countDis = distance > 10000 ? (distance / 10000).toFixed(1) + '萬km' : distance.toFixed(1) + 'km'
                }
            }
        }, GV.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.setInputAction((movement) => {
            if (isDraw) {
                let cartesian = this.isTerrain === true ? scene.pickPosition(movement.position) : viewer.camera.pickEllipsoid(movement.position, scene.globe.ellipsoid);
                if (cartesian) {

                    var tempPoints = this.tempPoints
                    tempPoints.push(this._car3ToLatLon(cartesian));
                    linePositionList.push(cartesian);
                    this._drawPoint(tempPoints[tempPoints.length - 1]);
                    // this._drawDiv(cartesian)
                    // this._countAll()
                    // this.countDis = null
                    this.callback(this.tempPoints,this.distance)
                }
                isDraw = false
                reDraw = true
            }
        }, GV.ScreenSpaceEventType.RIGHT_CLICK)
    }
    _reDraw(){
        this.tempPoints = []
        this.linePositionList.length = 0
        for (let entity of  this.tempEntities) {
            this.viewer.entities.remove(entity)
        }
        this.tempEntities=[]
    }
    _drawDis() {
        let self = this;
        let entity = this.viewer.entities.add({
            label: this.style.labelStyle
        });
        entity.position = new GV.CallbackProperty(function() {
            return self.labelPosition;
        }, false)
        entity.label.text = new GV.CallbackProperty(function() {
            return self.countDis;
        }, false)
        this.lineEntities.push(entity);
    }
    _countAll() {
        // console.log(1)
        let tempPoints = this.tempPoints
        let countDis = 0;
        // for (let i = 1; i < tempPoints.length; i++) {
        //     let result = this._getFlatternDistance(tempPoints[i - 1].lat, tempPoints[i - 1].lon, tempPoints[i].lat, tempPoints[i].lon);
        //     countDis += Number(result);
        // }
        countDis = this._getFlatternDistance(tempPoints)
        let dis = countDis > 10000 ? (countDis / 10000).toFixed(1) + '萬km' : countDis.toFixed(1) + 'km'
        var entity =
            this.viewer.entities.add({
                position: GV.Cartesian3.fromDegrees(tempPoints[tempPoints.length - 1].lon, tempPoints[tempPoints.length - 1].lat),
                label: this.style.labelStyle,

            });
        entity.label.text = '距離' + dis
        this.tempEntities.push(entity);
    }
    _drawLine(linePositionList) {
        let lineStyle = this.style.lineStyle
        let self = this;
        let entity = this.viewer.entities.add({
            polyline: lineStyle,
        });

        entity.polyline.positions = new GV.CallbackProperty(function() {
            return linePositionList;
        }, false)

        this.lineEntities.push(entity);
    }

    _drawPoint(point) {
        let entity =
            this.viewer.entities.add({
                position: GV.Cartesian3.fromDegrees(point.lon, point.lat),
                point: {
                    pixelSize: 5,
                    color: new GV.Color.fromBytes(96, 210, 255),
                    // disableDepthTestDistance: Number.POSITIVE_INFINITY,
                    // heightReference: GV.HeightReference.CLAMP_TO_GROUND
                }
            });
        this.tempEntities.push(entity);
    }


    _drawDiv(cartesian3) {
        let viewer = this.viewer
        let container = viewer.container
        let textDiv = document.createElement('div')
        this.textDivs.push(textDiv)
        container.appendChild(textDiv)
        textDiv.setAttribute('style', 'width:200px;height:30px;border:1px solid rgb(61,154,250);border-radius:4px;box-shadow:0px 0px 30px rgb(61,154,250) inset, 0px 0px 30px rgb(61,154,250);position:absolute;')

        viewer.clock.onTick.addEventListener(function(clock) {
            let cartesian = GV.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian3);
            // console.log(cartesian)
            textDiv.style.left = `${cartesian.x-100}px`
            textDiv.style.top = `${cartesian.y}px`
        })
    }
    _removeDiv(){
        for (let textDiv of this.textDivs) {
            this.viewer.container.removeChild(textDiv)
            this.textDivs = []
        }
    }
    // 世界座標轉經緯座標
    _car3ToLatLon(cartesian) {
        let cartographic = GV.Cartographic.fromCartesian(cartesian);
        let longitudeString = GV.Math.toDegrees(cartographic.longitude);
        let latitudeString = GV.Math.toDegrees(cartographic.latitude);
        return {
            lon: longitudeString,
            lat: latitudeString,
            height: cartographic.height
        };
    }
    //計算總距離
    _getFlatternDistance(points) {
        let arr = []
        for (let point of points) {
            arr.push([point.lon, point.lat])
        }
        let line = turf.lineString(arr)
        let length = turf.length(line, {
            units: ''
        })
        return length
    }

    //移除整個資源
    remove(){
        var viewer = this.viewer

        for (let tempEntity of this.tempEntities) {
            viewer.entities.remove(tempEntity)
        }
        for (let lineEntity of this.lineEntities) {
            viewer.entities.remove(lineEntity)
        }
        if (this.handler) {
            this.handler.destroy()
        }
    }
}
import * as turf from '@turf/turf'

export default class MeasureArea {
    constructor(viewer, isTerrain, style) {
		this.viewer = viewer;
		this.isTerrain = isTerrain;
		this.style = style

        this.handler = null
		this.tempEntities = [];
		this.lineEntities = []
		this.linePositionList = [];
        this.areaPositionList = []
		this.labelPosition = {
			x: 1,
			y: 1,
			z: 1
		};
		this.countArea = "";
		this.tempPoints = []
		this.textDivs = []

		this._addDisListener()
	}
    _addDisListener() {
        let viewer = this.viewer
        let scene = viewer.scene;
        let linePositionList = this.linePositionList
        // let areaPositionList = this.areaPositionList
        this.handler = new GV.ScreenSpaceEventHandler(scene.canvas);
        this._drawLine(linePositionList);
        this._countArea()
        this._drawPoly();
        let isDraw = false
        let reDraw = false
        this.handler.setInputAction((movement) => {
            if (reDraw) {
                this._reDraw()
                reDraw = false
            }
            let pickedObject = scene.pick(movement.position);
            if (!GV.defined(pickedObject) || pickedObject.primitive instanceof GV.Polyline) {
                let cartesian = this.isTerrain === true ? scene.pickPosition(movement.position) : viewer.camera.pickEllipsoid(movement.position, scene.globe.ellipsoid);
                if (cartesian) {
                    this.tempPoints.push(this._car3ToLatLon(cartesian));
                    linePositionList.push(cartesian);
                    // areaPositionList.push(cartesian)
                    this._drawPoint(this.tempPoints[this.tempPoints.length - 1]);
                }
                isDraw = true
            }
        }, GV.ScreenSpaceEventType.LEFT_CLICK);
        this.handler.setInputAction((movement) => {
            if (isDraw) {
                let cartesian = this.isTerrain === true ? scene.pickPosition(movement.endPosition) : viewer.camera.pickEllipsoid(movement.endPosition, scene.globe.ellipsoid);
                if (cartesian) {
                    let tempPoints = this.tempPoints
                    if (linePositionList.length > 1) {
                        linePositionList.pop();
                        linePositionList.push(cartesian);
                        this.labelPosition = cartesian
                    }
                    if (linePositionList.length === 1) {
                        linePositionList.push(cartesian);
                    }
                    if (tempPoints.length>2) {
                        tempPoints.pop()
                        tempPoints.push(this._car3ToLatLon(cartesian));

                    }
                    if(tempPoints.length===2){
                        tempPoints.push(this._car3ToLatLon(cartesian));
                    }
                    if (tempPoints.length<2) {
                        return ;
                    }
                    var area = this._SphericalPolygonAreaMeters(tempPoints)
					this.countArea = area > 1000000 ? (area / 1000000).toFixed(1) + 'k㎡' : area.toFixed(1) + '㎡'
                    if (area > 10000000000) this.countArea = (area / 10000000000).toFixed(1) + '萬k㎡'
                }
            }
        }, GV.ScreenSpaceEventType.MOUSE_MOVE);
        this.handler.setInputAction((movement) => {
            if (isDraw) {
                let cartesian = this.isTerrain === true ? scene.pickPosition(movement.position) : viewer.camera.pickEllipsoid(movement.position, scene.globe.ellipsoid);
                if (cartesian) {
                    var tempLength = this.tempPoints.length;
                    if (tempLength < 2) {
                        alert('請選擇3個以上的點再執行閉合操作命令');
                        this._reDraw()
                        return ;
                    }
                    let tempPoints = this.tempPoints
                    tempPoints.push(this._car3ToLatLon(cartesian));
                    linePositionList.push(cartesian);
                    this._drawPoint(tempPoints[tempPoints.length - 1]);
                    // this._drawDiv(cartesian)
                    // this._drawPoly(tempPoints);
                    // this._drawArea(tempPoints)
                    // this.countArea = null
                }
                isDraw = false
                reDraw = true
            }
        }, GV.ScreenSpaceEventType.RIGHT_CLICK)
    }
    _reDraw(){
        this.tempPoints = []
        this.linePositionList.length = 0
        for (let entity of  this.tempEntities) {
            this.viewer.entities.remove(entity)
        }
        this.tempEntities=[]
    }
    _drawArea(tempPoints){
        let area = this._SphericalPolygonAreaMeters(tempPoints)
        let are = area > 1000000 ? (area / 1000000).toFixed(1) + 'k㎡' : area.toFixed(1) + '㎡'
        if (area > 10000000000) are = (area / 10000000000).toFixed(1) + '萬k㎡'

        var entity =
            viewer.entities.add({
                position: GV.Cartesian3.fromDegrees(tempPoints[tempPoints.length - 1].lon, tempPoints[tempPoints.length - 1].lat),
                label: this.style.labelStyle
            });
        entity.label.text = '面積' + are
        this.tempEntities.push(entity);
    }
    _countArea(){
		let self = this;
		let entity =this.viewer.entities.add({
				label: this.style.labelStyle
			});
		entity.position = new GV.CallbackProperty(function() {
			return self.labelPosition;
		}, false)
		entity.label.text = new GV.CallbackProperty(function() {
			return self.countArea;
		}, false)
		this.lineEntities.push(entity);
	}

    _drawLine(linePositionList) {
		let lineStyle = this.style.lineStyle
		let self = this;
		let entity =this.viewer.entities.add({
				polyline: lineStyle,
			});

		entity.polyline.positions = new GV.CallbackProperty(function() {
			return linePositionList;
		}, false)

        this.lineEntities.push(entity);
	}
    _drawPoint(point) {
		let entity =
			this.viewer.entities.add({
				position: GV.Cartesian3.fromDegrees(point.lon, point.lat),
				point: {
                    pixelSize: 5,
					color: new GV.Color.fromBytes(96, 210, 255),
					// disableDepthTestDistance: Number.POSITIVE_INFINITY,
					// heightReference: GV.HeightReference.CLAMP_TO_GROUND
				}
			});
		this.tempEntities.push(entity);
	}

    _drawDiv(cartesian3) {
        let viewer = this.viewer
        let container = viewer.container
        let textDiv = document.createElement('div')
        this.textDivs.push(textDiv)
        container.appendChild(textDiv)
        textDiv.setAttribute('style', 'width:200px;height:30px;border:1px solid rgb(61,154,250);border-radius:4px;box-shadow:0px 0px 30px rgb(61,154,250) inset, 0px 0px 30px rgb(61,154,250);position:absolute;')

        viewer.clock.onTick.addEventListener(function(clock) {
            let cartesian = GV.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, cartesian3);
            // console.log(cartesian)
            textDiv.style.left = `${cartesian.x-100}px`
            textDiv.style.top = `${cartesian.y}px`
        })
    }
    _removeDiv(){
        for (let textDiv of this.textDivs) {
            this.viewer.container.removeChild(textDiv)
            this.textDivs = []
        }
    }

    _drawPoly() {
        // let points = this.tempPoints
        // if (points.length<3) {
        //     return ;
        // }
		let polyStyle = this.style.polyStyle
		// let pArray = [];
		// for (let i = 0; i < points.length; i++) {
		// 	pArray.push(points[i].lon);
		// 	pArray.push(points[i].lat);
		// 	// pArray.push(points[i].height)
		// }
		// polyStyle.hierarchy = new GV.PolygonHierarchy(GV.Cartesian3.fromDegreesArray(pArray))
		let entity =
			this.viewer.entities.add({
				polygon: polyStyle
			});
        entity.polygon.hierarchy = new GV.CallbackProperty(()=> {
			return this.linePositionList;
		}, false)
		// entity.polygon.hierarchy = GV.Cartesian3.fromDegreesArrayHeights(pArray)
		this.lineEntities.push(entity);
	}

	// 世界座標轉經緯座標
	_car3ToLatLon(cartesian) {
		let cartographic = GV.Cartographic.fromCartesian(cartesian);
		let longitudeString = GV.Math.toDegrees(cartographic.longitude);
		let latitudeString = GV.Math.toDegrees(cartographic.latitude);
		return {
			lon: longitudeString,
			lat: latitudeString,
			height: cartographic.height
		};
	}
    // 計算面積
	_SphericalPolygonAreaMeters(points) {
		let arr = []
		for (let point of points) {
			arr.push([point.lon, point.lat])
		}
		arr.push([points[0].lon, points[0].lat])
		let arr1 = []
		arr1.push(arr)
		let polygon = turf.polygon(arr1)
		let area = turf.area(polygon);
		// console.log(area)
		return area;
	}

    //移除整個資源
	remove(){
		let viewer = this.viewer
		// for (let textDiv of this.textDivs) {
		// 	viewer.container.removeChild(textDiv)
		// }
		for (let tempEntity of this.tempEntities) {
			viewer.entities.remove(tempEntity)
		}
		for (let lineEntity of this.lineEntities) {
			viewer.entities.remove(lineEntity)
		}
        this.handler.destroy()
	}

}

上面兩塊程式碼分別為量距和量面的,主要提供參考,有什麼問題的同學請留言,我每天都會看的,下圖為量面的