import { cartesian32LonLat } from '@/utils/pos' let handler = null let bMeasuring = false const measureIds = [] export const useMeasure = (viewer: any, target: string, terrain: any) => { return { distanceMeasure, angleMeasure, clearMeasure, } } function distanceMeasure() { //贴地测量距离函数 // var terrainProvider = this.terrainProvider viewer.scene.globe.depthTestAgainstTerrain = true handler = new Cesium.ScreenSpaceEventHandler( viewer.scene._imageryLayerCollection ) let positions: any[] = [] let poly: null = null // var tooltip = document.getElementById("toolTip"); let distance = 0 let cartesian = null let floatingPoint // tooltip.style.display = "block"; handler.setInputAction(function (movement) { // tooltip.style.left = movement.endPosition.x + 3 + "px"; // tooltip.style.top = movement.endPosition.y - 25 + "px"; // tooltip.innerHTML = '

单击开始,右击结束

'; cartesian = viewer.scene.pickPosition(movement.endPosition) if (!Cesium.defined(cartesian)) { const ray = viewer.camera.getPickRay(movement.endPosition) cartesian = viewer.scene.globe.pick(ray, viewer.scene) } const p = Cesium.Cartographic.fromCartesian(cartesian) p.height = viewer.scene.sampleHeight(p) cartesian = viewer.scene.globe.ellipsoid.cartographicToCartesian(p) //cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid); if (positions.length >= 2) { if (!Cesium.defined(poly)) { poly = new PolyLinePrimitive(positions) } else { positions.pop() // cartesian.y += (1 + Math.random()); positions.push(cartesian) } // console.log("distance: " + distance); // tooltip.innerHTML='

'+distance+'米

'; } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) handler.setInputAction(function (movement) { // tooltip.style.display = "none"; // cartesian = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid); cartesian = viewer.scene.pickPosition(movement.position) if (!Cesium.defined(cartesian)) { const ray = viewer.camera.getPickRay(movement.position) cartesian = viewer.scene.globe.pick(ray, viewer.scene) } let p = Cesium.Cartographic.fromCartesian(cartesian) p.height = viewer.scene.sampleHeight(p) cartesian = viewer.scene.globe.ellipsoid.cartographicToCartesian(p) if (positions.length == 0) { positions.push(cartesian.clone()) } positions.push(cartesian) getSpaceDistance(positions) }, Cesium.ScreenSpaceEventType.LEFT_CLICK) handler.setInputAction(function (movement) { handler.destroy() //关闭事件句柄 positions.pop() //最后一个点无效 // viewer.entities.remove(floatingPoint); // tooltip.style.display = "none"; bMeasuring = false viewer._container.style.cursor = '' viewer.scene.globe.depthTestAgainstTerrain = false }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) const PolyLinePrimitive = (function () { function _(positions) { this.options = { name: '直线', polyline: { show: true, positions: [], material: Cesium.Color.RED, width: 2, clampToGround: true, }, } this.positions = positions this._init() } _.prototype._init = function () { const _self = this const _update = function () { return _self.positions } //实时更新polyline.positions this.options.polyline.positions = new Cesium.CallbackProperty( _update, false ) const et = viewer.entities.add(this.options) measureIds.push(et.id) } return _ })() //空间两点距离计算函数 function getSpaceDistance(positions) { let distance_ = 0 if (positions.length > 2) { const positions_ = [] const sp = Cesium.Cartographic.fromCartesian( positions[positions.length - 3] ) const ep = Cesium.Cartographic.fromCartesian( positions[positions.length - 2] ) const geodesic = new Cesium.EllipsoidGeodesic() geodesic.setEndPoints(sp, ep) const s = geodesic.surfaceDistance positions_.push(sp) let num = parseInt((s / 100).toFixed(0)) num = num > 200 ? 200 : num num = num < 20 ? 20 : num for (let i = 1; i < num; i++) { const res = geodesic.interpolateUsingSurfaceDistance( (s / num) * i, new Cesium.Cartographic() ) res.height = viewer.scene.sampleHeight(res) positions_.push(res) } positions_.push(ep) // var promise = Cesium.sampleTerrainMostDetailed(terrainProvider, positions_); // Cesium.when(promise, function (updatedPositions) { for (let ii = 0; ii < positions_.length - 1; ii++) { geodesic.setEndPoints(positions_[ii], positions_[ii + 1]) const d = geodesic.surfaceDistance distance_ = Math.sqrt( Math.pow(d, 2) + Math.pow(positions_[ii + 1].height - positions_[ii].height, 2) ) + distance_ } //在三维场景中添加Label const distance_add = parseFloat(distance_.toFixed(2)) distance += distance_add const textDistance = (distance > 1000 ? (distance / 1000).toFixed(3) + '千米' : distance.toFixed(2) + '米') + '\n(+' + (distance_add > 1000 ? (distance_add / 1000).toFixed(3) + '千米' : distance_add + '米') + ')' // var textDistance = distance + "米"; // if (distance > 1000) { // textDistance = (distance / 1000).toFixed(3) + "千米"; // } floatingPoint = viewer.entities.add({ name: '空间直线距离', position: positions[positions.length - 1], point: { pixelSize: 5, color: Cesium.Color.WHITE, outlineColor: Cesium.Color.WHITE, outlineWidth: 2, // disableDepthTestDistance: Number.POSITIVE_INFINITY }, label: { text: textDistance, font: '16px sans-serif', fillColor: Cesium.Color.RED, style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, disableDepthTestDistance: Number.POSITIVE_INFINITY, pixelOffset: new Cesium.Cartesian2(20, -20), // disableDepthTestDistance: Number.POSITIVE_INFINITY }, }) measureIds.push(floatingPoint.id) // }); } } } function angleMeasure() { const pArr = [] let distanceLineNum = 0 let Line1 let Line2 let angleT let floatingPoint //浮动点 handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas) handler.setInputAction(function (movement) { // let cartesian = viewer.scene.pickPosition(movement.endPosition) // if (!Cesium.defined(cartesian)) { const ray = viewer.camera.getPickRay(movement.endPosition) let cartesian = viewer.scene.globe.pick(ray, viewer.scene) // } //cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid); if (distanceLineNum === 1) { pArr.length = 1 pArr.push(cartesian) // console.log(pArr, 'pArr') draw_Angle() } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) handler.setInputAction(function (movement) { // let cartesian = viewer.scene.pickPosition(movement.position) // console.log('cartesian', cartesian32LonLat(cartesian)) // if (!Cesium.defined(cartesian)) { // console.log('false') const ray = viewer.camera.getPickRay(movement.position) let cartesian = viewer.scene.globe.pick(ray, viewer.scene) // } // var cartesian = viewer.scene.pickPosition(movement.position); distanceLineNum++ if (distanceLineNum === 1) { pArr.push(cartesian) floatingPoint = viewer.entities.add({ name: '方位角', position: cartesian, point: { pixelSize: 3, color: Cesium.Color.WHITE, outlineColor: Cesium.Color.WHITE, outlineWidth: 2, heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, }, }) measureIds.push(floatingPoint.id) } else { pArr.length = 1 pArr.push(cartesian) handler.destroy() bMeasuring = false viewer._container.style.cursor = '' draw_Angle() } }, Cesium.ScreenSpaceEventType.LEFT_CLICK) handler.setInputAction(function (movement) { handler.destroy() bMeasuring = false viewer._container.style.cursor = '' }, Cesium.ScreenSpaceEventType.RIGHT_CLICK) function draw_Angle() { // 空间 const cartographic1 = Cesium.Cartographic.fromCartesian(pArr[0]) const lon1 = Cesium.Math.toDegrees(cartographic1.longitude) const lat1 = Cesium.Math.toDegrees(cartographic1.latitude) const cartographic2 = Cesium.Cartographic.fromCartesian(pArr[1]) const lon2 = Cesium.Math.toDegrees(cartographic2.longitude) const lat2 = Cesium.Math.toDegrees(cartographic2.latitude) const lineDistance = Cesium.Cartesian3.distance( Cesium.Cartesian3.fromDegrees(lon1, lat1), Cesium.Cartesian3.fromDegrees(lon2, lat2) ) const localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame( Cesium.Cartesian3.fromDegrees(lon1, lat1) ) const NorthPoint = Cesium.Cartographic.fromCartesian( Cesium.Matrix4.multiplyByPoint( localToWorld_Matrix, Cesium.Cartesian3.fromElements(0, lineDistance, 0), new Cesium.Cartesian3() ) ) const npLon = Cesium.Math.toDegrees(NorthPoint.longitude) const npLat = Cesium.Math.toDegrees(NorthPoint.latitude) // var angle = Cesium.Cartesian3.angleBetween(Cesium.Cartesian3.fromDegrees(lon1, lat1), // Cesium.Cartesian3.fromDegrees(lon2, lat2)); const angle = courseAngle(lon1, lat1, lon2, lat2) let textDistance = lineDistance.toFixed(2) + '米' if (lineDistance > 1000) { textDistance = (lineDistance / 1000).toFixed(3) + '千米' } if (Cesium.defined(Line1)) { //更新线 Line1.polyline.positions = new Cesium.Cartesian3.fromDegreesArray([ lon1, lat1, npLon, npLat, ]) Line2.polyline.positions = new Cesium.Cartesian3.fromDegreesArray([ lon1, lat1, lon2, lat2, ]) angleT.label.text = '角度:' + angle + '°\n距离:' + textDistance angleT.position = pArr[1] return } //北方线 Line1 = viewer.entities.add({ name: 'Angle1', polyline: { positions: new Cesium.Cartesian3.fromDegreesArray([ lon1, lat1, npLon, npLat, ]), width: 3, material: new Cesium.PolylineDashMaterialProperty({ color: Cesium.Color.RED, }), clampToGround: true, }, }) measureIds.push(Line1.id) //线 Line2 = viewer.entities.add({ name: 'Angle2', polyline: { positions: new Cesium.Cartesian3.fromDegreesArray([ lon1, lat1, lon2, lat2, ]), width: 10, material: new Cesium.PolylineArrowMaterialProperty(Cesium.Color.YELLOW), clampToGround: true, }, }) measureIds.push(Line2.id) //文字 angleT = viewer.entities.add({ name: 'AngleT', position: pArr[1], label: { text: '角度:' + angle + '°\n距离:' + textDistance, // scaleByDistance: new Cesium.NearFarScalar(7000000, 1.0, 18000000, 0.4), // translucencyByDistance: new Cesium.NearFarScalar(1.5e2, 2.0, 1.5e5, 0), font: '14px sans-serif', fillColor: Cesium.Color.RED, style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 2, pixelOffset: new Cesium.Cartesian2(0, -20), disableDepthTestDistance: Number.POSITIVE_INFINITY, backgroundColor: new Cesium.Color.fromCssColorString( 'rgba(0, 0, 0, 1)' ), backgroundPadding: new Cesium.Cartesian2(10, 10), verticalOrigin: Cesium.VerticalOrigin.BASELINE, }, }) measureIds.push(angleT.id) } function courseAngle(lng_a, lat_a, lng_b, lat_b) { /////////////方法 let dRotateAngle = Math.atan2( Math.abs(lng_a - lng_b), Math.abs(lat_a - lat_b) ) if (lng_b >= lng_a) { if (lat_b >= lat_a) { } else { dRotateAngle = Math.PI - dRotateAngle } } else { if (lat_b >= lat_a) { dRotateAngle = 2 * Math.PI - dRotateAngle } else { dRotateAngle = Math.PI + dRotateAngle } } dRotateAngle = (dRotateAngle * 180) / Math.PI return parseInt(dRotateAngle * 100) / 100 /////方法 // //以a点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵 // var localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(lng_a, lat_a)); // //求世界坐标到局部坐标的变换矩阵 // var worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4()); // //a点在局部坐标的位置,其实就是局部坐标原点 // var localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_a, lat_a), new Cesium.Cartesian3()); // //B点在以A点为原点的局部的坐标位置 // var localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, new Cesium.Cartesian3.fromDegrees(lng_b, lat_b), new Cesium.Cartesian3()); // //弧度 // var angle = Math.atan2((localPosition_B.y - localPosition_A.y), (localPosition_B.x - localPosition_A.x)) // //角度 // var theta = angle * (180 / Math.PI); // if (theta < 0) { // theta = theta + 360; // } // return theta.toFixed(2); } } function clearMeasure() { for (let jj = 0; jj < measureIds.length; jj++) { viewer.entities.removeById(measureIds[jj]) } measureIds.length = 0 if (handler && !handler.isDestroyed()) handler = handler && handler.destroy() }