riku
2025-06-05 16eb4bd55a4fd61ddd7a171b1a07378c45d1665b
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
/**
 * 高德地图3D图形绘制相关
 */
 
import { map, object3Dlayer } from './index_old';
 
// 3d图形
var _cylinder = undefined,
  // 当前绘制的图形中的最小高度
  _minH = -1,
  // 当前绘制的图形中的最大高度
  _maxH = -1;
 
//监测数据
var _factorDatas = {
    lnglats: [],
    heights: [],
    type: ''
  },
  //当前选中的监测因子数据
  _factor = {},
  _zoomFirst = true;
 
function onMapZoom() {
  // 首次地图缩放监听不执行(因为设定监听函数后会立即执行一次,可能官方函数有相关参数,后续待修改)
  if (_zoomFirst) {
    _zoomFirst = false;
    return;
  }
  const fDatas = _factorDatas;
  const factor = _factor;
  drawMesh(fDatas, factor);
 
  if (_polFactorDatasList.length > 0) {
    _polCylinderList.forEach((p) => {
      object3Dlayer.remove(p);
    });
    _polCylinderList = [];
    _polFactorDatasList.forEach((e, i) => {
      drawHighLight3DLayer(e, _polFactorList[i]);
    });
  }
  // console.log(map.getZoom());
}
 
var _maxHeight = 1000,
  _minHeight = 100,
  _lastZoom = -1;
/**
 * 获取当前地图缩放等级下的绘制高度缩放比例
 * @param {*} minH 当前监测数据的最小高度
 * @param {*} maxH 当前监测数据的最大高度
 */
function _getScale(minH, maxH) {
  var zoom = map.getZoom();
  if (_lastZoom == -1) {
    _lastZoom = zoom;
  } else if (_lastZoom <= 8) {
    _lastZoom = zoom;
    return;
  } else if (_lastZoom >= 18) {
    _lastZoom = zoom;
    return;
  }
  if (zoom <= 8) {
    _maxHeight = 10000;
    _minHeight = 1000;
  } else if (zoom <= 9) {
    _maxHeight = 9000;
    _minHeight = 900;
  } else if (zoom <= 10) {
    _maxHeight = 8000;
    _minHeight = 800;
  } else if (zoom <= 11) {
    _maxHeight = 7000;
    _minHeight = 700;
  } else if (zoom <= 12) {
    _maxHeight = 6000;
    _minHeight = 600;
  } else if (zoom <= 14) {
    _maxHeight = 5000;
    _minHeight = 500;
  } else if (zoom <= 15) {
    _maxHeight = 4500;
    _minHeight = 450;
  } else if (zoom <= 16) {
    _maxHeight = 4000;
    _minHeight = 400;
  } else if (zoom <= 17) {
    _maxHeight = 2500;
    _minHeight = 250;
  } else if (zoom > 17) {
    _maxHeight = 1000;
    _minHeight = 100;
  }
 
  var scale = (_maxHeight - _minHeight) / (maxH - minH);
  return scale;
}
 
/**
 * 绘图
 */
function drawMesh(fDatas, factor, merge) {
  const lnglats_GD = fDatas.lnglats_GD;
  const coors = fDatas.coors_GD;
  const heights = factor.heights;
  const colors = factor.colors;
  // const bColor = factor.bottomColor;
  const bColors = factor.bottomColors;
 
  // eslint-disable-next-line no-undef
  var cylinder = new AMap.Object3D.Mesh();
  cylinder.backOrFront = 'both';
  cylinder.transparent = true;
 
  var geometry = cylinder.geometry;
 
  var minH = heights[0];
  var maxH = heights[0];
  for (let i = 0; i < heights.length; i++) {
    const h = heights[i];
    minH = Math.min(minH, h);
    maxH = Math.max(maxH, h);
  }
 
  const scale = _getScale(minH, maxH);
  for (let i = 0; i < coors.length; i++) {
    var r = lnglats_GD[i];
    var lastP = lnglats_GD[i - 1];
    var p = coors[i];
    var h = (heights[i] - minH) * scale + _minHeight;
    if (heights[i] == -1) {
      h = -1;
    }
 
    geometry.vertices.push(p.x, p.y, 0); //底部顶点
    geometry.vertices.push(p.x, p.y, 0 - h); //顶部顶点
 
    if (i > 0) {
      // eslint-disable-next-line no-undef
      var distance = AMap.GeometryUtil.distance(r, lastP);
      //两个数据点最小间隔时间为4s,假设车速按照120km/h计算,4s行驶最大距离作为132米,
      //设定超过1分钟的数据绘制特殊的连线
      if (distance <= 500 && h != -1) {
        var bottomIndex = i * 2;
        var topIndex = bottomIndex + 1;
        var lastBottomIndex = bottomIndex - 2;
        var lastTopIndex = bottomIndex - 1;
        geometry.faces.push(bottomIndex, topIndex, lastTopIndex);
        geometry.faces.push(bottomIndex, lastBottomIndex, lastTopIndex);
      }
    }
 
    geometry.vertexColors.push.apply(geometry.vertexColors, bColors[i]); //底部顶点颜色
    geometry.vertexColors.push.apply(geometry.vertexColors, colors[i]); //顶部顶点颜色
  }
 
  // 7.根据合并选项重置或新增当前缓存数据
  if (merge != true) {
    _factorDatas = fDatas;
    _factor = factor;
    if (_cylinder != undefined) {
      object3Dlayer.remove(_cylinder);
    }
  } else {
    // _factorDatas.lnglats.push.apply(
    //   _factorDatas.lnglats,
    //   lnglats_GD
    // );
    // _factorDatas.coors.push.apply(_factorDatas.coors, coors);
    // _factorDatas.heights.push.apply(_factorDatas.heights, heights);
    // _factorDatas.colors.push.apply(_factorDatas.colors, colors);
    // _factorDatas.bottomColor = bColor;
  }
  object3Dlayer.add(cylinder);
  /**************test ****************/
  // object3Dlayer.on('mouseover', function (e) {
  //   console.log(
  //     `鼠标移入覆盖物! [${e.lnglat.getlng()}, ${e.lnglat.getLat()}]`
  //   );
  // });
  /**************test ****************/
  _cylinder = cylinder;
}
 
