maptalks 开发GIS地图(43)maptalks.three.36- custom-rgbimage-terrain-landscape

1.  这个最终效果有点像地形图的热力图了,高的地方颜色深,矮的地方颜色浅,用到合适的地方效果也不错吧。AR VR 三维地图以后使用的场景应该会越来越多吧。

 

2.  地形图数据使用的是 ./data/west-lake-area.geojson

   RGBImage 使用的是 mapbox 的数据,

                const url = `https://a.tiles.mapbox.com/v4/mapbox.terrain-rgb/${z}/${x}/${y}.pngraw?access_token=${accesstoken}`;

 

 Texture 使用的也是mapbox 的数据

                const url = `https://api.mapbox.com/v4/mapbox.satellite/${z}/${x}/${y}.webp?sku=101XzrMiclXn4&access_token=${accesstoken}`;

 

3. 使用 Terrain 扩展类来计算对应的高度。

 1  class Terrain extends maptalks.BaseObject {
 2             constructor(extent, options, material, layer) {
 3                 options = maptalks.Util.extend({}, OPTIONS, options, { layer, extent });
 4                 const { texture, image, altitude, imageHeight, imageWidth, factor, filterIndex } = options;
 5                 if (!image) {
 6                     console.error('not find image');
 7                 }
 8                 if (!(extent instanceof maptalks.Extent)) {
 9                     extent = new maptalks.Extent(extent);
10                 }
11                 const { xmin, ymin, xmax, ymax } = extent;
12                 const coords = [
13                     [xmin, ymin],
14                     [xmin, ymax],
15                     [xmax, ymax],
16                     [xmax, ymin]
17                 ];
18                 let vxmin = Infinity, vymin = Infinity, vxmax = -Infinity, vymax = -Infinity;
19                 coords.forEach(coord => {
20                     const v = layer.coordinateToVector3(coord);
21                     const { x, y } = v;
22                     vxmin = Math.min(x, vxmin);
23                     vymin = Math.min(y, vymin);
24                     vxmax = Math.max(x, vxmax);
25                     vymax = Math.max(y, vymax);
26                 });
27                 const w = Math.abs(vxmax - vxmin), h = Math.abs(vymax - vymin);
28                 const rgbImg = generateImage(image), img = generateImage(texture);
29                 const geometry = new THREE.PlaneBufferGeometry(w, h, imageWidth - 1, imageHeight - 1);
30                 super();
31                 this._initOptions(options);
32                 this._createMesh(geometry, material);
33                 const z = layer.distanceToVector3(altitude, altitude).x;
34                 const v = layer.coordinateToVector3(extent.getCenter(), z);
35                 this.getObject3d().position.copy(v);
36                 material.transparent = true;
37                 if (rgbImg) {
38                     material.opacity = 0;
39                     rgbImg.onload = () => {
40                         const width = imageWidth, height = imageHeight;
41                         const imgdata = getRGBData(rgbImg, width, height);
42                         let idx = 0;
43                         let maxZ = -Infinity;
44                         //rgb to height  https://docs.mapbox.com/help/troubleshooting/access-elevation-data/
45                         for (let i = 0, len = imgdata.length; i < len; i += 4) {
46                             const R = imgdata[i], G = imgdata[i + 1], B = imgdata[i + 2];
47                             const height = -10000 + ((R * 256 * 256 + G * 256 + B) * 0.1);
48                             const z = layer.distanceToVector3(height, height).x * factor;
49                             geometry.attributes.position.array[idx * 3 + 2] = z;
50                             maxZ = Math.max(z, maxZ);
51                             idx++;
52                         }
53                         this.getOptions().maxZ = maxZ;
54                         geometry.attributes.position.needsUpdate = true;
55                         if (filterIndex) {
56                             const _filterIndex = [];
57                             const index = geometry.getIndex().array;
58                             const position = geometry.attributes.position.array;
59                             const z = maxZ / 15;
60                             for (let i = 0, len = index.length; i < len; i += 3) {
61                                 const a = index[i];
62                                 const b = index[i + 1];
63                                 const c = index[i + 2];
64                                 const z1 = position[a * 3 + 2];
65                                 const z2 = position[b * 3 + 2];
66                                 const z3 = position[c * 3 + 2];
67                                 if (z1 > z || z2 > z || z3 > z) {
68                                     _filterIndex.push(a, b, c);
69                                 }
70                             }
71                             geometry.setIndex(new THREE.Uint32BufferAttribute(_filterIndex, 1));
72                         }
73                         if (img) {
74                             textureLoader.load(img.src, (texture) => {
75                                 material.map = texture;
76                                 material.opacity = 1;
77                                 material.needsUpdate = true;
78                                 this.fire('load');
79                             });
80                         } else {
81                             material.opacity = 1;
82                         }
83                     };
84                     rgbImg.onerror = function () {
85                         console.error(`not load ${rgbImg.src}`);
86                     };
87                 }
88             }
89         }

4. 页面显示

 

 

 

5. 源码地址

https://github.com/WhatGIS/maptalkMap/tree/main/threelayer/demo

 

 
posted @ 2021-05-31 08:26  googlegis  阅读(895)  评论(2编辑  收藏  举报

坐标合肥,非典型GIS开发人员 GitHub