Cesium加载bil格式高程数据


Cesium官网给出的api貌似只能加载.terrain格式的dem数据,这里我将简单介绍一下如何自定义加载bil格式的dem数据。

首先在自定义实现加载bil格式的js类,这个很简单,就是复制源码CesiumTerrainProvider.js,将名字改掉就好。
(改名字的时候最好用替换)
构造方法里面配置bil格式的数据信息。
如:
 this._url = options.url;
        this._proxy = options.proxy;

        this._tilingScheme = new GeographicTilingScheme({
            numberOfLevelZeroTilesX : 18,
            numberOfLevelZeroTilesY : 9,
            ellipsoid : options.ellipsoid
        });

        this._heightmapWidth = 150;
        this._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this._tilingScheme.ellipsoid, this._heightmapWidth, this._tilingScheme.getNumberOfXTilesAtLevel(0));

        this._heightmapStructure = undefined;
        this._hasWaterMask = false;

。。。。。

具体每个参数什么含义就不解释了,可以自行去看官网原文。


了解清楚下面代码意义
that._heightmapStructure = {
                        heightScale : 2.0,
                        heightOffset : -1000.0,
                        elementsPerHeight : 1,
                        stride : 1,
                        elementMultiplier : 512.0,
                        isBigEndian : false,
                        lowestEncodedHeight : 0,
                        highestEncodedHeight : 512 * 512 - 1
                    };
该代码主要用于设置高程信息和偏移量等,详细看官网。

索引信息读取方法requestMetadata();这个主要用于请求.terrain格式中的layer.json文件,其中
tiles: [
                        '{z}/{x}/{y}.terrain?v={version}'
                    ]
是用来遍历加载所有dem文件的。

接着在requestTileGeometry方法中控制自己的文件加载顺序逻辑。

加载bil格式高程几乎完成一大半了,现在告诉大家两个参数,就是.terrain数据内容除了有高程数据,最后还有两个标志数据,分别是有无子文件和有没有水印,水印没有研究,暂时都设置的为false,子节点根据切片最小级数而定。如果当前级数等于最小级数代表没有子文件了。

注意:bil高程数据会有负值,在做数据读取时注意转换。

