; if (typeof Cesium !== 'undefined') /** * @author zhangti * @param viewer {object} 三维对象 * @param options {object} 初始化参数 * @constructor */ Cesium.Measure = (function (Cesium) { /** * 绘制对象 * @param viewer * @param options * @constructor */ function _(viewer, options = {}) { if (viewer && viewer instanceof Cesium.Viewer) { this._drawLayer = new Cesium.CustomDataSource('measureLayer') viewer && viewer.dataSources.add(this._drawLayer) this._basePath = options.basePath || '' this._viewer = viewer } } _.prototype = { /*** * 坐标转换 84转笛卡尔 * * @param {Object} {lng,lat,alt} 地理坐标 * * @return {Object} Cartesian3 三维位置坐标 */ transformWGS84ToCartesian: function (position, alt) { if (this._viewer) { return position ? Cesium.Cartesian3.fromDegrees( position.lng || position.lon, position.lat, position.alt = alt || position.alt, Cesium.Ellipsoid.WGS84 ) : Cesium.Cartesian3.ZERO } }, /*** * 坐标数组转换 笛卡尔转84 * * @param {Array} WSG84Arr {lng,lat,alt} 地理坐标数组 * @param {Number} alt 拔高 * @return {Array} Cartesian3 三维位置坐标数组 */ transformWGS84ArrayToCartesianArray: function (WSG84Arr, alt) { if (this._viewer && WSG84Arr) { var $this = this return WSG84Arr ? WSG84Arr.map(function (item) { return $this.transformWGS84ToCartesian(item, alt) }) : [] } }, /*** * 坐标转换 笛卡尔转84 * * @param {Object} Cartesian3 三维位置坐标 * * @return {Object} {lng,lat,alt} 地理坐标 */ transformCartesianToWGS84: function (cartesian) { if (this._viewer && cartesian) { var ellipsoid = Cesium.Ellipsoid.WGS84 var cartographic = ellipsoid.cartesianToCartographic(cartesian) return { lng: Cesium.Math.toDegrees(cartographic.longitude), lat: Cesium.Math.toDegrees(cartographic.latitude), alt: cartographic.height } } }, /*** * 坐标数组转换 笛卡尔转86 * * @param {Array} cartesianArr 三维位置坐标数组 * * @return {Array} {lng,lat,alt} 地理坐标数组 */ transformCartesianArrayToWGS84Array: function (cartesianArr) { if (this._viewer) { var $this = this return cartesianArr ? cartesianArr.map(function (item) { return $this.transformCartesianToWGS84(item) }) : [] } }, /** * 84坐标转弧度坐标 * @param {Object} position wgs84 * @return {Object} Cartographic 弧度坐标 * */ transformWGS84ToCartographic: function (position) { return position ? Cesium.Cartographic.fromDegrees( position.lng || position.lon, position.lat, position.alt ) : Cesium.Cartographic.ZERO }, /** * 拾取位置点 * * @param {Object} px 屏幕坐标 * * @return {Object} Cartesian3 三维坐标 */ getCatesian3FromPX: function (px) { if (this._viewer && px) { var picks = this._viewer.scene.drillPick(px) var cartesian = null; var isOn3dtiles = false, isOnTerrain = false; // drillPick for (let i in picks) { let pick = picks[i] if (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature || pick && pick.primitive instanceof Cesium.Cesium3DTileset || pick && pick.primitive instanceof Cesium.Model) { //模型上拾取 isOn3dtiles = true; } // 3dtilset if (isOn3dtiles) { this._viewer.scene.pick(px) // pick cartesian = this._viewer.scene.pickPosition(px); if (cartesian) { let cartographic = Cesium.Cartographic.fromCartesian(cartesian); if (cartographic.height < 0) cartographic.height = 0; let lon = Cesium.Math.toDegrees(cartographic.longitude) , lat = Cesium.Math.toDegrees(cartographic.latitude) , height = cartographic.height; cartesian = this.transformWGS84ToCartesian({ lng: lon, lat: lat, alt: height }) } } } // 地形 let boolTerrain = this._viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider; // Terrain if (!isOn3dtiles && !boolTerrain) { var ray = this._viewer.scene.camera.getPickRay(px); if (!ray) return null; cartesian = this._viewer.scene.globe.pick(ray, this._viewer.scene); isOnTerrain = true } // 地球 if (!isOn3dtiles && !isOnTerrain && boolTerrain) { cartesian = this._viewer.scene.camera.pickEllipsoid(px, this._viewer.scene.globe.ellipsoid); } if (cartesian) { let position = this.transformCartesianToWGS84(cartesian) if (position.alt < 0) { cartesian = this.transformWGS84ToCartesian(position, 0.1) } return cartesian; } return false; } }, /** * 获取84坐标的距离 * @param {*} positions */ getPositionDistance: function (positions) { let distance = 0 for (let i = 0; i < positions.length - 1; i++) { let point1cartographic = this.transformWGS84ToCartographic(positions[i]) let point2cartographic = this.transformWGS84ToCartographic(positions[i + 1]) let geodesic = new Cesium.EllipsoidGeodesic() geodesic.setEndPoints(point1cartographic, point2cartographic) let s = geodesic.surfaceDistance s = Math.sqrt( Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2) ) distance = distance + s } return distance.toFixed(3) }, /** * 计算一组坐标组成多边形的面积 * @param {*} positions */ getPositionsArea: function (positions) { let result = 0 if (positions) { let h = 0 let ellipsoid = Cesium.Ellipsoid.WGS84 positions.push(positions[0]) for (let i = 1; i < positions.length; i++) { let oel = ellipsoid.cartographicToCartesian( this.transformWGS84ToCartographic(positions[i - 1]) ) let el = ellipsoid.cartographicToCartesian( this.transformWGS84ToCartographic(positions[i]) ) h += oel.x * el.y - el.x * oel.y } result = Math.abs(h).toFixed(2) } return result }, /** * 测距 * @param {*} options */ drawLineMeasureGraphics: function (options = {}) { if (this._viewer && options) { var positions = [], _lineEntity = new Cesium.Entity(), $this = this, lineObj; this._handler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); var _handlers = this._handler; // left _handlers.setInputAction(function (movement) { entityMouseClickListenerIsEnable = false; var cartesian = $this.getCatesian3FromPX(movement.position); if (cartesian && cartesian.x) { if (positions.length == 0) { positions.push(cartesian.clone()); } // 添加量测信息点 _addInfoPoint(cartesian) positions.push(cartesian); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); _handlers.setInputAction(function (movement) { var cartesian = $this.getCatesian3FromPX(movement.endPosition); if (positions.length >= 2) { if (cartesian && cartesian.x) { positions.pop(); positions.push(cartesian); } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // right _handlers.setInputAction(function (movement) { _handlers.destroy() _handlers = null let cartesian = $this.getCatesian3FromPX(movement.position); _addInfoPoint(cartesian) if (typeof options.callback === 'function') { options.callback($this.transformCartesianArrayToWGS84Array(positions), lineObj); } entityMouseClickListenerIsEnable = true; }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); _lineEntity.polyline = { width: options.width || 1 , material: options.material || Cesium.Color.BLUE.withAlpha(0.8) , clampToGround: options.clampToGround || false } _lineEntity.polyline.positions = new Cesium.CallbackProperty(function () { return positions }, false) lineObj = this._drawLayer.entities.add(_lineEntity) //添加坐标点 function _addInfoPoint(position) { _labelEntity = new Cesium.Entity() _labelEntity.position = position _labelEntity.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 2 } _labelEntity.label = { text: ($this.getPositionDistance($this.transformCartesianArrayToWGS84Array(positions)) / 1).toFixed(2) + '米', show: true, //showBackground: true, font: '20px monospace', //fillColor: Cesium.Color.LIME, horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(-20, -30) //left top } $this._drawLayer.entities.add(_labelEntity) } } }, /** * 测面积 * @param {*} options */ drawAreaMeasureGraphics: function (options = {}) { if (this._viewer && options) { var positions = [], polygon = new Cesium.PolygonHierarchy(), _polygonEntity = new Cesium.Entity(), $this = this, polyObj = null, _label = ''; this._handler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); // left var _handler = this._handler; _handler.setInputAction(function (movement) { entityMouseClickListenerIsEnable = false; var cartesian = $this.getCatesian3FromPX(movement.position); if (cartesian && cartesian.x) { if (positions.length == 0) { polygon.positions.push(cartesian.clone()) positions.push(cartesian.clone()); } positions.push(cartesian.clone()); polygon.positions.push(cartesian.clone()) if (!polyObj) create() } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); // mouse _handler.setInputAction(function (movement) { var cartesian = $this.getCatesian3FromPX(movement.endPosition); // var cartesian = $this._viewer.scene.camera.pickEllipsoid(movement.endPosition, $this._viewer.scene.globe.ellipsoid); if (positions.length >= 2) { if (cartesian && cartesian.x) { positions.pop() positions.push(cartesian); polygon.positions.pop() polygon.positions.push(cartesian); } } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // right _handler.setInputAction(function (movement) { let cartesian = $this.getCatesian3FromPX(movement.endPosition); _handler.destroy(); positions.push(positions[0]); // 添加信息点 _addInfoPoint(positions[0]) if (typeof options.callback === 'function') { options.callback($this.transformCartesianArrayToWGS84Array(positions), polyObj); } entityMouseClickListenerIsEnable = true; }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); function create() { _polygonEntity.polyline = { width: 1 , material: Cesium.Color.BLUE.withAlpha(0.8) , clampToGround: options.clampToGround || false } _polygonEntity.polyline.positions = new Cesium.CallbackProperty(function () { return positions }, false) _polygonEntity.polygon = { hierarchy: new Cesium.CallbackProperty(function () { return polygon }, false), material: Cesium.Color.WHITE.withAlpha(0.1) , clampToGround: options.clampToGround || false } polyObj = $this._drawLayer.entities.add(_polygonEntity) } function _addInfoPoint(position) { var _labelEntity = new Cesium.Entity() _labelEntity.position = position _labelEntity.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 2 } _labelEntity.label = { text: ($this.getPositionsArea($this.transformCartesianArrayToWGS84Array(positions)) / 1.0).toFixed(2) + '平方米', show: true, //showBackground: true, font: '20px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(-20, -30) //left top } $this._drawLayer.entities.add(_labelEntity) } } }, /** * 画三角量测 * @param {*} options */ drawTrianglesMeasureGraphics: function (options = {}) { options.style = options.style || { width: 3 , material: Cesium.Color.BLUE.withAlpha(0.5) } if (this._viewer && options) { var _trianglesEntity = new Cesium.Entity(), _tempLineEntity = new Cesium.Entity(), _tempLineEntity2 = new Cesium.Entity(), _positions = [], _tempPoints = [], _tempPoints2 = [], $this = this; this._handler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); var _handler = this._handler; // 高度 function _getHeading(startPosition, endPosition) { if (!startPosition && !endPosition) return 0 if (Cesium.Cartesian3.equals(startPosition, endPosition)) return 0 let cartographic = Cesium.Cartographic.fromCartesian(startPosition); let cartographic2 = Cesium.Cartographic.fromCartesian(endPosition); return (cartographic2.height - cartographic.height).toFixed(2) } // 偏移点 function _computesHorizontalLine(positions) { let cartographic = Cesium.Cartographic.fromCartesian(positions[0]); let cartographic2 = Cesium.Cartographic.fromCartesian(positions[1]); return Cesium.Cartesian3.fromDegrees( Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic2.height ) } // left _handler.setInputAction(function (movement) { var position = $this.getCatesian3FromPX(movement.position); if (!position && !position.z) return false if (_positions.length == 0) { _positions.push(position.clone()) _positions.push(position.clone()) _tempPoints.push(position.clone()) _tempPoints.push(position.clone()) } else { _handler.destroy(); if (typeof options.callback === 'function') { options.callback({ e: _trianglesEntity, e2: _tempLineEntity, e3: _tempLineEntity2 }); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); // mouse _handler.setInputAction(function (movement) { var position = $this.getCatesian3FromPX(movement.endPosition); if (position && _positions.length > 0) { //直线 _positions.pop() _positions.push(position.clone()); let horizontalPosition = _computesHorizontalLine(_positions) //高度 _tempPoints.pop() _tempPoints.push(horizontalPosition.clone()) //水平线 _tempPoints2.pop(), _tempPoints2.pop() _tempPoints2.push(position.clone()) _tempPoints2.push(horizontalPosition.clone()) } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE) // create entity //直线 _trianglesEntity.polyline = { positions: new Cesium.CallbackProperty(function () { return _positions }, false), ...options.style } _trianglesEntity.position = new Cesium.CallbackProperty(function () { return _positions[0] }, false) _trianglesEntity.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 5 } _trianglesEntity.label = { text: new Cesium.CallbackProperty(function () { return '直线:' + $this.getPositionDistance($this.transformCartesianArrayToWGS84Array(_positions)) + '米' }, false), show: true, showBackground: true, font: '14px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(50, -100), //left top disableDepthTestDistance: Number.POSITIVE_INFINITY, } //高度 _tempLineEntity.polyline = { positions: new Cesium.CallbackProperty(function () { return _tempPoints }, false), ...options.style } _tempLineEntity.position = new Cesium.CallbackProperty(function () { return _tempPoints2[1] }, false) _tempLineEntity.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 5 } _tempLineEntity.label = { text: new Cesium.CallbackProperty(function () { return '高度:' + _getHeading(_tempPoints[0], _tempPoints[1]) + '米' }, false), show: true, showBackground: true, font: '14px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(-20, 100), //left top disableDepthTestDistance: Number.POSITIVE_INFINITY, } //水平 _tempLineEntity2.polyline = { positions: new Cesium.CallbackProperty(function () { return _tempPoints2 }, false), ...options.style } _tempLineEntity2.position = new Cesium.CallbackProperty(function () { return _positions[1] }, false) _tempLineEntity2.point = { pixelSize: 5, outlineColor: Cesium.Color.BLUE, outlineWidth: 5 } _tempLineEntity2.label = { text: new Cesium.CallbackProperty(function () { return '水平距离:' + $this.getPositionDistance($this.transformCartesianArrayToWGS84Array(_tempPoints2)) + '米' }, false), show: true, showBackground: true, font: '14px monospace', horizontalOrigin: Cesium.HorizontalOrigin.LEFT, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(-150, -20), //left top disableDepthTestDistance: Number.POSITIVE_INFINITY, } this._drawLayer.entities.add(_tempLineEntity2) this._drawLayer.entities.add(_tempLineEntity) this._drawLayer.entities.add(_trianglesEntity) } }, measureClear:function() { this._drawLayer.entities.removeAll(); this._handler = this._handler&&this._handler.destroy(); } } return _ })(Cesium);