Custom LERC Layer
This sample demonstrates how to create a custom tile layer that displays elevation data requested from the ArcGIS world elevation service. Elevation changes are displayed in different shades of yellow. The brighter and stronger the color, the higher the elevation. Any elevation values higher than 6000 meters are colored with a complete yellow color.
Creating a custom tile layer
To create a custom Tilelayer you must call createSubclass() on BaseTileLayer. We'll name the custom layer LercLayer
with properties for setting the minimum elevation, maximum elevation, and the url template for requesting each elevation tile.
var LercLayer = BaseTileLayer.createSubclass({
properties: {
urlTemplate: null,
minElevation: 0,
maxElevation: 4000
},
});
The fetchTile() method of LercLayer
must be overriden so we can process raw elevation values and assign different shades of yellow to each pixel based on the elevation value. Once the url for a tile is returned, we can request the elevation data for that tile using esriRequest.
Since the world elevation service uses Esri LERC format, we must decode the data using the LercDecode.decode()
method. This method returns a simple array of elevations. Once we have elevation values for each pixel, we can draw elevation on the canvas by assigning RGBA values to the imageData
.
fetchTile: function (level, row, col) {
var url = this.getTileUrl(level, row, col);
return esriRequest(url, {
responseType: "array-buffer"
})
.then(function (response) {
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var width = this.tileInfo.size[0];
var height = this.tileInfo.size[1];
canvas.width = width;
canvas.height = height;
var lerc = LercDecode.decode(response.data, { noDataValue: 0 });
var pixels = lerc.pixels[0];
var stats = lerc.statistics[0];
var min = this.minElevation;
var max = this.maxElevation;
var noDataValue = stats.noDataValue;
var imageData = context.createImageData(width, height);
var data = imageData.data;
var factor = 256 / (max - min);
var value = 0;
var j;
for (var i = 0; i < width * height; i++) {
j = i + Math.floor(i / width);
pv = (pixels[j] - min) * factor;
data[i * 4] = value;
data[i * 4 + 1] = value;
data[i * 4 + 2] = 0;
data[i * 4 + 3] = pixels[i] === noDataValue ? 0 : value;
}
context.putImageData(imageData, 0, 0);
return canvas;
}.bind(this));
}