123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- /**
- * 地名注记数据提供者,通过改变LSGlobe实现地名注记数据的加载。
- *
- * * @alias CesiumTerrainProvider
- * @constructor
- *
- * @param {LSGlobe} LSGlobe The result of LSGlobe.js
- * @param {Object} options The options include:
- * @param {String} options.url 地形服务的url。
- * @param {Proxy} [options.proxy] 请求的代理。
- * @param {String} [options.tileUrlTemplate] url模板。
- * @param {Ellipsoid} [options.ellipsoid] 椭球体,默认为WGS84椭球体。
- * @param {String} [options.metadataUrl] 元数据文件路径。
- */
- var VTPMarkerProvider = function (LSGlobe, options) {
- "use strict"; // 进入严格模式
- if (typeof LSGlobe === 'undefined') {
- throw 'LSGlobe must be defined for this plugin to work.';
- }
- if (typeof LSGlobe.defined === 'undefined' || !LSGlobe.defined(LSGlobe.GlobeSurfaceTile)) {
- throw 'Your version of LSGlobe is out of date, please upgrade LSGlobe.';
- }
- this.LSGlobe = LSGlobe;
- // Provider自有的内容
- if (!LSGlobe.defined(options) || !LSGlobe.defined(options.url)) {
- throw new LSGlobe.DeveloperError('options.url is required.');
- }
- this.viewer = undefined;
- // 字体设置
- this.fontSize = LSGlobe.defaultValue(options.fontSize, 16);
- this.fontFamily = LSGlobe.defaultValue(options.fontFamily, "Microsoft YaHei");
- this._url = options.url;
- this._proxy = options.proxy;
- this.fatherGroup = options.fatherGroup;
- var tileUrlTemplate = this._url + '/ReadTerrainLrp?layer=' + options.layer + '&x={row}&y={col}&z={level}';
- this._tileUrlTemplate = LSGlobe.defaultValue(options.tileUrlTemplate, tileUrlTemplate);
- this._tilingScheme = new LSGlobe.GeographicTilingScheme({
- numberOfLevelZeroTilesX: 2,
- numberOfLevelZeroTilesY: 1,
- ellipsoid: options.ellipsoid
- });
- this._errorEvent = new LSGlobe.Event();
- this._availability = undefined;
- this._ready = false;
- this._readyPromise = LSGlobe.when.defer();
- var metadataUrl = this._url + '/CreateTerrainLrc?layer=' + options.layer;
- if (LSGlobe.defined(this._proxy)) {
- metadataUrl = this._proxy.getURL(metadataUrl);
- }
- metadataUrl = LSGlobe.defaultValue(options.metadataUrl, metadataUrl);
- var metadataError;
- var that = this;
- /**
- * 元数据请求成功函数,用于解析元数据文件。
- * @param {#document} xml 元数据文件
- * @private
- */
- function metadataSuccess(xml) {
- that._minimumLevel = parseInt(xml.getElementsByTagName('LevelBegin')[0].childNodes[0].nodeValue);
- that._maximumLevel = parseInt(xml.getElementsByTagName('LevelEnd')[0].childNodes[0].nodeValue);
- var west = LSGlobe.Math.toRadians(xml.getElementsByTagName('West')[0].childNodes[0].nodeValue);
- var south = LSGlobe.Math.toRadians(xml.getElementsByTagName('South')[0].childNodes[0].nodeValue);
- var east = LSGlobe.Math.toRadians(xml.getElementsByTagName('East')[0].childNodes[0].nodeValue);
- var north = LSGlobe.Math.toRadians(xml.getElementsByTagName('North')[0].childNodes[0].nodeValue);
- that._rectangle = new LSGlobe.Rectangle(west, south, east, north);
- that._ready = true;
- that._readyPromise.resolve(true);
- }
- /**
- * 元数据请求失败函数。
- * @private
- */
- function metadataFailure(data) {
- var message = 'An error occurred while accessing ' + metadataUrl + '.';
- metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
- }
- /**
- * 元数据请求函数。
- * @private
- */
- function requestMetadata() {
- function getxmlDoc(xmlFile) {
- var xmlDoc;
- if (window.ActiveXObject) {
- xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); //IE
- xmlDoc.async = false;
- xmlDoc.load(xmlFile);
- } else if (navigator.userAgent.indexOf("Firefox") > 0) { //火狐
- try {
- xmlDoc = document.implementation.createDocument('', '', null);
- xmlDoc.load(xmlFile);
- } catch (e) {
- var xmlhttp = new window.XMLHttpRequest();
- xmlhttp.open("GET", xmlFile, false);
- xmlhttp.send(null);
- if (xmlhttp.readyState == 4) {
- xmlDoc = xmlhttp.responseXML.documentElement;
- }
- }
- } else { //谷歌
- var xmlhttp = new window.XMLHttpRequest();
- xmlhttp.open("GET", xmlFile, false);
- xmlhttp.send(null);
- if (xmlhttp.readyState == 4) {
- xmlDoc = xmlhttp.responseXML.documentElement;
- }
- }
- return xmlDoc;
- }
- //加载XML
- var metadata = getxmlDoc(metadataUrl);
- //var metadata = LSGlobe.loadXML(metadataUrl);
- LSGlobe.when(metadata, metadataSuccess, metadataFailure);
- }
- // 请求元数据
- requestMetadata();
- /**
- * Modifying the passed in LSGlobe to allow for loading VTP markers...
- */
- // 使用新的 processStateMachine 函数,增加对地名注记的处理
- LSGlobe.GlobeSurfaceTile._oldProcessStateMachine = LSGlobe.GlobeSurfaceTile.processStateMachine;
- LSGlobe.GlobeSurfaceTile.processStateMachine = function (tile, frameState,
- terrainLayerCollection, imageryLayerCollection, vertexArraysToDestroy) {
- var priorityFunc = tile._priorityFunction; // _oldProcessStateMachine可能会改变tile._priorityFunction,提前备份。
- LSGlobe.GlobeSurfaceTile._oldProcessStateMachine(tile, frameState,
- terrainLayerCollection, imageryLayerCollection, vertexArraysToDestroy);
- // 地名注记的处理
- var surfaceTile = tile.data;
- var tileEntity = surfaceTile.tileEntity;
- if (!LSGlobe.defined(tileEntity)) {
- tileEntity = new TileEntity(that);
- surfaceTile.tileEntity = tileEntity;
- }
- // 地名注记没有加载完成,修改tile的状态不为QuadtreeTileLoadState.DONE
- var isDoneLoading = tileEntity.processStateMachine(frameState, that, tile.x, tile.y, tile.level, tile._priorityFunction);
- if (!isDoneLoading && tile.state === LSGlobe.QuadtreeTileLoadState.DONE) {
- tile.state = LSGlobe.QuadtreeTileLoadState.LOADING;
- tile._priorityFunction = priorityFunc;
- }
- };
- // 使用新的 freeResources 函数,增加对 tileEntity 的释放。
- LSGlobe.GlobeSurfaceTile.prototype._oldFreeResources = LSGlobe.GlobeSurfaceTile.prototype.freeResources;
- LSGlobe.GlobeSurfaceTile.prototype.freeResources = function () {
- this._oldFreeResources();
- if (LSGlobe.defined(this.tileEntity)) {
- this.tileEntity.freeResources();
- this.tileEntity = undefined;
- }
- };
- // 是否需要隐藏当前没有渲染的tile对应的地标,待确认.
- LSGlobe.GlobeSurfaceTileProvider.prototype._oldEndUpdate = LSGlobe.GlobeSurfaceTileProvider.prototype.endUpdate;
- LSGlobe.GlobeSurfaceTileProvider.prototype.endUpdate = function (frameState) {
- // Call the original update
- this._oldEndUpdate(frameState);
- // 先把所有的设置为不可见,然后把所有要渲染的瓦片设置可见。
- // 会晚一帧,因为给其添加command在这之前已经做了
- // var entities = that.viewer.entities;
- // for (var i = 0, len = entities.length; i < len; ++i) {
- // entities[i]._show = false;
- // }
- //
- // var tilesToRenderByTextureCount = this._tilesToRenderByTextureCount;
- // for (var textureCountIndex = 0, textureCountLength = tilesToRenderByTextureCount.length; textureCountIndex < textureCountLength; ++textureCountIndex) {
- // var tilesToRender = tilesToRenderByTextureCount[textureCountIndex];
- // if (!LSGlobe.defined(tilesToRender)) {
- // continue;
- // }
- //
- // for (var tileIndex = 0, tileLength = tilesToRender.length; tileIndex < tileLength; ++tileIndex) {
- // var tileEntity = tilesToRender[tileIndex].data.tileEntity;
- // for (var i = 0, len = tileEntity.dataList.length; i < len; ++i) {
- // entities.getById(tileEntity.dataList[i])._show = true;
- // }
- // }
- // }
- };
- };
- /**
- * 为给定瓦片请求几何数据。
- *
- * @param {Number} x x坐标。
- * @param {Number} y y坐标。
- * @param {Number} level tile等级。
- *
- * @returns {Promise.<TerrainData>|undefined} 地形数据对象。
- *
- * @exception {DeveloperError} 函数必须在{@link DTPTerrainProvider#ready}为ture之后调用。
- */
- VTPMarkerProvider.prototype.requestEntityData = function (x, y, level, request) {
- if (!this._ready) {
- return undefined; //throw new DeveloperError('requestTileGeometry must not be called before the terrain provider is ready.');
- }
- var urlTemplate = this._tileUrlTemplate;
- if (!isatCesium.defined(urlTemplate)) {
- return undefined;
- }
- if (!this.getTileDataAvailable(x, y, level)) {
- return undefined;
- }
- // 计算瓦片对应的地标块范围(一个瓦片可能对应多个地标块数据)
- var yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level) * 2;
- var minXY = new isatCesium.Cartesian2(-1, -1);
- var maxXY = new isatCesium.Cartesian2(-1, -1);
- calcMinMaxRowCol(this, x, y, level, minXY, maxXY);
- if (maxXY.x >= yTiles) {
- maxXY.x = yTiles - 1;
- }
- if (maxXY.y >= yTiles) {
- maxXY.y = yTiles - 1;
- }
- if (minXY.y >= yTiles || maxXY.x >= yTiles || // 无效范围
- minXY.y < 0 || maxXY.y < 0 || minXY.x < 0 || maxXY.x < 0) {
- return undefined;
- }
- // 数据请求数组
- var promiseArray = [];
- for (var i = minXY.y; i <= maxXY.y; ++i) {
- for (var j = minXY.x; j <= maxXY.x; ++j) {
- var url = buildUrl(this, j, yTiles - i - 1, level + 1);
- var promise = isatCesium.loadArrayBuffer(url);
- if (!isatCesium.defined(promise)) {
- return undefined;
- }
- promiseArray.push(promise);
- }
- }
- var that = this;
- return isatCesium.when.all(promiseArray, function (buffers) {
- return buffers;
- }, function () {
- return isatCesium.when.reject();
- });
- };
- /**
- * 判断瓦片数据是否可以加载。
- *
- * @param {Number} x 列号.
- * @param {Number} y 行号.
- * @param {Number} level 层号.
- * @returns {Boolean} Undefined if not supported, otherwise true or false.
- */
- VTPMarkerProvider.prototype.getTileDataAvailable = function (x, y, level) {
- if (!this._ready) {
- return undefined;
- }
- if (level > this._maximumLevel - 1 || level < this._minimumLevel - 1) {
- return false; // 不在层级范围内
- }
- var result = undefined;
- result = this._tilingScheme.tileXYToRectangle(x, y, level, result);
- if (Cesium.Rectangle.intersection(this._rectangle, result) == undefined) {
- return false; // 不在地理范围内
- }
- return true;
- };
- // 根据层号、行号和列号构建请求地址
- function buildUrl(provider, x, y, level) {
- var url = provider._tileUrlTemplate.replace('{z}', level).replace('{x}', x).replace('{y}', y);
- var proxy = provider._proxy;
- if (isatCesium.defined(proxy)) {
- url = proxy.getURL(url);
- }
- return url;
- }
- // 根据tile的层号、行号和列号计算地标块索引范围
- function calcMinMaxRowCol(provider, x, y, level, minXY, maxXY) {
- var tileRect = provider._tilingScheme.tileXYToRectangle(x, y, level);
- var tileSize = tileRect.width;
- var sample = 18;
- var sampleGap = tileSize / sample;
- var val = tileRect.west;
- while (val < tileRect.east) {
- adjustMinMaxRowCol(val, tileRect.south, tileSize, minXY, maxXY);
- adjustMinMaxRowCol(val, tileRect.north, tileSize, minXY, maxXY);
- val += sampleGap;
- }
- val = tileRect.south;
- while (val < tileRect.north) {
- adjustMinMaxRowCol(tileRect.west, val, tileSize, minXY, maxXY);
- adjustMinMaxRowCol(tileRect.east, val, tileSize, minXY, maxXY);
- val += sampleGap;
- }
- }
- // 根据经纬度及瓦片范围调整地标块索引范围
- function adjustMinMaxRowCol(lon, lat, tileSize, minXY, maxXY) {
- var result = getRowCol(lon, lat, tileSize);
- var x = Math.floor(result.x);
- var y = Math.floor(result.y);
- if (x >= 0) {
- if (minXY.x < 0 || x < minXY.x) {
- minXY.x = x;
- }
- if (maxXY.x < 0 || x > maxXY.x) {
- maxXY.x = x;
- }
- }
- if (y >= 0) {
- if (minXY.y < 0 || y < minXY.y) {
- minXY.y = y;
- }
- if (maxXY.y < 0 || y > maxXY.y) {
- maxXY.y = y;
- }
- }
- }
- // 根据经纬度及瓦片范围计算对应的地标块索引
- function getRowCol(lon, lat, tileSize, result) {
- if (!isatCesium.defined(result)) {
- result = new isatCesium.Cartesian2();
- }
- result.x = (lon + Math.PI) / tileSize;
- var temp = Math.tan(Math.PI / 4.0 + lat / 2.0);
- if (temp > 0) {
- result.y = (Math.log(temp) + Math.PI) / tileSize;
- } else {
- result.y = -1;
- }
- return result;
- }
|