/* eslint-disable no-irregular-whitespace */ /* eslint-disable no-mixed-spaces-and-tabs */ import { Cesium, wutu3d } from '@/global'; import { Evented, isArray } from './Event'; import { setEntityAttributes, Cartesian3_to_WGS84, getClockViewModel, checkWgs84Point, } from './utils'; import { Fence } from './Fence'; import * as R from 'ramda'; import { Beams } from './Beams'; import { DrawOption } from './draw'; import { PointCluster } from './Cluster'; const SINGLE_MAP_IMAGE = './libs/map/Cesium/Assets/Textures/waterNormalsSmall.jpg'; const UI_CHANGE_EVENT = 'ui'; /** * 地图主类 * @extends {Evented} */ export class Map extends Evented { constructor(container, option) { super(); this.option = R.merge( { sceneModePicker: false, // 视图模型选择按钮 fullscreenButton: false, // 全屏按钮 homeButton: false, // 回到初始化视图按钮 baseLayerPicker: false, // 底图选择按钮 navigationHelpButton: false, // 导航工具按钮 // 底图 imageryProvider: null, // 背景色,只有在底图无效的情况下才有用 backgroundColor: null, // 初始化视图值 viewpoint: null, // 显示罗盘控件 showCompass: false, // 当前时间 currentTime: undefined, // 自定义数据源 dataSources: [], }, option || {} ); // 视图控制器 const viewer = (this.viewer = this._initViewer(container)); // 隐藏Cesium官网信息 this.viewer._cesiumWidget._creditContainer.style.display = 'none'; if (!this.option.imageryProvider) { viewer.scene.skyBox = null; viewer.scene.sun.show = false; viewer.scene.moon.show = false; viewer.scene.globe.show = false; viewer.scene.backgroundColor = Cesium.Color.fromCssColorString( this.option.backgroundColor || 'rgba(0, 13, 22, 1)' ); viewer.scene.globe.depthTestAgainstTerrain = false; viewer.scene.logarithmicDepthBuffer = false; } // 实始化地图初始点 this.viewer.camera.flyHome = () => { this.option.viewpoint && this.setViewpoint(this.option.viewpoint, { duration: 1, }); }; this.viewer.scene.globe.depthTestAgainstTerrain = false; // 安装指南针、罗盘插件 if (Cesium.viewerCesiumNavigationMixin && this.option.showCompass) { const ops = {}; ops.enableCompass = true; //罗盘 ops.enableZoomControls = true; //缩放 ops.enableDistanceLegend = true; //比例尺 ops.enableCompassOuterRing = true; //指南针外环 this.viewer.extend(Cesium.viewerCesiumNavigationMixin, ops); } // 初始化数据源 this._initDataSources(); // 三维瓦片模型集合 this.models = []; this.tileModelCollection = new Cesium.PrimitiveCollection('tilemodel'); this.viewer.scene.primitives.add(this.tileModelCollection); // 绘制工具 this.measureTool = new wutu3d.analysi.Measure({ viewer: viewer, removeScreenSpaceEvent: true, label: { font_size: 18, border_width: 4, background: false, }, }); // 绘制工具 this.plotDrawTool = new wutu3d.Draw(viewer, { hasEdit: false }); // 交互 this._initEvent(); this.popups = []; // 修改鼠标事件 // this.viewer.scene.screenSpaceCameraController.zoomEventTypes = [ // Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH // ]; // this.viewer.scene.screenSpaceCameraController.tiltEventTypes = [ // Cesium.CameraEventType.PINCH, Cesium.CameraEventType.RIGHT_DRAG // ]; // 视点管理 this.viewPoints = []; // 漫游 this.romas = []; // 漫游工具 this._romaTool = new wutu3d.Draw(this.viewer, { hasEdit: true, }); this.beams = new Beams(this); // 实始化地图视点 if (this.option.viewpoint) { this.setViewpoint(this.option.viewpoint); } } _initDataSources() { this.dataSources = {}; this.option.dataSources.forEach(source => { const _source = (this.dataSources[source] = new Cesium.CustomDataSource( source )); this.viewer.dataSources.add(_source); }); } /** * 遍历所有数据源 * @param {Function} callback */ eachDataSources(callback) { Object.keys(key => { callback && callback(this.dataSources[key]); }); } /** * 获取数据源 * @param {String} dataSource * @returns Cesium.CustomDataSource */ getDataSource(dataSource) { return this.dataSources[dataSource]; } /** * 设置数据源可见度 * @param {Boolean} visible * @param {String} dataSource 数据源ID,如果不提供,则设置所有对象 */ setDataSourceVisible(visible, dataSource) { if (dataSource && this.dataSources[dataSource]) { this.dataSources[dataSource].show = visible; } else if (!dataSource) { this.eachDataSources(ds => { ds.show = visible; }); } } /** * 清除数据源 * @param {String|undefined} 数据源ID,如果不提供,则清空所有数据源 */ clearDataSourceEntities(dataSource) { if (dataSource && this.dataSources[dataSource]) { this.dataSources[dataSource].entities.removeAll(); } else if (!dataSource) { this.eachDataSources(ds => { ds.entities.removeAll(); }); } } /** * 初始化事件 * @private */ _initEvent() { // this.viewer.wutu3d.keyboardRoam.bind({ // speedRatio: 150, //平移步长,值越大步长越小。 // dirStep: 25, //相机原地旋转步长,值越大步长越小。 // rotateStep: 1.0, //相机围绕目标点旋转速率,0.3 - 2.0 // minPitch: 0.1, //最小仰角 0 - 1 // maxPitch: 0.95, //最大仰角 0 - 1 // }); this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas); const viewer = this.viewer; const plotDrawTool = this.plotDrawTool; const _mergeEvt = event => { try { let eventPosition = event.endPosition || event.position; let position1 = viewer.scene.pickPosition(eventPosition); if (position1) { let c = Cesium.Cartographic.fromCartesian(position1); //笛卡尔坐标转为经纬度(弧度) let point = [ Cesium.Math.toDegrees(c.longitude), Cesium.Math.toDegrees(c.latitude), c.height, ]; event.pointWithHeight = point; } let position = viewer.camera.pickEllipsoid( eventPosition, viewer.scene.globe.ellipsoid ); let pick = viewer.scene.pick(eventPosition); if ( Cesium.defined(pick) && pick.id && pick.id instanceof Cesium.Entity ) { event.entity = pick.id; if (event.entity.attribute && event.entity.attribute.attr) { event.attr = { ...event.entity.attribute.attr }; } else { event.attr = null; } } else { event.entity = null; event.attr = null; } event.editPlot = plotDrawTool.getCurrentEntity(); event.cartesian3 = position; event.latLngPosition = position && Cartesian3_to_WGS84(position); var ray = viewer.camera.getPickRay(eventPosition); let cartesian2 = viewer.scene.globe.pick(ray, viewer.scene); event.latLngPositionGlobe = cartesian2 && Cartesian3_to_WGS84(cartesian2); } catch (e) {} }; this.handler.setInputAction(evt => { _mergeEvt(evt); this.fire('click', evt); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); this.handler.setInputAction(evt => { _mergeEvt(evt); this.fire('mousemove', evt); }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // this.plotDrawTool.on(wutu3d.draw.event.DrawStop, (e) => { // this.fire("drawStop", e); // }); // this.plotDrawTool.on(wutu3d.draw.event.DrawAddPoint, (e) => { // this.fire("drawUpdate", e); // }); // this.plotDrawTool.on(wutu3d.draw.event.DrawRemovePoint, (e) => { // this.fire("drawUpdate", e); // }); // this.plotDrawTool.on(wutu3d.draw.event.EditMovePoint, (e) => { // this.fire("drawUpdate", e); // console.log(e); // }); this.handler.setInputAction(evt => { this.fire(UI_CHANGE_EVENT); }, Cesium.ScreenSpaceEventType.WHEEL); this.on(UI_CHANGE_EVENT, e => PointCluster(this, e)); } /** * 根据模型ID获取模型 * @param {String} id 模型ID * @return {Object|undefined} */ getModel(id) { return this.models.filter(d => d.id === id)[0]; } /** * 定位至模型 * @param {String} id 模型ID */ flyToModel(id) { const model = this.getModel(id); if (!model || !model.model) return; this.viewer.flyTo(model.model); } /** * 添加模型 * @param {String} * @param {Object} param 模型参数 * @param {String} param.id 模型ID * @param {String} param.name 模型名称 * @param {String} param.link 模型链接地址 * @param {String} param.visible 模型可见度 * @param {String} param.maximumScreenSpaceError 模型精度,1最高,越大越模糊,默认为4 * @param {String} param.modifyZ 模型Z值高度修复,默认为0 * @return {Object} */ addModel(option) { if (R.type(option) === 'String') { return this.tileModelCollection.add( new Cesium.Cesium3DTileset({ url: option, }) ); } const { maximumScreenSpaceError, id, name, link, visible, modelMatrix, loaded, focus, color, maximumMemoryUsage, callback, } = option || {}; let modifyZ = option.modifyZ; let transform = option.transform; var tileset = this.tileModelCollection.add( new Cesium.Cesium3DTileset({ url: link, show: visible === undefined ? true : !!visible, ...option, maximumScreenSpaceError: maximumScreenSpaceError || 16, modelMatrix: Cesium.Matrix4.fromArray( modelMatrix || [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] ), maximumMemoryUsage: maximumMemoryUsage || 1024, }) ); if (modifyZ && !transform) { transform = { tz: modifyZ }; } let _transform = R.merge( { tx: 0.0, ty: 0.0, tz: 0.0, rx: 0.0, ry: 0.0, rz: 0.0, scale: 1.0, }, transform || {} ); tileset.readyPromise .then(tileset => { var boundingSphere = tileset.boundingSphere; var cartographic = Cesium.Cartographic.fromCartesian( boundingSphere.center ); var surface = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, 0.0 ); var offset = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, cartographic.height ); let lnglat = Cartesian3_to_WGS84(offset); if (transform) { _transform = R.merge(_transform, { tx: _transform.tx || lnglat.x || 0.0, ty: _transform.ty || lnglat.y || 0.0, }); tileset._computeTransform = _transform; tileset._root.transform = this.update3dtilesMaxtrix(_transform); } else { tileset._computeTransform = R.merge( { tx: lnglat.x, ty: lnglat.y, tz: lnglat.z, // tz: 0.0, rx: 0.0, ry: 0.0, rz: 0.0, scale: 1.0, }, transform || {} ); } if (color) { this.setModelColor(tileset, color); } if (focus) { this.viewer.flyTo(tileset); } console.log(1); if (callback) { console.log(callback); callback(tileset); } // viewer.zoomTo(tileset); }) .otherwise(function() {}); tileset.allTilesLoaded.addEventListener(() => { loaded && loaded(tileset); }); var _model = { ...option, name, id: id || Cesium.createGuid(), link: link, model: tileset, visible: visible === undefined ? true : !!visible, modelMatrix: modelMatrix, transform: _transform, maximumScreenSpaceError: maximumScreenSpaceError, }; this.models.push(_model); this.fire(UI_CHANGE_EVENT); return _model; } removeModels() { this.models.forEach(model => { if ( model.model && model.model instanceof Cesium.Cesium3DTileset && this.tileModelCollection.contains(model.model) ) { this.tileModelCollection.remove(model.model); } }); this.models = []; this.fire(UI_CHANGE_EVENT); } // 设置模型颜色 setModelColor(id, color) { const tileset = id instanceof Cesium.Cesium3DTileset ? id : this.models.filter(d => d.id === id)[0].model; if (!tileset) return; if (!color) { tileset.style = undefined; } else { tileset.style = new Cesium.Cesium3DTileStyle(); tileset.style.color = { evaluateColor: (f, r) => { return Cesium.Color.fromCssColorString(color); }, }; } this.fire(UI_CHANGE_EVENT); } // 设置模型位置、旋转角度 setModelTransform(id, transform) { if (!transform) return; const model = this.models.filter(d => d.id === id)[0]; if (!model) return null; const tileset = model.model; const _transform = R.merge(model.model._computeTransform, transform); this._setTilesetTransform(tileset, _transform); this.fire(UI_CHANGE_EVENT); return this; } _setTilesetTransform(tileset, transform) { if (tileset instanceof Cesium.Cesium3DTileset && transform) { tileset._root.transform = this.update3dtilesMaxtrix(transform); this.zoom3dtiles(tileset, transform); return true; } } /** * 模型绽放 * @param {*} tileset * @param {*} transform * @returns */ zoom3dtiles(tileset, transform) { if (!tileset) return; var scale = (transform.scale || 1) * 1; tileset._root.customTransform = { matrix: { origin: tileset._root.transform.clone(), rotation: Cesium.Matrix4.IDENTITY, translation: Cesium.Matrix4.IDENTITY, }, }; var m1 = Cesium.Matrix4.fromScale( new Cesium.Cartesian3(scale, scale, scale) ); tileset._root.customTransform.matrix.scale = m1; tileset._root.customTransform.scale = scale; var m2 = new Cesium.Matrix4(); Cesium.Matrix4.multiply( tileset._root.customTransform.matrix.origin, tileset._root.customTransform.matrix.rotation, m2 ); Cesium.Matrix4.multiply(m2, tileset._root.customTransform.matrix.scale, m2); Cesium.Matrix4.multiply( m2, tileset._root.customTransform.matrix.translation, tileset._root.transform ); } update3dtilesMaxtrix(params) { var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(params.rx)); var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(params.ry)); var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(params.rz)); var rotationX = Cesium.Matrix4.fromRotationTranslation(mx); var rotationY = Cesium.Matrix4.fromRotationTranslation(my); var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz); //平移 var position = Cesium.Cartesian3.fromDegrees( params.tx, params.ty, params.tz ); var m = Cesium.Transforms.eastNorthUpToFixedFrame(position); //旋转、平移矩阵相乘 Cesium.Matrix4.multiply(m, rotationX, m); Cesium.Matrix4.multiply(m, rotationY, m); Cesium.Matrix4.multiply(m, rotationZ, m); return m; } //设置模型位置 setModelPosition(tileset, lon, lat, alt) { tileset._modelLon = lon || tileset._modelLon; tileset._modelLat = lat || tileset._modelLat; tileset._modelAlt = Cesium.defined(alt) ? alt : tileset._modelAlt; //平移 let position = Cesium.Cartesian3.fromDegrees( tileset._modelLon, tileset._modelLat, tileset._modelAlt ); let m = Cesium.Transforms.eastNorthUpToFixedFrame(position); //赋值给tileset tileset._root.transform = m; } /** * 根据模型ID删除模型 * @param {String} id 模型ID * @return this */ removeModel(id) { const model = this.models.filter(d => d.id === id)[0]; if (model && model.model) { if ( model.model instanceof Cesium.Cesium3DTileset && this.tileModelCollection.contains(model.model) ) { this.tileModelCollection.remove(model.model); } this.models = this.models.filter(d => d.id !== id); } return this; } /** * 设置模型可见度 * @param {String} id 模型ID * @param {Boolean} visible 可见性 * @return this */ setModelVisible(id, visible) { const model = this.models.filter(d => d.id === id)[0]; if (model && model.model) { if (model.model instanceof Cesium.Cesium3DTileset) { model.model.show = visible; } for (let i = 0; i < this.models.length; i++) { let md = this.models[i]; if (md.id === model.id) { md.visible = visible; } } } return this; } /** * 获取视图中心值 * @return {Object} {x, y, z, heading, roll, pitch} */ getViewPoint() { const viewer = this.viewer; return wutu3d.point.getCameraView(viewer, true); } /** * 设置视图中心 * @param {Object} viewpoint {x, y, z, heading, roll, pitch} */ setViewpoint(viewpoint, options) { if (viewpoint) { this.viewer.wutu3d.centerAt(viewpoint, options); } } /** * 初始化视图控制器 * @private * @param {String|HTMLElement} container 地图DIV容器 * @return {Cesium.Viewer} */ _initViewer(container) { const { sceneModePicker, vrButton, baseLayerPicker, fullscreenButton, navigationHelpButton, imageryProvider, homeButton, currentTime, } = this.option; let viewer = new Cesium.Viewer(container || 'map', { geocoder: false, homeButton: homeButton, sceneModePicker: sceneModePicker, fullscreenButton: fullscreenButton, vrButton: vrButton, baseLayerPicker: baseLayerPicker, infoBox: false, selectionIndicator: false, animation: false, timeline: false, shouldAnimate: true, clockViewModel: currentTime ? getClockViewModel(currentTime) : undefined, navigationHelpButton: navigationHelpButton, navigationInstructionsInitiallyVisible: false, imageryProvider: imageryProvider || new Cesium.SingleTileImageryProvider({ url: SINGLE_MAP_IMAGE, }), contextOptions: { webgl: { alpha: true, }, }, ...this.option, dataSources: undefined, }); viewer.wutu3d = new wutu3d.ViewerEx(viewer, { contextmenu: false, center: this.option.viewpoint || undefined, mouseZoom: false, contextmenuItems: [], }); return viewer; } _plusEntity(entity) { if (!entity) return; let attr = entity.attribute && entity.attribute.attr; let style = entity.attribute && (entity.attribute.style || (attr && attr.style)); if (entity.billboard) { entity.billboard.translucencyByDistance = undefined; entity.billboard.disableDepthTestDistance = Number.POSITIVE_INFINITY; entity.billboard.eyeOffset = new Cesium.Cartesian3(0, 0, -10); } if (entity.label) { entity.label.translucencyByDistance = undefined; entity.label.disableDepthTestDistance = Number.POSITIVE_INFINITY; entity.label.eyeOffset = new Cesium.Cartesian3(0, 0, -10); } if (style && attr && attr.animateLine) { entity.polyline.material = new wutu3d.LineFlowMaterial({ //动画线材质 color: Cesium.Color.fromCssColorString(style.color || '#ff0000'), duration: style.duration || 10000, //时长,控制速度 url: style.image || './images/texture/route.png', }); } if (style && attr && attr.wave) { entity.ellipse.material = new wutu3d.CircleWaveMaterial({ duration: style.duration, //动画时长,单位:毫秒 color: Cesium.Color.fromCssColorString(style.color), gradient: style.gradient || 0, count: style.count || 2, }); } if (attr && attr.isBeam) { const wgs84PosArr = this.plotDrawTool.getCoordinates(entity)[0]; this.beams.add( attr.id || entity.id, { x: wgs84PosArr[0], y: wgs84PosArr[1] }, style ); } } deltePlotsByKeyValues(queryObject) { const entites = this.queryPlotsByKeyValues(queryObject); entites.forEach(entity => { entity && this.plotDrawTool.deleteEntity(entity); }); this.fire(UI_CHANGE_EVENT); } /** * 查询绘制元素 * @param {Object} queryObject * @returns */ queryPlotsByKeyValues(queryObject) { let arrs = []; const keys = Object.keys(queryObject); const entities = this.plotDrawTool.getEntitys(); for (let i = 0; i < entities.length; i++) { let entity = entities[i]; let attr = entity && entity.attribute && entity.attribute.attr; let flag = true; for (let j = 0; j < keys.length; j++) { let key = keys[j]; if (attr[key] !== queryObject[key]) { flag = false; break; } } if (flag) { arrs.push(entity); } } return arrs; } /** * 查询元素 * @param {*} entities * @param {*} queryObject * @returns */ queryEntitiesByKeyValues(entities, queryObject) { if (!queryObject) return []; let arrs = []; const keys = Object.keys(queryObject); const array = entities._entities._array; for (let i = 0; i < array.length; i++) { let entity = array[i]; let attr = entity && entity.attribute; if (!attr) { continue; } let flag = true; for (let j = 0; j < keys.length; j++) { let key = keys[j]; if (attr[key] !== queryObject[key]) { flag = false; break; } } if (flag) { arrs.push(entity); } } return arrs; } /** * 删除元素 * @param {*} entities * @param {*} queryObject */ deleteEntitiesByKeyValues(entities, queryObject) { const targets = this.queryEntitiesByKeyValues(entities, queryObject); targets.forEach(target => { entities.remove(target); }); } /** * 定位到图标上 * @param {*} queryObject * @param {*} option * @returns */ focusMarker(queryObject, option) { if (!queryObject) return; option = option || {}; const target = this.queryPlotsByKeyValues(queryObject)[0]; if (!target) return; this.viewer.flyTo(target, { duration: 0.5, ...option, }); } /** * 定位到标绘上 * @param {*} option Cesium viewer flyTo Options */ flyToPlots(option) { if (this.plotDrawTool.getEntitys().length > 0) { this.viewer.flyTo(this.plotDrawTool.dataSource, { duration: 1, ...option, }); } return this; } /** * 开启编辑 * @param {Boolean} editable */ setPlotEditable(editable) { const pt = this.plotDrawTool; pt.hasEdit(editable); if (!editable) { pt.stopDraw(); pt.stopEditing(); } } /** * 是否编辑中 */ isPlotEditing() { return this.plotDrawTool._hasEdit; } _addLabel(entity, option) { if (!entity || !option || !option.text || !option.showLabel) return; entity.label = new Cesium.LabelGraphics({ style: Cesium.LabelStyle.FILL, pixelOffset: new Cesium.Cartesian2(0, (-64 - 10) * option.iconScale), translucencyByDistance: undefined, disableDepthTestDistance: Number.POSITIVE_INFINITY, eyeOffset: new Cesium.Cartesian3(0, 0, -10), showBackground: true, font: '14px Microsoft yahei', backgroundColor: new Cesium.Color(0.0, 0.0, 0.0, 0.8), backgroundPadding: new Cesium.Cartesian2(8, 6), horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, ...option, }); } /** * 添加图标 * @param {Object} option * @returns Cesium.Entity */ addMarker({ text, textStyle, showLabel, icon, iconStyle, attr, wgs84Pos }) { if (!wgs84Pos || !checkWgs84Point(wgs84Pos.x, wgs84Pos.y)) return null; attr = attr || {}; showLabel = showLabel === undefined ? true : showLabel; iconStyle = iconStyle || {}; const ops = { type: 'billboard', style: { image: icon, ...iconStyle, }, attr: { id: attr.mac || undefined, type: 'marker', ...attr }, }; const position = Cesium.Cartesian3.fromDegrees(wgs84Pos.x, wgs84Pos.y); let entity = this.plotDrawTool.attributeToEntity(ops, position); entity.billboard.disableDepthTestDistance = Number.POSITIVE_INFINITY; entity.billboard.eyeOffset = new Cesium.Cartesian3(0, 0, -10); this._addLabel(entity, { showLabel, text, ...textStyle, iconScale: iconStyle.scale || 0.5, }); this._plusEntity(entity); this.fire(UI_CHANGE_EVENT); return entity; } /** * 添加面 * @param {Object} option * @returns Cesium.Entity */ addPolygon({ style, attr, wgs84Poss }) { style = style || {}; wgs84Poss = wgs84Poss || []; const positions = wgs84Poss.map(wgs84Pos => { let point = wgs84Pos; if (isArray(wgs84Pos)) { point = { x: wgs84Pos[0], y: wgs84Pos[1], z: wgs84Pos[2], }; } return Cesium.Cartesian3.fromDegrees(point.x, point.y, point.z || 0); }); const entity = this.plotDrawTool.attributeToEntity( { type: 'polygon', style: { ...DrawOption.polygon, ...style, }, attr: { ...(attr || {}), }, }, positions ); this._plusEntity(entity); return entity; } /** * 添加线 * @param {Object} option * @returns Engity */ addPolyline({ attr, style, wgs84Poss }) { style = style || {}; wgs84Poss = wgs84Poss || []; const positions = wgs84Poss.map(wgs84Pos => { let point = wgs84Pos; if (isArray(wgs84Pos)) { point = { x: wgs84Pos[0], y: wgs84Pos[1], z: wgs84Pos[2], }; } return Cesium.Cartesian3.fromDegrees(point.x, point.y, point.z || 0); }); const entity = this.plotDrawTool.attributeToEntity( { type: 'polyline', style: { ...DrawOption.polyline, ...style, }, attr: { ...(attr || {}), }, }, positions ); this._plusEntity(entity); return entity; } /** * 开始绘制 * @param {Object} drawOption 绘制参数,详见说明user.md * @param {Function} callback 绘制完成时加回调 */ startDraw(drawOption, callback) { let option = { success: entity => { setEntityAttributes(entity, { id: entity.id, }); this._plusEntity(entity); callback && callback(entity); this.fire(UI_CHANGE_EVENT); }, ...drawOption, }; this.plotDrawTool.startDraw(option); } /** * 通过代码添加点位 * @param {Object} drawOption 绘制选项 * @param {Array} position 位置坐标 */ createPlot(drawOption, position) { if ( !drawOption || !drawOption.type || !drawOption.style || !position || position[0] === undefined || position.length < 2 ) return null; var entity = this.plotDrawTool.attributeToEntity( drawOption, wutu3d.draw.util.lonlat2cartesian([ position[0], position[1], position[2] || 0, ]) ); setEntityAttributes(entity, { id: entity.id, }); this._plusEntity(entity); return entity; } /** * 获取对象 * @param {String} id 对象ID */ getPlotById(id) { return this.plotDrawTool.getEntityById(id); } /** * 更新对象样式 * @param {String} id 对象ID * @param {Object} style 样式对象 */ updatePlotStyle(id, style) { if (!id || !style) return; const entity = this.getPlotById(id); if (!entity || !entity.attribute) return; const attribute = entity.attribute; let type = attribute.type; if (type === 'circle') { type = 'ellipse'; } if (wutu3d.draw.attr[type]) { wutu3d.draw.attr[type].style2Entity(style, entity[type]); this._plusEntity(entity); } this.fire(UI_CHANGE_EVENT); } /** * 更新样式属性 * @param {String} id 对象ID * @param {Object} attrs */ updatePlotAttribute(id, attrs) { const entity = this.getPlotById(id); setEntityAttributes(entity, attrs); this.fire(UI_CHANGE_EVENT); } /** * 删除绘制对象 * @param {String} id 对象ID */ deletePlot(id) { const entity = this.getPlotById(id); entity && this.plotDrawTool.deleteEntity(entity); this.fire(UI_CHANGE_EVENT); } /** * 加载GeoJSON * @param {GeoJSON} geojson */ loadGeoJSON(geojson) { this.plotDrawTool.loadJson(geojson); const entities = this.plotDrawTool.getEntitys(); for (let i = 0; i < entities.length; i++) { this._plusEntity(entities[i]); } setTimeout(() => { this.fire(UI_CHANGE_EVENT); }, 1000); } /** * 将绘制对象转为Geojson数据 */ toGeoJSON() { return this.plotDrawTool.toGeoJSON(); } // 清除所有绘制对象 clearAllPlots() { let pt = this.plotDrawTool; pt.stopEditing(); pt.clearDraw(); pt.deleteAll(); this.fire(UI_CHANGE_EVENT); } addFence(geojson, option) { if (!geojson || !geojson.features) return; if (!this.fenceDataSource) { const dataSource = (this.fenceDataSource = new Cesium.CustomDataSource( 'fence' )); dataSource.show = true; this.viewer.dataSources.add(dataSource); } option = option || {}; const color = option.color || '#ff9900'; const height = option.height || 50.0; const showDynamic = option.showDynamic; let dataSource = this.fenceDataSource; geojson.features.forEach(feature => { const coordinates = feature.geometry.coordinates[0][0]; let positions = []; coordinates.forEach(c => { let position = Cesium.Cartesian3.fromDegrees(c[0], c[1], c[2] || 0.5); positions.push(position); }); dataSource.fence = new Fence( dataSource, positions, height, Cesium.Color.fromCssColorString(color), showDynamic ); }); return this.fenceDataSource; } rain(enable) { if (enable) { this.rainPost = new Cesium.PostProcessStage({ fragmentShader: wutu3d.scene.RainFS, }); this.viewer.scene.postProcessStages.add(this.rainPost); } else { this.rainPost && this.viewer.scene.postProcessStages.remove(this.rainPost); } } snow(enable) { if (enable) { this.snowPost = new Cesium.PostProcessStage({ fragmentShader: wutu3d.scene.SnowFS, }); this.viewer.scene.postProcessStages.add(this.snowPost); } else { this.snowPost && this.viewer.scene.postProcessStages.remove(this.snowPost); } } /** * 获取屏幕中心点三维坐标 * @return {Cesium.Cartesian3} */ getScreenCenterPosition() { const { scene, canvas, camera } = this.viewer; const screenPosition = new Cesium.Cartesian2( canvas.width / 2, canvas.height / 2 ); return scene.globe.pick(camera.getPickRay(screenPosition), scene); } _getRomaPathGeometry(roma) { const { path } = roma || {}; if (!path || !path.length) return null; const coordinates = path.map(p => p.concat(0.5)); return { type: 'FeatureCollection', features: [ { type: 'Feature', properties: { type: 'polyline', style: { width: 6, color: 'rgba(255, 255, 0, 0.1)', }, }, geometry: { type: 'LineString', coordinates: coordinates, }, }, ], }; } _startDrawRoma(title, callback) { this.stopRoma(); const tool = this._romaTool; tool.deleteAll(); tool.startDraw({ type: 'polyline', style: { width: 6, lineType: 'solid', color: '#ff0000', }, success: entity => { const path = tool.toGeoJSON(); const _path = path.features[0].geometry.coordinates.map(d => d.slice(0, 2) ); // {id:2, title: "漫游路线2", height:1.5, path: [], speed:1, x: 0, y:0, z:0, type: "gs"}, this.addRoma({ title: title || '漫游线路' + this.romas.length, path: _path, speed: 1, type: 'dy', height: 1.7, }); callback && callback(); this.fire(UI_CHANGE_EVENT); }, }); } setRomas(romas) { this.romas = romas; this.fire(UI_CHANGE_EVENT); return this; } addRoma({ title, path, speed, x, y, z, type }) { this.romas.push({ id: Cesium.createGuid(), title, path, speed, x, y, z, type, }); this.fire(UI_CHANGE_EVENT); } /** * 移除漫游 * @param {*} id */ removeRoma(id) { if (id) { if (id === this._currentRoma) { this.stopRoma(); } this.romas = this.romas.filter(d => d.id !== id); } this.fire(UI_CHANGE_EVENT); return this; } /** * 播放漫游 * @param {*} id */ playRoma(id, showPath) { const roma = this.romas.filter(d => d.id === id)[0]; if (!roma) return; this.stopRoma(); const path = this._getRomaPathGeometry(roma); if (!path) return; if (showPath) { this._romaTool.loadJson(path); } this._currentRoma = roma.id; var flyDataPoints = path.features[0].geometry.coordinates.map(d => { return [d[0], d[1], 1.5]; }); var flydata = { name: 'plan1', interpolation: false, //是否setInterpolationOptions插值 clockLoop: true, //是否循环播放 // dy 第一视角, gs 跟随 camera: { type: 'dy', followedX: 5, followedZ: 0.5, }, points: flyDataPoints, // "clampToGround": true, speed: 16, // km/h }; this._romaFlyline = new wutu3d.FlyLine(this.viewer, flydata); this._romaFlyline.start(); this.fire(UI_CHANGE_EVENT); } /** * 停止漫游 */ stopRoma() { if (this._romaFlyline) { this._romaFlyline.stop(); } this._currentRoma = null; this.fire(UI_CHANGE_EVENT); } /** * 开启或关闭阴影 * @param {Boolean} enable */ setShadows(enable) { this.viewer.scene.globe.enableLighting = enable; this.viewer.shadows = enable; } // 开始日照模拟 startClockMock(speed) { speed = speed || 1; const viewer = this.viewer; // 起始时间 var start = new Cesium.JulianDate(); // 结束时间 var stop = Cesium.JulianDate.addSeconds( start, 86400, new Cesium.JulianDate() ); // 设置始时钟始时间 viewer.clock.startTime = start.clone(); // 设置时钟当前时间 viewer.clock.currentTime = start.clone(); // 设置始终停止时间 viewer.clock.stopTime = stop.clone(); viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER; viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // 时间速率,数字越大时间过的越快 viewer.clock.multiplier = speed * 9000; viewer.clock.shouldAnimate = true; return this; } // 停止日照模拟 stopClockMock() { const viewer = this.viewer; // 起始时间 var start = new Cesium.JulianDate(); // 结束时间 var stop = Cesium.JulianDate.addDays(start, 1, new Cesium.JulianDate()); // 设置始时钟始时间 viewer.clock.startTime = start.clone(); // 设置时钟当前时间 viewer.clock.currentTime = start.clone(); // 设置始终停止时间 viewer.clock.stopTime = stop.clone(); viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER; viewer.clock.clockRange = Cesium.ClockRange.UNBOUNDED; // 时间速率,数字越大时间过的越快 viewer.clock.multiplier = 1; viewer.clock.shouldAnimate = false; return this; } // 设置视点 setViewPoints(viewPoints) { this.viewPoints = viewPoints || []; } addViewPoint({ title } = {}) { this.viewPoints.push({ id: Cesium.createGuid(), title: title, viewPoint: this.getViewPoint(), }); } removeViewPoint(id) { this.viewPoints = this.viewPoints.filter(v => v.id !== id); } focusViewPoint(id) { const viewPoint = this.viewPoints.filter(v => v.id === id)[0]; if (!viewPoint) return; this.flyToViewPoint(viewPoint.viewPoint); } destroy() { this.measureTool.clearMeasure(); this.clearAllPlots(); this.removeModels(); // this.viewer.destroy(); // this.viewer = null; // this.fire(UI_CHANGE_EVENT); } }