/** * 创建者:王成 * 操作系统:MAC * 创建日期:2022年11月10日 * 描述:该类主要是绘制工具 提供各种绘制方法 */ /* 引入Cesium */ // import * as Cesium from 'cesium'; /* 引入地理工具箱 */ import * as turf from '@turf/turf' /* 引入属性编辑框 */ import DialogEditProperty from './CrEditProperty.ce.vue' /* 引入组件注册 */ import { defineCustomElement } from 'vue' /* 扩展数组方法 */ /** * 获取数组最后一个元素 */ Array.prototype.last = function() { if (this === undefined || this.length === undefined || this.length === 0) return undefined; return this[this.length - 1]; } /** * 获取数组第一个元素 */ Array.prototype.first = function() { if (this === undefined || this.length === undefined || this.length === 0) return undefined; return this[0]; } /** * 设置编辑点类型 * @ignore 生成方法时不对外公开 * @param {options} options 配置项 * @param {DrawTools.EditPointType} options.type 类型 * @param {Number} options.index 索引 */ Cesium.Entity.prototype.setEditType = function(options) { this._editType = options; } /** * 获取编辑点类型 * @ignore 生成方法时不对外公开 * @return {DrawTools.EditPointType} 编辑点类型 */ Cesium.Entity.prototype.getEditType = function() { return this._editType; } /** * 设置实体挂接的数据类型 * @ignore 生成方法时不对外公开 * @param {DrawTools.DrawType} entityType 实体挂接的数据类型 */ Cesium.Entity.prototype.setEntityType = function(entityType) { this._entityType = entityType; } /** * 获取实体挂接的数据类型 * @ignore 生成方法时不对外公开 * @@return {DrawTools.DrawType} 实体挂接的数据类型 */ Cesium.Entity.prototype.getEntityType = function(entityType) { return this._entityType; } /** * 设置实体是否可编辑 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit 是否可编辑 */ Cesium.Entity.prototype.setIsEdit = function(isEdit) { this._isEdit = isEdit; } /** * 获取实体是否可编辑 * @ignore 生成方法时不对外公开 * @return {Boolean} isEdit */ Cesium.Entity.prototype.getIsEdit = function() { return this._isEdit; } /** * 设置附加参数 * @ignore 生成方法时不对外公开 * @param {JSON} params 参数 */ Cesium.Entity.prototype.setParams = function(params) { this._params = params; } /** * 获取附加参数 * @ignore 生成方法时不对外公开 */ Cesium.Entity.prototype.getParams = function() { return this._params; } /** * 绑定实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} entity 绑定的实体 */ Cesium.Entity.prototype.bindEntity = function(entity) { this._bindEntity = entity; } /** * 获取绑定的实体 * @ignore 生成方法时不对外公开 * @return {Cesium.Entity} */ Cesium.Entity.prototype.getBindEntity = function() { return this._bindEntity; } /** * 类 */ class DrawTools { /** * 默认初始化 * @ignore 生成方法时不对外公开 * @param {Object} viewer 三维场景 * @param {JSON} options [配置项] * @param {Boolean} options.isDrawPoint 是否绘标记点 * @param {Boolean} options.isRetainDrawPoint 绘制完成,是否保留绘制点 * @param {DrawTools.SketchIconType} options.iconType 点图标类型 */ constructor(viewer, options) { /* 赋值三维视图 */ this._viewer = viewer; /* 初始化 */ this._init(options); } /** * 静态方法 初始化并获取属性编辑参数 */ static initEditPropertyParams() { return { id: undefined, //用于标识及传递当前编辑的实体类型 内容为DrawTools.DrawType height: 20, //用于高度标识 如墙、房屋等 或OD线的中间顶点高度 bottomHeight: 0, //用于标识底部高度值 如 墙、房屋等 color: 'rgba(0,255,0,0.75)', //用于颜色标识 direction: 'horizontal', //用于动态方向 取值为horizontal/vertical order: '-', //用于标识动态流动方向 取值范围为+/- count: 2, //用于标识动态子元素的数量 text: '', //用于标识文本 lineWidth: 0, //用于标识线宽 power: 0.25, //用于标识发光度[0-1] outlineWidth: 0, //用于标识描边线宽度 outlineColor: 'rgba(255,255,255,1)', //用于标识描边线颜色 videoUrl: '', //用于标识视频播放地址 duration: 1500, //默认播放速度 odlineHeight: 1000, //OD线的弧顶高度 odlineCount: 50, //OD线的插值数量 axisX: 0, //X坐标轴 平移距离 axisY: 0, //Y坐标轴 平移距离 axisZ: 0, //Z坐标轴 平移距离 } } /** * 初始化 * @ignore 生成方法时不对外公开 * @param {JSON} options [配置项] * @param {Boolean} options.isDrawPoint 是否绘标记点 * @param {Boolean} options.isRetainDrawPoint 绘制完成,是否保留绘制点 * @param {DrawTools.SketchIconType} options.iconType 点图标类型 */ _init(options) { /* 开启地形检测 必须开启 否则会导致获取地形高度时异常 导致鼠标移动时位置哆嗦 */ this._viewer.scene.globe.depthTestAgainstTerrain = true; /* 取消地图右键点击事件 */ this._viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType .LEFT_DOUBLE_CLICK); /* 创建的临时实体的名称 该名称通用 为了后期统一删除 */ this._sketchEntityName = this._guid(); /* 用DataSource方式管理绘制的Entity 实现工具分离 */ let dataSource = new Cesium.CustomDataSource(this._sketchEntityName); this._viewer.dataSources.add(dataSource); /* 实体数据集 */ this._entities = dataSource.entities; this._pointEntitys = []; /* 草图工具绘制的点图片 */ this._sketchPointImage = undefined; /* 点图标 */ this._iconNormal = 'data:image/png;base64,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'; this._iconBlue = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozNjZmZDYyMy02NmE4LWYzNDUtODc4MC00YmMwY2IzZWM4OTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkEyMUE1MDg3NTAyMTFFREI0RUY4MjBCRjRGRDc0QUIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkEyMUE1MDc3NTAyMTFFREI0RUY4MjBCRjRGRDc0QUIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OWFmM2ZiODktNzQ4OS1kMDRkLTkyNzUtZDM5MWNhYzYwMGE1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjM2NmZkNjIzLTY2YTgtZjM0NS04NzgwLTRiYzBjYjNlYzg5MyIv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'; this._iconGreen = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozNjZmZDYyMy02NmE4LWYzNDUtODc4MC00YmMwY2IzZWM4OTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjI1NDIwOUU3NTAyMTFFRDk0MTJGQzhGMTFCQkREODIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjI1NDIwOUQ3NTAyMTFFRDk0MTJGQzhGMTFCQkREODIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OWFmM2ZiODktNzQ4OS1kMDRkLTkyNzUtZDM5MWNhYzYwMGE1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjM2NmZkNjIzLTY2YTgtZjM0NS04NzgwLTRiYzBjYjNlYzg5MyIv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'; this._iconViolet = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozNjZmZDYyMy02NmE4LWYzNDUtODc4MC00YmMwY2IzZWM4OTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzFDREU3Mjk3NTAyMTFFREE4MThDODBGNzMxNDBCQzEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzFDREU3Mjg3NTAyMTFFREE4MThDODBGNzMxNDBCQzEiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OWFmM2ZiODktNzQ4OS1kMDRkLTkyNzUtZDM5MWNhYzYwMGE1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjM2NmZkNjIzLTY2YTgtZjM0NS04NzgwLTRiYzBjYjNlYzg5MyIv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'; /* 图片资源 */ this._image_arrow_forward = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAAgCAYAAABkS8DlAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA4FpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ4IDc5LjE2NDAzNiwgMjAxOS8wOC8xMy0wMTowNjo1NyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplMWFmZGVkNi00MTJhLTc5NDAtYjQxMC04NDExNjRiMzQ0ODciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QTA3MThEMzhCMjc3MTFFRDg1ODdDNkY4OTc4ODRCRjUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QTA3MThEMzdCMjc3MTFFRDg1ODdDNkY4OTc4ODRCRjUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6YjI3YWU1YjEtZmRkMy0wOTQyLWIyMzUtMDFkYWY3YTJlNGUyIiBzdFJlZjpkb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6YWUwMWJjYWItYzAxZS04YTQyLTg4MjAtNDU1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'; this._image_arrow_reverse = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAAgCAYAAABkS8DlAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA4FpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ4IDc5LjE2NDAzNiwgMjAxOS8wOC8xMy0wMTowNjo1NyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplMWFmZGVkNi00MTJhLTc5NDAtYjQxMC04NDExNjRiMzQ0ODciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QThBQTYyN0ZCMjc2MTFFREIzM0E4RjQ4Q0YwQTgyMzgiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QThBQTYyN0VCMjc2MTFFREIzM0E4RjQ4Q0YwQTgyMzgiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6YmIzYjdkNGEtYmQwYi04YjRjLTkwNmQtMTRhMTNkNjEwZWUxIiBzdFJlZjpkb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6YWUwMWJjYWItYzAxZS04YTQyLTg4MjAtNDU1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'; this._image_h_l_r = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAAgCAYAAABkS8DlAAABIklEQVR4nO3WbQuCMBiG0dn//80tiAp6WT4zi+A+54vTTdMKuZZ20Y/H2/is9/r+aFxdNz5/qa7t1/Gr+dlj79ZX5mrnvz93p+3T9zKznbnnynW/OPfwnLXP/v2xqXvolXv8dH7Ld7Vhvs+cf/2v/d/vd3dfq8/0zbm1a1d/18L2o3fIzHbtnVi51p5zK8f6q3Xj8cza8XjrusH+oQEAcQQAAAQSAAAQSAAAQCABAACBBAAABBIAABBIAABAIAEAAIEEAAAEEgAAEEgAAEAgAQAAgQQAAAQSAAAQSAAAQCABAACBBAAABBIAABBIAABAIAEAAIEEAAAEEgAAEEgAAEAgAQAAgQQAAAQSAAAQSAAAQCABAACBBAAABBIAAJCmtXYCutDwWwUr9cEAAAAASUVORK5CYII='; this._image_h_r_l = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAAgCAYAAABkS8DlAAAAAXNSR0IArs4c6QAAAFBlWElmTU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAABAAAAJgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAACAKADAAQAAAABAAAAIAAAAACVLBWUAAABWWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyI+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgoZXuEHAAAC90lEQVR4Ae3WzVbbMBAG0PzBgcOa93/M7nCj2F8zUUILdDmXjWTNSLauBMz+19vbstvvl139+c5zza39sd7hUNe99mveZ/3dbs3/LF7W3j/IXbZ5hzI/Yzf7TXxux/fPY3n+W+wrOfP3Zs5P26wXk22d/bzenJf8jNf82h/73XLOh7KeS51b++fEw/R8uQfzetvzsubmbtyuPXLmteo6W/9Qv2lZ7te4fde6l6xT52Ysbf22jK3t+o7j8frdt/H1HTWe96RdY+v8OnfrX84u45kznrPm6Cde2/THnPRrW/vjK+e8OT6e61j6OZcaH/ZbfDvXy+/Qsc5Jv55TxtKOWNY/t39+bx/NSV6dk3VGrM4Zu/2fsbFW/Ou69RvGO2rOFlvq2Pwdc2w8Z/0tdpqeL/HTab0/iaWd1xt5iaWd587PyXt6evyOOT939LP8jCcv66d9fn78nsSH2cvLv3OS//p6mzvmJza3Izb+D64/ae/zR/zR3IyN+MfH/fz39+tY9j9yv9//6pw57+45/xvOfzv9ECBAgAABAt0EFADdTtx+CRAgQIDAWUAB4BoQIECAAIGGAgqAhoduywQIECBAQAHgDhAgQIAAgYYCCoCGh27LBAgQIEBAAeAOECBAgACBhgIKgIaHbssECBAgQEAB4A4QIECAAIGGAgqAhoduywQIECBAQAHgDhAgQIAAgYYCCoCGh27LBAgQIEBAAeAOECBAgACBhgIKgIaHbssECBAgQEAB4A4QIECAAIGGAgqAhoduywQIECBAQAHgDhAgQIAAgYYCCoCGh27LBAgQIEBAAeAOECBAgACBhgIKgIaHbssECBAgQEAB4A4QIECAAIGGAgqAhoduywQIECBAQAHgDhAgQIAAgYYCCoCGh27LBAgQIEBAAeAOECBAgACBhgIKgIaHbssECBAgQEAB4A4QIECAAIGGAgqAhoduywQIECBAQAHgDhAgQIAAgYYCCoCGh27LBAgQIEBAAeAOECBAgACBhgK/AX08dE/3SOoSAAAAAElFTkSuQmCC'; this._image_v_b_t = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAAgCAYAAABkS8DlAAADcklEQVR4nO3di27bMAyFYdpWLuv2/o+aJfFFgxOp5VjKdjDM6rD/A4KkbZyhwIBzTMluE/s+CAAA+J/EIH1/SL9ws/KLR/5rAADwZb2S4zHIMBzVN9YOzh8QN74XAAD8HTmLt2Z3Ns3PId7vR/MB9oPihtcAAGBfOq9Lr3WOR/0Icrt5BaAxb14rAwAA4OsUAC/HPxWAk4i0hSmAF/iT8zMAALCvnNXtQiHwwn/O8WkuAGdTALy1hFhoEQAAoA5ver+W4aoAXK8UAAAA/j1/UgDGED8mAHYZQB/ofYBQAgAAqMIL/qXN/L+F/6MAyPX6TUS6lQLgPYQCAABAFaUCsJbjY3oMQS4XXQDaFwoAywAAANRRCv6lApDP/odHAYi3Wy4A3YYCMFEAAACozgv9tUn+qApAnycA4cUCMFEAAACoxgv+LQVgSI8Q5OdPWwDawoE2/CcKAAAAVZTC3zuRn5wC0M0F4LuIHJx9AHb3/2TCnwIAAEAdugC0zmtRWW4LwP0xAYjPCcAhTQHswZ9uHOAUAQAAsC971t8WLunXBeD97H9+X14COBT2Adj1flsCKAAAAOzPC35vGcBb/291ATguFIBS8FMAAACoo1QASpP8993/7wUgLQGcUgEICxMAHfojVwIAAFCNLQDdCwUgPDcBXi5vqQAcCgUgOsFv9wIAAID9NE74ezf1swXgnt7X6CWAo7oh0FIBGLkSAACAqvJGPxv+paX8UW8AnH+Q7wR4NhsBvQIwqgnASAEAAKAaO/7fUgB6lfEx3wnwbDYCLhWAkQIAAEBVXgHwbuufc3xQ9/xJBeB6PacCcFooAF74jxQAAACqWAp/fVdfXQD6lO+PE/ggH0sA+koAUQdKOpACAADA1/BKARC1AbDNpSDE5wQgXwrYpQKwNgEYKQAAAFRTKgD27/roCYC+1f84TwDOZg9AMAfa9f+BCQAAAFW16iqAYJ717YBzjg9qiX96/jng2+2Uzv6PqgSUJgCDKQHcDRAAgP3Zs/9gvvY2Abb6ioC5AOTgP5vw17p0QKueKQAAANThFYCgzvytLn2dpwHHEO/3tfCX9P2ggr8zlwICAIB9NGb8vxT8OsePefw/XxIYpO9/mJ3/S/LGgqDW/ikAAADsp9kQ+J45v9/S9+NcALaGv5X/4W77IQAAoLI3EWl/AQ/TsX9wLtbWAAAAAElFTkSuQmCC'; this._image_v_t_b = 'data:image/png;base64,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'; /* 存储的点集合 */ this._sketchTempPoints = []; //临时点集合 主要为了存储鼠标移动事件临时存储点 this._sketchPoints = []; //正式点集合 主要为了绘制正式图形 this._sketchOutputPoints = []; //输出点集合 主要为了存储输出的经纬度坐标点集合 this._sketchWallHeights = []; //墙的高度点集合 /* 当前绘制的实体 */ this._drawEntity = undefined; /* 点线标注 */ this._lineLabel = undefined; this._polygonLabel = undefined; /* 配置是否绘制点 */ if (options && options.isDrawPoint) this._isDrawPoint = options.isDrawPoint; else this._isDrawPoint = false; /* 配置绘制完成是否保留绘制点 */ if (options && options.isRetainDrawPoint) this._isRetainDrawPoint = options.isRetainDrawPoint; else this._isRetainDrawPoint = false; /* 通用参数集合 */ this._param = { lineWidth: 3, //线宽度 lineColor: 'rgba(0,255,0,0.75)', //线颜色 outlineWidth: 2, //边框宽度 outlineColor: 'rgba(255,255,255,1)', //边框颜色 polygonColor: 'rgba(0,255,0,0.5)', //面填充颜色 wallHeight: 30, //高度 墙、房屋 power: 0.25, //发光强度 odlineHeight: 1000, //OD线弧顶高度 odlineCount: 50, //OD线插值数量 text: '金田产业集团', //立体广告默认文字 duration: 1500, //动画播放速度 count: 1, //动态流动 展示数量 direction_h: 'horizontal', //水平方向 direction_v: 'vertical', //垂直方向 order_add: '+', //正向 order_minus: '-', //反向 houseColor: 'rgba(0,255,0,0.95)' //房屋默认填充颜色 } /* 设置点符号类型 */ if (options && options.iconType) { switch (options.iconType) { case DrawTools.IconType.Normal: this._sketchPointImage = this._iconNormal; break; case DrawTools.IconType.Blue: this._sketchPointImage = this._iconBlue; break; case DrawTools.IconType.Green: this._sketchPointImage = this._iconGreen; break; case DrawTools.IconType.Violet: this._sketchPointImage = this._iconViolet; break; default: this._sketchPointImage = this._iconNormal; break; } } else { this._sketchPointImage = this._iconNormal; } /* 获取画布的宽度和高度 */ this._canvasWidth = this._viewer.scene.canvas.width; this._canvasHeight = this._viewer.scene.canvas.height; /* 根据运行模式调整精细度 如果运行在App上 则调整精细度 使其看起来更加的精细 */ if (this._isRuntimeApp()) { /* 开启精细渲染 不要太大 否则会导致效率下降 */ this._viewer._cesiumWidget._supportsImageRenderingPixelated = Cesium.FeatureDetection .supportsImageRenderingPixelated(); this._viewer._cesiumWidget._forceResize = true; if (Cesium.FeatureDetection.supportsImageRenderingPixelated()) { var vtxf_dpr = window.devicePixelRatio; while (vtxf_dpr >= 2.0) { vtxf_dpr /= 2.0; } this._viewer.resolutionScale = 2.6; } } } /** * 弧度转度 * @ignore 生成方法时不对外公开 * @param {Number} arc 弧度 * @return {Number} 角度 */ _arcToDegree(arc) { return arc / Math.PI * 180; } /** * 普通颜色值转换为Cesium颜色 * @ignore 生成方法时不对外公开 * @param {int} red 红色[0~255] * @param {int} green 绿色[0~255] * @param {int} blue 蓝色[0~255] * @param {int} alpha 透明度[0~1] * @return {Cesium.Color} Cesium格式的颜色 */ _toColor(red, green, blue, alpha) { let normalColor = new Cesium.Color(0, 0, 0, 1.0); if (typeof red != 'number') return normalColor; if (typeof green != 'number') return normalColor; if (typeof blue != 'number') return normalColor; if (typeof alpha != 'number') return normalColor; if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255 || alpha < 0 || alpha > 1) return normalColor; return new Cesium.Color(red / 255.0, green / 255.0, blue / 255.0, alpha); } /** * 通过颜色数组转换为Cesium颜色 * @ignore 生成方法时不对外公开 * @param {Array} array 颜色数组 * @return {Cesium.Color} Cesium格式的颜色 */ _toColorFromArray(array) { if (!array || array.length === undefined || array.length === 0) return new Cesium.Color(255 / 255.0, 255 / 255.0, 255 / 255.0, 1.0); let r = 255, g = 255, b = 255, a = 1.0; if (array.length === 1) { r = parseInt(array[0]); } else if (array.length === 2) { r = parseInt(array[0]); g = parseInt(array[1]); } else if (array.length === 3) { r = parseInt(array[0]); g = parseInt(array[1]); b = parseInt(array[2]); } else if (array.length >= 4) { r = parseInt(array[0]); g = parseInt(array[1]); b = parseInt(array[2]); a = parseFloat(array[3]); } return new Cesium.Color(r / 255.0, g / 255.0, b / 255.0, a); } /** * 刷新场景 刷新一帧 * @ignore 生成方法时不对外公开 */ _updateScene() { this._viewer.scene.requestRender(); } /** * 根据地形或实景或模型检测当前屏幕位置的世界坐标系位置 * @ignore 生成方法时不对外公开 * @param {JSON} screenPosition 屏幕坐标 * @param {Number} screenPosition.x 屏幕坐标x * @param {Number} screenPosition.y 屏幕坐标y * @return {JSON} 位置信息{x,y,z} */ _getScreenClickPosition(screenPosition) { let resCartesian = undefined; let ray = this._viewer.scene.camera.getPickRay(screenPosition); let position = this._viewer.scene.globe.pick(ray, this._viewer.scene); let cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position); if (Cesium.defined(position)) { resCartesian = { x: position.x, y: position.y, z: position.z, } } return resCartesian; } /** * 根据地形或实景或模型检测当前屏幕位置的经纬度及高度 * @ignore 生成方法时不对外公开 * @param {JSON} screenPoint 屏幕坐标 * @param {Number} screenPoint.x 屏幕坐标x * @param {Number} screenPoint.y 屏幕坐标y * @return {JSON} 位置信息{lng,lat,height} */ _getScreenClickPositionAndHeight(screenPoint) { var lng = undefined, lat = undefined, height = undefined; /* 从相机位置到 windowPosition 处的像素创建射线在世界坐标系中 */ var ray = this._viewer.scene.camera.getPickRay(screenPoint); /* 找到射线与渲染的地球表面之间的交点 */ var position = this._viewer.scene.globe.pick(ray, this._viewer.scene); /* 获取地理位置的制图表达 */ var cartographic = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position); cartographic = Cesium.Cartographic.fromCartesian(position); /* 查询屏幕位置的要素 */ var feature = this._viewer.scene.pick(screenPoint); if (feature === undefined && Cesium.defined(cartographic)) { lng = this._arcToDegree(cartographic.longitude); lat = this._arcToDegree(cartographic.latitude); height = cartographic.height; } else { var cartesian = this._viewer.scene.pickPosition(screenPoint); if (Cesium.defined(cartesian)) { var cartographic = Cesium.Cartographic.fromCartesian(cartesian); if (Cesium.defined(cartographic)) { lng = this._arcToDegree(cartographic.longitude); lat = this._arcToDegree(cartographic.latitude); height = cartographic.height; } } } /* 返回结果 */ return { lng: lng, lat: lat, height: height, } } /** * 屏幕位置转换为经纬度位置及空间位置 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian2} screenPosition 屏幕位置 * @return {JSON} 经纬度位置及空间位置 */ _transfromFromScreenPoint(screenPosition) { /* 根据屏幕位置获取经度、纬度和高度信息 */ let location = this._getScreenClickPositionAndHeight(screenPosition); if (location.lng != undefined) { /* 经纬度位置转换为三维坐标 */ var cartesian = Cesium.Cartesian3.fromDegrees(location.lng, location.lat, location .height); /* 返回 */ return { gLocation: location, sLocation: cartesian, } } else { /* 返回 */ return { gLocation: undefined, sLocation: undefined, } } } /** * 根据Entity的名称批量删除Entity * @ignore 生成方法时不对外公开 * @param {String} entityName 实体名称 */ _removeEntityByName(entityName) { /* 获取实体集合 */ var entities = this._entities; /* 如果不存在实体集合或集合中没有数据 则返回 */ if (!entities || !entities.values) return; var delEntitys = []; /* 循环获取当前集合中的所有实体 */ for (var i = 0; i < entities.values.length; i++) { if (entities.values[i].name == entityName) { delEntitys.push(entities.values[i]); } } /* 删除符合条件的所有实体 */ for (var i = 0; i < delEntitys.length; i++) { entities.remove(delEntitys[i]); } /* 更新场景 */ this._updateScene(); } /** * 移除实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} objEntity 实体 */ _removeEntityByObject(objEntity) { if (!Cesium.defined(objEntity)) return; let res = this._entities.remove(objEntity); } /** * 绘制点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} coord 坐标 * @param {String} label [点上面显示的文字标注] */ _createPoint(coord, label) { let _self = this; /* 创建点实体 */ let entity = new Cesium.Entity({ name: _self._sketchEntityName + "_Point", position: coord, billboard: { image: _self._sketchPointImage, horizontalOrigin: Cesium.HorizontalOrigin.center, verticalOrigin: Cesium.VerticalOrigin.bottom, scale: 0.5, pixelOffset: new Cesium.Cartesian2(0, -11), disableDepthTestDistance: Number.POSITIVE_INFINITY, } }); /* 判断是否需要绘制文字 */ if (label) { entity.label = { text: label, font: '12px sans-serif', fillColor: this._toColor(255, 255, 255, 1.0), outlineColor: this._toColor(0, 154, 94, 1.0), style: Cesium.LabelStyle.FILL_AND_OUTLINE, outlineWidth: 1.0, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, pixelOffset: new Cesium.Cartesian2(0, -28), showBackground: true, backgroundColor: this._toColor(0, 0, 0, 0.6), disableDepthTestDistance: Number.POSITIVE_INFINITY, } } /* 加入集合中 */ this._entities.add(entity); /* 加入点集合数组中 */ this._pointEntitys.push(entity); this._updateScene(); } /** * 删除全部点 * @ignore 生成方法时不对外公开 */ _removePointEntitys() { /* 清除所有绘制的点实体 */ this._removeEntityByName(this._sketchEntityName + "_Point"); /* 清除用于临时存储的点实体集合 */ this._pointEntitys = []; } /** * 调用更新椭圆中心点位置信息 * @ignore 生成方法时不对外公开 * @return {Cesium.Cartesian3} */ _callUpdaeEllipseCenterPosition() { let _self = this; return function() { let point1cartographic = Cesium.Cartographic.fromCartesian(_self ._sketchTempPoints[0]); let point2cartographic = Cesium.Cartographic.fromCartesian(_self ._sketchTempPoints[1]); _self._sketchEllipseCenterPosition = Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees( point1cartographic .longitude), Cesium.Math.toDegrees(point1cartographic .latitude), point2cartographic.height); return _self._sketchEllipseCenterPosition; } } /** * 圆半径变更回调 * @ignore 生成方法时不对外公开 * @param {Array} positions 位置数据点集合 */ _callUpdateEllipseMinorAxis(positions) { let _self = this; return function() { if (positions === undefined || positions.length === undefined || positions.length < 2) { _self._sketchEllipseRadius = 0; } else { _self._sketchEllipseRadius = _self._calculateEllipseMinorAxis(positions[0], positions[1]); if (_self._sketchEllipseRadius <= 0) _self._sketchEllipseRadius = 1; } return _self._sketchEllipseRadius; } } /** * 计算两点组成椭圆的半径 * @ignore * @param {Cesium.Cartesian3} position1 Location center * @param {Cesium.Cartesian3} position2 Location outline * @return {Number} radius */ _calculateEllipseMinorAxis(position1, position2) { let point1cartographic = Cesium.Cartographic.fromCartesian(position1); let point2cartographic = Cesium.Cartographic.fromCartesian(position2); /* 计算距离 */ let geodesic = new Cesium.EllipsoidGeodesic(); geodesic.setEndPoints(point1cartographic, point2cartographic); return geodesic.surfaceDistance; } /** * 计算两点组成椭圆的边界线坐标集合 * @ignore * @param {Cesium.Cartesian3} position1 圆心 * @param {Cesium.Cartesian3} position2 外边界点 * @return {Array} */ _calculateEllipseOutlineCoordinate(position1, position2) { let positionCenter = position1; let positionRotate = position2; let ellipseOutlineCoordinates = []; for (let angle = 5; angle < 360;) { let newPosition = this._rotatedPointByAngle(positionRotate, positionCenter, angle); ellipseOutlineCoordinates.push(newPosition); angle = angle + 5; } ellipseOutlineCoordinates.push(ellipseOutlineCoordinates[0]); return ellipseOutlineCoordinates; } /** * 圆的边界变更回调 * @ignore 生成方法时不对外公开 * @param {Array} positions 圆的点数据集合 */ _callEllipseOutlineCoordinate(positions) { let _self = this; return function() { _self._ellipseOutlineCoordinates = _self._calculateEllipseOutlineCoordinate(positions[0], positions[ 1]); return _self._ellipseOutlineCoordinates; } } /** * position_A绕position_B逆时针旋转angle度(角度)得到新点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position_A 动点 * @param {Cesium.Cartesian3} position_B 中心点 * @param {Number} angle 旋转角度 */ _rotatedPointByAngle(position_A, position_B, angle) { //以B点为原点建立局部坐标系(东方向为x轴,北方向为y轴,垂直于地面为z轴),得到一个局部坐标到世界坐标转换的变换矩阵 var localToWorld_Matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position_B); //求世界坐标到局部坐标的变换矩阵 var worldToLocal_Matrix = Cesium.Matrix4.inverse(localToWorld_Matrix, new Cesium.Matrix4()); //B点在局部坐标的位置,其实就是局部坐标原点 var localPosition_B = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, position_B, new Cesium .Cartesian3()); //A点在以B点为原点的局部的坐标位置 var localPosition_A = Cesium.Matrix4.multiplyByPoint(worldToLocal_Matrix, position_A, new Cesium .Cartesian3()); //根据数学公式A点逆时针旋转angle度后在局部坐标系中的x,y,z位置 var new_x = localPosition_A.x * Math.cos(Cesium.Math.toRadians(angle)) + localPosition_A.y * Math.sin(Cesium .Math.toRadians(angle)); var new_y = localPosition_A.y * Math.cos(Cesium.Math.toRadians(angle)) - localPosition_A.x * Math.sin(Cesium .Math.toRadians(angle)); var new_z = localPosition_A.z; //最后应用局部坐标到世界坐标的转换矩阵求得旋转后的A点世界坐标 return Cesium.Matrix4.multiplyByPoint(localToWorld_Matrix, new Cesium.Cartesian3(new_x, new_y, new_z), new Cesium.Cartesian3()); } /** * 矩形坐标更新回调 * @ignore 生成方法时不对外公开 * @param {Array} positions 坐标数据集合 */ _callUpdateRectangleCoordinates(positions) { let _self = this; return function() { /* 对坐标进行转换 */ let g0 = Cesium.Ellipsoid.WGS84.cartesianToCartographic(positions[0]); let g1 = Cesium.Ellipsoid.WGS84.cartesianToCartographic(positions[1]); /* 获取转换 */ let lng0 = Cesium.Math.toDegrees(g0.longitude); let lat0 = Cesium.Math.toDegrees(g0.latitude); let lng1 = Cesium.Math.toDegrees(g1.longitude); let lat1 = Cesium.Math.toDegrees(g1.latitude); _self._rectangleCoordinates = [0, 0, 1, 1]; if (lng0 < lng1) { _self._rectangleCoordinates[0] = lng0; _self._rectangleCoordinates[2] = lng1; } else { _self._rectangleCoordinates[0] = lng1; _self._rectangleCoordinates[2] = lng0; } if (lat0 < lat1) { _self._rectangleCoordinates[1] = lat0; _self._rectangleCoordinates[3] = lat1; } else { _self._rectangleCoordinates[1] = lat1; _self._rectangleCoordinates[3] = lat0; } let rectangle = Cesium.Rectangle.fromDegrees(_self._rectangleCoordinates[0], _self ._rectangleCoordinates[1], _self._rectangleCoordinates[2], _self._rectangleCoordinates[3]); /* 计算并返回矩形的边界线坐标数组 */ let res = _self._calculateRectangleOutlineCoordinates(rectangle); _self._rectangleOutlineCoordinates = res.cPoints; _self._sketchOutputPoints = res.gPoints; return rectangle; } } /** * 计算矩形的外围坐标串 * @ignore 生成方法时不对外公开 * @param {Cesium.Rectangle} rectangle 矩形 * @return {Array} 坐标串集合 */ _calculateRectangleOutlineCoordinates(rectangle) { /* 计算东南角 */ let south_east = Cesium.Rectangle.southeast(rectangle); let se = Cesium.Cartographic.toCartesian(south_east); /* 计算西南角 */ let south_west = Cesium.Rectangle.southwest(rectangle); let sw = Cesium.Cartographic.toCartesian(south_west); /* 计算东北角 */ let north_east = Cesium.Rectangle.northeast(rectangle); let ne = Cesium.Cartographic.toCartesian(north_east); /* 计算西北角 */ let north_west = Cesium.Rectangle.northwest(rectangle); let nw = Cesium.Cartographic.toCartesian(north_west); /* 经纬度坐标数组 */ let gPoints = []; gPoints.push({ lng: Cesium.Math.toDegrees(south_west.longitude), lat: Cesium.Math.toDegrees(south_west.latitude), height: south_west.height, }); gPoints.push({ lng: Cesium.Math.toDegrees(south_east.longitude), lat: Cesium.Math.toDegrees(south_east.latitude), height: south_east.height, }); gPoints.push({ lng: Cesium.Math.toDegrees(north_east.longitude), lat: Cesium.Math.toDegrees(north_east.latitude), height: north_east.height, }); gPoints.push({ lng: Cesium.Math.toDegrees(north_west.longitude), lat: Cesium.Math.toDegrees(north_west.latitude), height: north_west.height, }); gPoints.push({ lng: Cesium.Math.toDegrees(south_west.longitude), lat: Cesium.Math.toDegrees(south_west.latitude), height: south_west.height, }); /* 返回坐标串 */ return { cPoints: [sw, se, ne, nw, sw], gPoints: gPoints, }; } /** * 矩形外边框轮廓线回调 * @ignore 生成方法时不对外公开 */ _callUpdateRectangleOutlineCoordinates() { let _self = this; return function() { return _self._rectangleOutlineCoordinates; } } /** * 文字材质 * @ignore 生成方法时不对外公开 * @param {JSON} options 配置项 * @param {String} options.text 文字内容 * @param {String} options.color 文字颜色 rgba(r,g,b,a) */ _materialTextImageProperty(options) { this._canvasId = 'canvasJt'; /* 获取画布 */ let canvasObj = document.getElementById(this._canvasId); /* 如果画布已经存在则删除 */ if (canvasObj != null) { document.body.removeChild(canvasObj); } /* 创建画布 */ canvasObj = document.createElement('canvas'); canvasObj.id = this._canvasId; /* 设置画布尺寸 */ canvasObj.setAttribute('width', '1024px'); canvasObj.setAttribute('height', '256px'); /* 加入画布 */ document.body.appendChild(canvasObj); /* 获取上下文绘制 */ let context = canvasObj.getContext('2d'); context.fillStyle = options.color === undefined ? 'rgba(255,0,0,1)' : options.color; context.font = 'bold 240px 微软雅黑'; context.textAlign = 'left'; context.textBaseline = 'bottom'; context.fillText(options.text, 12, 250, 1000); /* 创建材质 */ let textMaterial = new Cesium.ImageMaterialProperty({ image: canvasObj, transparent: true, }); textMaterial._param = { color: context.fillStyle, text: options.text, } /* 返回材质 */ return textMaterial; } /** * 颜色材质 * @ignore 生成方法时不对外公开 * @param {JSON} options 配置项 * @param {String} options.color 文字颜色 rgba(r,g,b,a) */ _materialColorProperty(options) { let mColor = 'rgba(0,255,0,1)'; if (options !== undefined && options.color !== undefined) mColor = options.color; /* 创建材质 */ let colorMaterial = new Cesium.ColorMaterialProperty(Cesium.Color.fromCssColorString(mColor)); colorMaterial._param = { color: mColor, } /* 返回材质 */ return colorMaterial; } /** * 箭头线材质 * @ignore 生成方法时不对外公开 * @param {JSON} options 配置项 * @param {String} options.color 线的颜色 rgba(r,g,b,a) */ _materialPolylineArrowProperty(options) { let mColor = 'rgba(0,255,0,1)'; if (options !== undefined && options.color !== undefined) mColor = options.color; /* 创建材质 */ let colorMaterial = new Cesium.PolylineArrowMaterialProperty(Cesium.Color.fromCssColorString(mColor)); colorMaterial._param = { color: mColor, } /* 返回材质 */ return colorMaterial; } /** * 发光线材质 * @ignore 生成方法时不对外公开 * @param {JSON} options 配置项 * @param {String} options.color 线的颜色 rgba(r,g,b,a) * @param {Number} options.power 发光强度 0~1 */ _materialPolylineGlowProperty(options) { let mColor = 'rgba(0,255,0,1)'; if (options !== undefined && options.color !== undefined) mColor = options.color; let power = 0.25; if (options !== undefined && options.power !== undefined && typeof(options.power) === 'number') power = options.power; /* 创建材质 */ let colorMaterial = new Cesium.PolylineGlowMaterialProperty({ color: Cesium.Color.fromCssColorString(mColor), glowPower: power, }); colorMaterial._param = { color: mColor, power: power, } /* 返回材质 */ return colorMaterial; } /** * 描边线材质 * @ignore 生成方法时不对外公开 * @param {JSON} options 配置项 * @param {String} options.color 线的颜色 rgba(r,g,b,a) * @param {String} options.outlineColor 描边线的颜色 rgba(r,g,b,a) * @param {Number} options.outlineWidth 描边线的宽度 */ _materialPolylineOutlineProperty(options) { let mColor = 'rgba(0,255,0,1)'; let outlineColor = 'rgba(255,255,255,1.0)'; let outlineWidth = 1.2; if (options !== undefined && options.color !== undefined) mColor = options.color; if (options !== undefined && options.outlineColor !== undefined) outlineColor = options.outlineColor; if (options !== undefined && options.outlineWidth !== undefined && typeof(options.outlineWidth) === 'number') outlineWidth = options.outlineWidth; /* 创建材质 */ let colorMaterial = new Cesium.PolylineOutlineMaterialProperty({ color: Cesium.Color.fromCssColorString(mColor), outlineColor: Cesium.Color.fromCssColorString(outlineColor), outlineWidth: outlineWidth, }); colorMaterial._param = { color: mColor, outlineColor: outlineColor, outlineWidth: outlineWidth, } /* 返回材��������������������� */ return colorMaterial; } /** * 清理资源 * @ignore 生成方法时不对外公开 * @param {Boolean} isAll 是否删除已经绘制的全部实体 */ _clear(isAll) { if (isAll != undefined && isAll === true) { this._removeEntityByName(this._sketchEntityName); this._removePointEntitys(); } /* 重置数组变量 */ this._sketchTempPoints = []; this._sketchPoints = []; this._sketchOutputPoints = []; this._sketchWallHeights = []; this._drawEntity = undefined; /* Clear Tooltip */ this._removeOperationDom(); this._tooltipRemove(); /* 释放事件 */ if (this._drawEventHandler !== null && this._drawEventHandler !== undefined && this._drawEventHandler .isDestroyed() === false) { this._clearEvent(this._drawEventHandler); } } } /** * 设置方法 */ Object.assign(DrawTools.prototype, { /** * Set Label * @param {JSNO} options 配置项 * @param {String} options.lineLabel 线点文字标注 * @param {String} options.polygonLabel 面点文字标注 */ setLabel: function(options) { if (!options) { options = { lineLabel: undefined, polygonLabel: undefined, } } if (options.lineLabel) this._lineLabel = options.lineLabel; if (options.polygonLabel) this._lineLabel = options.polygonLabel; } }) /** * 事件相关 */ Object.assign(DrawTools.prototype, { /** * 注册鼠标左键点击事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler 事件句柄 * @param {Function} callChange 回调callChange(event) */ _registerLeftClickEvent: function(handler, callChange) { let _self = this; if (!handler) return; handler.setInputAction(function(event) { /* 锁定点击事件 以免和移动事件冲突 */ _self._lock = true; clearTimeout(_self._timer); _self._timer = setTimeout(function() { if (callChange) callChange(event); /* 解除锁定 */ _self._lock = false; }, 200); }, Cesium.ScreenSpaceEventType.LEFT_CLICK); }, /** * 注册鼠标左键双击事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler 事件句柄 * @param {Function} callChange 回调callChange(event) */ _registerLeftDoubleClickEvent: function(handler, callChange) { let _self = this; if (!handler) return; handler.setInputAction(function(event) { clearTimeout(_self._timer); /* 解除锁定 */ _self._lock = false; if (callChange) callChange(event); }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); }, /** * 注册鼠标移动事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler 事件句柄 * @param {Function} callChange 回调callChange(event) */ _registerMouseMoveEvent: function(handler, callChange) { let _self = this; if (!handler) return; handler.setInputAction(function(event) { if (_self._lock === undefined || _self._lock === false) { if (callChange) callChange(event); } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); }, /** * 注册鼠标右键点击事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler 事件句柄 * @param {Function} callChange ���调callChange(event) */ _registerRightClickEvent: function(handler, callChange) { if (!handler) return; handler.setInputAction(function(event) { if (callChange) callChange(event); }, Cesium.ScreenSpaceEventType.RIGHT_CLICK); }, /** * 注册鼠标左键按下事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler 事件句柄 * @param {Function} callChange 回调callChange(event) */ _registerLeftDownEvent: function(handler, callChange) { if (!handler) return; handler.setInputAction(function(event) { if (callChange) callChange(event); }, Cesium.ScreenSpaceEventType.LEFT_DOWN); }, /** * 注册鼠标左键抬起事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler 事件句柄 * @param {Function} callChange 回调callChange(event) */ _registerLeftUpEvent: function(handler, callChange) { if (!handler) return; handler.setInputAction(function(event) { if (callChange) callChange(event); }, Cesium.ScreenSpaceEventType.LEFT_UP); }, /** * 清除事件 * @ignore 生成方法时不对外公开 * @param {Cesium.ScreenSpaceEventHandler} handler */ _clearEvent: function(handler) { /* 清理事件的同时 彻底清理提示标签 */ this._endTooltip(); /* 隐藏操作容器 */ this._removeOperationDom(); if (!handler) return; /* 干掉事件句柄 释放资源 */ handler.destroy(); handler = null; }, }) /** * 绘制的具体实现方法 */ Object.assign(DrawTools.prototype, { /** * 创建贴地线 * @ignore 生成方法时不对外公开 * @param {DrawTools.PolylineType} polylineType 线类型 */ _createPolyline: function(polylineType) { let _self = this; /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); let polylineWidth = _self._param.lineWidth; /* 创建普通线材质 */ let polylineMaterial = this._materialColorProperty({ color: _self._param.lineColor, }); entityParam.id = DrawTools.DrawType.Polyline; if (polylineType !== undefined && polylineType === DrawTools.PolylineType.ArrowsPolyline) { polylineMaterial = this._materialPolylineArrowProperty({ color: _self._param.lineColor, }); polylineWidth = _self._param.lineWidth * 3; /* 设置实体参数 */ entityParam.color = _self._param.lineColor; entityParam.id = DrawTools.DrawType.ArrowPolyline; } else if (polylineType !== undefined && polylineType === DrawTools.PolylineType.GrowPolyline) { polylineMaterial = this._materialPolylineGlowProperty({ color: _self._param.lineColor, power: _self._param.power, }) polylineWidth = _self._param.lineWidth * 3; /* 设置实体参数 */ entityParam.color = _self._param.lineColor; entityParam.power = _self._param.power; entityParam.id = DrawTools.DrawType.GrowPolyline; } else if (polylineType !== undefined && polylineType === DrawTools.PolylineType.OutlinePolyline) { polylineMaterial = this._materialPolylineOutlineProperty({ color: _self._param.lineColor, outlineColor: _self._param.outlineColor, outlineWidth: _self._param.outlineWidth }); polylineWidth = _self._param.lineWidth * 2; /* 设置实体参数 */ entityParam.color = _self._param.lineColor; entityParam.outlineColor = _self._param.outlineColor; entityParam.outlineWidth = _self._param.outlineWidth; entityParam.id = DrawTools.DrawType.OutlinePolyline; } else if (polylineType !== undefined && polylineType === DrawTools.PolylineType.DynamicPolyline) { polylineMaterial = new WallMaterialProperty({ viewer: _self._viewer, trailImage: _self._image_h_l_r, duration: _self._param.duration, color: Cesium.Color.fromCssColorString(_self._param.lineColor), param: { direction: _self._param.direction_h, count: _self._param.count, order: _self._param.order_minus, }, }); polylineWidth = _self._param.lineWidth; /* 设置实体参数 */ entityParam.color = _self._param.lineColor; entityParam.duration = _self._param.duration; entityParam.direction = _self._param.direction_h; entityParam.count = _self._param.count; entityParam.order = _self._param.order_minus; entityParam.id = DrawTools.DrawType.DynamicPolyline; } /* 设置实体通用参数 */ entityParam.lineWidth = polylineWidth; /* 创建贴地线 */ let entityPolyline = new Cesium.Entity({ name: _self._sketchEntityName, polyline: { show: true, positions: new Cesium.CallbackProperty(function() { return _self._sketchTempPoints; }, false), material: polylineMaterial, width: polylineWidth, clampToGround: true, //开启贴地 如果有模型则贴模型 } }) /* 渲染贴地线 */ this._drawEntity = this._entities.add(entityPolyline); /* 挂接参数到实体上 */ this._drawEntity.setParams(entityParam); }, /** * 更新贴地线 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit [是否可编辑] 可选 */ _updatePolyline: function(isEdit) { /* 更新数据 */ this._drawEntity.polyline.positions = this._sketchPoints; /* 设置实体类型 */ this._drawEntity.setEntityType(DrawTools.DrawType.Polyline); /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { /* 删除所有的临时点 忽略是否保留设置 */ this._removePointEntitys(); this._setEntityIsEdit(this._drawEntity); } }, /** * 创建空间线 * @ignore 生成方法时不对外公开 */ _createSpatialPolyline: function() { let _self = this; /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); /* 创建空间线材质 */ let lineMaterial = this._materialColorProperty({ color: _self._param.lineColor, }) /* 设置实体参数 */ entityParam.id = DrawTools.DrawType.SpatialLine; entityParam.color = _self._param.lineColor; entityParam.lineWidth = _self._param.lineWidth; /* 创建空间线实体 */ let entity = new Cesium.Entity({ name: _self._sketchEntityName, polyline: { show: true, positions: new Cesium.CallbackProperty(function() { return _self._sketchTempPoints; }, false), material: lineMaterial, width: _self._param.lineWidth, clampToGround: false, //由于是空间线禁止贴地或贴模型 } }) /* 加入集合 */ this._drawEntity = this._entities.add(entity); /* 挂接实体参数 */ this._drawEntity.setParams(entityParam); }, /** * 更新空间线 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit [是否可编辑] 可选 */ _updateSpatialPolyline: function(isEdit) { this._drawEntity.polyline.positions = this._sketchPoints; this._drawEntity.setEntityType(DrawTools.DrawType.SpatialLine); /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { /* 删除所有的临时点 忽略是否保留设置 */ this._removePointEntitys(); this._setEntityIsEdit(this._drawEntity); } }, /** * 绘制面 * @ignore 生成方法时不对外公开 * @param {DrawTools.PolygonType} polygonType 面类型 */ _createPolygon: function(polygonType) { let _self = this; /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); /* 创建面材质 */ let polygonMaterial = this._materialColorProperty({ color: _self._param.polygonColor, }) /* 创建线材质 */ let lineMaterial = this._materialColorProperty({ color: _self._param.outlineColor, }) /* 创建贴地面 */ let entityPolygon = new Cesium.Entity({ name: _self._sketchEntityName, polygon: { show: true, hierarchy: new Cesium.CallbackProperty(function() { return { positions: _self._sketchTempPoints, }; }, false), material: polygonMaterial, classificationType: Cesium.ClassificationType.BOTH, }, polyline: { show: true, positions: new Cesium.CallbackProperty(function() { return _self._sketchTempPoints; }, false), material: lineMaterial, width: _self._param.outlineWidth, clampToGround: true, //开启贴地 如果有模型则贴模型 } }) /* 设置实体参数 */ entityParam.color = _self._param.polygonColor; entityParam.outlineColor = _self._param.outlineColor; entityParam.outlineWidth = _self._param.outlineWidth; /* 渲染贴地面 */ this._drawEntity = this._entities.add(entityPolygon); if (polygonType !== undefined && polygonType === DrawTools.PolygonType.NormalPolygon) { this._drawEntity.setEntityType(DrawTools.DrawType.Polygon); entityParam.id = DrawTools.DrawType.Polygon; } else if (polygonType !== undefined && polygonType === DrawTools.PolygonType.HousePolygon) { this._drawEntity.setEntityType(DrawTools.DrawType.House); entityParam.id = DrawTools.DrawType.House; } /* 设置实体参数 */ this._drawEntity.setParams(entityParam); }, /** * 创建正式面 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit [是否可编辑] 可选 */ _updatePolygon: function(isEdit) { let _self = this; /* 创建房屋材质 */ let houseMaterial = this._materialColorProperty({ color: _self._param.houseColor, }) /* 获取实体类型 */ let entityType = this._drawEntity.getEntityType(); if (entityType === DrawTools.DrawType.Polygon) { /* 更新数据 */ this._drawEntity.polygon.hierarchy = { positions: _self._sketchPoints, }; this._drawEntity.polyline.positions = this._sketchPoints; } else if (entityType === DrawTools.DrawType.House) { /* 删除底面实体之前获取存储的属性 */ let entityParam = this._drawEntity.getParams(); /* 删除原来创建的实体 */ this._removeEntityByObject(this._drawEntity); /* 创建房屋的高度 */ let height = parseFloat(this._sketchOutputPoints[0].height); let houseHeight = height + parseInt(_self._param.wallHeight); /* 创建一个房屋实体 */ let houseEntity = new Cesium.Entity({ name: _self._sketchEntityName, polygon: { show: true, hierarchy: { positions: _self._sketchPoints, }, extrudedHeight: houseHeight, material: houseMaterial, }, }) /* 渲染实体 */ this._drawEntity = this._entities.add(houseEntity); /* 设置实体类型 */ this._drawEntity.setEntityType(entityType); entityParam.height = _self._param.wallHeight; entityParam.bottomHeight = height; entityParam.color = _self._param.houseColor; this._drawEntity.setParams(entityParam); } /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { /* 删除所有的临时点 忽略是否保留设置 */ this._removePointEntitys(); this._setEntityIsEdit(this._drawEntity); } }, /** * 创建矩形 * @ignore 生成方法时不对外公开 */ _createRectangle: function() { let _self = this; /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); /* 创建面材质 */ let rectMaterial = this._materialColorProperty({ color: _self._param.polygonColor, }); /* 创建线材质 */ let lineMaterial = this._materialColorProperty({ color: _self._param.outlineColor, }) /* 创建贴地矩形 */ let entityRectangle = new Cesium.Entity({ name: _self._sketchEntityName, polyline: { show: true, positions: new Cesium.CallbackProperty(_self ._callUpdateRectangleOutlineCoordinates(), false), material: lineMaterial, width: _self._param.outlineWidth, clampToGround: true, //开启贴地 如果有模型则贴模型 }, rectangle: { show: true, coordinates: new Cesium.CallbackProperty(_self._callUpdateRectangleCoordinates( _self ._sketchTempPoints), false), material: rectMaterial, classificationType: Cesium.ClassificationType.BOTH, }, }); /* 设置实体属性 */ entityParam.id = DrawTools.DrawType.Rectangle; entityParam.color = _self._param.polygonColor; entityParam.outlineColor = _self._param.outlineColor; entityParam.outlineWidth = _self._param.outlineWidth; /* 贴地矩形渲染 */ this._drawEntity = this._entities.add(entityRectangle); /* 挂接实体属性 */ this._drawEntity.setParams(entityParam); }, /** * 更新矩形 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit [是否可编辑] 可选 */ _updateRectangle(isEdit) { let _self = this; /* 更新贴地矩形数据 */ this._drawEntity.polyline.positions = this._rectangleOutlineCoordinates; let coordinates = this._rectangleCoordinates; this._drawEntity.rectangle.coordinates = Cesium.Rectangle.fromDegrees(coordinates[0], coordinates[ 1], coordinates[2], coordinates[3]); /* 设置实体类型 */ this._drawEntity.setEntityType(DrawTools.DrawType.Rectangle); /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { this._setEntityIsEdit(this._drawEntity); } }, /** * 创建贴地圆 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} centerPosition 圆的中心点位置 */ _createCircle: function(centerPosition, circleType) { let _self = this; /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); /* 创建颜色材质 */ let circleMaterial = this._materialColorProperty({ color: _self._param.polygonColor, }); /* 创建线材质 */ let lineMaterial = this._materialColorProperty({ color: _self._param.outlineColor, }) /* 如果是动态圆 创建动态圆材质 */ if (circleType != undefined && circleType === DrawTools.CircleType.DynamicCircle) { circleMaterial = new CircleMaterialProperty({ viewer: _self._viewer, duration: _self._param.duration, color: Cesium.Color.fromCssColorString(_self._param.polygonColor), count: _self._param.count, }); } /* 存储椭圆中心点位置 */ this._sketchEllipseCenterPosition = centerPosition.clone(); /* 创建贴地圆 */ let entityCircle = new Cesium.Entity({ name: _self._sketchEntityName, position: centerPosition, ellipse: { show: true, semiMinorAxis: new Cesium.CallbackProperty(_self._callUpdateEllipseMinorAxis( _self ._sketchTempPoints), false), semiMajorAxis: new Cesium.CallbackProperty(_self._callUpdateEllipseMinorAxis( _self ._sketchTempPoints), false), material: circleMaterial, classificationType: Cesium.ClassificationType.BOTH, }, }); if (circleType === undefined || circleType === DrawTools.CircleType.ColorCircle) { entityCircle.polyline = { show: true, positions: new Cesium.CallbackProperty(_self._callEllipseOutlineCoordinate( _self._sketchTempPoints), false), material: lineMaterial, width: _self._param.outlineWidth, clampToGround: true, //开启贴地 如果有模型则贴模型 }; } /* 渲染贴地圆 */ this._drawEntity = this._entities.add(entityCircle); /* 设置实体类型 */ if (circleType === undefined || circleType === DrawTools.CircleType.ColorCircle) { this._drawEntity.setEntityType(DrawTools.DrawType.Circle); /* 设置实体属性 */ entityParam.id = DrawTools.DrawType.Circle; entityParam.color = _self._param.polygonColor; entityParam.outlineColor = _self._param.outlineColor; entityParam.outlineWidth = _self._param.outlineWidth; } else if (circleType != undefined && circleType === DrawTools.CircleType.DynamicCircle) { this._drawEntity.setEntityType(DrawTools.DrawType.DynamicCircle); /* 设置实体属性 */ entityParam.id = DrawTools.DrawType.DynamicCircle; entityParam.color = _self._param.polygonColor; entityParam.duration = _self._param.duration; entityParam.count = _self._param.count; } /* 挂接实体属性 */ this._drawEntity.setParams(entityParam); }, /** * 更新贴地圆 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit [是否可编辑] 可选 */ _updateCircle(isEdit) { let _self = this; /* 更新贴地圆数据 */ this._drawEntity.position = this._sketchEllipseCenterPosition; let center = this._sketchTempPoints.first(); let outpoint = this._sketchTempPoints.last(); this._ellipseOutlineCoordinates = this._calculateEllipseOutlineCoordinate(center, outpoint); this._sketchEllipseRadius = this._calculateEllipseMinorAxis(center, outpoint); if (this._drawEntity.polyline != undefined) { this._drawEntity.polyline.positions = this._ellipseOutlineCoordinates; } this._drawEntity.ellipse.semiMajorAxis = this._sketchEllipseRadius; this._drawEntity.ellipse.semiMinorAxis = this._sketchEllipseRadius; /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { this._setEntityIsEdit(this._drawEntity); } }, /** * 绘制墙 * @ignore 生成方法时不对外公开 * @param {DrawTools.WallType} wallType 墙的类型 */ _createWall: function(wallType) { let _self = this; /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); /* 颜色墙材质 */ let wallMaterial = this._materialColorProperty({ color: _self._param.polygonColor, }); /* 设置实体属性 */ entityParam.color = _self._param.polygonColor; if (wallType !== undefined && wallType === DrawTools.WallType.TextWall) { wallMaterial = this._materialTextImageProperty({ color: _self._param.polygonColor, text: _self._param.text, }); /* 设置实体属性 */ entityParam.text = _self._param.text; entityParam.color = _self._param.polygonColor; } else if (wallType !== undefined && wallType === DrawTools.WallType.DynamicWall) { /* 动态墙材质 */ wallMaterial = new WallMaterialProperty({ viewer: _self._viewer, trailImage: _self._image_v_t_b, duration: _self._param.duration, color: Cesium.Color.fromCssColorString(_self._param.polygonColor), param: { count: _self._param.count, direction: _self._param.direction_v, order: _self._param.order_minus } }); /* 设置实体属性 */ entityParam.color = _self._param.polygonColor; entityParam.duration = _self._param.duration; entityParam.direction = _self._param.direction_v; entityParam.count = _self._param.count; entityParam.order = _self._param.order_minus; } /* 创建墙 */ let normalWall = new Cesium.Entity({ name: _self._sketchEntityName, wall: { show: true, positions: new Cesium.CallbackProperty(function() { return _self._sketchTempPoints; }, false), minimumHeights: new Cesium.CallbackProperty(function() { return _self._sketchWallHeights; }, false), maximumHeights: new Cesium.CallbackProperty(function() { _self._sketchWallMaxHeights = []; for (let i = 0; i < _self._sketchWallHeights.length; i++) { _self._sketchWallMaxHeights.push(_self._sketchWallHeights[i] + _self ._param.wallHeight); } return _self._sketchWallMaxHeights; }, false), material: wallMaterial, } }); /* 渲染墙 */ this._drawEntity = this._entities.add(normalWall); /* 设置实体通用属性 */ entityParam.height = this._param.wallHeight; /* 设置实体类型 */ if (wallType === undefined || wallType === DrawTools.WallType.ColorWall) { this._drawEntity.setEntityType(DrawTools.DrawType.NormalWall); /* 设置实体属性 */ entityParam.id = DrawTools.DrawType.NormalWall; } else if (wallType !== undefined && wallType === DrawTools.WallType.DynamicWall) { this._drawEntity.setEntityType(DrawTools.DrawType.DynamicWall); /* 设置实体属性 */ entityParam.id = DrawTools.DrawType.DynamicWall; } else if (wallType !== undefined && wallType === DrawTools.WallType.TextWall) { this._drawEntity.setEntityType(DrawTools.DrawType.TextWall); /* 设置实体属性 */ entityParam.id = DrawTools.DrawType.TextWall; } /* 挂接实体属性 */ this._drawEntity.setParams(entityParam); }, /** * 更新墙 * @ignore 生成方法时不对外公开 * @param {Boolean} isEdit [是否可编辑]可选 */ _updateWall: function(isEdit) { /* 获取三个数组的长度 */ let hLength = this._sketchWallHeights.length; let mhLength = this._sketchWallMaxHeights.length; let pLength = this._sketchPoints.length; if (hLength === mhLength && hLength - pLength === 1) { /* 移除最后一个高度点 */ this._sketchWallHeights.pop(); this._sketchWallMaxHeights.pop(); /* 设置并停止墙的动态属性 */ this._drawEntity.wall.positions = this._sketchPoints; this._drawEntity.wall.minimumHeights = this._sketchWallHeights; this._drawEntity.wall.maximumHeights = this._sketchWallMaxHeights; /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { /* 删除所有的临时点 忽略是否保留设置 */ this._removePointEntitys(); this._setEntityIsEdit(this._drawEntity); } } else { this._console(hLength, mhLength, pLength); } }, /** * 创建视频墙 * @ignore 生成方法时不对外公开 */ _createVideoWall: function() { let _self = this; /* 绘制面 干掉事件 */ let entityWall = new Cesium.Entity({ name: _self._sketchEntityName, position: _self._sketchOutputPoints[0], wall: { show: true, positions: new Cesium.CallbackProperty(function() { let pt0 = _self._sketchOutputPoints[0]; let pt1 = _self._sketchOutputPoints[1]; /* 视频墙的位置集合 */ _self._wallPositions = []; _self._wallPositions.push(Cesium.Cartesian3.fromDegrees(pt0.lng, pt0 .lat, pt0.height)); _self._wallPositions.push(Cesium.Cartesian3.fromDegrees(pt1.lng, pt1 .lat, pt0.height)); return _self._wallPositions; }, false), maximumHeights: new Cesium.CallbackProperty(function() { _self._sketchWallHeights = []; let pt = _self._sketchOutputPoints[0]; _self._sketchWallHeights.push(pt.height); _self._sketchWallHeights.push(pt.height); return _self._sketchWallHeights; }, false), minimumHeights: new Cesium.CallbackProperty(function() { _self._sketchWallMaxHeights = []; let pt = _self._sketchOutputPoints[1]; _self._sketchWallMaxHeights.push(pt.height); _self._sketchWallMaxHeights.push(pt.height); return _self._sketchWallMaxHeights; }, false), material: Cesium.Color.fromCssColorString(_self._param.polygonColor), outline: true, outlineColor: Cesium.Color.fromCssColorString(_self._param.outlineColor), outlineWidth: _self._param.outlineWidth, } }); /* 渲染视频墙 */ _self._drawEntity = _self._entities.add(entityWall); }, /** * 更新视频墙 * @ignore 生成方法时不对外公开 */ _updateVideoWall: function(isEdit) { /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); entityParam.id = DrawTools.DrawType.VideoWall; /* 查找视频画布 */ let videoElement = document.getElementById('wallVideo'); if (videoElement !== null) { document.body.removeChild(videoElement); } videoElement = document.createElement("video"); videoElement.id = 'wallVideo'; videoElement.setAttribute('crossorigin', 'anonymous'); //必须设置 为了防止跨域调用网络视频导致播放失败 videoElement.setAttribute("width", "1024px"); videoElement.setAttribute("height", "256px"); videoElement.setAttribute("controls", "controls"); videoElement.setAttribute("src", "https://lf3-cdn-tos.bytescm.com/obj/eden-cn/lmeh7pfuho/campus/campus_intro_20200522.mp4"); videoElement.setAttribute("loop", "loop"); videoElement.play(); document.body.appendChild(videoElement); /* 更新数据 */ this._drawEntity.wall.positions = this._wallPositions; this._drawEntity.wall.minimumHeights = this._sketchWallHeights; this._drawEntity.wall.maximumHeights = this._sketchWallMaxHeights; /* 设置高度参数 */ entityParam.height = this._sketchWallMaxHeights[0] - this._sketchWallHeights[0]; this._drawEntity.wall.material = videoElement; /* 删除点 */ this._removePointEntitys(); /* 设置实体类型 */ this._drawEntity.setEntityType(DrawTools.DrawType.VideoWall); entityParam.videoUrl = 'https://lf3-cdn-tos.bytescm.com/obj/eden-cn/lmeh7pfuho/campus/campus_intro_20200522.mp4'; entityParam.id = DrawTools.DrawType.VideoWall; /* 挂接实体属性 */ this._drawEntity.setParams(entityParam); /* 设置是否可编辑 */ if (isEdit != undefined && isEdit === true) { this._setEntityIsEdit(this._drawEntity); } }, /** * 计算OD线的中间点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} strPoint 起始点 * @param {Cesium.Cartesian3} endPoint 终止点 * @param {Number} height 最大高度 * @param {Number} count 内插点数 */ _calculateOdlinePositios: function(strPoint, endPoint, height, count) { let pt1 = this._cartesian3ToGeo(strPoint); let pt2 = this._cartesian3ToGeo(endPoint); //方程 y=-(4h/L^2)*x^2+h h:顶点高度 L:横纵间距较大者 var h = height && height < 1000 ? height : 1000; var L = Math.abs(pt1.longitude - pt2.longitude) > Math.abs(pt1.latitude - pt2.latitude) ? Math.abs(pt1.longitude - pt2.longitude) : Math.abs(pt1.latitude - pt2.latitude); var num = count && count > 50 ? count : 50; var result = []; var tempResult = []; //临时数组 var dlt = L / num; var addHeight = pt1.height > pt2.height ? pt1.height : pt2.height; var maxHeight = addHeight + h; var minHeight1 = pt1.height; var minHeight2 = pt2.height; if (Math.abs(pt1.longitude - pt2.longitude) > Math.abs(pt1.latitude - pt2 .latitude)) { //以lon为基准 var delLat = (pt2.latitude - pt1.latitude) / num; if (pt1.longitude - pt2.longitude > 0) { dlt = -dlt; } for (var i = 1; i < num; i++) { var tempH = h - Math.pow((-0.5 * L + Math.abs(dlt) * i), 2) * 4 * h / Math.pow(L, 2); var lon = pt1.longitude + dlt * i; var lat = pt1.latitude + delLat * i; var alt = undefined; if (Math.abs(dlt) * i == 0.5 * L) { alt = maxHeight; } else if (Math.abs(dlt) * i < 0.5 * L) { //说明是抛物线左侧 alt = ((maxHeight - minHeight1) / h) * tempH + minHeight1; } else { //说明是抛物线右侧 alt = ((maxHeight - minHeight2) / h) * tempH + minHeight2; } tempResult.push([lon, lat, alt]); } } else { //以lat为基准 var delLon = (pt2.longitude - pt1.longitude) / num; if (pt1.latitude - pt2.latitude > 0) { dlt = -dlt; } for (var i = 1; i < num; i++) { var tempH = h - Math.pow((-0.5 * L + Math.abs(dlt) * i), 2) * 4 * h / Math.pow(L, 2); var lon = pt1.longitude + delLon * i; var lat = pt1.latitude + dlt * i; var alt = undefined; if (Math.abs(dlt) * i == 0.5 * L) { alt = maxHeight; } else if (Math.abs(dlt) * i < 0.5 * L) { //说明是抛物线左侧 alt = ((maxHeight - minHeight1) / h) * tempH + minHeight1; } else { //说明是抛物线右侧 alt = ((maxHeight - minHeight2) / h) * tempH + minHeight2; } tempResult.push([lon, lat, alt]); } } /* 对结果进行处理 */ result.push([pt1.longitude, pt1.latitude, pt1.height]); for (var i = 0; i < tempResult.length; i++) { result.push(tempResult[i]); } result.push([pt2.longitude, pt2.latitude, pt2.height]); /* 对结果进行转换 */ let results = []; for (let i = 0; i < result.length; i++) { results.push(Cesium.Cartesian3.fromDegrees(result[i][0], result[i][1], result[i][2])); } return results; }, /** * 创建OD线 * @ignore 生成方法时不对外公开 * @param {Boolean} isFirst 是否第一次 */ _createOdline: function(isFirst) { let _self = this; /* 如果初次创建 创建一个父实体*/ if (isFirst !== undefined && isFirst === true) { let fatherEntity = new Cesium.Entity({ name: this._sketchEntityName, }); this._odlineFatherEntity = this._entities.add(fatherEntity); /* 初始化一个实体参数变量 */ let entityParam = DrawTools.initEditPropertyParams(); entityParam.id = DrawTools.DrawType.OdLine; entityParam.color = _self._param.polygonColor; entityParam.duration = _self._param.duration; entityParam.direction = _self._param.direction_h; entityParam.count = _self._param.count; entityParam.order = _self._param.order_add; entityParam.odlineHeight = _self._param.odlineHeight; entityParam.odlineCount = _self._param.odlineCount; entityParam.lineWidth = _self._param.lineWidth * 3; /* 为父实体设置参数 保存该OD线集合的必要参数 */ this._odlineFatherEntity.setParams(entityParam); /* 创建一个临时集合 方便回退删除 */ this._odlineEntitys = []; } /* 从父节点获取必要参数 */ let faterParam = this._odlineFatherEntity.getParams(); /* 创建OD线材质 */ let odLineMaterial = new WallMaterialProperty({ viewer: _self._viewer, trailImage: _self._image_arrow_reverse, duration: faterParam.duration, color: Cesium.Color.fromCssColorString(faterParam.color), param: { direction: faterParam.direction, count: faterParam.count, order: faterParam.order, }, }); /* 创建OD线 */ let entity = new Cesium.Entity({ name: _self._sketchEntityName, parent: this._odlineFatherEntity, polyline: { show: true, positions: new Cesium.CallbackProperty(function() { let center = _self._sketchTempPoints[0]; let endPoint = _self._sketchTempPoints[_self._sketchTempPoints.length - 1]; let results = _self._calculateOdlinePositios(center, endPoint, parseInt( faterParam.odlineHeight), parseInt(faterParam.odlineCount)); return results; }, false), material: odLineMaterial, width: faterParam.lineWidth, clampToGround: false, //由于是空间线禁止贴地或贴模型 } }) /* 加入集合 */ this._drawEntity = this._entities.add(entity); }, /** * 更新OD线 * @ignore 生成方法时不对外公开 * @param {Boolean} isLast 是否是最后一个 * @param {Boolean} isEdit 是否为可编辑 */ _updateOdline: function(isLast, isEdit) { if (isLast !== undefined && isLast === true) { if (isEdit !== undefined && isEdit === true) { this._drawEntity.setEntityType(DrawTools.DrawType.OdLine); this._setEntityIsEdit(this._drawEntity); this._drawEntity.parent.setIsEdit(true); } } else { let params = this._drawEntity.parent.getParams(); let center = this._sketchTempPoints[0]; let endPoint = this._sketchTempPoints[this._sketchTempPoints.length - 1]; let results = this._calculateOdlinePositios(center, endPoint, parseInt(params.odlineHeight), parseInt(params.odlineCount)); this._drawEntity.polyline.positions = results; this._drawEntity.setEntityType(DrawTools.DrawType.OdLine); this._odlineEntitys.push(this._drawEntity); if (isEdit !== undefined && isEdit === true) { this._drawEntity.setIsEdit(true); } } }, /** * 生成GUID随机数 * @ignore 生成方法时不对外公开 */ _guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); }, /** * 输出消息 * @ignore 生成方法时不对外公开 * @param {Object} res */ _console(...rest) { console.log('===>>>', rest); } }) /** * 对外方法 */ Object.assign(DrawTools.prototype, { /** * 鼠标双击结束提示事件 * @ignore * @param {Cesium.Cartesian2} position 位置 */ _drawMovingDoubleTooltip(position) { this._updateTooltip('左键单击绘制,右键单击撤销
左键双击结束绘制', position); }, /** * 鼠标单击结束提示事件 * @ignore * @param {Cesium.Cartesian2} position 位置 */ _drawMovingSimpleTooltip(position) { this._updateTooltip('左键单击结束绘制', position); }, /** * 移除最后绘制的一个点元素 * @ignore */ _removeLastDrawPointEntity() { let lastPointEntity = this._pointEntitys.last(); if (lastPointEntity !== undefined) { this._removeEntityByObject(lastPointEntity); this._pointEntitys.pop(); } }, /** * 绘制点工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Function} [options.onComplete(cPoint, gPoint)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawPoint(handler, options) { let _self = this; /* 注册鼠标左键点击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ // let loc = _self._transfromFromScreenPoint(event.position); // if (!Cesium.defined(loc.sLocation)) return; let scene = _self._viewer.scene; if (scene.mode !== Cesium.SceneMode.MORPHING) { var pickedObject = scene.pick(event.position); if (scene.pickPositionSupported && Cesium.defined(pickedObject)) { var cartesian = scene.pickPosition(event.position); if (Cesium.defined(cartesian)) { var cartographic = Cesium.Cartographic.fromCartesian(cartesian); var lng = Cesium.Math.toDegrees(cartographic.longitude); var lat = Cesium.Math.toDegrees(cartographic.latitude); var height = cartographic.height; //模型高度 _self._sketchOutputPoints.push({ lng: lng, lat: lat, height: height }) } _self._createPoint(cartesian, '点'); _self._sketchPoints.push(cartesian.clone()); if (_self._sketchPoints.length >= 2) { _self._createVideoWall(); /* 干掉事件句柄 释放资源 */ _self._clearEvent(handler); } } } /* 监听输出 */ if (options.onComplete) options.onComplete(loc.sLocation, loc.gLocation); }) }, /** * 绘制多点 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Function} [options.onAdded(cPoinit,gPoint)] 添加回调 可选 * @param {Function} [options.onUndo()] 撤销回调 可选 * @param {Function} [options.onComplete(cPoints,gPoints)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回调 可选 */ _sketchDrawMultiplePoint(handler, options) { let _self = this; /* 注册鼠标左键点击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } _self._sketchPoints.push(loc.sLocation); _self._sketchOutputPoints.push(loc.gLocation); /* 监听输出 */ if (options.onAdded) options.onAdded(loc.sLocation, loc.gLocation); }) /* 注册鼠标右键事件 */ this._registerRightClickEvent(handler, function(event) { if (_self._sketchPoints.length > 0) { _self._sketchPoints.pop(); _self._sketchOutputPoints.pop(); if (options.onUndo) options.onUndo(); } }) /* 注册鼠标左键双击事件 */ this._registerLeftDoubleClickEvent(handler, function(event) { /* 干掉事件句柄 释放资源 */ _self._clearEvent(handler); /* 回调 */ if (options.onComplete) options.onComplete(_self._sketchPoints, _self._sketchOutputPoints); }) }, /** * 绘制贴地线工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} isEdit 是否可编辑 可选 默认可编辑 * @param {DrawTools.PolylineType} options.polylineType 线的类型 可选 * @param {Function} [options.onAdded(cPoints,gPoints)] 添加回调 可选 * @param {Function} [options.onMoving(cPoint)] 移动回调 可选 * @param {Function} [options.onUndo()] 撤销回调 可选 * @param {Function} [options.onComplete(cPoints,gPoints)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回调 可选 */ _sketchDrawPolyline(handler, options) { let _self = this; /* 注册鼠标左键点击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制参考点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } /* 第一点击的时候绘制线 */ if (_self._sketchTempPoints.length === 0) { _self._createPolyline(options.polylineType); _self._sketchTempPoints.push(loc.sLocation.clone()); } _self._sketchTempPoints.push(loc.sLocation); /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.sLocation.clone()); /* 存储输出经纬度点集合 */ _self._sketchOutputPoints.push(loc.gLocation); /* 监听输出 */ if (options.onAdded) options.onAdded(_self._sketchPoints, _self ._sketchOutputPoints); /* 添加操作容器 */ _self._createOperationDom(); }) /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { /* 如果运行环境是App 则禁止使用移动事件 */ if (_self._isRuntimeApp()) return; /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchTempPoints.length > 1) { /* 标签提示 */ _self._drawMovingDoubleTooltip(event.endPosition); _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(loc.sLocation); /* 监听输出 */ if (options.onMoving) options.onMoving(loc.sLocation); } }); /* 注册鼠标右键点击事件 */ this._registerRightClickEvent(handler, function(event) { if (_self._sketchTempPoints.length > 2) { _self._drawByUndo(); if (options.onUndo) options.onUndo(); } }); /* 注册鼠标左键双击事件 */ this._registerLeftDoubleClickEvent(handler, function(event) { if (_self._sketchPoints.length < 2) { if (options.onError) options.onError('点数少于两个,禁止结束绘制!'); return; } /* 更新贴地线 */ _self._updatePolyline(options.isEdit); /* 删除标记点 */ if (!_self._isRetainDrawPoint) _self._removePointEntitys(); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); /* 监听输出 */ if (options.onComplete) options.onComplete(_self._sketchPoints, _self ._sketchOutputPoints); }) }, /** * 绘制空间线工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} isEdit 是否可编辑 可选 默认可编辑 * @param {Function} [options.onAdded(cPoints,gPoints)] 添加回调 可选 * @param {Function} [options.onMoving(cPoint)] 移动回调 可选 * @param {Function} [options.onUndo()] 撤销回调 可选 * @param {Function} [options.onComplete(cPoints,gPoints)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawSpatialPolyline(handler, options) { let _self = this; /* 注册鼠标左键单击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } /* 第一点击的时候绘制线 */ if (_self._sketchTempPoints.length === 0) { _self._createSpatialPolyline(); _self._sketchTempPoints.push(loc.sLocation.clone()); } _self._sketchTempPoints.push(loc.sLocation); /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.sLocation.clone()); /* 存储输出经纬度点集合 */ _self._sketchOutputPoints.push(loc.gLocation); /* 监听输出 */ if (options.onAdded) options.onAdded(_self._sketchPoints, _self._sketchOutputPoints); /* 添加操作容器 */ _self._createOperationDom(); }) /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { /* 如果运行环境是App 则禁止使用移动事件 */ if (_self._isRuntimeApp()) return; /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchTempPoints.length > 1) { /* 标签提示 */ _self._drawMovingDoubleTooltip(event.endPosition); _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(loc.sLocation); /* 监听输出 */ if (options.onMoving) options.onMoving(loc.sLocation); } }) /* 注册鼠标左键双击事件 */ this._registerLeftDoubleClickEvent(handler, function(event) { if (_self._sketchPoints.length < 2) { if (options.onError) options.onError('绘制点少于2个,禁止结束绘制!'); return; } /* 绘制正式空间线 */ _self._updateSpatialPolyline(options.isEdit); /* 删除标记点 */ _self._removePointEntitys(); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); /* 监听输出 */ if (options.onComplete) options.onComplete(_self._sketchPoints, _self ._sketchOutputPoints); }) /* 注册鼠标右键单击事件 */ this._registerRightClickEvent(handler, function(event) { if (_self._sketchTempPoints.length > 2) { _self._drawByUndo(); if (options.onUndo) options.onUndo(); } }); }, /** * 绘制OD线工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} isEdit 是否可编辑 可选 默认可编辑 * @param {Function} [options.onAdded(cPoints,gPoints)] 添加回调 可选 * @param {Function} [options.onMoving(cPoint)] 移动回调 可选 * @param {Function} [options.onUndo()] 撤销回调 可选 * @param {Function} [options.onComplete(cPoints,gPoints)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawOdline(handler, options) { let _self = this; /* 注册鼠标左键单击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } if (_self._isRuntimeApp()) { _self._showTooltipMessage('再次单击绘制一条OD线!'); } /* 第一点击的时候绘制线 */ if (_self._sketchTempPoints.length === 0) { _self._createOdline(true); _self._sketchTempPoints.push(loc.sLocation.clone()); } else { _self._sketchTempPoints.push(loc.sLocation.clone()); _self._updateOdline(false, options.isEdit); _self._createOdline(); } _self._sketchTempPoints.push(loc.sLocation); /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.sLocation.clone()); /* 存储输出经纬度点集合 */ _self._sketchOutputPoints.push(loc.gLocation); /* 监听输出 */ if (options.onAdded) options.onAdded(_self._sketchPoints, _self._sketchOutputPoints); /* 添加操作容器 */ _self._createOperationDom(); }) /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { /* 如果运行环境是App 则禁止使用移动事件 */ if (_self._isRuntimeApp()) return; /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchTempPoints.length > 1) { /* 标签提示 */ _self._drawMovingDoubleTooltip(event.endPosition); _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(loc.sLocation); /* 监听输出 */ if (options.onMoving) options.onMoving(loc.sLocation); } }) /* 注册鼠标左键双击事件 */ this._registerLeftDoubleClickEvent(handler, function(event) { /* 绘制正式OD线 */ _self._removeEntityByObject(_self._drawEntity); _self._updateOdline(true, options.isEdit); /* 删除标记点 */ _self._removePointEntitys(); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); /* 监听输出 */ if (options.onComplete) options.onComplete(_self._sketchPoints, _self ._sketchOutputPoints); }) /* 注册鼠标右键单击事件 */ this._registerRightClickEvent(handler, function(event) { if (_self._odlineEntitys.length > 0) { /* 删除最后一个绘制点 */ if (_self._isDrawPoint) { _self._removeLastDrawPointEntity(); } _self._removeEntityByObject(_self._odlineEntitys.last()); _self._odlineEntitys.pop(); if (options.onUndo) options.onUndo(); } }); }, /** * 绘制贴地面工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} isEdit 是否可编辑 可选 默认可编辑 * @param {DrawTools.PolygonType} options.polygonType 绘制面类型 可选 * @param {Function} [options.onAdded(cPoints,gPoints)] 添加回调 可选 * @param {Function} [options.onMoving(cPoint)] 移动回调 可选 * @param {Function} [options.onUndo()] 撤销回调 可选 * @param {Function} [options.onComplete(cPoints,gPoints)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawPolygon(handler, options) { let _self = this; /* 注册鼠标左键点击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } /* 当点数为0时绘制线和面 */ if (_self._sketchTempPoints.length === 0) { _self._createPolygon(options.polygonType); _self._sketchTempPoints.push(loc.sLocation.clone()); } _self._sketchTempPoints.push(loc.sLocation); /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.sLocation.clone()); /* 存储输出经纬度点集合 */ _self._sketchOutputPoints.push(loc.gLocation); /* 监听输出 */ if (options.onAdded) options.onAdded(_self._sketchPoints, _self._sketchOutputPoints); /* 添加操作容器 */ _self._createOperationDom(); }); /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { /* 如果运行环境是App 则禁止使用移动事件 */ if (_self._isRuntimeApp()) return; /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchTempPoints.length > 1) { /* 标签提示 */ _self._drawMovingDoubleTooltip(event.endPosition); _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(loc.sLocation); /* 监听输出 */ if (options.onMoving) options.onMoving(loc.sLocation); } }); /* 注册鼠标右键单击事件 */ this._registerRightClickEvent(handler, function(event) { if (_self._sketchTempPoints.length > 2) { _self._drawByUndo(); if (options.onUndo) options.onUndo(); } }); /* 注册鼠标左键双击事件 */ this._registerLeftDoubleClickEvent(handler, function(event) { if (_self._sketchPoints.length < 3) { if (options.onError) options.onError('点数少于3个,禁止结束绘制!'); return; } /* 更新贴地面 */ _self._updatePolygon(options.isEdit); /* 删除标记点 */ if (!_self._isRetainDrawPoint) _self._removePointEntitys(); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); /* 监听输出 */ if (options.onComplete) options.onComplete(_self._sketchPoints, _self ._sketchOutputPoints); }) }, /** * 绘制贴地圆工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} isEdit 是否可编辑 可选 默认可编辑 * @param {DrawTools.CircleType} options.circleType 绘制圆的类型 可选 * @param {Function} [options.onAdded(center)] 添加回调 可选 * @param {Function} [options.onComplete(center,radius)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawCircle: function(handler, options) { let _self = this; /* 注册鼠标左键单击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchTempPoints.length === 0) { /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, '起点'); } /* 添加数据 */ _self._sketchTempPoints.push(loc.sLocation.clone()); _self._sketchTempPoints.push(loc.sLocation); //凑数的 /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.sLocation.clone()); /* 存储经纬度 */ _self._sketchOutputPoints.push(loc.gLocation); /* 创建圆 */ _self._createCircle(loc.sLocation, options.circleType); /* App提示信息 */ if (_self._isRuntimeApp()) { _self._showTooltipMessage('再次单击结束绘制!'); } /* 监听输出 */ if (options.onAdded) options.onAdded(loc.sLocation); } else { _self._sketchTempPoints.push(loc.sLocation.clone()); /* 删除标记点 */ _self._removePointEntitys(); /* 更新圆 */ _self._updateCircle(options.isEdit); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); /* 回调返回 */ if (options.onComplete) options.onComplete(_self._sketchOutputPoints[0], _self ._sketchEllipseRadius); } }); /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { if (_self._isRuntimeApp()) { return; } /* 如果还未创建圆 则直接返回 */ if (_self._sketchTempPoints.length <= 0) return; /* 标签提示 */ _self._drawMovingSimpleTooltip(event.endPosition); /* 获取空间位置 */ var cartesian = _self._viewer.scene.pickPosition(event.endPosition); /* 如果获取点失败 则直接返回 */ if (cartesian == undefined) return; _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(cartesian); }) }, /** * 绘制贴地矩形工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} isEdit 是否可编辑 可选 默认可编辑 * @param {Function} [options.onAdded(cPoint)] 添加回调 可选 * @param {Function} [options.onComplete(points)] 完成回调 可选 */ _sketchDrawRectangle: function(handler, options) { let _self = this; /* 注册鼠标左键单击事件 */ this._registerLeftClickEvent(handler, function(event) { if (_self._sketchTempPoints.length === 0) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, '起点'); } /* 添加数据 */ _self._sketchTempPoints.push(loc.sLocation); _self._sketchTempPoints.push(loc.sLocation); //凑数的 /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.gLocation); /* 创建矩形 */ _self._createRectangle(); /* 回调 */ if (options.onAdded) options.onAdded(loc.sLocation); /* App提示信息 */ if (_self._isRuntimeApp()) { _self._showTooltipMessage('再次单击结束绘制!'); } } else { /* 删除标记点 */ _self._removePointEntitys(); /* 删除临时矩形 */ _self._removeEntityByObject(_self._sketchTempRectangle); /* 创建正式矩形 */ _self._updateRectangle(options.isEdit); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); /* 回调返回 */ if (options.onComplete) options.onComplete(_self._sketchOutputPoints); } }); /* 挂接鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { /* 如果还未创矩形 则直接返回 */ if (_self._sketchTempPoints.length < 1) return; /* 标签提示 */ _self._drawMovingSimpleTooltip(event.endPosition); /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(loc.sLocation); }); }, /** * 绘制墙 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} options.isEdit [是否可编辑 可选] * @param {DrawTools.WallType} options.wallType [绘制墙的类型 可选] * @param {Function} [options.onMoving(cPoint)] 移动回调 可选 * @param {Function} [options.onComplete(positions)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawWall: function(handler, options) { let _self = this; /* 注册鼠标左键点击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } /* 第一点击的时候绘制线 */ if (_self._sketchTempPoints.length === 0) { _self._createWall(options.wallType); _self._sketchTempPoints.push(loc.sLocation.clone()); /* 存储墙的高度点集合 */ _self._sketchWallHeights.push(loc.gLocation.height); } _self._sketchTempPoints.push(loc.sLocation); _self._sketchWallHeights.push(loc.gLocation.height); /* 存储正式绘制点集合 */ _self._sketchPoints.push(loc.sLocation.clone()); /* 添加操作容器 */ _self._createOperationDom(); }) /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { if (_self._isRuntimeApp()) { return; } /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchTempPoints.length > 1) { /* 标签提示 */ _self._drawMovingDoubleTooltip(event.endPosition); _self._sketchTempPoints.pop(); _self._sketchTempPoints.push(loc.sLocation); _self._sketchWallHeights.pop(); _self._sketchWallHeights.push(loc.gLocation.height); } }); /* 注册鼠标右键点击事件 */ this._registerRightClickEvent(handler, function(event) { if (_self._sketchTempPoints.length > 2) { /* 移除正式点最有一个元素 */ _self._sketchPoints.pop(); if (_self._isRuntimeApp()) { /* 移除临时点倒数第二个元素 */ _self._sketchTempPoints.splice(_self._sketchTempPoints.length - 1, 1); /* 移除临时高度点倒数第二个元素 */ _self._sketchWallHeights.splice(_self._sketchWallHeights.length - 1, 1); } else { /* 移除临时点倒数第二个元素 */ _self._sketchTempPoints.splice(_self._sketchTempPoints.length - 2, 1); /* 移除临时高度点倒数第二个元素 */ _self._sketchWallHeights.splice(_self._sketchWallHeights.length - 2, 1); } /* 如果绘制了点 则删除最后一个 */ if (_self._isDrawPoint) { _self._removeLastDrawPointEntity(); } } }); /* 注册鼠标左键双击事件 */ this._registerLeftDoubleClickEvent(handler, function(event) { if (_self._sketchPoints.length < 2) { if (options.onError) options.onError('点数少于两个,禁止结束绘制!'); return; } /* 更新墙属性 */ _self._updateWall(options.isEdit); /* 删除标记点 */ if (!_self._isRetainDrawPoint) _self._removePointEntitys(); /* 干掉事件句柄 释放资源*/ _self._clearEvent(handler); }) }, /** * 绘制视频墙工具 * @ignore 生成方法时不对外公开 * @param {Object} handler 事件句柄 * @param {JSON} options 配置项 * @param {Boolean} options.isEdit [是否可编辑 可选] * @param {Function} [options.onMoving(cPoint)] 移动回调 可选 * @param {Function} [options.onComplete(positions)] 完成回调 可选 * @param {Function} [options.onError(message)] 错误回到 可选 */ _sketchDrawVideoWall: function(handler, options) { let _self = this; /* 注册鼠标左键点击事件 */ this._registerLeftClickEvent(handler, function(event) { /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.position); if (!Cesium.defined(loc.sLocation)) return; /* 绘制点 */ if (_self._isDrawPoint) { _self._createPoint(loc.sLocation, _self._lineLabel); } /* 第一点击的时候绘制 */ if (_self._sketchOutputPoints.length === 0) { _self._sketchOutputPoints.push(loc.gLocation); _self._sketchOutputPoints.push(loc.gLocation); _self._createVideoWall(); if (_self._isRuntimeApp()) { _self._showTooltipMessage('再次单击结束绘制'); } } else { _self._updateVideoWall(options.isEdit); _self._clearEvent(handler); } // _self._removeCoorinateAxis(); // _self._createCoordinateAxis(loc.sLocation); // _self._clearEvent(handler); }) /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(handler, function(event) { if (_self._isRuntimeApp()) return; /* 识别屏幕位置 */ let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; if (_self._sketchOutputPoints.length > 1) { /* 标签提示 */ _self._drawMovingSimpleTooltip(event.endPosition); _self._sketchOutputPoints.pop(); _self._sketchOutputPoints.push(loc.gLocation); } }); }, /** * 撤销上一步的绘制 */ _drawByUndo: function() { /* 移除正式点最有一个元素 */ this._sketchPoints.pop(); if (this._isRuntimeApp()) { /* 移除临时点倒数第一个元素 */ this._sketchTempPoints.splice(this._sketchTempPoints.length - 1, 1); } else { /* 移除临时点倒数第二个元素 */ this._sketchTempPoints.splice(this._sketchTempPoints.length - 2, 1); } /* 如果绘制了点 则删除最后一个 */ if (this._isDrawPoint) { this._removeLastDrawPointEntity(); } }, /** * 启用绘制 * @param {DrawTools.DrawType} type 绘制类型 * @param {JSON} options 回调集合 * @param {Boolean} [isEdit] 是否可编辑 可选 默认不可编辑 * @param {Function} [options.onAdded] 添加回调 可选 子方法自定义 * @param {Function} [options.onMoving] 移动回调 可选 子方法自定义 * @param {Function} [options.onUndo] 撤销回调 可选 子方法自定义 * @param {Function} [options.onComplete] 完成回调 可选 子方法自定义 * @param {Function} [options.onError] 错误回调 可选 子方法自定义 */ draw: function(type, options) { /* 定义自身 */ let _self = this; /* 初始化 */ this._clear(); /* 注册事件 */ this._drawEventHandler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); if (this._isRuntimeApp()) { this._showTooltipMessage("单击绘制"); } else { this._beginTooltip('左键单击绘制', undefined); } this._drawType = type; /* 分类型注册事件 */ switch (type) { case DrawTools.DrawType.Point: //绘制点 _self._sketchDrawPoint(_self._drawEventHandler, options); break; case DrawTools.DrawType.Polyline: //绘制贴地线 options.polylineType = DrawTools.PolylineType.NormalPolyline; _self._sketchDrawPolyline(_self._drawEventHandler, options); break; case DrawTools.DrawType.ArrowPolyline: //绘制箭头线 options.polylineType = DrawTools.PolylineType.ArrowsPolyline; _self._sketchDrawPolyline(_self._drawEventHandler, options); break; case DrawTools.DrawType.DynamicPolyline: //绘制流动线 options.polylineType = DrawTools.PolylineType.DynamicPolyline; _self._sketchDrawPolyline(_self._drawEventHandler, options); break; case DrawTools.DrawType.GrowPolyline: //绘制发光线 options.polylineType = DrawTools.PolylineType.GrowPolyline; _self._sketchDrawPolyline(_self._drawEventHandler, options); break; case DrawTools.DrawType.OutlinePolyline: //绘制描边线 options.polylineType = DrawTools.PolylineType.OutlinePolyline; _self._sketchDrawPolyline(_self._drawEventHandler, options); break; case DrawTools.DrawType.Polygon: //绘制贴地面 options.polygonType = DrawTools.PolygonType.NormalPolygon; _self._sketchDrawPolygon(_self._drawEventHandler, options); break; case DrawTools.DrawType.SpatialLine: //绘制空���线 _self._sketchDrawSpatialPolyline(_self._drawEventHandler, options); break; case DrawTools.DrawType.Circle: //绘�����贴�����圆 options.circleType = DrawTools.CircleType.ColorCircle; _self._sketchDrawCircle(_self._drawEventHandler, options); break; case DrawTools.DrawType.Rectangle: //绘制矩形 _self._sketchDrawRectangle(_self._drawEventHandler, options); break; case DrawTools.DrawType.NormalWall: //������普通墙 options.wallType = DrawTools.WallType.ColorWall; _self._sketchDrawWall(_self._drawEventHandler, options); break; case DrawTools.DrawType.DynamicWall: //绘制动态墙 options.wallType = DrawTools.WallType.DynamicWall; _self._sketchDrawWall(_self._drawEventHandler, options); break; case DrawTools.DrawType.TextWall: //绘制文字墙 options.wallType = DrawTools.WallType.TextWall; _self._sketchDrawWall(_self._drawEventHandler, options); break; case DrawTools.DrawType.DynamicCircle: //���制扩散圆 options.circleType = DrawTools.CircleType.DynamicCircle; _self._sketchDrawCircle(_self._drawEventHandler, options); break; case DrawTools.DrawType.House: //绘制房屋 options.polygonType = DrawTools.PolygonType.HousePolygon; _self._sketchDrawPolygon(_self._drawEventHandler, options); break; case DrawTools.DrawType.VideoWall: _self._sketchDrawVideoWall(_self._drawEventHandler, options); break; case DrawTools.DrawType.OdLine: _self._sketchDrawOdline(_self._drawEventHandler, options); break; } }, /** * 清理资源 */ Clear: function() { /* 清理全部绘制内容 */ this._clear(true); /* 结束编辑状态 */ this._unActivateEdit(); /* 关闭属性编辑框 */ this._closePropertyEditDialog(); /* 移除操作容器 */ this._removeOperationDom(); }, /** * 初始化 */ sketchInit: function() { this._clear(false); }, /** * 检测程序运行环境 * @ignore * @return {DrawTools.RuntimeEnvironment} */ _checkAppOrWeb() { if (window.navigator.userAgent.match( /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i )) { return DrawTools.RuntimeEnvironment.App; } else { return DrawTools.RuntimeEnvironment.Web; } }, /** * 是否是运行于App * @ignore */ _isRuntimeApp() { if (this._checkAppOrWeb() === DrawTools.RuntimeEnvironment.App) { return true; } return false; } }) /** * 鼠标跟随标签相关 */ Object.assign(DrawTools.prototype, { /** * 提示标签初始化 * @ignore 生成方法时不对外公开 * @param {String} text 显示的文本内容 * @param {JSON} mousePosition 鼠标位置 */ _tooltipInit: function(text, mousePosition) { let _self = this; this._tooltipId = 'tooltipSketchmodel'; let tooltipObj = document.getElementById(this._tooltipId); if (tooltipObj === null) { tooltipObj = document.createElement('div'); tooltipObj.id = this._tooltipId; document.body.appendChild(tooltipObj); let divStyle = ''; divStyle += "top: 30px;"; divStyle += "left: 30px;"; divStyle += "position: absolute;"; divStyle += "display: flex;"; divStyle += "align-items: center;"; divStyle += "width: 12x0px;"; divStyle += "height: auto;"; divStyle += "background-color: rgba(0, 0, 0, 0.65);"; divStyle += "border-radius: 5px;"; divStyle += "color: rgb(255, 255, 255);"; divStyle += "font-size: 12px;"; divStyle += "font-family: 'Alimama_ShuHeiTi_Bold';"; divStyle += "padding: 8px;"; divStyle += "border:solid 1px rgb(255,0,0);"; tooltipObj.setAttribute('style', divStyle); } if (text != undefined) tooltipObj.innerHTML = text; if (mousePosition === undefined) { /* 挂接鼠标移动事件 */ document.onmousemove = function(event) { if (event.clientX < 100 || event.clientX > _self._canvasWidth - 100 || event.clientY < 100 || event.clientY > _self._canvasHeight - 100) { tooltipObj.style.display = 'none'; } else { tooltipObj.style.display = 'flex'; tooltipObj.style.left = (event.clientX + 10) + 'px'; tooltipObj.style.top = (event.clientY - tooltipObj.offsetHeight / 2) + 'px'; } } } else { if (mousePosition.x < 100 || mousePosition.x > _self._canvasWidth - 100 || mousePosition.y < 100 || mousePosition.y > _self._canvasHeight - 100) { tooltipObj.style.display = 'none'; } else { tooltipObj.style.display = 'flex'; tooltipObj.style.left = (mousePosition.x + 10) + 'px'; tooltipObj.style.top = (mousePosition.y - tooltipObj.offsetHeight / 2) + 'px'; } } }, /** * 移除提示标签 * @ignore 生成方法时不对外公开 */ _tooltipRemove: function() { let tooltipObj = document.getElementById(this._tooltipId); if (tooltipObj != null) { document.body.removeChild(tooltipObj); } }, /** * 设置提示标签文本 * @ignore 生成方法时不对外公开 * @param {String} text 文本 * @param {JSON} mousePosition 鼠标位置 */ _tooltipSetText: function(text, mousePosition) { let tooltipObj = document.getElementById(this._tooltipId); if (tooltipObj != null) { if (text != undefined) tooltipObj.innerHTML = text; if (mousePosition != undefined) { if (mousePosition.x < 100 || mousePosition.x > this._canvasWidth - 100 || mousePosition.y < 100 || mousePosition.y > this._canvasHeight - 100) { tooltipObj.style.display = 'none'; } else { tooltipObj.style.display = 'flex'; tooltipObj.style.left = (mousePosition.x + 10) + 'px'; tooltipObj.style.top = (mousePosition.y - tooltipObj.offsetHeight / 2) + 'px'; } } } }, /** * 设置鼠标为十字样式 * @ignore 生成方法时不对外公开 */ _setMousePointerStyle: function() { document.querySelector('body').style.cursor = 'crosshair'; }, /** * 恢复鼠标指针为默认样式 * @ignore 生成方法时不对外公开 */ _setMouseDefaultStyle: function() { document.querySelector('body').style.cursor = 'default'; }, /** * 启用标签 * @ignore 不公开 * @param {String} text 标签文字 * @param {Cesium.Cartesian2} position 鼠标位置 */ _beginTooltip(text, position) { this._tooltipInit(text, position); this._setMousePointerStyle(); }, /** * 更新标签标签 * @ignore 不公开 * @param {String} text 标签文字 * @param {Cesium.Cartesian2} position 鼠标位置 */ _updateTooltip(text, position) { this._tooltipSetText(text, position); }, /** * 结束标签 * @ignore 不公开 */ _endTooltip() { this._tooltipRemove(); this._setMouseDefaultStyle(); }, /** * 创建顶部弹出提示消息 1秒后自动消失 * @param {String} message 消息内容 */ _showTooltipMessage: function(message) { let msgMainDom = document.getElementById('messageMainDom'); if (msgMainDom !== null && msgMainDom !== undefined) { document.body.removeChild(msgMainDom); } msgMainDom = document.createElement('div'); msgMainDom.style.width = '30%'; msgMainDom.style.backgroundColor = 'rgba(237, 248, 230, 1.0)'; msgMainDom.style.height = '45px'; msgMainDom.style.border = 'solid 2px rgb(219, 241, 208)'; msgMainDom.style.borderRadius = '8px'; msgMainDom.style.display = 'flex'; msgMainDom.style.alignItems = 'center'; msgMainDom.style.paddingLeft = '10px'; msgMainDom.style.color = 'rgb(91, 188, 48)'; msgMainDom.style.fontSize = '14px'; msgMainDom.style.fontWeight = '600'; msgMainDom.style.position = 'absolute'; msgMainDom.style.left = '35%'; msgMainDom.style.transition = 'transform 1s'; msgMainDom.style.transform = 'translateY(-90px)'; msgMainDom.style.top = '0px'; msgMainDom.style.zIndex = 1000; document.body.appendChild(msgMainDom); let strHtml = ''; strHtml += "
"; strHtml += "
" + message + "
"; msgMainDom.innerHTML = strHtml; msgMainDom.addEventListener('transitionend', function() { setTimeout(function() { document.body.removeChild(msgMainDom); }, 1000); }, false); setTimeout(function() { msgMainDom.style.transform = 'translateY(50px)'; }, 100) } }) /** * 拖拽坐标轴相关 */ Object.assign(DrawTools.prototype, { /** * 创建单个坐标轴 * @ignore 生成方法时不对外公开 * @param {Array} positions 坐标集合 * @param {String} color 坐标轴颜色 rgba(r,g,b,a) * @param {String} axisEntityId 坐标轴实体的Id */ _createSingleCoordinateAxisArrow(positions, color, axisEntityId) { let _self = this; /* 创建坐标轴 */ let coordinateAxisEntity = new Cesium.Entity({ id: axisEntityId, name: _self._coordinateAxisEntityName, position: positions[0], polyline: { positions: positions, width: 10.0, material: _self._materialPolylineArrowProperty({ color: color, }) } }) /* 设置类型 */ coordinateAxisEntity.setEditType({ type: DrawTools.EditPointType.CoordinateAxis, }); /* 渲染坐标轴 */ return this._entities.add(coordinateAxisEntity); }, /** * 平移目标点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} originPosition 参考点 * @param {Cesium.Cartesian3} translateCartesian 平移距离 * @return {Cesium.Cartesian3} */ _getTranslatePostion: function(originPosition, translateCartesian) { let transform = Cesium.Transforms.eastNorthUpToFixedFrame(originPosition); //东-北-上参考系构造出4*4的矩阵 let m = new Cesium.Matrix4(); Cesium.Matrix4.setTranslation( Cesium.Matrix4.IDENTITY, translateCartesian, m ); //构造平移矩阵 let modelMatrix = Cesium.Matrix4.multiply(transform, m, transform); //将当前位置矩阵乘以平移矩阵得到平移之后的位置矩阵 let outPosition = new Cesium.Cartesian3(0, 0, 0); Cesium.Matrix4.getTranslation(modelMatrix, outPosition); //从位置矩阵中取出坐标信息 return outPosition; }, /** * 创建3个坐标轴 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position 坐标轴中心点位置 */ _createCoordinateAxis: function(position) { this._showTooltipMessage('单击右键移除调整轴线!'); /* 创建坐标轴之前先移除已创建的坐标轴 */ this._removeCoorinateAxis(); let _self = this; /* 获取相机在世界坐标系中的正确方向 */ let cameraRight = this._viewer.scene.camera.rightWC; this._tx = cameraRight.x > 0 ? 150 : -150; this._ty = cameraRight.y > 0 ? 150 : -150; this._tz = 150; /* 坐标轴的Id */ this._coordinateAxisEntityId_x = 'coordinateAxisId_x'; this._coordinateAxisEntityId_y = 'coordinateAxisId_y'; this._coordinateAxisEntityId_z = 'coordinateAxisId_z'; /* 坐标轴的名称 */ this._coordinateAxisEntityName = "coordinateAxisEntity"; /* 创建X轴 */ let translateCartesian = new Cesium.Cartesian3(this._tx, 0, 0); //单位为米 let endPosition = this._getTranslatePostion(position, translateCartesian); const xPos = [position, endPosition]; this._coordinateEntity_x = this._createSingleCoordinateAxisArrow(xPos, 'rgba(0,255,0,1.0)', this ._coordinateAxisEntityId_x); /* 给坐标轴绑定编辑实体 */ this._coordinateAxisBindEntity(this._coordinateEntity_x); /* 创建Y轴 */ translateCartesian = new Cesium.Cartesian3(0, this._ty, 0); //单位为 endPosition = this._getTranslatePostion(position, translateCartesian); const yPos = [position, endPosition]; this._coordinateEntity_y = this._createSingleCoordinateAxisArrow(yPos, 'rgba(0,0,255,1.0)', this ._coordinateAxisEntityId_y); /* 给坐标轴绑定编辑实体 */ this._coordinateAxisBindEntity(this._coordinateEntity_y); /* 创建Z轴 */ translateCartesian = new Cesium.Cartesian3(0, 0, this._tz); //单位为 endPosition = this._getTranslatePostion(position, translateCartesian); const zPos = [position, endPosition]; this._coordinateEntity_z = this._createSingleCoordinateAxisArrow(zPos, 'rgba(255,0,0,1.0)', this ._coordinateAxisEntityId_z); /* 给坐标轴绑定编辑实体 */ this._coordinateAxisBindEntity(this._coordinateEntity_z); /* 注册坐标轴事件 */ this._eventCoorinateAxis = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); this._registerLeftDownEvent(this._eventCoorinateAxis, function(event) { _self._coorinateAxisMouseDown(event); }); this._registerMouseMoveEvent(this._eventCoorinateAxis, function(event) { _self._coorinateAxisMouseMove(event); }); this._registerLeftUpEvent(this._eventCoorinateAxis, function(event) { _self._coorinateAxisMouseUp(event); }); this._registerRightClickEvent(this._eventCoorinateAxis, function(event) { _self._removeCoorinateAxis(); }); }, /** * 给坐标轴绑定编辑的实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} axisEntity 轴实体 */ _coordinateAxisBindEntity: function(axisEntity) { if (this._editEntity === undefined) return; /* 获取当前编辑的实体类型 */ let editEntityType = this._editEntity.getEntityType(); if (editEntityType === undefined) return; if (editEntityType === DrawTools.DrawType.VideoWall) { axisEntity.bindEntity(this._editEntity); } }, /** * 坐标轴鼠标按下事件 * @ignore 生成方法时不对外公开 * @param {Cesium.Event} event 事件 */ _coorinateAxisMouseDown: function(event) { let _self = this; let feature = this._viewer.scene.pick(event.position); if (feature === undefined) return; if (feature.id != undefined && feature.id instanceof Cesium.Entity) { this._viewer.scene.screenSpaceCameraController.enableRotate = false; if (feature.id.getEditType() === undefined) return; let entityType = feature.id.getEditType().type; if (entityType !== DrawTools.EditPointType.CoordinateAxis) return; this._editCoorinateAxis = feature.id; this._editCoorinateAxis.polyline.width = 15; /* 设置坐标移动起始点 */ this._coordinateAxisMoveStartPosition = this._viewer.scene.camera.pickEllipsoid(event.position, this._viewer.scene.globe.ellipsoid); this._coordinateAxisMoveStartScreen = event.position; this._coorinateAxisPosition = this._editCoorinateAxis.position._value; /* 设置动态 */ this._coordinateEntity_x.polyline.positions = new Cesium.CallbackProperty(function() { let translateCartesian = new Cesium.Cartesian3(_self._tx, 0, 0); //单位为米 let endPosition = _self._getTranslatePostion(_self._coorinateAxisPosition, translateCartesian); return [_self._coorinateAxisPosition, endPosition]; }, false); this._coordinateEntity_y.polyline.positions = new Cesium.CallbackProperty(function() { let translateCartesian = new Cesium.Cartesian3(0, _self._ty, 0); //单位为米 let endPosition = _self._getTranslatePostion(_self._coorinateAxisPosition, translateCartesian); return [_self._coorinateAxisPosition, endPosition]; }, false); this._coordinateEntity_z.polyline.positions = new Cesium.CallbackProperty(function() { let translateCartesian = new Cesium.Cartesian3(0, 0, _self._tz); //单位为米 let endPosition = _self._getTranslatePostion(_self._coorinateAxisPosition, translateCartesian); return [_self._coorinateAxisPosition, endPosition]; }, false); /* 激活平移实体 */ this._coordinateAxisActivateEditEntity(this._editCoorinateAxis); } }, /** * 坐标轴鼠标移动事件 * @ignore 生成方法时不对外公开 * @param {Cesium.Event} event 事件 */ _coorinateAxisMouseMove: function(event) { if (!Cesium.defined(this._editCoorinateAxis)) return; let position = this._viewer.scene.camera.pickEllipsoid(event.endPosition, this._viewer.scene.globe.ellipsoid); if (!position) return; let strGeo = this._cartesian3ToGeo(this._coordinateAxisMoveStartPosition); let endGeo = this._cartesian3ToGeo(position); let entityId = this._editCoorinateAxis.id; let entityPosition = this._editCoorinateAxis.position._value; let entityGeo = this._cartesian3ToGeo(entityPosition); let heightDifference = 0; if (entityId === this._coordinateAxisEntityId_x) { let difference = strGeo.longitude - endGeo.longitude; entityGeo.longitude = entityGeo.longitude - difference; } else if (entityId === this._coordinateAxisEntityId_y) { let difference = strGeo.latitude - endGeo.latitude; entityGeo.latitude = entityGeo.latitude - difference; } else if (entityId === this._coordinateAxisEntityId_z) { heightDifference = event.endPosition.y - this._coordinateAxisMoveStartScreen.y; heightDifference = heightDifference * 0.5; entityGeo.height = entityGeo.height - heightDifference; } this._coorinateAxisPosition = Cesium.Cartesian3.fromDegrees(entityGeo.longitude, entityGeo .latitude, entityGeo.height); this._moveEditEntityByCoordinateAxis(entityPosition, this._coorinateAxisPosition, heightDifference); }, /** * 坐标轴鼠标抬起事件 * @ignore 生成方法时不对外公开 * @param {Cesium.Event} event 事件 */ _coorinateAxisMouseUp: function(event) { this._viewer.scene.screenSpaceCameraController.enableRotate = true; if (this._editCoorinateAxis !== undefined) { this._editCoorinateAxis.polyline.width = 10; /* 确定最终位置 */ let translateCartesian = new Cesium.Cartesian3(this._tx, 0, 0); //单位为米 let endPosition = this._getTranslatePostion(this._coorinateAxisPosition, translateCartesian); this._coordinateEntity_x.polyline.positions = [this._coorinateAxisPosition, endPosition]; translateCartesian = new Cesium.Cartesian3(0, this._ty, 0); //单位为米 endPosition = this._getTranslatePostion(this._coorinateAxisPosition, translateCartesian); this._coordinateEntity_y.polyline.positions = [this._coorinateAxisPosition, endPosition] translateCartesian = new Cesium.Cartesian3(0, 0, this._tz); //单位为米 endPosition = this._getTranslatePostion(this._coorinateAxisPosition, translateCartesian); this._coordinateEntity_z.polyline.positions = [this._coorinateAxisPosition, endPosition]; this._coordinateEntity_x.position = this._coorinateAxisPosition; this._coordinateEntity_y.position = this._coorinateAxisPosition; this._coordinateEntity_z.position = this._coorinateAxisPosition; /* 结束并更新坐标轴绑定的实体 */ this._coordinateAxisUpdateEditEntity(this._editCoorinateAxis); this._editCoorinateAxis = undefined; } }, /** * 通过移动坐标轴移动编辑实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} strPosition 起始位置 * @param {Cesium.Cartesian3} endPosition 终止位置 * @param {Number} heightDifference 高度差 */ _moveEditEntityByCoordinateAxis: function(strPosition, endPosition, heightDifference) { /* 计算平移距离 */ let movePosition = Cesium.Cartesian3.subtract(endPosition, strPosition, new Cesium.Cartesian3()); for (let i = 0; i < this._moveInitPositions.length; i++) { let moveResult = Cesium.Cartesian3.add(this._moveInitPositions[i], movePosition, new Cesium .Cartesian3()); this._moveUpdatePositions[i] = moveResult.clone(); } for (let i = 0; i < this._moveInitHeights.length; i++) { this._moveUpdateHeights[i] = parseFloat(this._moveInitHeights[i]) + heightDifference * (-1); } }, /** * 激活当前拖拽的坐标轴关联的实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} moveAxisEntity 当前拖拽的坐标轴 */ _coordinateAxisActivateEditEntity: function(moveAxisEntity) { let _self = this; /* 获取坐标轴绑定的实体 */ let bindEntity = moveAxisEntity.getBindEntity(); if (bindEntity === undefined) return; let bindEntityType = bindEntity.getEntityType(); if (bindEntityType === DrawTools.DrawType.VideoWall) { /* 初始数据集合 */ let wall = bindEntity.wall; this._moveInitPositions = wall.positions._value; this._moveInitHeights = wall.minimumHeights._value; this._moveInitHeight = wall.maximumHeights._value[0] - wall.minimumHeights._value[0]; /* 平面移动数据点 */ this._moveUpdatePositions = []; for (let i = 0; i < this._moveInitPositions.length; i++) { this._moveUpdatePositions.push(this._moveInitPositions[i].clone()); } /* 设置属性回调变更 */ wall.positions = new Cesium.CallbackProperty(function() { return _self._moveUpdatePositions; }, false); /* 高度移动点 */ this._moveUpdateHeights = []; for (let i = 0; i < this._moveInitHeights.length; i++) { this._moveUpdateHeights.push(this._moveInitHeights[i]); } /* 设置属性回调变更 */ wall.minimumHeights = new Cesium.CallbackProperty(function() { return _self._moveUpdateHeights; }, false); wall.maximumHeights = new Cesium.CallbackProperty(function() { let maxHeights = []; for (let i = 0; i < _self._moveUpdateHeights.length; i++) { maxHeights.push(parseFloat(_self._moveUpdateHeights[i]) + _self ._moveInitHeight); } return maxHeights; }, false); } }, /** * 更新当前坐标轴绑定的实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} moveAxisEntity 当前拖拽的坐标轴 */ _coordinateAxisUpdateEditEntity: function(moveAxisEntity) { /* 获取坐标轴绑定的实体 */ let bindEntity = moveAxisEntity.getBindEntity(); if (bindEntity === undefined) return; let bindEntityType = bindEntity.getEntityType(); if (bindEntityType === DrawTools.DrawType.VideoWall) { /* 初始数据机 */ let wall = bindEntity.wall; /* 更新属性 */ wall.positions = this._moveUpdatePositions; wall.minimumHeights = this._moveUpdateHeights; let maxHeights = []; for (let i = 0; i < this._moveUpdateHeights.length; i++) { maxHeights.push(parseFloat(this._moveUpdateHeights[i]) + this._moveInitHeight); } wall.maximumHeights = maxHeights; } }, /** * 计算实体转换后的方向 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} entity 实体 * @param {JSON} options 配置项 * @param {Number} options.x 绕X轴旋转 度 * @param {Number} options.y 绕Y轴旋转 度 * @param {Number} options.z 绕Z轴旋转 度 */ _coordinateCalculateEntityOrientation: function(entity, options) { /* 获取实体的位置 */ let position = entity.position._value; /* 获取实体的朝向 */ let orientation = entity.orientation === undefined ? new Cesium.Cartesian3(0, 0, 0) : entity .orientation._value; /* 根据方向、朝向和缩放计算4*4矩阵 */ let transform = Cesium.Matrix4.fromTranslationQuaternionRotationScale(position, orientation, new Cesium.Cartesian3(1, 1, 1), new Cesium.Matrix4()); /* 计算3个轴的3*3旋转矩阵 */ let _rotateX = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(options.x)); let _rotateY = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(options.y)); let _rotateZ = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(options.z)); /* 计算4*4旋转矩阵 */ transform = Cesium.Matrix4.multiplyByMatrix3(transform, _rotateX, transform); transform = Cesium.Matrix4.multiplyByMatrix3(transform, _rotateY, transform); transform = Cesium.Matrix4.multiplyByMatrix3(transform, _rotateZ, transform); /* 4*4旋转矩阵转换为3*3旋转矩阵 */ let m3 = Cesium.Matrix4.getRotation(transform, new Cesium.Matrix3()); /* 转换旋转矩阵转换为齐次坐标 */ let resOrientation = new Cesium.Quaternion(); Cesium.Quaternion.fromRotationMatrix(m3, resOrientation); return resOrientation; }, /** * 移除坐标轴 * @ignore 生成方法时不对外公开 */ _removeCoorinateAxis: function() { if (this._coordinateAxisEntityName !== undefined) { this._removeEntityByName(this._coordinateAxisEntityName); } if (this._eventCoorinateAxis !== undefined) { this._clearEvent(this._eventCoorinateAxis); this._eventCoorinateAxis = undefined; } } }); /** * 实体编辑相关方法 */ Object.assign(DrawTools.prototype, { /** * 设置实体可编辑,编辑的实体必须包含编辑类型 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} entity 编辑的实体 */ _setEntityIsEdit(entity) { let _self = this; /* 设置实体要素可编辑 */ entity.setIsEdit(true); /* 先撤销编辑 */ this._unActivateEdit(); /* 激活编辑 并显示属性编辑框 */ this._sendShowPropertyDialog(entity); /* 注册统一事件 用于单击拾取实体 */ let handler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); this._registerLeftClickEvent(handler, function(event) { /* 只要点击 就清除选中状态 */ _self._unActivateEdit(); let feature = _self._viewer.scene.pick(event.position); if (feature !== undefined && feature.id instanceof Cesium.Entity) { let featureType = feature.id.getEditType(); let entityType = feature.id.getEntityType(); if (featureType === DrawTools.EditPointType.Node || featureType === DrawTools.EditPointType.Middle || featureType === DrawTools.EditPointType.Center || featureType === DrawTools.EditPointType.CoordinateAxis || featureType === DrawTools.EditPointType.OdlineStrartNode || featureType === DrawTools.EditPointType.OdlineEndNode || entityType === DrawTools.DrawType.Polyline || entityType === DrawTools.DrawType.ArrowPolyline || entityType === DrawTools.DrawType.DynamicPolyline || entityType === DrawTools.DrawType.GrowPolyline || entityType === DrawTools.DrawType.OutlinePolyline || entityType === DrawTools.DrawType.OdLine || entityType === DrawTools.DrawType.Polygon || entityType === DrawTools.DrawType.SpatialLine || entityType === DrawTools.DrawType.Circle || entityType === DrawTools.DrawType.DynamicCircle || entityType === DrawTools.DrawType.Rectangle || entityType === DrawTools.DrawType.NormalWall || entityType === DrawTools.DrawType.DynamicWall || entityType === DrawTools.DrawType.House || entityType === DrawTools.DrawType.TextWall || entityType === DrawTools.DrawType.VideoWall ) { _self._sendShowPropertyDialog(feature.id); } } }) }, /** * 打开实体编辑对话框 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} entity */ _sendShowPropertyDialog(entity) { let _self = this; /* 获取可编辑实体的类型 */ let editEntityType = entity.getEntityType(); if (entity.getIsEdit() === undefined || entity.getIsEdit() === false || editEntityType === undefined) { /* 选择的实体不可编辑 */ this._unActivateEdit(); return; } /* 编辑属性 */ let editProperty = entity.getParams(); if (editEntityType === DrawTools.DrawType.OdLine) { editProperty = entity.parent.getParams(); } this._console('选择实体的属性', editProperty); if (editProperty !== undefined && this.onEditProperty !== undefined) { /* 改进后不在对外提供监听事件 改为内部流转 */ // this.onEditProperty(editProperty); /* 更改测试 */ this._openPropertyEditDialog(editProperty, function(params) { _self.updateEditEntityProperty(params); }, function() { _self._removeEditEntity(); }); } this._activateEdit(entity); }, /** * 删除当前编辑实体 */ _removeEditEntity() { if (this._editEntity !== undefined) { this._console('移除实体', this._editEntity); let entityType = this._editEntity.getEntityType(); if (entityType === DrawTools.DrawType.OdLine) { let fatherEntityId = this._editEntity.parent.id; let removeEntitys = []; for (let entity of this._entities.values) { if (entity.parent !== undefined && entity.parent.id === fatherEntityId) { removeEntitys.push(entity); } } for (let removeEntity of removeEntitys) { this._removeEntityByObject(removeEntity); } } else { this._removeEntityByObject(this._editEntity); } this._unActivateEdit(); this._editEntity = undefined; } }, /** * 更新当前编辑的实体属性 * @param {JSON} params */ updateEditEntityProperty: function(params) { let _self = this; if (this._editEntity === undefined) return; if (this._editEntity.getIsEdit() === undefined || this._editEntity.getIsEdit() === false) return; let editEntityType = this._editEntity.getEntityType(); if (editEntityType === undefined) return; if (editEntityType === DrawTools.DrawType.NormalWall || editEntityType === DrawTools.DrawType .DynamicWall || editEntityType === DrawTools.DrawType.TextWall) { this._updateWallProperty(params); } else if (editEntityType === DrawTools.DrawType.Circle || editEntityType === DrawTools.DrawType .DynamicCircle) { this._updateCircleProperty(params); } else if (editEntityType === DrawTools.DrawType.House) { this._updateHouseProperty(params); } else if (editEntityType === DrawTools.DrawType.VideoWall) { this._updateVideoWallProperty(params); } else if (editEntityType === DrawTools.DrawType.Polyline) { this._updatePolylineProperty(params); } else if (editEntityType === DrawTools.DrawType.Polygon) { this._updatePolygonProperty(params); } else if (editEntityType === DrawTools.DrawType.Rectangle) { this._updateRectangleProperty(params); } else if (editEntityType === DrawTools.DrawType.SpatialLine) { this._updateSpatialPolylineProperty(params); } else if (editEntityType === DrawTools.DrawType.OdLine) { this._updateOdlineProperty(params); } }, /** * 更新OD线属性 * @ignore 不公开方法 * @param {Object} params */ _updateOdlineProperty(params) { let _self = this; /* 获取父实体Id */ let fatherEntity = this._editEntity.parent; /* 当前编辑OD线集合 */ this._editOdlineEntities = []; /* 循环集合寻找符合条件的实体 */ for (let entity of this._entities.values) { if (entity.parent !== undefined && entity.parent.id === fatherEntity.id) { this._editOdlineEntities.push(entity); } } let meterialImage = this._image_arrow_reverse; if (params.order === this._param.order_add) { meterialImage = this._image_arrow_reverse; } else if (params.order === this._param.order_minus) { meterialImage = this._image_arrow_forward; } /* 创建OD线材质 */ let odLineMaterial = new WallMaterialProperty({ viewer: _self._viewer, trailImage: meterialImage, duration: params.duration, color: Cesium.Color.fromCssColorString(params.color), param: { direction: params.direction, count: params.count, order: params.order, }, }); /* 循环处理需要编辑的实体 */ for (let entity of this._editOdlineEntities) { entity.polyline.material = odLineMaterial; /* 获取OD线的位置 */ let positions = entity.polyline.positions._value; let strPoint = positions.first(); let endPoint = positions.last(); let newPositios = this._calculateOdlinePositios(strPoint, endPoint, parseInt(params.odlineHeight), parseInt(params.odlineCount)); /* 设置OD线新位置 */ entity.polyline.positions = newPositios; entity.polyline.width = parseInt(params.lineWidth); } /* 重置材质 */ fatherEntity.setParams(params); }, /** * 更新空间线属性 * @ignore 不公开方法 * @param {Object} params */ _updateSpatialPolylineProperty(params) { let material = this._editEntity.polyline.material; let newMaterial = undefined; if (material instanceof Cesium.ColorMaterialProperty) { newMaterial = this._materialColorProperty({ color: params.color, }); } /* 设置材质 */ if (newMaterial !== undefined) this._editEntity.polyline.material = newMaterial; this._editEntity.polyline.width = parseFloat(params.lineWidth); /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); }, /** * 更新矩形属性 * @ignore 不公开方法 * @param {Object} params */ _updateRectangleProperty(params) { let material = this._editEntity.rectangle.material; if (material instanceof Cesium.ColorMaterialProperty) { let newMaterial = this._materialColorProperty({ color: params.color, }); this._editEntity.rectangle.material = newMaterial; } if (this._editEntity.polyline !== undefined) { let newMaterial = this._materialColorProperty({ color: params.outlineColor, }); this._editEntity.polyline.material = newMaterial; this._editEntity.polyline.width = parseFloat(params.outlineWidth); } /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); }, /** * 更新面的属性 * @ignore 不公开方法 * @param {Object} params */ _updatePolygonProperty(params) { let material = this._editEntity.polygon.material; if (material instanceof Cesium.ColorMaterialProperty) { let newMaterial = this._materialColorProperty({ color: params.color, }); this._editEntity.polygon.material = newMaterial; } if (this._editEntity.polyline !== undefined) { let newMaterial = this._materialColorProperty({ color: params.outlineColor, }); this._editEntity.polyline.material = newMaterial; this._editEntity.polyline.width = parseFloat(params.outlineWidth); } /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); }, /** * 更新线的属性 * @ignore 不公开方法 * @param {Object} params */ _updatePolylineProperty(params) { let material = this._editEntity.polyline.material; let newMaterial = undefined; if (material instanceof Cesium.ColorMaterialProperty) { newMaterial = this._materialColorProperty({ color: params.color, }); } else if (material instanceof Cesium.PolylineArrowMaterialProperty) { newMaterial = this._materialPolylineArrowProperty({ color: params.color, }); } else if (material instanceof WallMaterialProperty) { /* 设置方向对应图片 */ let materialImage = this._image_h_l_r; if (params.order === this._param.order_minus) { materialImage = this._image_h_r_l; } else if (params.order === this._param.order_add) { materialImage = this._image_h_l_r; } newMaterial = new WallMaterialProperty({ viewer: this._viewer, trailImage: materialImage, duration: params.duration, color: Cesium.Color.fromCssColorString(params.color), param: { count: parseInt(params.count), direction: params.direction, order: params.order, } }); } else if (material instanceof Cesium.PolylineGlowMaterialProperty) { newMaterial = this._materialPolylineGlowProperty({ color: params.color, power: parseFloat(params.power), }) } else if (material instanceof Cesium.PolylineOutlineMaterialProperty) { newMaterial = this._materialPolylineOutlineProperty({ color: params.color, outlineWidth: parseFloat(params.outlineWidth), outlineColor: params.outlineColor, }) } /* 设置材质 */ if (newMaterial !== undefined) this._editEntity.polyline.material = newMaterial; this._editEntity.polyline.width = params.lineWidth; /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); }, /** * 更新房屋属性 * @ignore 不公开方法 * @param {Object} params */ _updateHouseProperty(params) { let entityParams = this._editEntity.getParams(); let polygonMaterial = this._editEntity.polygon.material; if (polygonMaterial instanceof Cesium.ColorMaterialProperty) { let material = this._materialColorProperty({ color: params.color, }); /* 设置材质 */ this._editEntity.polygon.material = material; /* 设置高度 */ this._editEntity.polygon.extrudedHeight = parseFloat(params.height) + parseFloat( entityParams.bottomHeight); /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); } }, /** * 更新圆的属性 * @ignore 不公开方法 * @param {Object} params */ _updateCircleProperty(params) { let circleMaterial = this._editEntity.ellipse.material; if (circleMaterial instanceof CircleMaterialProperty) { let material = new CircleMaterialProperty({ viewer: this._viewer, duration: params.duration, color: Cesium.Color.fromCssColorString(params.color), count: parseFloat(params.count), }); this._editEntity.ellipse.material = material; } else if (circleMaterial instanceof Cesium.ColorMaterialProperty) { let material = this._materialColorProperty({ color: params.color, }); this._editEntity.ellipse.material = material; if (this._editEntity.polyline !== undefined) { let newMaterial = this._materialColorProperty({ color: params.outlineColor, }); this._editEntity.polyline.material = newMaterial; this._editEntity.polyline.width = parseFloat(params.outlineWidth); } } /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); }, /** * 更新视频墙的属性 * @ignore 不公开方法 * @param {Object} params */ _updateVideoWallProperty(params) { /* 查找视频画布 */ let videoElement = document.getElementById('wallVideo'); if (videoElement !== null) { document.body.removeChild(videoElement); } videoElement = document.createElement("video"); videoElement.id = 'wallVideo'; videoElement.setAttribute('crossorigin', 'anonymous'); //必须设置 为了防止跨域调用网络视频导致播放失败 videoElement.setAttribute("width", "1024px"); videoElement.setAttribute("height", "256px"); videoElement.setAttribute("controls", "controls"); videoElement.setAttribute("src", params.videoUrl); videoElement.setAttribute("loop", "loop"); videoElement.play(); document.body.appendChild(videoElement); /* 更新数据 */ let minimumHeights = this._editEntity.wall.minimumHeights._value; /* 更新最大高度 */ let maximumHeights = []; for (let i = 0; i < minimumHeights.length; i++) { maximumHeights.push(minimumHeights[i] + parseFloat(params.height)); } this._editEntity.wall.maximumHeights = maximumHeights; this._editEntity.wall.material = videoElement; /* 更新平移位置 */ let wallPositions = this._editEntity.wall.positions._value; let newPositions = []; for (let wallPosition of wallPositions) { /* 获取当前位置的东北上坐标系 */ let transform = Cesium.Transforms.eastNorthUpToFixedFrame(wallPosition); /* 构建平移矩阵 */ let m = new Cesium.Matrix4(); Cesium.Matrix4.setTranslation(Cesium.Matrix4.IDENTITY, new Cesium.Cartesian3(parseFloat(params.axisX), parseFloat(params.axisY), parseFloat(params.axisZ)), m); /* 矩阵相乘 */ let moveMatrix = Cesium.Matrix4.multiply(transform, m, transform); /* 提取位置 */ let newPosition = new Cesium.Cartesian3(); Cesium.Matrix4.getTranslation(moveMatrix, newPosition); newPositions.push(newPosition); } this._editEntity.wall.positions = newPositions; /* 将平移距离设置为0 */ params.axisX = params.axisY = params.axisZ = 0 /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); /* 重置调整坐标轴 已保证坐标轴的位置正确+ */ this._activateEdit(this._editEntity); }, /** * 更新墙的属性 * @ignore 不公开方法 * @param {Object} params */ _updateWallProperty(params) { let minHeights = this._editEntity.wall.minimumHeights._value; let maxHeights = []; for (let i = 0; i < minHeights.length; i++) { maxHeights.push(minHeights[i] + parseFloat(params.height)); } /* 设置墙的最大高度 */ this._editEntity.wall.maximumHeights = maxHeights; /* 更改存储墙的最大高度的数组 */ this._sketchWallMaxHeights = maxHeights; /* 根据传入的参数id判断需什么材质 */ let wallMaterial = this._editEntity.wall.material; if (wallMaterial instanceof Cesium.ImageMaterialProperty) { let material = this._materialTextImageProperty({ color: params.color, text: params.text, }); this._editEntity.wall.material = material; } else if (wallMaterial instanceof WallMaterialProperty) { /* 判断使用的照片 */ let materialImage = this._image_h_l_r; if (params.direction === this._param.direction_h && params.order === this._param.order_add) { materialImage = this._image_h_l_r; } else if (params.direction === this._param.direction_h && params.order === this._param.order_add) { materialImage = this._image_h_r_l; } else if (params.direction === this._param.direction_v && params.order === this._param .order_minus) { materialImage = this._image_v_t_b; } else if (params.direction === this._param.direction_v && params.order === this._param.order_add) { materialImage = this._image_v_b_t; } let material = new WallMaterialProperty({ viewer: this._viewer, trailImage: materialImage, duration: params.duration, color: Cesium.Color.fromCssColorString(params.color), param: { count: parseFloat(params.count), direction: params.direction, order: params.order } }); this._editEntity.wall.material = material; } else if (wallMaterial instanceof Cesium.ColorMaterialProperty) { let material = this._materialColorProperty({ color: params.color, }); this._editEntity.wall.material = material; } /* 重新关联墙实体的属性 */ this._editEntity.setParams(params); }, /** * 旋转实体 * @ignore * @param {JSON} options 配置项 * @param {Number} options.x 绕X轴旋转 度 * @param {Number} options.y 绕Y轴旋转 度 * @param {Number} options.z 绕Z轴旋转 度 */ rotationEntity(options) { if (this._editEntity === undefined) return; let orientation = this._coordinateCalculateEntityOrientation(this._editEntity, options); }, /** * 获取实体可编辑数据 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} entity 实体 * @return {Array} positions */ _getEntityEditData: function(entity) { if (entity instanceof Cesium.Entity) { /* 获取实体的类型 */ let editEntityType = entity.getEntityType(); if (editEntityType === DrawTools.DrawType.Polyline || editEntityType === DrawTools.DrawType .SpatialLine) { return entity.polyline.positions._value; } else if (editEntityType === DrawTools.DrawType.Polygon || editEntityType === DrawTools .DrawType.House) { let positions = entity.polygon.hierarchy._value.positions; /* 判断是否需要加上终点 */ if (positions[0].x !== positions[positions.length - 1].x) { positions.push(positions[0].clone()); } return positions; } else if (editEntityType === DrawTools.DrawType.Rectangle) { let rect = entity.rectangle.coordinates._value; /* 计算西北角的位置 */ let gNw = Cesium.Rectangle.northwest(rect); if (gNw.height <= 0) { let height = this._queryHeightFromGeo(Cesium.Math.toDegrees(gNw.longitude), Cesium.Math .toDegrees(gNw.latitude)); gNw.height = height; } let cNw = Cesium.Cartesian3.fromRadians(gNw.longitude, gNw.latitude, gNw.height); /* 计算东南角位置 */ let gSe = Cesium.Rectangle.southeast(rect); if (gSe.height <= 0) { let height = this._queryHeightFromGeo(Cesium.Math.toDegrees(gSe.longitude), Cesium.Math .toDegrees(gSe.latitude)); gSe.height = height; } let cSe = Cesium.Cartesian3.fromRadians(gSe.longitude, gSe.latitude, gSe.height); /* 组合坐标数组 */ return [cNw, cSe]; } else if (editEntityType === DrawTools.DrawType.Circle || editEntityType === DrawTools.DrawType .DynamicCircle) { /* 圆中心点位置 */ let centerPosition = entity.position._value; /* 获取圆的半径 */ let radius = entity.ellipse.semiMajorAxis._value; let cbPoint = this._calculateCircleBoundaryPoint(centerPosition, radius); return [centerPosition, cbPoint]; } else if (editEntityType === DrawTools.DrawType.NormalWall || editEntityType === DrawTools .DrawType.DynamicWall || editEntityType === DrawTools.DrawType.TextWall) { /* 存储墙的最大高度和最小高度数组 */ this._sketchWallHeights = []; this._sketchWallMaxHeights = []; let minHeights = entity.wall.minimumHeights._value; let maxHeights = entity.wall.maximumHeights._value; for (let i = 0; i < minHeights.length; i++) { this._sketchWallHeights.push(minHeights[i]); this._sketchWallMaxHeights.push(maxHeights[i]); } return entity.wall.positions._value; } else if (editEntityType === DrawTools.DrawType.VideoWall) { let positions = entity.wall.positions._value; return [positions[0].clone()]; } else { return []; } } else { return []; } }, /** * 根据圆的中心点和半径计算边界点坐标位置 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} centerPosition 圆的中心点位置 * @param {Number} radius 半径 * @return {Cesium.Cartesian3} boundaryPosition 边界点位置 */ _calculateCircleBoundaryPoint: function(centerPosition, radius) { let gCenter = Cesium.Ellipsoid.WGS84.cartesianToCartographic(centerPosition); /* 计算边界线上的点坐标 */ let cPoint = turf.point([Cesium.Math.toDegrees(gCenter.longitude), Cesium.Math.toDegrees( gCenter.latitude)]); let boundaryPoint = turf.destination(cPoint, radius / 1000, 90, { units: 'kilometers' }).geometry.coordinates; /* 查询高度创建边界点 */ let height = this._queryHeightFromGeo(boundaryPoint[0], boundaryPoint[1]); let cbPoint = Cesium.Cartesian3.fromDegrees(boundaryPoint[0], boundaryPoint[1], height); return cbPoint; }, /** * 根据一组点计算中心点位置 * @ignore 生成方法时不对外公开 * @param {Array} positions 点集合 */ _calculateCenterPosition: function(positions) { if (positions === undefined || positions.length === 0) return undefined; else if (positions.length === 1) { return positions[0]; } else if (positions.length === 2) { let pt0 = this._cartesian3ToGeo(positions[0]); let pt1 = this._cartesian3ToGeo(positions[1]); let point0 = turf.point([pt0.longitude, pt0.latitude]); let point1 = turf.point([pt1.longitude, pt1.latitude]); let center = turf.midpoint(point0, point1).geometry.coordinates; /* 查询高度 */ let height = this._queryHeightFromGeo(center[0], center[1]); /* 返回 */ return Cesium.Cartesian3.fromDegrees(center[0], center[1], height); } else { let geoPoints = [ [] ]; for (let i = 0; i < positions.length; i++) { /* 将世界坐标转换为经纬度坐标 */ let geoPoint = this._cartesian3ToGeo(positions[i]); geoPoints[0].push([geoPoint.longitude, geoPoint.latitude]); } geoPoints[0].push(geoPoints[0][0]); /* 创建区域 */ let polygon = turf.polygon(geoPoints); /* 计算中心点 */ let center = turf.centerOfMass(polygon).geometry.coordinates; /* 查询高度 */ let height = this._queryHeightFromGeo(center[0], center[1]); /* 返回 */ return Cesium.Cartesian3.fromDegrees(center[0], center[1], height); } }, /** * 计算转换后的位置,根据角度和距离计算转换后的位置 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position 待转换位置 * @param {Number} distance 距离<距离的表示单位在options中配置> * @param {Number} bearing 角度 * @param {JSON} options 配置项 * @return {Cesium.Cartesian3} 转换后的位置 */ _calculateTransformPosition: function(position, distance, bearing, options) { /* 将移动点转换为经纬度格式 */ let geoPoint = this._cartesian3ToGeo(position); /* 根据点的角度度 距离计算移动后的位置 */ let point = turf.point([geoPoint.longitude, geoPoint.latitude]); let resPoint = turf.destination(point, distance, bearing, options).geometry .coordinates; /* 根据经纬度查询高度 该步骤耗时 且容易出错 */ let height = geoPoint.height; if (options !== undefined && options.calculateHeight !== undefined && options.calculateHeight === true) { height = this._queryHeightFromGeo(resPoint[0], resPoint[1]); } /* 将移动后的点转换为世界坐标系坐标点 */ let cPosition = Cesium.Cartesian3.fromDegrees(resPoint[0], resPoint[1], height); /* 返回 */ return cPosition; }, /** * 取消实体编辑激活状态 * @ignore 生成方法时不对外公开 */ _unActivateEdit: function() { /* 移除编辑点 */ this._clearEditPoint(); /* 删除坐标轴 */ this._removeCoorinateAxis(); /* 关闭属性编辑框 */ this._closePropertyEditDialog(); }, /** * 激活编辑 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} editEntity 编辑实体 */ _activateEdit: function(editEntity) { /* 获取编辑类型 */ let entityType = editEntity.getEntityType(); /* 获取实体是否可编辑 */ let entityIsEdit = editEntity.getIsEdit(); /* 不可编辑对象 直接退出 */ if (entityIsEdit === undefined || entityType === undefined || entityIsEdit === false) { this._console('该实体不可编辑'); return; }; if (entityType === DrawTools.DrawType.OdLine) { this._activeteOdlineEdit(editEntity); } else { this._activeteNormalEdit(editEntity); } }, /** * 激活编辑OD线实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} editEntity 编辑实体 */ _activeteOdlineEdit: function(editEntity) { let _self = this; let entityType = editEntity.getEntityType(); /* 不可编辑对象 直接退出 */ if (entityType === undefined || entityType !== DrawTools.DrawType.OdLine) { this._console('该实体不可编辑或该实体不是OD线类型'); return; }; /* 获取父实体Id */ let faterEntityId = editEntity.parent.id; /* 当前编辑OD线集合 */ this._editOdlineEntities = []; /* 循环集合寻找符合条件的实体 */ for (let entity of this._entities.values) { if (entity.parent !== undefined && entity.parent.id === faterEntityId) { this._editOdlineEntities.push(entity); } } /* 不存在可编辑的OD线 */ if (this._editOdlineEntities.length === 0) return; /* 赋值可编辑对象 */ this._editEntity = this._editOdlineEntities[0]; for (let i = 0; i < this._editOdlineEntities.length; i++) { let entity = this._editOdlineEntities[i]; let positions = entity.polyline.positions._value; if (i === 0) { this._createEditOdlineStartPoint(positions.first(), entity); this._createEditOdlineEndPoint(positions.last(), entity); } else { this._createEditOdlineEndPoint(positions.last(), entity); } } /* 创建事件句柄 */ if (this._sketchEditHandler === undefined) { this._sketchEditHandler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); } /* 注册鼠标左键按下事件 */ this._registerLeftDownEvent(this._sketchEditHandler, function(event) { _self._eventEditMouseDown(event); }); /* 注册鼠标左键移动事件 */ this._registerMouseMoveEvent(this._sketchEditHandler, function(event) { _self._eventEditMouseMove(event); }); /* 注册鼠标左键抬起事件 */ this._registerLeftUpEvent(this._sketchEditHandler, function(event) { _self._eventEditMouseUp(event); }); }, /** * 激活编辑单实体 * @ignore 生成方法时不对外公开 * @param {Cesium.Entity} editEntity 编辑实体 */ _activeteNormalEdit: function(editEntity) { let _self = this; let positions = this._getEntityEditData(editEntity); /* 删除所有临时绘制的点 */ this._removePointEntitys(); /* 获取编辑类型 */ let entityType = editEntity.getEntityType(); /* 赋值可编辑对象 */ this._editEntity = editEntity; /* 创建节点和中心点 */ if (entityType === DrawTools.DrawType.Circle || entityType === DrawTools .DrawType.DynamicCircle) { this._createEditCenterPoint(positions[0]); this._createEditNodePoint(positions, 1); } else if (entityType === DrawTools.DrawType.VideoWall) { if (!this._isRuntimeApp()) { /* 如果不是App运行环境,则创建拖动轴 */ let position = positions[0]; this._removeCoorinateAxis(); this._createCoordinateAxis(position); } } else { this._createEditNodePoint(positions); let centerPosition = this._calculateCenterPosition(positions); if (centerPosition !== undefined) { this._createEditCenterPoint(centerPosition); } } /* 创建中点 */ if (entityType !== DrawTools.DrawType.Rectangle && entityType !== DrawTools .DrawType.Circle && entityType !== DrawTools.DrawType.DynamicCircle && entityType !== DrawTools .DrawType.VideoWall) { if (entityType === DrawTools.DrawType.SpatialLine) { this._createEditMiddlePoint(positions, true); } else { this._createEditMiddlePoint(positions); } } /* 创建事件句柄 */ if (this._sketchEditHandler === undefined) { this._sketchEditHandler = new Cesium.ScreenSpaceEventHandler(this._viewer.scene.canvas); } /* 注册鼠标左键按下事件 */ this._registerLeftDownEvent(this._sketchEditHandler, function(event) { _self._eventEditMouseDown(event); }) /* 注册鼠标移动事件 */ this._registerMouseMoveEvent(this._sketchEditHandler, function(event) { _self._eventEditMouseMove(event); }); /* 注册鼠标抬起事件 */ this._registerLeftUpEvent(this._sketchEditHandler, function(event) { _self._eventEditMouseUp(event); }) }, /** * 编辑点鼠标抬起事件 * @ignore 生成方法时不对外公开 * @param {Object} event 事件 */ _eventEditMouseDown: function(event) { let _self = this; /* 拾取实体 */ let feature = _self._viewer.scene.pick(event.position); /* 分类处理 */ if (feature != undefined && feature.id instanceof Cesium.Entity) { /* 获取选择实体的样式 */ let featureType = feature.id.getEditType(); /* 说明当前选中的实体 不是编辑点 */ if (featureType === undefined) return; /* 禁用场景的旋转移动功能 保留缩放功能 */ _self._viewer.scene.screenSpaceCameraController.enableRotate = false; /* 位置信息 */ let entityPosition = feature.id.position._value; /* 保存当前可编辑的实体 */ _self._editPointEntity = feature.id; /* 设置鼠标样式为十字 */ _self._setMousePointerStyle(); /* 判断类型 是节点或中点 进行不同的操作 */ if (featureType.type === DrawTools.EditPointType.Node || featureType.type === DrawTools.EditPointType.Middle) { /* 处理鼠标按下实体的属性变更回调 */ _self._entityCallbackPropertyByMouseDown(); /* 移除当前移动的点 */ _self._removeEntityByObject(_self._editPointEntity); /* 删除高空点 */ if (_self._sketchEditEntitySpatialName != undefined) { _self._removeEntityByName(_self._sketchEditEntitySpatialName); } } else if (featureType.type === DrawTools.EditPointType.Center) { _self._entityCenterMouseDownEvent(); } else if (featureType.type === DrawTools.EditPointType.OdlineEndNode) { /* 删除当前移动点 */ _self._removeEntityByObject(_self._editPointEntity); /* 设置当前编辑的实体 */ _self._editEntity = featureType.joinEntity; /* 获取OD线的必要参数 */ let params = _self._editEntity.parent.getParams(); _self._sketchEditPoints = []; let joinEntityPositions = _self._editEntity.polyline.positions._value; _self._sketchEditPoints.push(joinEntityPositions.first()); _self._sketchEditPoints.push(joinEntityPositions.last()); _self._editEntity.polyline.positions = new Cesium.CallbackProperty(function() { let positions = _self._calculateOdlinePositios(_self._sketchEditPoints[0], _self ._sketchEditPoints[1], parseInt(params.odlineHeight), parseInt(params .odlineCount)); return positions; }, false) } else if (featureType.type === DrawTools.EditPointType.OdlineStrartNode) { /* 删除当前移动点 */ _self._removeEntityByObject(_self._editPointEntity); /* 设置当前编辑的实体 */ _self._editEntity = featureType.joinEntity; /* 获取OD线的必要参数 */ let params = _self._editEntity.parent.getParams(); _self._sketchEditPoints = []; let joinEntityPositions = _self._editEntity.polyline.positions._value; _self._sketchEditPoints.push(joinEntityPositions.first()); for (let odEntity of _self._editOdlineEntities) { let odEntityPositions = odEntity.polyline.positions._value; let lastPosition = odEntityPositions.last(); _self._sketchEditPoints.push(lastPosition.clone()); odEntity.polyline.positions = new Cesium.CallbackProperty(function() { let positions = _self._calculateOdlinePositios(_self._sketchEditPoints[0], lastPosition, parseInt(params.odlineHeight), parseInt(params .odlineCount)); return positions; }, false); } } /* 根据节点类型不同进行特殊的处理 */ if (featureType.type === DrawTools.EditPointType.Middle) { /* 如果选择的是中点 则插入节点 并记录当前的索引 */ let index = featureType.index; _self._sketchEditPoints.splice(index, 0, entityPosition); _self._sketchEditIndex = index; /* 如果当前移动的中点为墙的中点,则需要进行特殊处理一下,主要为了修正高度 */ if (_self._sketchWallHeights != undefined && _self._sketchWallHeights.length > 0) { /* 查询一下高度 */ let geoPoint = _self._cartesian3ToGeo(entityPosition); let height = _self._queryHeightFromGeo(geoPoint.longitude, geoPoint .latitude); /* 墙的最小高度加入值 */ _self._sketchWallHeights.splice(index, 0, height); /* 墙的最大高度需要加入值 */ let heightDifference = _self._sketchWallMaxHeights[0] - _self ._sketchWallHeights[0]; _self._sketchWallMaxHeights.splice(index, 0, height + heightDifference); } /* 设置提示标签 */ _self._tooltipInit('拖动中点,改变形状', event.position); } else if (featureType.type === DrawTools.EditPointType.Node) { /* 如果是节点 则直接记录索引 */ _self._sketchEditIndex = featureType.index; /* 设置提示标签 */ _self._tooltipInit('拖动节点,改变形状', event.position); } else if (featureType.type === DrawTools.EditPointType.Spatial) { /* 如果是节点 则直接记录索引 */ _self._sketchEditIndex = featureType.index; /* 设置提示标签 */ _self._tooltipInit('拖动节点,改变高度', event.position); } else if (featureType.type === DrawTools.EditPointType.CoordinateAxis) { /* 设置提示标签 */ _self._tooltipInit('拖动坐标轴,改变位置', event.position); } else if (featureType.type === DrawTools.EditPointType.OdlineEndNode || featureType.type === DrawTools.EditPointType.OdlineStrartNode) { /* 设置提示标签 */ _self._tooltipInit('拖动节点,改变OD线位置', event.position); } } }, /** * 编辑点鼠标移动事件 * @ignore 生成方法时不对外公开 * @param {Object} event 事件 */ _eventEditMouseMove: function(event) { let _self = this; if (_self._editPointEntity != undefined) { let loc = _self._transfromFromScreenPoint(event.endPosition); if (!Cesium.defined(loc.sLocation)) return; _self._editPosition = loc.sLocation; /* 获取当前可编辑点的类型 */ let editEntityType = _self._editPointEntity.getEditType(); if (editEntityType.type === DrawTools.EditPointType.Node) { _self._sketchEditPoints[_self._sketchEditIndex] = loc.sLocation; /* 获取当前编辑的实体的类型 */ let editEntityType = _self._editEntity.getEntityType(); if (editEntityType != DrawTools.DrawType.Rectangle && editEntityType != DrawTools.DrawType.Circle && editEntityType != DrawTools .DrawType.DynamicCircle) { /* 这里对面对象需要进特殊处理 保证第0号点和最后一个点是一致的 */ if ((editEntityType === DrawTools.DrawType.Polygon || editEntityType === DrawTools.DrawType.House) && _self ._sketchEditIndex === 0) { _self._sketchEditPoints[_self._sketchEditPoints.length - 1] = loc .sLocation; } else if (editEntityType === DrawTools.DrawType.NormalWall || editEntityType === DrawTools.DrawType.DynamicWall || editEntityType === DrawTools.DrawType.TextWall) { _self._sketchWallHeights[_self._sketchEditIndex] = loc.gLocation.height; } /* 移除所有中点 */ _self._removeEntityByName(_self._sketchEditEntityMiddleName); /* 创建所有中点 */ if (editEntityType === DrawTools.DrawType.SpatialLine) { _self._createEditMiddlePoint(_self._sketchEditPoints, true); } else { _self._createEditMiddlePoint(_self._sketchEditPoints); } } } else if (editEntityType.type === DrawTools.EditPointType.Middle) { _self._sketchEditPoints[_self._sketchEditIndex] = loc.sLocation; } else if (editEntityType.type === DrawTools.EditPointType.Center) { _self._entityCenterMouseMoveEvent(event); } else if (editEntityType.type === DrawTools.EditPointType.Spatial) { /* 当前移动的是空中点 */ let ellipsoid = _self._viewer.scene.globe.ellipsoid; let cartesian = _self._viewer.camera.pickEllipsoid(event.endPosition, ellipsoid); let bottomPoint = _self._sketchEditPoints[_self._sketchEditIndex]; /* 计算高差 */ let heightDifference = cartesian.z - bottomPoint.z; if (heightDifference > 0 && heightDifference < 500) { for (let i = 0; i < _self._sketchWallHeights.length; i++) { _self._sketchWallMaxHeights[i] = _self._sketchWallHeights[i] + heightDifference; } } } else if (editEntityType.type === DrawTools.EditPointType.OdlineEndNode) { _self._sketchEditPoints[_self._sketchEditPoints.length - 1] = loc.sLocation; } else if (editEntityType.type === DrawTools.EditPointType.OdlineStrartNode) { _self._sketchEditPoints[0] = loc.sLocation; } /* 更改标签文字 */ _self._tooltipInit('抬起鼠标,完成更改', event.endPosition); } }, /** * 编辑点鼠标抬起事件 * @ignore 生成方法时不对外公开 * @param {Object} event 事件 */ _eventEditMouseUp: function(event) { let _self = this; if (_self._editPointEntity != undefined) { /* 恢复所有鼠标默认事件 */ _self._viewer.scene.screenSpaceCameraController.enableRotate = true; /* 移除标签 */ _self._tooltipRemove(); /* 恢复鼠标默认样式 */ _self._setMouseDefaultStyle(); /* 获取当前编辑的点类型 */ let editEntityPointType = _self._editPointEntity.getEditType().type; let entityType = _self._editEntity.getEntityType(); if (editEntityPointType === DrawTools.EditPointType.CoordinateAxis) { } else if (editEntityPointType === DrawTools.EditPointType.OdlineEndNode) { /* 获取OD线的必要参数 */ let params = _self._editEntity.parent.getParams(); /* 重置编辑实体的位置 */ let positions = _self._calculateOdlinePositios(_self._sketchEditPoints[0], _self ._sketchEditPoints[1], parseInt(params.odlineHeight), parseInt(params.odlineCount)); _self._editEntity.polyline.positions = positions; /* 创建OD线的终点 */ _self._createEditOdlineEndPoint(_self._sketchEditPoints[1], _self._editEntity); } else if (editEntityPointType === DrawTools.EditPointType.OdlineStrartNode) { /* 获取OD线的必要参数 */ let params = _self._editEntity.parent.getParams(); let index = 1; for (let odEntity of _self._editOdlineEntities) { let lastPosition = _self._sketchEditPoints[index++]; let positions = _self._calculateOdlinePositios(_self._sketchEditPoints[0], lastPosition, parseInt(params.odlineHeight), parseInt(params.odlineCount)); odEntity.polyline.positions = positions; } _self._createEditOdlineStartPoint(_self._sketchEditPoints[0], _self._editOdlineEntities[0]); } else { if (editEntityPointType === DrawTools.EditPointType.Node || editEntityPointType === DrawTools.EditPointType.Middle) { /* 处理鼠标抬起实体的属性变更回调 */ _self._entityCallbackPropertyByMouseUp(); } else if (editEntityPointType === DrawTools.EditPointType.Center) { _self._entityCenterMouseUpEvent(event); } /* 删除节点、中点和中心点 */ _self._removeEntityByName(_self._sketchEditEntityNodeName); _self._removeEntityByName(_self._sketchEditEntityMiddleName); _self._removeEntityByName(_self._sketchEditEntityCenterName); /* 创建节点、中点和中心点 */ if (entityType === DrawTools.DrawType.Circle || entityType === DrawTools .DrawType .DynamicCircle) { /* 需要对点进行特殊处理 保证圆边界点始终在统一位置 */ let centerPosition = _self._editEntity.position._value; let boundaryPosition = _self._calculateCircleBoundaryPoint(centerPosition, _self ._sketchEllipseRadius); _self._sketchEditPoints[0] = centerPosition; _self._sketchEditPoints[1] = boundaryPosition; _self._createEditNodePoint(_self._sketchEditPoints, 1); _self._createEditCenterPoint(centerPosition); } else { /* 创建节点 */ _self._createEditNodePoint(_self._sketchEditPoints); /* 创建中心点 */ let centerPosition = _self._calculateCenterPosition(_self ._sketchEditPoints); _self._createEditCenterPoint(centerPosition); } /* 创建中点 */ if (entityType != DrawTools.DrawType.Rectangle && entityType != DrawTools.DrawType.Circle && entityType != DrawTools.DrawType .DynamicCircle) { if (entityType === DrawTools.DrawType.SpatialLine) { _self._createEditMiddlePoint(_self._sketchEditPoints, true); } else { _self._createEditMiddlePoint(_self._sketchEditPoints); } } } /* 清除选�����的实体 */ _self._editPointEntity = undefined; } }, /** * 实体中心点鼠标按下(拖拽点按下) * @ignore 生成方法时不对外公开 */ _entityCenterMouseDownEvent: function() { let _self = this; let entityPosition = this._editEntity.position._value; /* 删除节点、中点和中心点 */ this._removeEntityByName(this._sketchEditEntityNodeName); this._removeEntityByName(this._sketchEditEntityMiddleName); this._removeEntityByName(this._sketchEditEntityCenterName); /* 记录相关位置信息 */ this._startPoint = entityPosition; this._startMovePoints = []; this._movePoint = entityPosition; /* 获取编辑实体的类型 */ let editEntityType = this._editEntity.getEntityType(); /* 操作的如果是圆 */ if (editEntityType === DrawTools.DrawType.Circle || editEntityType === DrawTools .DrawType.DynamicCircle) { /* 记录移动点为所有的圆边界点 */ if (this._editEntity.polyline !== undefined) { for (let i = 0; i < this._ellipseOutlineCoordinates.length; i++) { this._startMovePoints.push(this._ellipseOutlineCoordinates[i]); } this._editEntity.polyline.positions = new Cesium.CallbackProperty( function() { return _self._ellipseOutlineCoordinates; }, false); } this._editEntity.position = new Cesium.CallbackProperty(function() { return _self._movePoint; }, false); } else if (editEntityType === DrawTools.DrawType.Polygon || editEntityType === DrawTools.DrawType .House) { /* 记录移动点为所有边界点 */ for (let i = 0; i < this._sketchEditPoints.length; i++) { this._startMovePoints.push(this._sketchEditPoints[i]); } /* 设置位置属性更新方式 */ _self._editEntity.polygon.hierarchy = new Cesium.CallbackProperty(function() { return { positions: _self._sketchEditPoints, }; }, false); if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = new Cesium.CallbackProperty(function() { return _self._sketchEditPoints; }, false); } } else if (editEntityType === DrawTools.DrawType.Polyline || editEntityType === DrawTools.DrawType .SpatialLine) { /* 记录移动点为所有边界点 */ for (let i = 0; i < this._sketchEditPoints.length; i++) { this._startMovePoints.push(this._sketchEditPoints[i]); } /* 设置属性更新方法回调 */ _self._editEntity.polyline.positions = new Cesium.CallbackProperty(function() { return _self._sketchEditPoints; }, false); } else if (editEntityType === DrawTools.DrawType.Rectangle) { /* 记录移动点为所有边界点 */ for (let i = 0; i < this._sketchEditPoints.length; i++) { this._startMovePoints.push(this._sketchEditPoints[i]); } /* 设置属性变更回调 */ _self._editEntity.rectangle.coordinates = new Cesium.CallbackProperty(_self ._callUpdateRectangleCoordinates(_self ._sketchEditPoints), false); /* 如果存在边界线 则特殊处理 */ if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = new Cesium.CallbackProperty(_self ._callUpdateRectangleOutlineCoordinates(), false); } } }, /** * 实体中心点鼠标移动 * @ignore * @param {Cesium.Event} event 事件 */ _entityCenterMouseMoveEvent: function(event) { this._calculatePositionsByCenter(event.endPosition, false); }, /* 换个思路试试 移动过程中不计算 待移动完成后计算 以便保���移动速度 要不实时计算高度 导致卡顿 */ /** * 计算中心拖拽点移动后实体点随之移动后的位置数据 * @ignore 生成方法时不对外公开 * @param {JSON} screenPosition 移动后的屏幕点 * @param {Boolean} calculateHeight 是否计算移动点的高度 */ _calculatePositionsByCenter: function(screenPosition, calculateHeight) { let _self = this; /* 起点转换为经纬度 */ let strLoc = this._cartesian3ToGeo(this._startPoint); /* 获取终止点 */ let endLoc = this._transfromFromScreenPoint(screenPosition); /* 计算两点之间的角度 */ var point1 = turf.point([strLoc.longitude, strLoc.latitude]); var point2 = turf.point([endLoc.gLocation.lng, endLoc.gLocation.lat]); var bearing = turf.bearing(point1, point2); /* 计算亮点���间���距��� 距���单���和���否���算���度*/ var options = { units: 'kilometers', calculateHeight: calculateHeight }; var distance = turf.distance(point1, point2, options); /* 根据移动的不同类型实体进行不同的操作 */ let editEntityType = this._editEntity.getEntityType(); if (editEntityType === DrawTools.DrawType.Circle || editEntityType === DrawTools .DrawType.DynamicCircle) { /* 循环处理所有移动点 */ for (let i = 0; i < this._startMovePoints.length; i++) { /* 计算转换后的位置 */ let position = this._calculateTransformPosition(this._startMovePoints[i], distance, bearing, options); /* 更新移动点数组 */ this._ellipseOutlineCoordinates[i] = position.clone(); } /* �������新中心���置数组 */ this._movePoint = endLoc.sLocation; } else { /* 循环处理所有移动点 */ for (let i = 0; i < this._startMovePoints.length; i++) { /* 计算转换后的位置 */ let position = this._calculateTransformPosition(this._startMovePoints[i], distance, bearing, options); /* 更新移动点数组 */ this._sketchEditPoints[i] = position.clone(); } } }, /** * 实体中心点鼠标抬起(即拖拽点) * @ignore 生成方法时不对外公开 * @param {Object} event 事件 */ _entityCenterMouseUpEvent: function(event) { /* 计算最新位置点 */ this._calculatePositionsByCenter(event.position, true); let _self = this; /* 根据不同的实体进行不同的操作 */ let editEntityType = this._editEntity.getEntityType(); if (editEntityType === DrawTools.DrawType.Circle || editEntityType === DrawTools .DrawType.DynamicCircle) { this._editEntity.position = this._movePoint; if (this._editEntity.polyline !== undefined) { this._editEntity.polyline.positions = this._ellipseOutlineCoordinates; } } else if (editEntityType === DrawTools.DrawType.Polyline || editEntityType === DrawTools.DrawType .SpatialLine) { this._editEntity.polyline.positions = this._sketchEditPoints; } else if (editEntityType === DrawTools.DrawType.Polygon || editEntityType === DrawTools.DrawType .House) { this._editEntity.polygon.hierarchy = { positions: _self._sketchEditPoints, }; if (this._editEntity.polyline != undefined) { this._editEntity.polyline.positions = this._sketchEditPoints; } } else if (editEntityType === DrawTools.DrawType.Rectangle) { this._editEntity.rectangle.coordinates = Cesium.Rectangle.fromDegrees(_self ._rectangleCoordinates[ 0], _self ._rectangleCoordinates[1], _self._rectangleCoordinates[2], _self ._rectangleCoordinates[3]); if (this._editEntity.polyline != undefined) { this._editEntity.polyline.positions = _self._rectangleOutlineCoordinates; } } }, /** * 处理鼠标抬起实体的属性变更回调 * @ignore 生成方法时不对外公开 */ _entityCallbackPropertyByMouseUp: function() { let _self = this; let entityType = _self._editEntity.getEntityType(); if (entityType === DrawTools.DrawType.Polyline) { _self._editEntity.polyline.positions = _self._sketchEditPoints; } else if (entityType === DrawTools.DrawType.Polygon || entityType === DrawTools.DrawType.House) { _self._editEntity.polygon.hierarchy = { positions: _self._sketchEditPoints, }; /* 此处���要特殊处理一下 */ if (_self._editEntity.polyline != undefined) { /* 如果创建区域的同时 创建了边界线 则根据区域的边界创建线 */ let polygonPositions = _self._editEntity.polygon.hierarchy._value.positions; let linePositions = []; for (let i = 0; i < polygonPositions.length; i++) { linePositions.push(polygonPositions[i].clone()); } /* 判断是否需要加入0号点 */ if (linePositions[0].x !== linePositions[linePositions.length - 1].x) { linePositions.push(linePositions[0].clone()); } _self._editEntity.polyline.positions = linePositions; } } else if (entityType === DrawTools.DrawType.Rectangle) { _self._editEntity.rectangle.coordinates = Cesium.Rectangle.fromDegrees(_self ._rectangleCoordinates[0], _self ._rectangleCoordinates[1], _self._rectangleCoordinates[2], _self ._rectangleCoordinates[3]); /* 判断矩形有边界线 特殊处理 */ if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = _self._rectangleOutlineCoordinates; } } else if (entityType === DrawTools.DrawType.Circle || entityType === DrawTools.DrawType .DynamicCircle) { /* 移动的是圆的点 需要特殊处理 */ _self._editEntity.ellipse.semiMajorAxis = _self._sketchEllipseRadius; _self._editEntity.ellipse.semiMinorAxis = _self._sketchEllipseRadius; /* 如果圆有边界线 则进行特殊处理 */ if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = _self._ellipseOutlineCoordinates; } } else if (entityType === DrawTools.DrawType.NormalWall || entityType === DrawTools.DrawType .DynamicWall || entityType === DrawTools.DrawType.TextWall) { _self._editEntity.wall.positions = _self._sketchEditPoints; _self._editEntity.wall.minimumHeights = _self._sketchWallHeights; _self._editEntity.wall.maximumHeights = _self._sketchWallMaxHeights; } }, /** * 处理鼠标按下实体的属性变更回调 * @ignore 生成方法时不对外公开 */ _entityCallbackPropertyByMouseDown: function() { let _self = this; /* 更改编辑实体的坐标数据获取方式 */ let entityType = _self._editEntity.getEntityType(); if (entityType === DrawTools.DrawType.Polyline || entityType === DrawTools.DrawType.SpatialLine) { _self._editEntity.polyline.positions = new Cesium.CallbackProperty( function() { return _self._sketchEditPoints; }, false); } else if (entityType === DrawTools.DrawType.Polygon || entityType === DrawTools.DrawType.House) { _self._editEntity.polygon.hierarchy = new Cesium.CallbackProperty( function() { return { positions: _self._sketchEditPoints, }; }, false); /* 此处需要特殊处理 ���断���面实体是否挂接着线 */ if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = new Cesium.CallbackProperty( function() { /* 如果创建区域的同时 创建了边界线 则根据区域的边界创建线 */ let polygonPositions = _self._sketchEditPoints; let linePositions = []; for (let i = 0; i < polygonPositions.length; i++) { linePositions.push(polygonPositions[i].clone()); } /* 判断是否需要加入0号点 */ if (linePositions[0].x !== linePositions[linePositions.length - 1].x) { linePositions.push(linePositions[0].clone()); } return linePositions; }, false); } } else if (entityType === DrawTools.DrawType.Rectangle) { _self._editEntity.rectangle.coordinates = new Cesium.CallbackProperty(_self ._callUpdateRectangleCoordinates(_self ._sketchEditPoints), false); /* 如果存在边界线则特殊处理 */ if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = new Cesium.CallbackProperty(_self ._callUpdateRectangleOutlineCoordinates(), false); } } else if (entityType === DrawTools.DrawType.Circle || entityType === DrawTools.DrawType .DynamicCircle) { /* 移动的是圆的点 需要特殊处理 */ if (_self._editPointEntity.getEditType().index === 1) { _self._editEntity.ellipse.semiMajorAxis = new Cesium.CallbackProperty( _self ._callUpdateEllipseMinorAxis(_self._sketchEditPoints), false); _self._editEntity.ellipse.semiMinorAxis = new Cesium.CallbackProperty( _self ._callUpdateEllipseMinorAxis(_self._sketchEditPoints), false); } /* 如果圆有边界线 则进行特殊���理 */ if (_self._editEntity.polyline != undefined) { _self._editEntity.polyline.positions = new Cesium.CallbackProperty( _self._callEllipseOutlineCoordinate(_self ._sketchEditPoints), false); } } else if (entityType === DrawTools.DrawType.NormalWall || entityType === DrawTools.DrawType .DynamicWall || entityType === DrawTools.DrawType.TextWall) { /* 位置属性变更 */ _self._editEntity.wall.positions = new Cesium.CallbackProperty(function() { return _self._sketchEditPoints; }, false); /* 高度属性变更 */ _self._editEntity.wall.minimumHeights = new Cesium.CallbackProperty(function() { return _self._sketchWallHeights; }, false); _self._editEntity.wall.maximumHeights = new Cesium.CallbackProperty(function() { return _self._sketchWallMaxHeights; }, false); } }, /** * 创建编辑点 * @ignore 生成方法时不对外公开 * @param {JSON} options 配置项 * @param {Cesium.Cartesian3} options.position 位置<必须填写> * @param {Array} options.color [颜色] 可选 * @param {Number} options.size [大小] 可选 * @param {Number} options.outlineWidth [边框大小] 可选 * @param {Array} options.outlineColor [边框颜色] 可选 * @param {DrawTools.EditPointType} options.editType 编辑点类型<必须填写> * @param {String} options.name [实体的名称] 可选 */ _createEditPointEntity(options) { let _self = this; if (options === undefined || options.position === undefined) return; if (options === undefined || options.editType === undefined) return; /* 初始化参数 */ let color = options.color != undefined ? options.color : [255, 0, 0, 1.0]; let size = options.size != undefined && typeof options.size === 'number' ? options.size : 9; let outlineWidth = options.outlineWidth != undefined && typeof options.outlineWidth === 'number' ? options.outlineWidth : 1; let outlineColor = options.outlineColor != undefined ? options.outlineColor : [255, 255, 255, 1.0]; /* 创建编辑点 */ let pointEntity = new Cesium.Entity({ name: options.name != undefined ? options.name : _self._sketchEntityName, position: options.position, point: { show: true, pixelSize: size, heightReference: Cesium.HeightReference.NONE, color: _self._toColorFromArray(color), outlineWidth: outlineWidth, outlineColor: _self._toColorFromArray(outlineColor), disableDepthTestDistance: 1.5e12, //小于该数值后关闭深度检测默认为空 // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, }, }) /* 设置编辑实体类型 */ pointEntity.setEditType(options.editType); /* 追加到集合中 */ _self._entities.add(pointEntity); }, /** * 创建可编辑的节点 * @ignore 生成方法时不对外公开 * @param {Array} positions 坐标集合 * @param {Number} startIndex [开始索引] 可选 默认为0 */ _createEditNodePoint(positions, startIndex) { this._sketchEditEntityNodeName = "SketchEditEntityNode"; let _self = this; /* 创建节点 */ this._sketchEditPoints = []; /* 判断开始创建索引 */ let strIndex = startIndex === undefined ? 0 : startIndex; for (let i = 0; i < positions.length; i++) { /* 获取当前点 */ let position = positions[i]; /* 存储可编辑点 */ this._sketchEditPoints.push(position.clone()); /* 小于索引不会创建 */ if (i < strIndex) continue; /* 为了保证不重复创建节点 需要进行特殊过滤处理 */ if (i !== 0 && position.x === positions[0].x && position.y === positions[0].y && position.z === positions[0] .z) { continue; } /* 创建节点前 特殊处理一下 以保证创建的节点 高度是正确的 */ let geoPoint = this._cartesian3ToGeo(position); /* 查询高度 */ let height = this._queryHeightFromGeo(geoPoint.longitude, geoPoint.latitude); /* 创建新位置 */ let newPosition = Cesium.Cartesian3.fromDegrees(geoPoint.longitude, geoPoint.latitude, height); /* 创建实体 */ _self._createEditPointEntity({ name: _self._sketchEditEntityNodeName, position: newPosition, size: 12, color: [0, 0, 255, 1.0], editType: { type: DrawTools.EditPointType.Node, index: i, }, }); } }, /** * 创建可编辑的空中点 * @ignore 生成方法时不对外公开 * @param {Array} positions 底部坐标集合 * @param {Array} heights 高度集合 * @param {Number} startIndex [开始索引] 可选 默认为0 */ _createEditSpatialPoint(positions, heights, startIndex) { /* 暂时不创建高空点 */ return; if (positions === undefined || heights === undefined) return; if (positions.length === undefined || heights.length === undefined) return; if (heights.length < positions.length) return; this._sketchEditEntitySpatialName = "SketchEditEntitySpatial"; let _self = this; /* 判断开始创建索引 */ let strIndex = startIndex === undefined ? 0 : startIndex; for (let i = 0; i < positions.length; i++) { /* 获取当前点 */ let p = positions[i]; /* 当前点转换为经纬度 */ let geoPoint = this._cartesian3ToGeo(p); /* 重新获取新的空间位置 */ let position = Cesium.Cartesian3.fromDegrees(geoPoint.longitude, geoPoint.latitude, heights[i]); /* 小于索引不会创建 */ if (i < strIndex) continue; /* 创建实体 */ this._createEditPointEntity({ name: _self._sketchEditEntitySpatialName, position: position, size: 12, color: [255, 0, 0, 1.0], editType: { type: DrawTools.EditPointType.Spatial, index: i, }, }); } }, /** * 创建可编辑的中点 * @ignore 生成方法时不对外公开 * @param {Array} positions 坐标集合 * @param {Boolean} isSpatial 是否是空中点 */ _createEditMiddlePoint(positions, isSpatial = false) { this._sketchEditEntityMiddleName = "SketchEditEntityMiddle"; let _self = this; if (!isSpatial) { /* 创建中点 */ for (let i = 1; i < positions.length; i++) { let p1 = positions[i - 1]; let p2 = positions[i]; /* 计算中点 */ let pCenter = this._calculateMiddlePoint(p1, p2); /* 创建中点实体 */ this._createEditPointEntity({ name: _self._sketchEditEntityMiddleName, position: pCenter, size: 9, color: [255, 255, 0, 1.0], editType: { type: DrawTools.EditPointType.Middle, index: i }, }); } } else { /* 创建中点 */ for (let i = 1; i < positions.length; i++) { let p1 = positions[i - 1]; let p2 = positions[i]; /* 计算中点 */ let pCenter = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2, z: (p1.z + p2.z) / 2, }; /* 创建中点实体 */ this._createEditPointEntity({ name: _self._sketchEditEntityMiddleName, position: pCenter, size: 9, color: [255, 255, 0, 1.0], editType: { type: DrawTools.EditPointType.Middle, index: i }, }); } } }, /** * 创建可编辑的中心点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position 坐标 */ _createEditCenterPoint(position) { let _self = this; this._sketchEditEntityCenterName = "SketchEditEntityCenter"; /* 创建实体 */ this._createEditPointEntity({ name: _self._sketchEditEntityCenterName, position: position, size: 12, color: [0, 255, 0, 0.1], outlineWidth: 2.0, outlineColor: [255, 255, 255, 1.0], editType: { type: DrawTools.EditPointType.Center, }, }); /* 创建中心点的同时将中心点付给当前的编辑实体 */ if (this._editEntity != undefined) { this._editEntity.position = position.clone(); } }, /** * 创建可编辑的OD线编辑终点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position 坐标 * @param {Cesium.Entity} joinEntity 关联的实体 */ _createEditOdlineEndPoint(position, joinEntity) { this._sketchEditEntityNodeName = "SketchEditEntityNode"; let _self = this; /* 创建节点前 特殊处理一下 以保证创建的节点 高度是正确的 */ let geoPoint = this._cartesian3ToGeo(position); /* 查询高度 */ let height = this._queryHeightFromGeo(geoPoint.longitude, geoPoint.latitude); /* 创建新位置 */ let newPosition = Cesium.Cartesian3.fromDegrees(geoPoint.longitude, geoPoint.latitude, height); /* 创建实体 */ _self._createEditPointEntity({ name: _self._sketchEditEntityNodeName, position: position, size: 12, color: [0, 0, 255, 1.0], editType: { type: DrawTools.EditPointType.OdlineEndNode, joinEntity: joinEntity, }, }); }, /** * 创建可编辑的OD线编辑起点 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position 坐标 * @param {Cesium.Entity} joinEntity 关联的实体 */ _createEditOdlineStartPoint(position, joinEntity) { this._sketchEditEntityNodeName = "SketchEditEntityNode"; let _self = this; /* 创建节点前 特殊处理一下 以保证创建的节点 高度是正确的 */ let geoPoint = this._cartesian3ToGeo(position); /* 查询高度 */ let height = this._queryHeightFromGeo(geoPoint.longitude, geoPoint.latitude); /* 创建新位置 */ let newPosition = Cesium.Cartesian3.fromDegrees(geoPoint.longitude, geoPoint.latitude, height); /* 创建实体 */ _self._createEditPointEntity({ name: _self._sketchEditEntityNodeName, position: position, size: 12, color: [0, 255, 0, 0.6], editType: { type: DrawTools.EditPointType.OdlineStrartNode, joinEntity: joinEntity, }, }); }, /** * 计算两个点的中点坐标 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position1 第一点 * @param {Cesium.Cartesian3} position2 第二点 */ _calculateMiddlePoint(position1, position2) { /* 计算经纬度坐标 */ let g1 = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position1); let g2 = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position2); /* 转换为度格式 */ let pt1 = [Cesium.Math.toDegrees(g1.longitude), Cesium.Math.toDegrees(g1.latitude)]; let pt2 = [Cesium.Math.toDegrees(g2.longitude), Cesium.Math.toDegrees(g2.latitude)]; /* 计算中间点 */ let tpt1 = turf.point(pt1); let tpt2 = turf.point(pt2); let midpoint = turf.midpoint(tpt1, tpt2).geometry.coordinates; /* 查询高度 */ let height = this._queryHeightFromGeo(midpoint[0], midpoint[1]); /* 转换为世界坐标 */ let result = Cesium.Cartesian3.fromDegrees(midpoint[0], midpoint[1], height); return result; }, /** * 世界坐标转换为经纬度坐标 * @ignore 生成方法时不对外公开 * @param {Cesium.Cartesian3} position 点 */ _cartesian3ToGeo: function(position) { let g = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position); return { longitude: Cesium.Math.toDegrees(g.longitude), latitude: Cesium.Math.toDegrees(g.latitude), height: g.height, } }, /** * 查询指定经纬度位置的高度 有地形则查地形 有模型则查模型 查询错误或未查询到,返回0 * @ignore 生成方法时不对外公开 * @param {Number} longitude 经度<度格式> * @param {Number} latitude 纬度<度格式> * @return {Number} 查询位置的高度值 */ _queryHeightFromGeo: function(longitude, latitude) { if (longitude === undefined || latitude === undefined || typeof longitude != 'number' || typeof latitude != 'number') return 0; let rLng = Cesium.Math.toRadians(longitude); let rLat = Cesium.Math.toRadians(latitude); let cartographic = new Cesium.Cartographic(rLng, rLat); /* 获取不采样的实体数组 */ let noQueryEntities = []; for (let i = 0; i < this._entities.values.length; i++) { if (this._entities.values[i].name === this._sketchEntityName) { noQueryEntities.push(this._entities.values[i]); } } let height = this._viewer.scene.sampleHeight(cartographic, noQueryEntities); if (height === undefined) return 0 else return height; }, /** * 查询指定经纬度位置的高度 有地形则查地形 有模型则查模型 查询错误或未查询到,返回0 * @ignore 生成方法时不对外公开 * @param {Number} longitude 经度<度格式> * @param {Number} latitude 纬度<度格式> * @param {Function} callComplete 查询回调函数callComplete(Number) 查询错误时为undefined */ _queryHeightFromGeoAsync: function(longitude, latitude, callComplete) { if (longitude === undefined || latitude === undefined || typeof longitude != 'number' || typeof latitude != 'number') return 0; let rLng = Cesium.Math.toRadians(longitude); let rLat = Cesium.Math.toRadians(latitude); let cartographic = new Cesium.Cartographic(rLng, rLat); let promise = this._viewer.scene.sampleHeightMostDetailed([cartographic]); promise.then(function(updatedPositions) { if (callComplete) callComplete(updatedPositions[0].height); }) }, /** * 清理编辑点 * @ignore 生成方法时不对外公开 */ _clearEditPoint: function() { /* 清理事件句柄 */ if (this._sketchEditHandler != undefined) { this._sketchEditHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN); this._sketchEditHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP); this._sketchEditHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); } /* 处理理编辑点数据 */ this._sketchEditPoints = []; this._sketchEditIndex = undefined; this._editEntity = undefined; this._removeEntityByName(this._sketchEditEntityNodeName); this._removeEntityByName(this._sketchEditEntityMiddleName); this._removeEntityByName(this._sketchEditEntityCenterName); this._removeEntityByName(this._sketchEditEntitySpatialName); }, }) /* 编辑函数相关 */ Object.assign(DrawTools.prototype, { /** * 检查颜色值 * @ignore 生成方法时不对外公开 * @param {Number} color 颜色值[0~255] * @return {Boolean} 是否满足颜色值要求 */ _checkColor: function(color) { if (color === undefined || color === null) return false; if (typeof color != 'number') return false; let intColor = parseInt(color); if (intColor < 0 || intColor > 255) return false; return true; }, /** * 检查透明度是否符合要求 * @ignore 生成方法时不对外公开 * @param {Object} alpha 透明度[0~1] */ _checkAlpha: function(alpha) { if (alpha === undefined || alpha === null) return false; if (typeof alpha != 'number') return false; let floatAlpha = parseFloat(alpha); if (floatAlpha < 0 || floatAlpha > 1) return false; return true; }, /** * 颜色和透明度检测 * @ignore 生成方法时不对外公开 * @param {Array} colorAndAlpah 颜���和透明度 * @return {Array} [0~255,0~255,0~255,0~1] 如果异常 则�����回undefined */ _checkColorAndAlpha: function(colorAndAlpah) { let setColor = undefined; if (!colorAndAlpah || colorAndAlpah.length === undefined || colorAndAlpah.length === 0) return undefined; if (colorAndAlpah.length === 1 && this._checkColor(colorAndAlpah[0])) { setColor = [colorAndAlpah[0], 0, 0, 1.0]; } else if (colorAndAlpah.length === 2 && this._checkColor(colorAndAlpah[0]) && this._checkColor( colorAndAlpah[1])) { setColor = [colorAndAlpah[0], colorAndAlpah[1], 0, 1.0]; } else if (colorAndAlpah.length === 3 && this._checkColor(colorAndAlpah[0]) && this._checkColor( colorAndAlpah[1]) && this._checkColor(colorAndAlpah[2])) { setColor = [colorAndAlpah[0], colorAndAlpah[1], colorAndAlpah[2], 1.0]; } else if (colorAndAlpah.length === 4 && this._checkColor(colorAndAlpah[0]) && this._checkColor( colorAndAlpah[1]) && this._checkColor(colorAndAlpah[2]) && this._checkAlpha( colorAndAlpah[ 3])) { setColor = [colorAndAlpah[0], colorAndAlpah[1], colorAndAlpah[2], colorAndAlpah[3]]; } return setColor; }, }); /** * 操作容器及按钮相关 主要为了适应App操作 */ Object.assign(DrawTools.prototype, { /** * 初始化操作容器 * @ignore */ _initOperationDom: function() { let _self = this; this._operationDomId = 'drawButtonDiv' this._operationDom = document.getElementById(this._operationDomId); /* 移除主容器 */ this._removeOperationDom() /* 创建主容器 */ this._createOperationMainDom() if ([DrawTools.DrawType.Rectangle, DrawTools.DrawType.Circle, DrawTools.DrawType.DynamicCircle, DrawTools.DrawType.VideoWall ].indexOf(this._drawType) === -1) { /* 创建回退按钮 */ let btnUndo = this._createOperationUndoButtonDom(); /* 挂接事件 */ btnUndo.onclick = function() { _self._operationExecuteEvent(Cesium.ScreenSpaceEventType.RIGHT_CLICK); } } if ([DrawTools.DrawType.Rectangle, DrawTools.DrawType.Circle, DrawTools.DrawType.DynamicCircle, DrawTools.DrawType.VideoWall ] === -1) { /* 创建完成按钮 */ let btnCompletion = this._crateOperationCompletionButtonDom(); /* 挂接事件 */ btnCompletion.onclick = function() { _self._operationExecuteEvent(Cesium.ScreenSpaceEventType.LEFT_CLICK); } } else { /* 创建完成按钮 */ let btnCompletion = this._crateOperationCompletionButtonDom(); /* 挂接事件 */ btnCompletion.onclick = function() { _self._operationExecuteEvent(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK); } } }, /** * 执行事件 * @ignore * @param {Cesium.ScreenSpaceEventType} eventType 事件类型 */ _operationExecuteEvent(eventType) { if (this._drawEventHandler !== undefined && this._drawEventHandler.isDestroyed() === false) { let event = { position: new Cesium.Cartesian2(300, 300), } let action = this._drawEventHandler.getInputAction(eventType); action(event); } }, /** * @ignore * 创建操作的主容器 */ _createOperationMainDom: function() { this._operationDom = document.createElement('div'); this._operationDom.id = this._operationDomId; this._operationDom.style.width = '80px'; this._operationDom.style.backgroundColor = 'rgba(5, 45, 155, 0.7)'; this._operationDom.style.borderRadius = '5px'; this._operationDom.style.display = 'flex'; this._operationDom.style.flexDirection = 'column'; this._operationDom.style.padding = '8px'; this._operationDom.style.justifyContent = 'center'; this._operationDom.style.position = 'absolute'; this._operationDom.style.bottom = '150px'; this._operationDom.style.right = '10px'; document.body.appendChild(this._operationDom); }, /** * 创建回退按钮 并返回示例 * @ignore * @return {Element} */ _createOperationUndoButtonDom: function() { let btnUndo = document.createElement('button'); btnUndo.id = "btnDrawBackout"; btnUndo.style.height = '30px'; btnUndo.style.marginBottom = '8px'; btnUndo.style.backgroundColor = 'rgba(52, 137, 255, 1.0)'; btnUndo.style.color = 'rgb(255, 255, 255)'; btnUndo.style.border = '0px solid red'; btnUndo.style.borderRadius = '5px'; btnUndo.innerHTML = '回退'; btnUndo.style.fontSize = '13px'; btnUndo.style.cursor = 'pointer'; this._operationDom.appendChild(btnUndo); return btnUndo; }, /** * 创建完成按钮 * @ignore * @return {Element} */ _crateOperationCompletionButtonDom: function() { let btnCompletion = document.createElement('button'); btnCompletion.id = "btnDrawComplete"; btnCompletion.style.height = '30px'; btnCompletion.style.backgroundColor = 'rgba(88, 185, 45, 1.0)'; btnCompletion.style.color = 'rgb(255, 255, 255)'; btnCompletion.style.border = '0px solid red'; btnCompletion.style.borderRadius = '5px'; btnCompletion.innerHTML = '完成'; btnCompletion.style.fontSize = '13px'; btnCompletion.style.cursor = 'pointer'; this._operationDom.appendChild(btnCompletion); return btnCompletion; }, /** * 移除操作容器 * @ignore */ _removeOperationDom: function() { if (this._operationDom !== null && this._operationDom !== undefined) { document.body.removeChild(this._operationDom); this._operationDom = undefined; } }, /** * 添加操作容器 * @ignore */ _createOperationDom: function() { if (this._isRuntimeApp()) { this._initOperationDom(); } } }) /** * 属性编辑相关(UI) */ Object.assign(DrawTools.prototype, { /** * 打开属性编辑窗口 * @ignore * @param {JSON} params 参数 * @param {Function} callEdit 编辑回调 * @param {Function} callRemove 移除回调 */ _openPropertyEditDialog: function(params, callEdit, callRemove) { this._editPropertyDialogDomId = 'dialog-property-dom'; this._registerDOMPropertyEdit = 'dialog-edit-property' /* 获取一个属性编辑组件 */ let PropertyEditComponent = customElements.get(this._registerDOMPropertyEdit); /* 如果组件还未注册 则进行注册 否则不在注册 避免重复注册的BUG */ if (PropertyEditComponent === undefined) { PropertyEditComponent = defineCustomElement(DialogEditProperty); customElements.define(this._registerDOMPropertyEdit, PropertyEditComponent); } /* 先关闭编辑框 */ this._closePropertyEditDialog(); /* 创建组件 */ let dialogPropertyElement = new PropertyEditComponent({ params: params, }) dialogPropertyElement.id = this._editPropertyDialogDomId; dialogPropertyElement.showDialog = true; document.body.appendChild(dialogPropertyElement); /* 监听修改事件 */ dialogPropertyElement.addEventListener( "submit", (e) => { if (callEdit) callEdit(e.detail[0]); }, false ); /* 监听移除事件 */ dialogPropertyElement.addEventListener( "remove", (e) => { if (callRemove) callRemove(); }, false ); }, /** * 关闭属性编辑框 * @ignore */ _closePropertyEditDialog() { let dom = document.getElementById(this._editPropertyDialogDomId); if (dom !== null && dom !== undefined) { document.body.removeChild(dom); } } }) /** * 绘制类型 */ DrawTools.DrawType = Object.freeze({ Point: 'point', Polyline: 'polyline', //贴地线 ArrowPolyline: 'arrowPolyline', //箭头线 DynamicPolyline: 'dynamicPolyline', //流动线 GrowPolyline: '发光线', OutlinePolyline: 'outlinePolyline', //描边线 OdLine: 'odLine', //OD线 Polygon: 'polygon', //贴地面 SpatialLine: 'spatialLine', //空间线 Circle: 'circle', //普通圆 DynamicCircle: 'dynamicCircle', //动态圆 Rectangle: 'rectangle', //矩形 NormalWall: 'normalWall', //普通墙 DynamicWall: 'dynamicWall', //动态墙 House: 'house', //房屋 TextWall: 'text', //文字 VideoWall: 'videoWall', //视频墙 }) /** * 点图标类型 */ DrawTools.IconType = Object.freeze({ Normal: 'normal', Blue: 'blue', Green: 'green', Violet: 'violter', }) /** * 编辑点类型 */ DrawTools.EditPointType = Object.freeze({ Node: 'node', //节点 Middle: 'middle', //中间点 Center: 'center', //中心点 CoordinateAxis: 'coordinateAxis', //坐标轴 OdlineStrartNode: 'odlineStartNode', //OD线起始点 OdlineEndNode: 'odlineEndNode', //OD线终点 }) /** * 绘制墙的类型 */ DrawTools.WallType = Object.freeze({ ColorWall: 'colorWall', //颜色墙 DynamicWall: 'dynamicWall', //动态墙 TextWall: 'textWall', //文字墙 }) /** * 绘制圆类型 */ DrawTools.CircleType = Object.freeze({ ColorCircle: 'colorCircle', //颜色圆 DynamicCircle: 'dynamicCircle', //动态圆 }) /** * 绘制线类型 */ DrawTools.PolylineType = Object.freeze({ NormalPolyline: 'normalPolyline', //普通线 ArrowsPolyline: 'arrowsPolyline', //箭头线 DynamicPolyline: 'dynamicPolyline', //流动线 DottedPolyline: 'dottedPolyline', //虚线 GrowPolyline: 'growPolyline', //发光线 OutlinePolyline: 'outlinePolyline', //描边线 }) /** * 绘制面类型 */ DrawTools.PolygonType = Object.freeze({ NormalPolygon: 'normalPolygon', //贴地面 HousePolygon: 'housePolygon', //拉伸贴地面 }) /** * 运行环境类型 */ DrawTools.RuntimeEnvironment = Object.freeze(({ App: 'app', Web: 'web' })) class WallMaterialProperty { /** * 构造方法 * @ignore 无需公开 * @param {JSON} options 配置项 * @param {Cesium.Viewer} options.viewer 着色器运行所需的视图 * @param {Cesium.Color} options.color [墙的颜色,默认蓝色] 可选 * @param {Number} options.duration [循环时间 默认1000] 可选 * @param {String} options.trailImage 墙的贴图 * @param {JSON} options.param 着色器参数 * @param {Number} options.param.count [数量 可选 默认为1] * @param {String} options.param.direction [方向 可选 默认竖直 ] 取值vertical/horizontal * @param {String} options.param.order [顺序 可选 上下/下上/顺时针/逆时针 与方向配合使用 ] 取值+/- */ constructor(options) { /* 着色器运行依赖的视图 */ this._viewer = options.viewer; /* 变更事件 */ this._definitionChanged = new Cesium.Event(); this._color = undefined; /* 墙的颜色 */ this.color = options.color || Cesium.Color.BLUE; /* 动态循环周期 */ this.duration = options.duration || 1000; /* 墙的贴图 */ this.trailImage = options.trailImage; /* 默认时间 */ this._time = (new Date()).getTime(); /* 材质类型名称 */ this._materialTypeName = 'WallMaterial' + this._guid(); /* 存储相关参数的属性 以便后期进行追踪修改 */ this._param = { color: this.color._value.toCssColorString(), image: this.trailImage, duration: this.duration, count: 0, direction: '', order: '', } /* 将材质加入缓存 以便重复利用 */ Cesium.Material._materialCache.addMaterial(this._materialTypeName, { fabric: { type: this._materialTypeName, uniforms: { time: -20, color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), image: options.trailImage, }, source: this._getDirectionWallShader(options.param) }, translucent: function(material) { /* 材质是否半透明 */ return true; } }); } /** * 生成GUID随机数 * @ignore 无需公开 */ _guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } /** * 重新获取类型方法 * @ignore 无需公开 * @param {Cesium.JulianDate} time 时间 */ getType(time) { return this._materialTypeName; } /** * 重写获取值方法 * @ignore 无需公开 * @param {Cesium.JulianDate} time * @param {JSON} result */ getValue(time, result) { if (!Cesium.defined(result)) { result = {}; } result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.BLUE, result.color); result.image = this.trailImage; if (this.duration) { result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration; } this._viewer.scene.requestRender(); return result; } /** * 重写对比函数 * @ignore 无需公开 * @param {Object} other 传入对比对象 */ equals(other) { return (this === other || (other instanceof WallMaterialProperty && Cesium.Property.equals(this ._color, other._color) && other._param.order === this._param.order && other._param.count === this._param.count && other._param.direction === this._param.direction && other.duration === this .duration)); } /** * 创建着色器资源 * @ignore 无需公开 * @param {JSON} options 配置项 * @param {Number} options.count [数量 可选 默认为1] * @param {String} options.direction [方向 可选 默认竖直 ] 取值vertical/horizontal * @param {String} options.order [顺序 可选 上下/下上/顺时针/逆时针 与方向配合使用 ] 取值+/- */ _getDirectionWallShader(options) { let op = Cesium.defaultValue(options, {}); // console.log('>>>op===', op); let count = op.count !== undefined && typeof op.count === 'number' && op.count > 0 ? op .count : 1; let direction = op.direction === 'horizontal' ? 'horizontal' : 'vertical'; let order = op.order === '+' ? '+' : '-'; this._param.count = count; this._param.direction = direction; this._param.order = order; let materail = ''; /* 补充参数 */ // console.log(this._param); materail += 'czm_material czm_getMaterial(czm_materialInput materialInput){\n' + ' czm_material material = czm_getDefaultMaterial(materialInput);\n' + ' vec2 st = materialInput.st;\n'; if (direction === 'vertical') { materail += ' vec4 colorImage = texture2D(image,vec2(st.s,fract(float(' + count + ')*st.t ' + order + ' time)));\n'; } else if (direction === 'horizontal') { materail += ' vec4 colorImage = texture2D(image, vec2(fract(float(' + count + ')*st.s ' + order + ' time), st.t));\n' } materail += ' vec4 fragColor;\n' + ' fragColor.rgb = color.rgb / 1.0;\n' + ' fragColor = czm_gammaCorrect(fragColor);\n' + ' material.alpha = colorImage.a * color.a;\n' + ' material.diffuse = color.rgb;\n' + ' material.emission = fragColor.rgb;\n' + ' return material;\n' + '}'; return materail; } } /** * 增加默认属性 */ Object.defineProperties(WallMaterialProperty.prototype, { /** * @ignore 无需公开 * 判断是否相等,返回false表示属性一直在变化中 */ isConstant: { get: function() { return false; } }, /** * @ignore 无需公开 * 事件变更 */ definitionChanged: { get: function() { return this._definitionChanged; } }, /* 颜色属性 */ color: Cesium.createPropertyDescriptor('color') }) /** * 创建者:王成 * 操作系统:MAC * 创建日期:2022年12月29日 * 描述:动态扩散圆材质 */ class CircleMaterialProperty { /** * 构造方法 * @ignore 无需公开 * @param {JSON} options 配置项 * @param {Cesium.Viewer} options.viewer 着色器运行所需的视图 * @param {Cesium.Color} options.color [圆环的颜色,默认蓝色] 可选 * @param {Number} options.duration [循环时间 默认1000] 可选 * @param {Number} options.count [圆环的数量 可选 默认为1] */ constructor(options) { /* 着色器运行依赖的视图 */ this._viewer = options.viewer; /* 变更事件 */ this._definitionChanged = new Cesium.Event(); this._color = undefined; /* 扩算圆环的颜色 */ this.color = options.color || Cesium.Color.BLUE; /* 扩散圆环的数量 */ this.count = options.count || 1.0; /* 动态循环周期 */ this.duration = options.duration || 1000; /* 默认时间 */ this._time = (new Date()).getTime(); /* 材质类型名称 */ this._materialTypeName = 'jtCircleMaterial' /* 存储相关参数的属性 以便后期进行追踪修改 */ this._param = { color: this.color._value.toCssColorString(), duration: this.duration, count: this.count, } /* 将材质加入缓存 以便重复利用 */ Cesium.Material._materialCache.addMaterial(this._materialTypeName, { fabric: { type: this._materialTypeName, uniforms: { time: 0, color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), count: 1.0, }, source: this._getCircleMaterial(), }, translucent: function(material) { /* 材质是否半透明 */ return true; } }); } /** * @ignore 无需公开 * 获取材质着色器Shader */ _getCircleMaterial() { let circleMaterial = "czm_material czm_getMaterial(czm_materialInput materialInput)\n" + "{\n" + " czm_material material = czm_getDefaultMaterial(materialInput);\n" + " material.diffuse = 1.5 * color.rgb;\n" + " vec2 st = materialInput.st;\n" + " vec3 str = materialInput.str;\n" + " float dis = distance(st, vec2(0.5, 0.5));\n" + " float per = fract(time);\n" + " if (abs(str.z) > 0.001)\n" + " {\n" + " //着色器渲染停止,不在绘制内容 \n" + " discard;\n" + " }\n" + " if (dis > 0.5)\n" + " {\n" + " //超出半径范围时,着色器渲染停止 \n" + " discard;\n" + " } else {\n" + " //把半径分成count份,每两份之间的间隔距离 \n" + " float perDis = 0.5 / count;\n" + " float disNum;\n" + " float bl = 0.0;\n" + " //循环,最多999个环 \n" + " for (int i = 0; i <= 999; i++)\n" + " {\n" + " //判断是否属于数量内的环 \n" + " if (float(i) <= count)\n" + " {\n" + " disNum = perDis * float(i) - dis + per / count;\n" + " if (disNum > 0.0)\n" + " {\n" + " if (disNum < perDis)\n" + " {\n" + " bl = 1.0 - disNum / perDis;\n" + " } else if (disNum - perDis < perDis) {\n" + " bl = 1.0 - abs(1.0 - disNum / perDis);\n" + " }\n" + " material.alpha = color.a * pow(bl, 3.0);\n" + " }\n" + " }\n" + " }\n" + " }\n" + " return material;\n" + "}\n"; return circleMaterial; } } /** * @ignore 无需公开 * 必须重写的方法 */ Object.assign(CircleMaterialProperty.prototype, { /** * 重新获取类型方法 * @ignore 无需公开 * @param {Cesium.JulianDate} time 时间 */ getType: function(time) { return this._materialTypeName; }, /** * 重写获取值方法 * @ignore 无需公开 * @param {Cesium.JulianDate} time * @param {JSON} result */ getValue: function(time, result) { if (!Cesium.defined(result)) { result = {}; } result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.BLUE, result .color); result.count = this.count; if (this.duration) { result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration; } this._viewer.scene.requestRender(); return result; }, /** * 重写对比函数 * @ignore 无需公开 * @param {Object} other 传入对比对象 */ equals: function(other) { return (this === other || (other instanceof CircleMaterialProperty && Cesium.Property.equals(this ._color, other._color))); } }) /** * 默认属性 */ Object.defineProperties(CircleMaterialProperty.prototype, { /** * 判断是否相等,返回false表示属性一直在变化中 * @ignore 无需公开 */ isConstant: { get: function() { return false; } }, /** * 事件变更 * @ignore 无需公开 */ definitionChanged: { get: function() { return this._definitionChanged; } }, /* 颜色属性 */ color: Cesium.createPropertyDescriptor('color') }) /* 输出 */ export { DrawTools }