/* 引入Cesium */ // import * as Cesium from 'Cesium'; /** * Cesium 的各种定位方法汇总,只列出项目中经常使用的,如果不够灵活,可直接调用Cesium官方API,也很方便。 * Cesium的定位从效果上包含两种:直接定位、飞行定位。在方法封装上,姑且将直接定位分类为zoomTo系列,飞行定位分类flyTo。 * 定位的对象上包括:坐标点、矩形范围、entities、3dtiles、gltf、kml、geojson、影像、地形、geometry * Cesium的定位主要是使用Camera对象和Viewer对象,Viewer的定位zoomTo,flyTo等方法是较高级别的函数,可以定位到Entity、3dtiles、DataSource等添加到三维球上显示的实体, * Viewer的定位方法内部都是调用Camera的相关定位方法,针对不同的定位对象,通过一些列计算得出传入实体的合适定位范围和摄像机视角,然后定位,使用起来很方便。 * Camera的flyTo、flyToBoundingSphere、lookat、setView等方法是较低级别函数,通过定位坐标和角度参数的传入,精细化控制定位视角,灵活。 */ class LocateUtil { /** * 默认初始化 * @param {Object} viewer 三维场景 */ constructor(viewer) { if (!viewer) throw new Cesium.DeveloperError('no viewer object!'); this._viewer = viewer; this._locationEntity = null; } } /** * 通用对外公开函数(坐标定位) */ Object.assign(LocateUtil.prototype, /** @lends LocateUtil.prototype */ { /** * 飞行定位到一个笛卡尔空间直角坐标点位置 * @param {Object} options 具有以下属性: * @param {Number} options.longitude 经度,以度为单位 * @param {Number} options.latitude 纬度,以度为单位 * @param {Number} [options.height=0.0] 椭球的高度,以米为单位 * @param {Number} [options.heading=0.0] 指向,默认值0.0(北) * @param {Number} [options.pitch=-90] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.range=0.0] 距目标点距离 * @param {Number} [options.duration=3] 持续时间 */ flyToPoint: function(options) { return new Promise((resolve, reject) => { if (!Cesium.defined(options) || !Cesium.defined(options.longitude) || !Cesium.defined(options.latitude)) { throw new Cesium.DeveloperError("options.longitude and options.latitude are required."); } // 初始化参数默认值 options.height = Cesium.defaultValue(options.height, 0); options.heading = Cesium.defaultValue(options.heading, 0); options.pitch = Cesium.defaultValue(options.pitch, -90); options.range = Cesium.defaultValue(options.range, 0.0); options.duration = Cesium.defaultValue(options.duration, 3); var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(options.longitude, options.latitude, options.height), 0.0); this._viewer.camera.flyToBoundingSphere(boundingSphere, { duration: options.duration, complete: function() { resolve(true); }, offset: { heading: Cesium.Math.toRadians(options.heading), pitch: Cesium.Math.toRadians(options.pitch), range: options.range }, }); }); }, /** * @description 根据坐标飞行定位,支持点、线、面等 * @param {Array} points 坐标集合 [[lng,lat],[lng,lat],......] * @param {String} type 定位类型 point multiplePoint polyline polygon * @param {Object} [options] 飞行的样式,具有以下属性: * @param {Number} [options.heading=0.0] 指向,默认值0.0(北) * @param {Number} [options.pitch=-90] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.range=0.0] 距目标点距离 * @param {Number} [options.duration=3] 持续时间 */ flyToEntityByPoints: function(points, type, options) { return new Promise((resolve, reject) => { let _self = this; options = options || {}; if (points === undefined || points.length === undefined) { reject("输入的坐标集合异常!"); return; } /* 转换坐标 */ let pointsArray = points.map(point => { return Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2] || 0); }); if (_self._locationEntity) { _self._viewer.entities.remove(_self._locationEntity); } /* 分别判断 */ switch (type) { case "point": _self._locationEntity = _self._viewer.entities.add({ position: pointsArray[0], point: { pixelSize: 1, }, }); break; case "polyline": if (pointsArray.length < 2) { reject("线对象定位,点数至少2个"); } else { _self._locationEntity = _self._viewer.entities.add({ polyline: { positions: pointsArray, clampToGround: true, //指定折线是否应该固定在地面上 // material: new Cesium.Color.fromCssColorString("#ffffff00"), material: new Cesium.Color(255, 0, 0, 0.5), width: 1, } }); } break; case "polygon": if (pointsArray.length < 3) { reject("面对象定位,点数至少3个"); } else { _self._locationEntity = _self._viewer.entities.add({ polygon: { hierarchy: { positions: pointsArray }, // material: new Cesium.Color.fromCssColorString("#ffffff00"), material: new Cesium.Color(255, 0, 0, 0.5), outline: true, } }); } break; default: reject("坐标异常!"); break; } // 初始化参数默认值 options.duration = Cesium.defaultValue(options.duration, 3); options.heading = Cesium.defaultValue(options.heading, 0); options.pitch = Cesium.defaultValue(options.pitch, -90); options.range = Cesium.defaultValue(options.range, 0.0); let flyPromise = _self._viewer.flyTo(_self._locationEntity, { duration: options.duration, offset: { heading: Cesium.Math.toRadians(options.heading), pitch: Cesium.Math.toRadians(options.pitch), range: options.range } }); flyPromise.then(function(flag) { if (flag) { // _self._viewer.entities.remove(_self._locationEntity); resolve(_self._locationEntity); } }); }); }, /** * @description 飞行定位到一个实体 * @param {Object} entity * @param {Number} [options.heading=0.0] 指向,默认值0.0(北) * @param {Number} [options.pitch=-90] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.range=0.0] 距目标点距离 * @param {Number} [options.duration=3] 持续时间 */ flyToEntity: function(entity, options) { return new Promise((resolve, reject) => { let _self = this; options = options || {}; if (_self._locationEntity) { _self._viewer.entities.remove(_self._locationEntity); } _self._locationEntity = entity; // 初始化参数默认值 options.duration = Cesium.defaultValue(options.duration, 3); options.heading = Cesium.defaultValue(options.heading, 0); options.pitch = Cesium.defaultValue(options.pitch, -90); options.range = Cesium.defaultValue(options.range, 0.0); let flyPromise = _self._viewer.flyTo(_self._locationEntity, { duration: options.duration, offset: { heading: Cesium.Math.toRadians(options.heading), pitch: Cesium.Math.toRadians(options.pitch), range: options.range } }); flyPromise.then(function(flag) { if (flag) { // _self._viewer.entities.remove(_self._locationEntity); resolve(_self._locationEntity); } }); }); }, /** * 定位实景三维 * @param {Object} tileset * @param {Object} [options] 飞行的样式,具有以下属性: * @param {Number} [options.heading=120] 指向,默认值0.0(北) * @param {Number} [options.pitch=-10] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.range=450.0] 距目标点距离 * @param {Number} [options.duration=3] 持续时间 */ zoomToTilesets(tileset, options) { return new Promise((resolve, reject) => { let _self = this; if (!Cesium.defined(tileset)) { throw new Cesium.DeveloperError("tileset is required."); } // 初始化参数默认值 options = options || {}; options.heading = Cesium.defaultValue(options.heading, 120); options.pitch = Cesium.defaultValue(options.pitch, -10); options.range = Cesium.defaultValue(options.range, 450.0); options.duration = Cesium.defaultValue(options.duration, 3); // var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(options.longitude, options.latitude, options.height), 0.0); let boundingSphere = tileset.boundingSphere; _self._viewer.camera.flyToBoundingSphere(boundingSphere, { duration: options.duration, complete: function() { resolve(true); }, offset: { heading: Cesium.Math.toRadians(options.heading), pitch: Cesium.Math.toRadians(options.pitch), range: options.range }, }); }); }, /** * 飞行定位实景三维 * @param {Object} tileset * @param {Object} [options] 飞行的样式,具有以下属性: * @param {Number} [options.heading=120] 指向,默认值0.0(北) * @param {Number} [options.pitch=-10] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球 * @param {Number} [options.range=450.0] 距目标点距离 * @param {Number} [options.duration=3] 持续时间 */ flyToTileset(tileset, options) { return new Promise((resolve, reject) => { let _self = this; if (!Cesium.defined(tileset)) { throw new Cesium.DeveloperError("tileset is required."); } // 初始化参数默认值 options = options || {}; options.heading = Cesium.defaultValue(options.heading, 120); options.pitch = Cesium.defaultValue(options.pitch, -10); options.range = Cesium.defaultValue(options.range, 450.0); options.duration = Cesium.defaultValue(options.duration, 3); /*viewer.flyTo() 方法,返回一个 promise (承诺)。 * 如果飞行成功,该承诺将解析为 true; * 如果视图中目标不可见或飞行被取消,该承诺将解析为 false。 * 用途:在飞到某实体后,移除该实体。*/ let flyPromise = _self._viewer.flyTo(tileset, { duration: options.duration, offset: { heading: Cesium.Math.toRadians(options.heading), pitch: Cesium.Math.toRadians(options.pitch), range: options.range } }); flyPromise.then(function(flag) { if (flag) { resolve(true); } }); }); } }); export default LocateUtil;