cesium的量測外掛(支援有無地形)
阿新 • • 發佈:2018-12-20
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() } }
上面兩塊程式碼分別為量距和量面的,主要提供參考,有什麼問題的同學請留言,我每天都會看的,下圖為量面的