最后上传个代码大家参考下

  1 /*global define*/
  2 define([
  3         '../ThirdParty/Uri',
  4         '../ThirdParty/when',
  5         './BoundingSphere',
  6         './Cartesian3',
  7         './Credit',
  8         './defaultValue',
  9         './defined',
 10         './defineProperties',
 11         './DeveloperError',
 12         './Event',
 13         './GeographicTilingScheme',
 14         './HeightmapTerrainData',
 15         './IndexDatatype',
 16         './joinUrls',
 17         './loadArrayBuffer',
 18         './loadJson',
 19         './Math',
 20         './Matrix3',
 21         './OrientedBoundingBox',
 22         './QuantizedMeshTerrainData',
 23         './RuntimeError',
 24         './TerrainProvider',
 25         './throttleRequestByServer',
 26         './TileProviderError'
 27 ], function (
 28         Uri,
 29         when,
 30         BoundingSphere,
 31         Cartesian3,
 32         Credit,
 33         defaultValue,
 34         defined,
 35         defineProperties,
 36         DeveloperError,
 37         Event,
 38         GeographicTilingScheme,
 39         HeightmapTerrainData,
 40         IndexDatatype,
 41         joinUrls,
 42         loadArrayBuffer,
 43         loadJson,
 44         CesiumMath,
 45         Matrix3,
 46         OrientedBoundingBox,
 47         QuantizedMeshTerrainData,
 48         RuntimeError,
 49         TerrainProvider,
 50         throttleRequestByServer,
 51         TileProviderError) {
 52     'use strict';
 53 
 54     /**
 55      * A {@link TerrainProvider} that access terrain data in a Cesium terrain format.
 56      * The format is described on the
 57      * {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/Cesium-Terrain-Server|Cesium wiki}.
 58      *
 59      * @alias CesiumTerrainProvider
 60      * @constructor
 61      *
 62      * @param {Object} options Object with the following properties:
 63      * @param {String} options.url The URL of the Cesium terrain server.
 64      * @param {Proxy} [options.proxy] A proxy to use for requests. This object is expected to have a getURL function which returns the proxied URL, if needed.
 65      * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available.
 66      * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server,  if available.
 67      * @param {Ellipsoid} [options.ellipsoid] The ellipsoid.  If not specified, the WGS84 ellipsoid is used.
 68      * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.
 69      *
 70      *
 71      * @example
 72      * // Construct a terrain provider that uses per vertex normals for lighting
 73      * // to add shading detail to an imagery provider.
 74      * var terrainProvider = new Cesium.CesiumTerrainProvider({
 75      *     url : 'https://assets.agi.com/stk-terrain/world',
 76      *     requestVertexNormals : true
 77      * });
 78      *
 79      * // Terrain geometry near the surface of the globe is difficult to view when using NaturalEarthII imagery,
 80      * // unless the TerrainProvider provides additional lighting information to shade the terrain (as shown above).
 81      * var imageryProvider = Cesium.createTileMapServiceImageryProvider({
 82      *        url : 'http://localhost:8080/Source/Assets/Textures/NaturalEarthII',
 83      *        fileExtension : 'jpg'
 84      *    });
 85      *
 86      * var viewer = new Cesium.Viewer('cesiumContainer', {
 87      *     imageryProvider : imageryProvider,
 88      *     baseLayerPicker : false,
 89      *     terrainProvider : terrainProvider
 90      * });
 91      *
 92      * // The globe must enable lighting to make use of the terrain's vertex normals
 93      * viewer.scene.globe.enableLighting = true;
 94      *
 95      * @see TerrainProvider
 96      */
 97     function InfoCesiumTerrainProvider(options) {
 98         //>>includeStart('debug', pragmas.debug)
 99         if (!defined(options) || !defined(options.url)) {
100             throw new DeveloperError('options.url is required.');
101         }
102         //>>includeEnd('debug');
103 
104         this.maxLevel = defaultValue(options.maxLevel, 0);
105         this._url = options.url;
106         this._proxy = options.proxy;
107 
108         this._tilingScheme = new GeographicTilingScheme({
109             numberOfLevelZeroTilesX: 18,
110             numberOfLevelZeroTilesY: 9,
111             ellipsoid: options.ellipsoid
112         });
113 
114         this._heightmapWidth = 150;
115         this._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(this._tilingScheme.ellipsoid, this._heightmapWidth, this._tilingScheme.getNumberOfXTilesAtLevel(0));
116 
117         this._heightmapStructure = undefined;
118         this._hasWaterMask = false;
119 
120         /**
121          * Boolean flag that indicates if the Terrain Server can provide vertex normals.
122          * @type {Boolean}
123          * @default false
124          * @private
125          */
126         this._hasVertexNormals = false;
127         /**
128          * Boolean flag that indicates if the client should request vertex normals from the server.
129          * @type {Boolean}
130          * @default false
131          * @private
132          */
133         this._requestVertexNormals = defaultValue(options.requestVertexNormals, false);
134         this._littleEndianExtensionSize = true;
135         /**
136          * Boolean flag that indicates if the client should request tile watermasks from the server.
137          * @type {Boolean}
138          * @default false
139          * @private
140          */
141         this._requestWaterMask = defaultValue(options.requestWaterMask, false);
142 
143         this._errorEvent = new Event();
144 
145         var credit = options.credit;
146         if (typeof credit === 'string') {
147             credit = new Credit(credit);
148         }
149         this._credit = credit;
150 
151         this._ready = false;
152         this._readyPromise = when.defer();
153 
154         var metadataUrl = this._url;
155         if (defined(this._proxy)) {
156             metadataUrl = this._proxy.getURL(metadataUrl);
157         }
158 
159         var that = this;
160         var metadataError;
161 
162         function metadataSuccess(data) {
163             var message;
164 
165             if (!data.format) {
166                 message = 'The tile format is not specified in the layer.json file.';
167                 metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
168                 return;
169             }
170 
171             if (!data.tiles || data.tiles.length === 0) {
172                 message = 'The layer.json file does not specify any tile URL templates.';
173                 metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
174                 return;
175             }
176 
177             if (data.format === 'heightmap-1.0') {
178                 that._heightmapStructure = {
179                     heightScale: 1.0,
180                     heightOffset: 0,
181                     elementsPerHeight: 1,
182                     stride: 1,
183                     elementMultiplier: 512.0,
184                     isBigEndian: false,
185                     lowestEncodedHeight: 0,
186                     highestEncodedHeight: 512 * 512 - 1
187                 };
188                 that._hasWaterMask = true;
189                 that._requestWaterMask = true;
190             } else if (data.format.indexOf('quantized-mesh-1.') !== 0) {
191                 message = 'The tile format "' + data.format + '" is invalid or not supported.';
192                 metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
193                 return;
194             }
195 
196             that._tileUrlTemplates = that._url;//已更改 by wanghui
197 
198             that._availableTiles = data.available;
199 
200             if (!defined(that._credit) && defined(data.attribution) && data.attribution !== null) {
201                 that._credit = new Credit(data.attribution);
202             }
203 
204             // The vertex normals defined in the 'octvertexnormals' extension is identical to the original
205             // contents of the original 'vertexnormals' extension.  'vertexnormals' extension is now
206             // deprecated, as the extensionLength for this extension was incorrectly using big endian.
207             // We maintain backwards compatibility with the legacy 'vertexnormal' implementation
208             // by setting the _littleEndianExtensionSize to false. Always prefer 'octvertexnormals'
209             // over 'vertexnormals' if both extensions are supported by the server.
210             if (defined(data.extensions) && data.extensions.indexOf('octvertexnormals') !== -1) {
211                 that._hasVertexNormals = true;
212             } else if (defined(data.extensions) && data.extensions.indexOf('vertexnormals') !== -1) {
213                 that._hasVertexNormals = true;
214                 that._littleEndianExtensionSize = false;
215             }
216             if (defined(data.extensions) && data.extensions.indexOf('watermask') !== -1) {
217                 that._hasWaterMask = true;
218             }
219 
220             that._ready = true;
221             that._readyPromise.resolve(true);
222         }
223 
224         /****源码更改,不读配置文件,直接初始数据***/
225         function metadataIni() {
226             metadataSuccess({
227                 tilejson: '2.1.0',
228                 format: 'heightmap-1.0',
229                 version: '1.0.0',
230                 scheme: 'tms',
231                 tiles: [
232                     '?'
233                 ]
234             });
235             return;
236         }
237         /*
238         function metadataFailure(data) {
239             // If the metadata is not found, assume this is a pre-metadata heightmap tileset.
240             if (defined(data) && data.statusCode === 404) {
241                 metadataSuccess({
242                     tilejson: '2.1.0',
243                     format: 'heightmap-1.0',
244                     version: '1.0.0',
245                     scheme: 'tms',
246                     tiles: [
247                         '{z}/{x}/{y}.terrain?v={version}'
248                     ]
249                 });
250                 return;
251             }
252             var message = 'An error occurred while accessing ' + metadataUrl + '.';
253             metadataError = TileProviderError.handleError(metadataError, that, that._errorEvent, message, undefined, undefined, undefined, requestMetadata);
254         }
255 
256         function requestMetadata() {
257             var metadata = loadJson(metadataUrl);
258             when(metadata, metadataSuccess, metadataFailure);
259         }
260 
261         requestMetadata();*/
262         metadataIni();
263     }
264 
265     /**
266      * When using the Quantized-Mesh format, a tile may be returned that includes additional extensions, such as PerVertexNormals, watermask, etc.
267      * This enumeration defines the unique identifiers for each type of extension data that has been appended to the standard mesh data.
268      *
269      * @exports QuantizedMeshExtensionIds
270      * @see CesiumTerrainProvider
271      * @private
272      */
273     var QuantizedMeshExtensionIds = {
274         /**
275          * Oct-Encoded Per-Vertex Normals are included as an extension to the tile mesh
276          *
277          * @type {Number}
278          * @constant
279          * @default 1
280          */
281         OCT_VERTEX_NORMALS: 1,
282         /**
283          * A watermask is included as an extension to the tile mesh
284          *
285          * @type {Number}
286          * @constant
287          * @default 2
288          */
289         WATER_MASK: 2
290     };
291 
292     function getRequestHeader(extensionsList) {
293         if (!defined(extensionsList) || extensionsList.length === 0) {
294             return {
295                 Accept: 'application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01'
296             };
297         } else {
298             var extensions = extensionsList.join('-');
299             return {
300                 Accept: 'application/vnd.quantized-mesh;extensions=' + extensions + ',application/octet-stream;q=0.9,*/*;q=0.01'
301             };
302         }
303     }
304 
305     function createHeightmapTerrainData(provider, buffer, level, x, y, tmsY) {
306         var hasChildOrNot;
307         if (level < provider.maxLevel) {
308             hasChildOrNot = new Uint8Array([15])[0];
309         }
310         else {
311             hasChildOrNot = new Uint8Array([0])[0];
312         }
313         if (buffer.byteLength > 0) {
314             var intBuffer = new Int16Array(buffer, 0, provider._heightmapWidth * provider._heightmapWidth);
315             var temp = 0;
316             for (var i = 0; i < intBuffer.length; i++) {
317                 if (temp > intBuffer[i]) {
318                     temp = intBuffer[i];
319                 }
320                 if (intBuffer[i] < 0) {
321                     console.log(temp);
322                 }
323             }
324             var heightBuffer = new Uint16Array(intBuffer.length);
325             for (var i = 0; i < intBuffer.length; i++) {
326                 heightBuffer[i] = intBuffer[i] - temp;
327             }
328             var heightmapStructure = {
329                 heightScale: 3.0,
330                 heightOffset: temp*3,
331                 elementsPerHeight: 1,
332                 stride: 1,
333                 elementMultiplier: 512.0,
334                 isBigEndian: false,
335                 lowestEncodedHeight: 0,
336                 highestEncodedHeight: 512 * 512 - 1
337             };
338             //console.log(temp);
339 
340             return new HeightmapTerrainData({
341                 buffer: heightBuffer,
342                 childTileMask: hasChildOrNot,
343                 waterMask: new Uint8Array([0]),
344                 width: provider._heightmapWidth,
345                 height: provider._heightmapWidth,
346                 structure: heightmapStructure
347             });
348         }
349         else {
350             var heightBuffer = new Uint16Array(provider._heightmapWidth * provider._heightmapWidth);
351             for (var i = 0; i < heightBuffer.byteLength; i++) {
352                 heightBuffer[i] = 0;
353             }
354             return new HeightmapTerrainData({
355                 buffer: heightBuffer,
356                 childTileMask: hasChildOrNot,
357                 waterMask: new Uint8Array([0]),
358                 width: provider._heightmapWidth,
359                 height: provider._heightmapWidth,
360                 structure: provider._heightmapStructure
361             });
362         }
363     }
364 
365     function createQuantizedMeshTerrainData(provider, buffer, level, x, y, tmsY) {
366         var pos = 0;
367         var cartesian3Elements = 3;
368         var boundingSphereElements = cartesian3Elements + 1;
369         var cartesian3Length = Float64Array.BYTES_PER_ELEMENT * cartesian3Elements;
370         var boundingSphereLength = Float64Array.BYTES_PER_ELEMENT * boundingSphereElements;
371         var encodedVertexElements = 3;
372         var encodedVertexLength = Uint16Array.BYTES_PER_ELEMENT * encodedVertexElements;
373         var triangleElements = 3;
374         var bytesPerIndex = Uint16Array.BYTES_PER_ELEMENT;
375         var triangleLength = bytesPerIndex * triangleElements;
376 
377         var view = new DataView(buffer);
378         var center = new Cartesian3(view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true));
379         pos += cartesian3Length;
380 
381         var minimumHeight = view.getFloat32(pos, true);
382         pos += Float32Array.BYTES_PER_ELEMENT;
383         var maximumHeight = view.getFloat32(pos, true);
384         pos += Float32Array.BYTES_PER_ELEMENT;
385 
386         var boundingSphere = new BoundingSphere(
387                 new Cartesian3(view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true)),
388                 view.getFloat64(pos + cartesian3Length, true));
389         pos += boundingSphereLength;
390 
391         var horizonOcclusionPoint = new Cartesian3(view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true));
392         pos += cartesian3Length;
393 
394         var vertexCount = view.getUint32(pos, true);
395         pos += Uint32Array.BYTES_PER_ELEMENT;
396         var encodedVertexBuffer = new Uint16Array(buffer, pos, vertexCount * 3);
397         pos += vertexCount * encodedVertexLength;
398 
399         if (vertexCount > 64 * 1024) {
400             // More than 64k vertices, so indices are 32-bit.
401             bytesPerIndex = Uint32Array.BYTES_PER_ELEMENT;
402             triangleLength = bytesPerIndex * triangleElements;
403         }
404 
405         // Decode the vertex buffer.
406         var uBuffer = encodedVertexBuffer.subarray(0, vertexCount);
407         var vBuffer = encodedVertexBuffer.subarray(vertexCount, 2 * vertexCount);
408         var heightBuffer = encodedVertexBuffer.subarray(vertexCount * 2, 3 * vertexCount);
409 
410         var i;
411         var u = 0;
412         var v = 0;
413         var height = 0;
414 
415         function zigZagDecode(value) {
416             return (value >> 1) ^ (-(value & 1));
417         }
418 
419         for (i = 0; i < vertexCount; ++i) {
420             u += zigZagDecode(uBuffer[i]);
421             v += zigZagDecode(vBuffer[i]);
422             height += zigZagDecode(heightBuffer[i]);
423 
424             uBuffer[i] = u;
425             vBuffer[i] = v;
426             heightBuffer[i] = height;
427         }
428 
429         // skip over any additional padding that was added for 2/4 byte alignment
430         if (pos % bytesPerIndex !== 0) {
431             pos += (bytesPerIndex - (pos % bytesPerIndex));
432         }
433 
434         var triangleCount = view.getUint32(pos, true);
435         pos += Uint32Array.BYTES_PER_ELEMENT;
436         var indices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, triangleCount * triangleElements);
437         pos += triangleCount * triangleLength;
438 
439         // High water mark decoding based on decompressIndices_ in webgl-loader's loader.js.
440         // https://code.google.com/p/webgl-loader/source/browse/trunk/samples/loader.js?r=99#55
441         // Copyright 2012 Google Inc., Apache 2.0 license.
442         var highest = 0;
443         for (i = 0; i < indices.length; ++i) {
444             var code = indices[i];
445             indices[i] = highest - code;
446             if (code === 0) {
447                 ++highest;
448             }
449         }
450 
451         var westVertexCount = view.getUint32(pos, true);
452         pos += Uint32Array.BYTES_PER_ELEMENT;
453         var westIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, westVertexCount);
454         pos += westVertexCount * bytesPerIndex;
455 
456         var southVertexCount = view.getUint32(pos, true);
457         pos += Uint32Array.BYTES_PER_ELEMENT;
458         var southIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, southVertexCount);
459         pos += southVertexCount * bytesPerIndex;
460 
461         var eastVertexCount = view.getUint32(pos, true);
462         pos += Uint32Array.BYTES_PER_ELEMENT;
463         var eastIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, eastVertexCount);
464         pos += eastVertexCount * bytesPerIndex;
465 
466         var northVertexCount = view.getUint32(pos, true);
467         pos += Uint32Array.BYTES_PER_ELEMENT;
468         var northIndices = IndexDatatype.createTypedArrayFromArrayBuffer(vertexCount, buffer, pos, northVertexCount);
469         pos += northVertexCount * bytesPerIndex;
470 
471         var encodedNormalBuffer;
472         var waterMaskBuffer;
473         while (pos < view.byteLength) {
474             var extensionId = view.getUint8(pos, true);
475             pos += Uint8Array.BYTES_PER_ELEMENT;
476             var extensionLength = view.getUint32(pos, provider._littleEndianExtensionSize);
477             pos += Uint32Array.BYTES_PER_ELEMENT;
478 
479             if (extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS && provider._requestVertexNormals) {
480                 encodedNormalBuffer = new Uint8Array(buffer, pos, vertexCount * 2);
481             } else if (extensionId === QuantizedMeshExtensionIds.WATER_MASK && provider._requestWaterMask) {
482                 waterMaskBuffer = new Uint8Array(buffer, pos, extensionLength);
483             }
484             pos += extensionLength;
485         }
486 
487         var skirtHeight = provider.getLevelMaximumGeometricError(level) * 5.0;
488 
489         var rectangle = provider._tilingScheme.tileXYToRectangle(x, y, level);
490         var orientedBoundingBox;
491         if (rectangle.width < CesiumMath.PI_OVER_TWO + CesiumMath.EPSILON5) {
492             // Here, rectangle.width < pi/2, and rectangle.height < pi
493             // (though it would still work with rectangle.width up to pi)
494 
495             // The skirt is not included in the OBB computation. If this ever
496             // causes any rendering artifacts (cracks), they are expected to be
497             // minor and in the corners of the screen. It's possible that this
498             // might need to be changed - just change to `minimumHeight - skirtHeight`
499             // A similar change might also be needed in `upsampleQuantizedTerrainMesh.js`.
500             orientedBoundingBox = OrientedBoundingBox.fromRectangle(rectangle, minimumHeight, maximumHeight, provider._tilingScheme.ellipsoid);
501         }
502 
503         return new QuantizedMeshTerrainData({
504             center: center,
505             minimumHeight: minimumHeight,
506             maximumHeight: maximumHeight,
507             boundingSphere: boundingSphere,
508             orientedBoundingBox: orientedBoundingBox,
509             horizonOcclusionPoint: horizonOcclusionPoint,
510             quantizedVertices: encodedVertexBuffer,
511             encodedNormals: encodedNormalBuffer,
512             indices: indices,
513             westIndices: westIndices,
514             southIndices: southIndices,
515             eastIndices: eastIndices,
516             northIndices: northIndices,
517             westSkirtHeight: skirtHeight,
518             southSkirtHeight: skirtHeight,
519             eastSkirtHeight: skirtHeight,
520             northSkirtHeight: skirtHeight,
521             childTileMask: getChildMaskForTile(provider, level, x, tmsY),
522             waterMask: waterMaskBuffer
523         });
524     }
525 
526     /**
527      * Requests the geometry for a given tile.  This function should not be called before
528      * {@link CesiumTerrainProvider#ready} returns true.  The result must include terrain data and
529      * may optionally include a water mask and an indication of which child tiles are available.
530      *
531      * @param {Number} x The X coordinate of the tile for which to request geometry.
532      * @param {Number} y The Y coordinate of the tile for which to request geometry.
533      * @param {Number} level The level of the tile for which to request geometry.
534      * @param {Boolean} [throttleRequests=true] True if the number of simultaneous requests should be limited,
535      *                  or false if the request should be initiated regardless of the number of requests
536      *                  already in progress.
537      * @returns {Promise.<TerrainData>|undefined} A promise for the requested geometry.  If this method
538      *          returns undefined instead of a promise, it is an indication that too many requests are already
539      *          pending and the request will be retried later.
540      *
541      * @exception {DeveloperError} This function must not be called before {@link CesiumTerrainProvider#ready}
542      *            returns true.
543      */
544     InfoCesiumTerrainProvider.prototype.requestTileGeometry = function (x, y, level, throttleRequests) {
545         //>>includeStart('debug', pragmas.debug)
546         if (!this._ready) {
547             throw new DeveloperError('requestTileGeometry must not be called before the terrain provider is ready.');
548         }
549         //>>includeEnd('debug');
550 
551         var urlTemplates = this._tileUrlTemplates;
552         if (urlTemplates.length === 0) {
553             return undefined;
554         }
555 
556         var yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);
557 
558         var tmsY = (yTiles - y - 1);
559 
560         //var url = urlTemplates[(x + tmsY + level) % urlTemplates.length].replace('{z}', level).replace('{x}', x).replace('{y}', x+"_"+tmsY);
561         var url = urlTemplates + '?T=30mDEMS&L=' + level + '&X=' + x + '&Y=' + tmsY + '&UserToken='
562 
563         var proxy = this._proxy;
564         if (defined(proxy)) {
565             url = proxy.getURL(url);
566         }
567 
568         var promise;
569 
570         var extensionList = [];
571         if (this._requestVertexNormals && this._hasVertexNormals) {
572             extensionList.push(this._littleEndianExtensionSize ? "octvertexnormals" : "vertexnormals");
573         }
574         if (this._requestWaterMask && this._hasWaterMask) {
575             extensionList.push("watermask");
576         }
577 
578         function tileLoader(tileUrl) {
579             return loadArrayBuffer(tileUrl, getRequestHeader(extensionList));
580         }
581         throttleRequests = defaultValue(throttleRequests, true);
582         if (throttleRequests) {
583             promise = throttleRequestByServer(url, tileLoader);
584             if (!defined(promise)) {
585                 return undefined;
586             }
587         } else {
588             promise = tileLoader(url);
589         }
590 
591         var that = this;
592         return when(promise, function (buffer) {
593             if (defined(that._heightmapStructure)) {
594                 return createHeightmapTerrainData(that, buffer, level, x, y, tmsY);
595             } else {
596                 return createQuantizedMeshTerrainData(that, buffer, level, x, y, tmsY);
597             }
598         });
599     };
600 
601     defineProperties(InfoCesiumTerrainProvider.prototype, {
602         /**
603          * Gets an event that is raised when the terrain provider encounters an asynchronous error.  By subscribing
604          * to the event, you will be notified of the error and can potentially recover from it.  Event listeners
605          * are passed an instance of {@link TileProviderError}.
606          * @memberof CesiumTerrainProvider.prototype
607          * @type {Event}
608          */
609         errorEvent: {
610             get: function () {
611                 return this._errorEvent;
612             }
613         },
614 
615         /**
616          * Gets the credit to display when this terrain provider is active.  Typically this is used to credit
617          * the source of the terrain.  This function should not be called before {@link CesiumTerrainProvider#ready} returns true.
618          * @memberof CesiumTerrainProvider.prototype
619          * @type {Credit}
620          */
621         credit: {
622             get: function () {
623                 //>>includeStart('debug', pragmas.debug)
624                 if (!this._ready) {
625                     throw new DeveloperError('credit must not be called before the terrain provider is ready.');
626                 }
627                 //>>includeEnd('debug');
628 
629                 return this._credit;
630             }
631         },
632 
633         /**
634          * Gets the tiling scheme used by this provider.  This function should
635          * not be called before {@link CesiumTerrainProvider#ready} returns true.
636          * @memberof CesiumTerrainProvider.prototype
637          * @type {GeographicTilingScheme}
638          */
639         tilingScheme: {
640             get: function () {
641                 //>>includeStart('debug', pragmas.debug)
642                 if (!this._ready) {
643                     throw new DeveloperError('tilingScheme must not be called before the terrain provider is ready.');
644                 }
645                 //>>includeEnd('debug');
646 
647                 return this._tilingScheme;
648             }
649         },
650 
651         /**
652          * Gets a value indicating whether or not the provider is ready for use.
653          * @memberof CesiumTerrainProvider.prototype
654          * @type {Boolean}
655          */
656         ready: {
657             get: function () {
658                 return this._ready;
659             }
660         },
661 
662         /**
663          * Gets a promise that resolves to true when the provider is ready for use.
664          * @memberof CesiumTerrainProvider.prototype
665          * @type {Promise.<Boolean>}
666          * @readonly
667          */
668         readyPromise: {
669             get: function () {
670                 return this._readyPromise.promise;
671             }
672         },
673 
674         /**
675          * Gets a value indicating whether or not the provider includes a water mask.  The water mask
676          * indicates which areas of the globe are water rather than land, so they can be rendered
677          * as a reflective surface with animated waves.  This function should not be
678          * called before {@link CesiumTerrainProvider#ready} returns true.
679          * @memberof CesiumTerrainProvider.prototype
680          * @type {Boolean}
681          * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}
682          */
683         hasWaterMask: {
684             get: function () {
685                 //>>includeStart('debug', pragmas.debug)
686                 if (!this._ready) {
687                     throw new DeveloperError('hasWaterMask must not be called before the terrain provider is ready.');
688                 }
689                 //>>includeEnd('debug');
690 
691                 return this._hasWaterMask && this._requestWaterMask;
692             }
693         },
694 
695         /**
696          * Gets a value indicating whether or not the requested tiles include vertex normals.
697          * This function should not be called before {@link CesiumTerrainProvider#ready} returns true.
698          * @memberof CesiumTerrainProvider.prototype
699          * @type {Boolean}
700          * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}
701          */
702         hasVertexNormals: {
703             get: function () {
704                 //>>includeStart('debug', pragmas.debug)
705                 if (!this._ready) {
706                     throw new DeveloperError('hasVertexNormals must not be called before the terrain provider is ready.');
707                 }
708                 //>>includeEnd('debug');
709 
710                 // returns true if we can request vertex normals from the server
711                 return this._hasVertexNormals && this._requestVertexNormals;
712             }
713         },
714 
715         /**
716          * Boolean flag that indicates if the client should request vertex normals from the server.
717          * Vertex normals data is appended to the standard tile mesh data only if the client requests the vertex normals and
718          * if the server provides vertex normals.
719          * @memberof CesiumTerrainProvider.prototype
720          * @type {Boolean}
721          */
722         requestVertexNormals: {
723             get: function () {
724                 return this._requestVertexNormals;
725             }
726         },
727 
728         /**
729          * Boolean flag that indicates if the client should request a watermask from the server.
730          * Watermask data is appended to the standard tile mesh data only if the client requests the watermask and
731          * if the server provides a watermask.
732          * @memberof CesiumTerrainProvider.prototype
733          * @type {Boolean}
734          */
735         requestWaterMask: {
736             get: function () {
737                 return this._requestWaterMask;
738             }
739         }
740     });
741 
742     /**
743      * Gets the maximum geometric error allowed in a tile at a given level.
744      *
745      * @param {Number} level The tile level for which to get the maximum geometric error.
746      * @returns {Number} The maximum geometric error.
747      */
748     InfoCesiumTerrainProvider.prototype.getLevelMaximumGeometricError = function (level) {
749         return this._levelZeroMaximumGeometricError / (1 << level);
750     };
751 
752     function getChildMaskForTile(terrainProvider, level, x, y) {
753         var available = terrainProvider._availableTiles;
754         if (!available || available.length === 0) {
755             return 15;
756         }
757 
758         var childLevel = level + 1;
759         if (childLevel >= available.length) {
760             return 0;
761         }
762 
763         var levelAvailable = available[childLevel];
764 
765         var mask = 0;
766 
767         mask |= isTileInRange(levelAvailable, 2 * x, 2 * y) ? 1 : 0;
768         mask |= isTileInRange(levelAvailable, 2 * x + 1, 2 * y) ? 2 : 0;
769         mask |= isTileInRange(levelAvailable, 2 * x, 2 * y + 1) ? 4 : 0;
770         mask |= isTileInRange(levelAvailable, 2 * x + 1, 2 * y + 1) ? 8 : 0;
771 
772         return mask;
773     }
774 
775     function isTileInRange(levelAvailable, x, y) {
776         for (var i = 0, len = levelAvailable.length; i < len; ++i) {
777             var range = levelAvailable[i];
778             if (x >= range.startX && x <= range.endX && y >= range.startY && y <= range.endY) {
779                 return true;
780             }
781         }
782 
783         return false;
784     }
785 
786     /**
787      * Determines whether data for a tile is available to be loaded.
788      *
789      * @param {Number} x The X coordinate of the tile for which to request geometry.
790      * @param {Number} y The Y coordinate of the tile for which to request geometry.
791      * @param {Number} level The level of the tile for which to request geometry.
792      * @returns {Boolean} Undefined if not supported, otherwise true or false.
793      */
794     InfoCesiumTerrainProvider.prototype.getTileDataAvailable = function (x, y, level) {
795         var available = this._availableTiles;
796 
797         if (!available || available.length === 0) {
798             return undefined;
799         } else {
800             if (level >= available.length) {
801                 return false;
802             }
803             var levelAvailable = available[level];
804             var yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);
805             var tmsY = (yTiles - y - 1);
806             return isTileInRange(levelAvailable, x, tmsY);
807         }
808     };
809 
810     return InfoCesiumTerrainProvider;
811 });

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM