12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028 |
- /**
- * 创建者:王成
- * 操作系统: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<Cesium.Cartesian3>} 坐标串集合
- */
- _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<String>} event.data.removePrimitives 存储当前需要移除的集合
- * @param {Array<JSON>} 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
|