/** * 创建者:王成 * 操作系统:MAC * 创建日期:2023年1月30日 * 描述:通过矩形渲染tile,从而达到渲染图片可以浮动在实景三维上面的效果 */ /* 扩展系统Date属性Format 用于格式化日期 yyMMdd HH:ss:mm */ Date.prototype.Format = function(fmt) { // author: meizz var o = { "M+": this.getMonth() + 1, // 月份 "d+": this.getDate(), // 日 "h+": this.getHours(), // 小时 "m+": this.getMinutes(), // 分 "s+": this.getSeconds(), // 秒 "q+": Math.floor((this.getMonth() + 3) / 3), // 季度 "S": this.getMilliseconds() // 毫秒 }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (( "00" + o[k]).substr(("" + o[k]).length))); return fmt; } /* 引入Cesium */ import * as Cesium from 'cesium'; /* 扩展primivite方法 */ /** * 设置Id * @param {String} id */ Cesium.GroundPrimitive.prototype.setId = function(id) { this._id = id; } /** * 获取Id */ Cesium.GroundPrimitive.prototype.getId = function() { return this._id; } /** * 根据Id进行查询 * @param {String} id * @return {Cesium.GroundPrimitive} 返回查询到的Primivite 未查询到 则返回undefined */ Cesium.PrimitiveCollection.prototype.getById = function(id) { let findPrimivite = this._primitives.find(obj => { if (obj._id === id) return obj; }) return findPrimivite; } /** * 根据Id进行移除操作 * @param {String} id */ Cesium.PrimitiveCollection.prototype.removeById = function(id) { let findPrimitive = this.getById(id); if (findPrimitive !== undefined) { return this.remove(findPrimitive); } else { return false; } } /* 创建类 */ class CrImageServerLayer { /** * 构造函数 * @param {Cesium.Viewer} options.viewer 地图视图容器 * @param {CrImageServerLayer.ProviderType} options.providerType 数据提供器类型 * @param {JSON} options.config 对应该提供器的配置参数 * @param {Number} options.opacity 图层透明度[0.0~1.0] [默认0.3] */ constructor({ viewer, providerType = CrImageServerLayer.ArcGisMapServerImageryProvider, config = {}, opacity = 0.75, show = true, } = {}) { let _self = this; /* 地图视图 外部传入 必须参数 */ this._viewer = viewer; /* 服务提供者配置参数 */ this._providerType = providerType; /* 服务提供者 */ this._provider = undefined; /* 服务提供者切片方案 */ this._tilingScheme = undefined; /* 服务的切片的最大/最小层级 */ this._maximumLevel = 0; this._minimumLevel = 20; /* 切片大小 */ this._tileWidth = 0; this._tileHeight = 0; /* 服务数据范围 */ this._rectangle = undefined; /* 服务提供者的配置参数 */ this._config = config; /* 透明度 外部传入 */ this._opacity = opacity; /* 图层随机标识 */ this._renderName = this._guid(); /* 当前图层的渲染集合 */ this._primitives = new Cesium.PrimitiveCollection(); this._viewer.scene.primitives.add(this._primitives); /* 渲染集合 */ this._renderPrimitives = new Map(); /* 移除渲染集合 */ this._removePrimitives = new Map(); /* 是否渲染标志 */ this._isUpdateTile = show; /* 是否输出测试信息 */ this._isDebug = true; /* 缓存 */ this._chacheImages = new Map(); /* 创建一个线程 用于处理移除任务 */ this._sendTask = true; let workerBlob = new Blob([`(${downloadWorker.toString ()})()`]); // 把函数转成一个自执行函数 this._worker = new Worker(URL.createObjectURL(workerBlob)); /* 接收反馈 */ this._worker.onmessage = function(event) { for (let key of event.data) { _self._primitives.removeById(key); _self._removePrimitives.delete(key); _self._renderPrimitives.delete(key); } _self._sendTask = true; } /* 初始化 */ this._init(); } /** * 初始化 */ _init() { let _self = this; /* 创建服务提供者 */ switch (this._providerType) { case CrImageServerLayer.ProviderType.ArcGisMapServerImageryProvider: this._provider = new Cesium.ArcGisMapServerImageryProvider(this._config); break; case CrImageServerLayer.ProviderType.UrlTemplateImageryProvider: this._provider = new Cesium.UrlTemplateImageryProvider(this._config); break; case CrImageServerLayer.ProviderType.WebMapTileServiceImageryProvider: this._provider = new Cesium.WebMapTileServiceImageryProvider({ url: _self._config.url, layer: 1, style: 'default', format: 'image/png', tileMatrixSetID: 'default028mm', maximumLevel: _self._config.maxLevel ? _self._config.maxLevel : 19, minimumLevel: _self._config.minLevel ? _self._config.maxLevel : 0, }); break; } /* 服务提供者判断 */ if (this._provider === undefined) { this._console('没有服务提供者,无法初始化!'); return; } /* 激活服务提供者 注册刷帧事件 */ this._provider.readyPromise.then(function(result) { /* 初始化参数 */ _self._rectangle = _self._provider.rectangle; _self._tilingScheme = _self._provider.tilingScheme; _self._maximumLevel = _self._provider.maximumLevel === undefined ? 22 : _self._provider .maximumLevel; _self._minimumLevel = _self._provider.minimumLevel === undefined ? 0 : _self._provider .minimumLevel; _self._tileWidth = _self._provider.tileWidth; _self._tileHeight = _self._provider.tileHeight; /* 输出调试信息 */ if (_self._isDebug) _self._printDebug(); /* 注册事件 */ _self._viewer.scene.postRender.addEventListener(() => { if (_self._isUpdateTile) { /* 设置运行标志为false 等待计算完成 */ _self._isUpdateTile = false; /* 投影瓦片集合 */ _self._renderTiles(); } }); /* 测试 */ // for (let i = 0; i < 20; i++) { // /* 找到对应级别的子节点 */ // let filterQuadTree = quadTree.filter(function(obj) { // return obj.level === i; // }) // /* 创建子节点 */ // for (let findQuadTree of filterQuadTree) { // let rectangle = findQuadTree.rectangle; // /* 将该矩形按照四叉树规则分割为4个高层级的矩形 */ // let rect1 = Cesium.Rectangle.subsection(rectangle, 0, 0, 0.5, 0.5); // let rect2 = Cesium.Rectangle.subsection(rectangle, 0.5, 0, 1.0, 0.5); // let rect3 = Cesium.Rectangle.subsection(rectangle, 0, 0.5, 0.5, 1.0); // let rect4 = Cesium.Rectangle.subsection(rectangle, 0.5, 0.5, 1.0, 1.0); // /* 查询当前节点的行列号 */ // let centerPoint = Cesium.Rectangle.center(rectangle); // let xy = _self._tilingScheme.positionToTileXY(centerPoint, 0); // findQuadTree.x = xy.x; // findQuadTree.y = xy.y; // } // } // let quadTree = new QuadTreeTile(0, 0, _self._tilingScheme, _self._rectangle, 0, 20); // _self._console(quadTree); /* 找到有效数据 */ // _self._findTile(quadTree); }) } _findTile(tile) { // this._console(tile); if (tile.children.length > 0) { if (Cesium.Rectangle.intersection(tile.rectangle, this._rectangle)) { this._console(tile.x, tile.y, tile.level); } this._findTile(tile.children[0]); this._findTile(tile.children[1]); this._findTile(tile.children[2]); this._findTile(tile.children[3]); } else { this._console('结束'); } } /** * 生成GUID随机数 */ _guid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); } return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4()); } /** * 输出调试信息 */ _printDebug() { /* 数据提供者的切片方案 */ let tiling = this._provider.tilingScheme; /* WGS84坐标系的切片方案 */ let tiling84 = new Cesium.GeographicTilingScheme(); /* 绘制数据提供者的数据范围 */ this._drawDebugRectangle(this._rectangle, Cesium.Color.GREEN); /* 根据行列号和等级创建调试矩形 */ let rect = tiling84.tileXYToRectangle(1696, 312, 10); } /** * 绘制调试矩形 * @param {Cesium.Rectangle} rectangle 绘制的矩形 * @param {Cesium.Color} color 矩形边框颜色 */ _drawDebugRectangle(rectangle, color) { /* 计算矩形的外包范围 */ let positions = this._calculateRectangleOutlineCoordinates(rectangle); /* 创建矩形图元 */ let rectangleInstance = new Cesium.GeometryInstance({ geometry: new Cesium.GroundPolylineGeometry({ positions: positions, width: 8, }) }) /* 创建对象 */ let primivite = new Cesium.GroundPolylinePrimitive({ geometryInstances: rectangleInstance, appearance: this._createMaterialColorAppearance('rgba(0,255,0,1)'), classificationType: Cesium.ClassificationType.BOTH, }) /* 加入数据集 */ this._primitives.add(primivite); } /** * 创建颜色着色器 * @param {String} color rgba(r,g,b,a) */ _createMaterialColorAppearance(color) { /* 创建材质 */ let material = new Cesium.Material({ fabric: { type: 'Color', uniforms: { color: new Cesium.Color.fromCssColorString(color), } } }); /* 创建着色器 */ let appearance = new Cesium.MaterialAppearance({ material: material, }); /* 返回 */ return appearance; } /** * 根据画布创建材质 * @param {Canvas} canvas 画布 */ _createMaterialImageAppearance(canvas) { /* 创建着色器 */ let material = Cesium.Material.fromType('Image', { image: canvas, }) let appearance = new Cesium.MaterialAppearance({ material: material, }) /* 返回 */ return appearance; } /** * 输出消息 * @param {Object} res */ _console(...rest) { if (this._isDebug) console.log('===' + new Date().Format('yyyy-MM-dd HH:mm:ss') + '>>>', rest); } /** * 渲染瓦片集合 */ _renderTiles() { let _self = this; /* 获取当前视图渲染的瓦片集合 */ let tilesToRender = this._viewer.scene.globe._surface._tilesToRender; if (tilesToRender === undefined || tilesToRender.length === 0) { this._isUpdateTile = true; return; } else { new Promise((resolve, reject) => { /* 对瓦片数组按照level进行排序 以保证后续瓦片重投影时的重叠移除无误 */ tilesToRender.sort(function(obj1, obj2) { let level1 = parseInt(obj1.level); let level2 = parseInt(obj2.level); return level1 - level2; }) /* 返回排序后的渲染瓦片数据集 开始异步计算 */ resolve(tilesToRender); }).then(tiles => { /* Cesium渲染瓦片为84投影,如果不一致需要异步重投影瓦片数据集 */ _self._asyncProjectionTiles(tiles); }) } } /** * 根据行列和等级生成key * @param {Number} x 行 * @param {Number} y 列 * @param {Number} level 等级 */ _createKey(x, y, level) { let key = `${this._renderName}_${x}_${y}_${level}`; return key; } /** * 投影瓦片集合 * @param {Object} tiles 原始渲染瓦片集合 */ _asyncProjectionTiles(tiles) { let renderTiles = []; /* 循环投影 */ for (let tile of tiles) { /* 对单个瓦片进行重投影 */ let proTiles = this._projectionTile(tile); for (let proTile of proTiles) { /* 瓦片实体唯一标识 */ let key = this._createKey(proTile.x, proTile.y, proTile.level); /* 查找瓦片是否已经存在 存在则过滤 以免重复存在 */ let subTile = renderTiles.find(obj => { return obj.x === proTile.x && obj.y === proTile.y; }) if (subTile === undefined) { /* 重投影瓦片范围与数据范围的叠合计算 */ let isExists = false; for (let eTile of renderTiles) { if (Cesium.Rectangle.intersection(eTile.rectangle, proTile.rectangle)) { /* 追加子集 方便后期进行层级处理 */ eTile.childTiles.push(key); isExists = true; break; } } /* 加入渲染集合 */ if (!isExists) { renderTiles.push({ key: key, x: proTile.x, y: proTile.y, level: proTile.level, rectangle: proTile.rectangle, childTiles: [], }); } } } } /* 清理低层级元素 */ let i = renderTiles.length; let appendTiles = []; while (i--) { let findTile = renderTiles[i]; if (findTile.childTiles.length >= 1) { /* 创建高层级的瓦片 */ let tiles = this._createFourTiles(findTile); for (let tile of tiles) { appendTiles.push(tile); } /* 如果存在高层级 则删除低层级 */ renderTiles.splice(i, 1); } } /* 将四叉树追加的层级数据加入到渲染集合中 */ for (let appendTile of appendTiles) { renderTiles.push(appendTile); } /* 对数组进行排序 */ renderTiles.sort(function(obj1, obj2) { let level1 = parseInt(obj1.level); let level2 = parseInt(obj2.level); return level1 - level2; }) /* 渲染数据到视图中 */ this._renderTilesToViewer(renderTiles); } /** * 根据矩形和登记查询高一等级的行列号 * @param {Cesium.Rectangle} rectangle */ _createTileByRectangleAndLevel(rectangle, level) { /* 获取矩形中心点 */ let center = Cesium.Rectangle.center(rectangle); /* 新层级 */ let nLevel = parseInt(level) + 1; /* 查询高一层级的行列号 */ let query = this._provider.tilingScheme.positionToTileXY(center, nLevel); if (query === undefined) return undefined; /* 返回结果 */ return { key: this._createKey(query.x, query.y, nLevel), x: query.x, y: query.y, level: nLevel, rectangle: rectangle, childTiles: [], } } /** * 创建四个高层级的瓦片 * @param {Object} tile 当前瓦片 */ _createFourTiles(tile) { let rects = []; let results = []; let rectangle = tile.rectangle; /* 将该矩形按照四叉树规则分割为4个高层级的矩形 */ rects.push(Cesium.Rectangle.subsection(rectangle, 0, 0, 0.5, 0.5)); rects.push(Cesium.Rectangle.subsection(rectangle, 0.5, 0, 1.0, 0.5)); rects.push(Cesium.Rectangle.subsection(rectangle, 0, 0.5, 0.5, 1.0)); rects.push(Cesium.Rectangle.subsection(rectangle, 0.5, 0.5, 1.0, 1.0)); for (let rect of rects) { /* 判断高层级的矩形是否与谁范围存在交集 */ if (Cesium.Rectangle.intersection(rect, this._rectangle)) { /* 查询高一层级的Tile */ let newTile = this._createTileByRectangleAndLevel(rect, tile.level); /* 如果存在加入到返回集合中 */ if (newTile !== undefined) results.push(newTile); } } return results; } /** * 渲染瓦片到视图中 * @param {Object} tiles */ _renderTilesToViewer(tiles) { let _self = this; /* 确定哪些渲染瓦片已失效 对失效的实体进行清理 */ let deleteKeys = []; for (let [key, tile] of this._renderPrimitives) { let findTile = tiles.find(obj => { return obj.key === key; }) if (findTile === undefined) { deleteKeys.push(key); } } for (let key of deleteKeys) { /* 从当前渲染集合中将失效瓦片移除元素 */ // this._renderPrimitives.delete(key); /* 移除渲染元素 */ // this._primitives.removeById(key); this._removePrimitives.set(key, { key: key, }); } /* 对过滤后的数据集进行渲染 */ for (let tile of tiles) { /* 判断当前渲染的数据是否已经渲染且有效 */ if (!this._renderPrimitives.has(tile.key)) { /* 将数据渲染到视图中 */ this._renderSimpleTileToViewer(tile); /* 追加到渲染集合中 该集合中始终保持当前渲染的最新数据 */ this._renderPrimitives.set(tile.key, { key: tile.key, renderImage: false, }); /* 初始化y */ let tile_y = tile.y; /* 利用数据提供器获取图片 */ this._provider.requestImage(tile.x, tile_y, tile.level).then(function(image) { /* 判断是否返回图片资源 */ if (image !== undefined) { /* 对图片资源进行Y轴翻转 */ let primise = createImageBitmap(image, { imageOrientation: 'flipY', }); primise.then(function(resImage) { let renderPrimitive = _self._primitives.getById(tile .key); if (renderPrimitive !== undefined) { let canvas = _self._createCanvas(tile, resImage, _self ._isDebug); renderPrimitive.appearance = _self ._createMaterialImageAppearance( canvas); /* 修改集合中内容 */ if (_self._renderPrimitives.has(tile.key)) { let item = _self._renderPrimitives.get(tile .key); item.renderImage = true; _self._renderPrimitives.set(tile.key, item); } /* 缓存起来备用 */ // if (!_self._chacheImages.has(tile.key)) { // _self._chacheImages.set(tile.key, resImage); // } } /* 释放图片资源 */ image.close(); }) } }).catch(err => { _self._console('错误', err); /* 修改集合中内容 */ if (_self._renderPrimitives.has(tile.key)) { let item = _self._renderPrimitives.get(tile.key); item.renderImage = true; _self._renderPrimitives.set(tile.key, item); } }); } } if (this._sendTask && this._removePrimitives.size > 0) { this._sendTask = false; this._console('发送处理任务...'); let renderPrimitives = new Map(); /* 传递之前深度克隆 */ for (let [key, item] of this._renderPrimitives) { let strItem = JSON.stringify(item); renderPrimitives.set(key, JSON.parse(strItem)); } /* 深度克隆需要移除的实体集合 */ let removePrimitives = []; for (let [key, removeEntity] of this._removePrimitives) { removePrimitives.push(key); } /* 发送处理任务 */ this._worker.postMessage({ removePrimitives: removePrimitives, renderPrimitives: renderPrimitives, }); } /* 重启计算标志 */ // this._console('循环结束...'); this._isUpdateTile = true; } /** * 渲染单个瓦片到视图中 * @param {Object} tile */ _renderSimpleTileToViewer(tile) { /* 创建画布 */ const canvas = this._createCanvas(tile, undefined, this._isDebug); let bjPositions = this._calculateRectangleOutlineCoordinates(tile .rectangle); /* 创建图形要素 */ let instance = new Cesium.GeometryInstance({ geometry: new Cesium.RectangleGeometry({ rectangle: tile.rectangle, }) }); /* 创建着色器 */ let appearance = this._createMaterialImageAppearance(canvas); /* 创建源语 */ let primitive = new Cesium.GroundPrimitive({ geometryInstances: instance, appearance: appearance, }); /* 设置Id */ primitive.setId(tile.key); /* 加入集合 */ return this._primitives.add(primitive); } /** * 根据瓦片创建画布 * @param {Object} tile 瓦片 * @param {Object} image 绘制的图片 * @param {boolean} islabel 是否绘制标签 */ _createCanvas(tile, image, islabel) { /* 获取服务提供者的切片方案 */ let provider = this._provider; const canvas = document.createElement("canvas"); canvas.width = provider.tileWidth; canvas.height = provider.tileHeight; const context = canvas.getContext("2d"); if (image !== undefined) { context.globalAlpha = this._opacity; context.drawImage(image, 0, 0, canvas.width, canvas.height); } if (this._isDebug) { context.strokeStyle = 'rgba(255,255,0,1)'; context.lineWidth = 2; context.strokeRect(0, 0, canvas.width, canvas.height); } if (islabel !== undefined && islabel === true) { context.globalAlpha = 1.0; /* 创建标签 */ context.font = "20px Arial"; context.textAlign = "center"; context.fillStyle = 'rgba(255,255,0)'; context.strokeStyle = 'rgba(255,255,255,1)'; context.lineWidth = 2; context.strokeText(`L: ${tile.level}`, 126, 86); context.fillText(`L: ${tile.level}`, 126, 86); context.strokeText(`X: ${tile.x}`, 126, 136); context.fillText(`X: ${tile.x}`, 126, 136); context.strokeText(`Y: ${tile.y}`, 126, 186); context.fillText(`Y: ${tile.y}`, 126, 186); } /* 返回画布 */ return canvas; } /** * 投影当前瓦片 * @param {Object} tile */ _projectionTile(tile) { if (this._tilingScheme instanceof Cesium.GeographicTilingScheme) { return [{ x: tile.x, y: tile.y, level: tile.level, rectangle: tile._rectangle, }]; } /* 获取矩形 */ let rectangle = tile._rectangle; // let imageryLevel = parseInt(tile.level) + 1; let imageryLevel = parseInt(tile.level); let mercatorTilingScheme = this._provider.tilingScheme; let res = []; /* 先判断当前的切片范围是否与提供者的数据范围有交集 */ let interRectangle = Cesium.Rectangle.intersection(rectangle, this._rectangle); /* 如果当前计算的瓦片与数据范围无交集 则舍弃 */ if (interRectangle === undefined) return res; /* 判断北西角点的墨卡托投影瓦片信息 */ let northwestTileCoordinates = mercatorTilingScheme.positionToTileXY( Cesium.Rectangle.northwest(rectangle), imageryLevel ); /* 判断南东角点的墨卡托投影瓦片信息 */ let southeastTileCoordinates = mercatorTilingScheme.positionToTileXY( Cesium.Rectangle.southeast(rectangle), imageryLevel ); /* 根据不同类型分别进行计算 */ if (northwestTileCoordinates !== undefined && southeastTileCoordinates !== undefined) { for (let i = northwestTileCoordinates.x; i <= southeastTileCoordinates.x; i++) { for (let j = northwestTileCoordinates.y; j <= southeastTileCoordinates.y; j++) { let _webRectangle = mercatorTilingScheme.tileXYToRectangle(i, j, imageryLevel); if (Cesium.Rectangle.intersection(_webRectangle, this._rectangle)) { res.push({ x: i, y: j, level: imageryLevel, rectangle: _webRectangle, }); } } } } else if (northwestTileCoordinates !== undefined) { let _webRectangle = mercatorTilingScheme.tileXYToRectangle(northwestTileCoordinates.x, northwestTileCoordinates.y, imageryLevel); if (Cesium.Rectangle.intersection(_webRectangle, this._rectangle)) { res.push({ x: northwestTileCoordinates.x, y: northwestTileCoordinates.y, level: imageryLevel, rectangle: _webRectangle, }); } } else if (southeastTileCoordinates !== undefined) { let _webRectangle = mercatorTilingScheme.tileXYToRectangle(southeastTileCoordinates.x, southeastTileCoordinates.y, imageryLevel); if (Cesium.Rectangle.intersection(_webRectangle, this._rectangle)) { res.push({ x: southeastTileCoordinates.x, y: southeastTileCoordinates.y, level: imageryLevel, rectangle: _webRectangle, }); } } return res; } /** * 计算矩形的外围坐标串 * @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); return [sw, se, ne, nw, sw]; } /** * 根据Entity的名称批量删除Entity * @param {String} entityName 实体名称 */ _removeEntityByName(entityName) { /* 获取实体集合 */ var entities = this._primitives; /* 如果不存在实体集合或集合中没有数据 则返回 */ 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]); } } } /* 对外方法 */ Object.assign(CrImageServerLayer.prototype, { /** * 隐藏 */ hide: function() { this._console('隐藏'); this._isUpdateTile = false; /* 清理资源 */ this._removeEntityByName(this._renderName); /* 清理渲染 */ this._renderPrimitives.clear(); }, /** * 显示 */ show: function() { this._console('显示'); this._isUpdateTile = true; }, /** * 设置透明度 * @param {Number} opacity [0-1] */ setOpacity: function(opacity) { if (opacity === undefined || typeof opacity !== 'number') return; if (opacity >= 1) this._opacity = 1.0; if (opacity <= 0) this._opacity = 0.0; this._opacity = parseFloat(opacity); } }) /* 下载线程函数 */ function downloadWorker() { /** * 判断矩形相交函数 * @ignore * @param {Object} rectangle * @param {Object} otherRectangle * @param {Object} result */ function intersection(rectangle, otherRectangle, result) { let TWO_PI = 2.0 * Math.PI; let rectangleEast = rectangle.east; let rectangleWest = rectangle.west; let otherRectangleEast = otherRectangle.east; let otherRectangleWest = otherRectangle.west; if (rectangleEast < rectangleWest && otherRectangleEast > 0.0) { rectangleEast += TWO_PI; } else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0.0) { otherRectangleEast += TWO_PI; } if (rectangleEast < rectangleWest && otherRectangleWest < 0.0) { otherRectangleWest += TWO_PI; } else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0.0) { rectangleWest += TWO_PI; } const west = negativePiToPi( Math.max(rectangleWest, otherRectangleWest) ); const east = negativePiToPi( Math.min(rectangleEast, otherRectangleEast) ); if ( (rectangle.west < rectangle.east || otherRectangle.west < otherRectangle.east) && east <= west ) { return undefined; } const south = Math.max(rectangle.south, otherRectangle.south); const north = Math.min(rectangle.north, otherRectangle.north); if (south >= north) { return undefined; } if (result === undefined) { return { west: west, south: south, east: east, north: north }; } result.west = west; result.south = south; result.east = east; result.north = north; return result; }; /** * 判断矩形相交辅助函数 * @ignore * @param {Object} angle */ function negativePiToPi(angle) { if (angle >= -Math.PI && angle <= Math.PI) { return angle; } return zeroToTwoPi(angle + Math.PI) - Math.PI; }; /** * 判断矩形相交辅助函数 * @ignore * @param {Object} angle */ function zeroToTwoPi(angle) { let TWO_PI = 2.0 * Math.PI; let EPSILON14 = 0.00000000000001; if (angle >= 0 && angle <= TWO_PI) { return angle; } const mod = mod(angle, TWO_PI); if ( Math.abs(mod) < EPSILON14 && Math.abs(angle) > EPSILON14 ) { return TWO_PI; } return mod; }; /** * 判断矩形相交辅助函数 * @ignore * @param {Object} m * @param {Object} n */ function mod(m, n) { if (sign(m) === sign(n) && Math.abs(m) < Math.abs(n)) { return m; } return ((m % n) + n) % n; }; /** * 判断矩形相交辅助函数 * @ignore * @param {Object} value */ function sign(value) { value = +value; if (value === 0 || value !== value) { return value; } return value > 0 ? 1 : -1; }; /** * 接收主线发送的处理任务 * @ignore * @param {Object} event * @param {JSON} event.data * @param {Array} event.data.removePrimitives 存储当前需要移除的集合 * @param {Array} event.data.renderPrimitives 当前渲染的数据集合 * event.data.entities 参数说明 * @param {String} key 主键<对应Id> * @param {Boolean} renderImage 是否已经渲染了图片 */ onmessage = function(event) { let data = event.data; let isRemove = true; for (let [key, item] of data.renderPrimitives) { if (item.renderImage === false) isRemove = false; break; } if (isRemove) { setTimeout(function() { postMessage(data.removePrimitives); }, 300); } else { postMessage([]); console.log('===>>>', '渲染未完成!'); } } } /** * 数据提供器类型 */ CrImageServerLayer.ProviderType = Object.freeze({ ArcGisMapServerImageryProvider: 'ArcGisMapServerImageryProvider', BingMapsImageryProvider: 'BingMapsImageryProvider', OpenStreetMapImageryProvider: 'OpenStreetMapImageryProvider', TileMapServiceImageryProvider: 'TileMapServiceImageryProvider', GoogleEarthEnterpriseImageryProvider: 'GoogleEarthEnterpriseImageryProvider', GoogleEarthEnterpriseMapsProvider: 'GoogleEarthEnterpriseMapsProvider', GridImageryProvider: 'GridImageryProvider', IonImageryProvider: 'IonImageryProvider', MapboxImageryProvider: 'MapboxImageryProvider', MapboxStyleImageryProvider: 'MapboxStyleImageryProvider', SingleTileImageryProvider: 'SingleTileImageryProvider', TileCoordinatesImageryProvider: 'TileCoordinatesImageryProvider', UrlTemplateImageryProvider: 'UrlTemplateImageryProvider', WebMapServiceImageryProvider: 'WebMapServiceImageryProvider', WebMapTileServiceImageryProvider: 'WebMapTileServiceImageryProvider', }) function QuadTreeTile(x, y, tilingScheme, dataRectangle, depth, maxDepth) { this.x = x; this.y = y; this.level = depth; //最小层数 this.maxDepth = maxDepth; //最大分几层 下面规则就是每次4分直到到达规定最大层数 // this.rectangle = tilingScheme.tileXYToRectangle(this.x, this.y, this.level); // let tempRectangle = tilingScheme.tileXYToNativeRectangle(this.x, this.y, this.level); // if (Cesium.Rectangle.intersection(tempRectangle, dataRectangle)) { // console.log('===>>>', this.x, this.y, this.level, this.rectangle); // // let center = Cesium.Rectangle.center(this.rectangle); // // let xy = tilingScheme.positionToTileXY(center); // // if (xy !== undefined) { // // console.log('===>>>', xy.x, xy.y, this.level); // // } // } if (this.level === 11 && this.x === 1695 && this.y === 808) { console.log('===>>>', this.x, this.y, this.level, this.rectangle); } if (depth < maxDepth) { this.children = [ // 北西 new QuadTreeTile(this.x * 2, this.y * 2, tilingScheme, dataRectangle, depth + 1, maxDepth), // 北东 new QuadTreeTile(this.x * 2, this.y * 2 + 1, tilingScheme, dataRectangle, depth + 1, maxDepth), // 南西 new QuadTreeTile(this.x * 2, this.y * 2 + 1, tilingScheme, dataRectangle, depth + 1, maxDepth), // 南东 new QuadTreeTile(this.x * 2 + 1, this.y * 2 + 1, tilingScheme, dataRectangle, depth + 1, maxDepth), ] } else { this.children = [] } } /* 输出类 */ export default CrImageServerLayer