自定义 LERC 图层

尝试一下在线预览

这个示例演示了如何创建一个自定义切片图层,以显示从 GeoScene 世界海拔服务 请求的仰角数据。高度变化用不同深浅的黄色显示。颜色越亮越强,海拔越高。任何海拔超过 6000 米的地方都是完全黄色的。

创建一个自定义切片图层

要创建一个自定义的  Tilelayer  ,你必须在 BaseTileLayer  上调用 createSubclass()  我们将自定义图层命名为 LercLayer ,带有设置最小高程、最大高程和请求每个高程切片的 url 模板的属性。

         
1
2
3
4
5
6
7
8
9
const LercLayer = BaseTileLayer.createSubclass({
  properties: {
    urlTemplate: null,
    minElevation: 0,
    maxElevation: 4000
  }

  //override required methods
});

必须重写 LercLayer 的  fetchTile() 方法,这样我们才能处理原始的高程值,并根据高程值为每个像素分配不同的黄色阴影。一旦返回了切片的 url ,我们就可以使用  geosceneRequest 请求该切片的高程数据。

由于世界海拔服务使用  Esri LERC 格式,我们必须使用LercDecode.decode() 方法对数据进行解码。这个方法返回一个简单的仰角数组。一旦有了每个像素的仰角值,就可以通过将 RGBA 值分配给 imageData 来在画布上绘制仰角。

                                                                               
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// fetch tiles visible in the view
fetchTile: function (level, row, col, options) {
  const url = this.getTileUrl(level, row, col);

  // requested encoded elevation information
  // the signal option ensures that obsolete requests are aborted
  return geosceneRequest(url, {
    responseType: "array-buffer",
    signal: options && options.signal
  })
  .then((response) => {
    // create a canvas to draw the processed image
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d");
    const width = this.tileInfo.size[0];
    const height = this.tileInfo.size[1];

    canvas.width = width;
    canvas.height = height;

    // uncompress raw elevation values in lerc format
    // into a pre-allocated array of elevation values.
    const lerc = LercDecode.decode(response.data, { noDataValue: 0 });

    // Array of elevation values width*height.
    const pixels = lerc.pixels[0];

    // stats for min, max and no data
    // values for uncompressed elevation
    const stats = lerc.statistics[0];

    // set the min and max elevation values set
    // by the layer
    const min = this.minElevation;
    const max = this.maxElevation;
    const noDataValue = stats.noDataValue;

    // Create a new blank image data object with the specified
    // dimensions.
    const imageData = context.createImageData(width, height);

    // get Uint8ClampedArray representing a one-dimensional array
    // containing the data in the RGBA order, with integer values
    // between 0 and 255 (included).
    const data = imageData.data;

    const factor = 256 / (max - min);
    let value = 0;
    let j;

    // Loop through elevation array from lerc to generate an
    // image that will be displayed.
    // `pixels` is a flat array of color values and alpha
    // [r, g, b, a, r, g, b, a, ...]
    // We need to iterate through elevation and assign color
    // and alpha values respectively.
    for (let i = 0; i < width * height; i++) {
      // map tile size is 256x256. Elevation values have a
      // tile size of 257 so we skip the last elevation
      // whenever "i" is incremented by 256 to jump to the next row.
      j = i + Math.floor(i / width);
      // read the elevation value at the given index from the elevation
      // array and multiply it by the factor. This will define
      // the shade of yellow color for the pixel.
      value = (pixels[j] - min) * factor;

      // create RGBA value for the pixel
      data[i * 4] = value;
      data[i * 4 + 1] = value;
      data[i * 4 + 2] = 0;
      data[i * 4 + 3] = pixels[i] === noDataValue ? 0 : value;
    }

    // The elevation change image and ready for display
    context.putImageData(imageData, 0, 0);

    return canvas;
  });
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.