riku
2025-05-09 977e332a5338942df338728dbfb77a359e35bd0b
src/utils/map/3dLayer.js
@@ -1 +1,305 @@
import { object3Dlayer } from '../map';
/**
 * 高德地图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;
  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
};