/**
 * 绘制高亮的污染区域3D立面
 */
var _polCylinderList = [];
var _polFactorDatasList = [],
  //当前选中的监测因子数据
  _polFactorList = [];
function drawHighLight3DLayer(fDatas, factor) {
  const offsetH = 100;
 
  const lnglats_GD = fDatas.lnglats_GD;
  const coors = fDatas.coors_GD;
  const heights = factor.heights;
  const colors = factor.colors;
  const bColors = factor.bottomColors;
 
  // eslint-disable-next-line no-undef
  var cylinder = new AMap.Object3D.Mesh();
  cylinder.backOrFront = 'both';
  cylinder.transparent = true;
 
  var geometry = cylinder.geometry;
 
  const scale = _getScale(_minH, _maxH);
  for (let i = 0; i < coors.length; i++) {
    var r = lnglats_GD[i];
    var lastP = lnglats_GD[i - 1];
    var p = coors[i];
    var h = (heights[i] - _minH) * scale + _minHeight;
    if (heights[i] == -1) {
      h = -1;
    }
 
    geometry.vertices.push(p.x, p.y, 0 - h); //底部顶点
    geometry.vertices.push(p.x, p.y, 0 - h - offsetH); //顶部顶点
 
    if (i > 0) {
      // eslint-disable-next-line no-undef
      var distance = AMap.GeometryUtil.distance(r, lastP);
      //两个数据点最小间隔时间为4s,假设车速按照120km/h计算,4s行驶最大距离作为132米,
      //设定超过1分钟的数据绘制特殊的连线
      if (distance <= 500 && h != -1) {
        var bottomIndex = i * 2;
        var topIndex = bottomIndex + 1;
        var lastBottomIndex = bottomIndex - 2;
        var lastTopIndex = bottomIndex - 1;
        geometry.faces.push(bottomIndex, topIndex, lastTopIndex);
        geometry.faces.push(bottomIndex, lastBottomIndex, lastTopIndex);
      }
    }
 
    const color = [1, 1, 1, 1];
    // const color = [1, 0, 0, 0.75];
    geometry.vertexColors.push.apply(geometry.vertexColors, color); //底部顶点颜色
    geometry.vertexColors.push.apply(geometry.vertexColors, color); //顶部顶点颜色
  }
 
  // 7.根据合并选项重置或新增当前缓存数据
  _polFactorDatasList.push(fDatas);
  _polFactorList.push(factor);
  // if (_polCylinderList.length > 0) {
  //   _polCylinderList.forEach((p) => {
  //     object3Dlayer.remove(p);
  //   });
  // }
  object3Dlayer.add(cylinder);
 
  _polCylinderList.push(cylinder);
}
 
export default {
  clear() {
    map.off('zoomend', onMapZoom);
    if (_cylinder != undefined) {
      object3Dlayer.remove(_cylinder);
    }
    if (_polCylinderList.length > 0) {
      _polCylinderList.forEach((p) => {
        object3Dlayer.remove(p);
      });
      _polCylinderList = [];
    }
    _polFactorDatasList = [];
    _polFactorList = [];
  },
 
  drawMesh: drawMesh,
  /**
   * 绘制3D走行路线图
   * @param fDatas 完整监测数据
   * @param factor 当前展示的监测因子对象
   * @param merge 是否和之前绘制的图形合并
   */
  drawRoadMap(fDatas, factor, merge) {
    const lnglats_GD = fDatas.lnglats_GD;
    const heights = factor.heights;
 
    // 1.关闭地图缩放监听
    map.off('zoomend', onMapZoom);
 
    // 2.计算绘图高度的边界值
    // if (merge != true) {
    //   var minH = _minH < 0 ? heights[0] : _minH;
    //   var maxH = _maxH < 0 ? heights[0] : _maxH;
    //   for (let i = 0; i < heights.length; i++) {
    //     const h = heights[i];
    //     minH = Math.min(minH, h);
    //     maxH = Math.max(maxH, h);
    //   }
    //   _minH = minH;
    //   _maxH = maxH;
    // }
 
    // 5.绘制3D图形
    this.drawMesh(fDatas, factor, merge);
 
    // 缩放地图到合适的视野级别
    // map.setFitView()
 
    // 6.开启地图缩放监听
    if (lnglats_GD.length > 0) {
      map.on('zoomend', onMapZoom);
    }
  },
 
  drawHighLight3DLayer
};