riku
2024-04-30 add483d13841cf472a9adb5c0cc72454f501fb7c
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
/**
 * 高德地图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);
}
 
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, center, merge) {
  const lnglats_GD = fDatas.lnglats_GD;
  const coors = fDatas.coors_GD;
  const heights = factor.heights;
  const colors = factor.colors;
  const bColor = factor.bottomColor;
  if (center) {
    map.setZoomAndCenter(16, center);
  }
 
  // 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); //底部顶点
    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);
      }
    }
 
    // var bColor = bColor
    var tColor = colors[i];
    geometry.vertexColors.push.apply(geometry.vertexColors, bColor); //底部顶点颜色
    geometry.vertexColors.push.apply(geometry.vertexColors, tColor); //顶部顶点颜色
  }
 
  // 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;
}
 
export default {
  /**
   * 绘制3D走行路线图
   * @param fDatas 完整监测数据
   * @param factor 当前展示的监测因子对象
   * @param merge 是否和之前绘制的图形合并
   * @param setCenter 镜头是否自动移动至图形中心
   */
  drawRoadMap(fDatas, factor, merge, setCenter) {
    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;
    }
 
    // 3.确定定位坐标点
    var center;
    if (setCenter && lnglats_GD.length > 0) {
      var p = lnglats_GD[0];
      for (let i = 0; i < lnglats_GD.length; i++) {
        const e = lnglats_GD[i];
        if (e[0] != 0) {
          p = e;
          break;
        }
      }
      // eslint-disable-next-line no-undef
      center = new AMap.LngLat(...p);
    }
 
    // 5.绘制3D图形
    drawMesh(fDatas, factor, center, merge);
 
    // 缩放地图到合适的视野级别
    // map.setFitView()
 
    // 6.开启地图缩放监听
    if (lnglats_GD.length > 0) {
      map.on('zoomend', onMapZoom);
    }
  }
};