feiyu02
2025-03-21 da67648220f86993fac22b8199165995df3d8563
走航融合(待完成)
已修改4个文件
已添加2个文件
479 ■■■■ 文件已修改
src/components.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/grid/GridSearch.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/model/SatelliteGrid.js 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stores/grid-info.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/HomePage.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/underwaymix/UnderwayMixMode.vue 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts
@@ -54,6 +54,7 @@
    FactorRadio: typeof import('./components/monitor/FactorRadio.vue')['default']
    FactorTrend: typeof import('./components/monitor/FactorTrend.vue')['default']
    GaugeChart: typeof import('./components/chart/GaugeChart.vue')['default']
    GridSearch: typeof import('./components/grid/GridSearch.vue')['default']
    HistoricalTrajectory: typeof import('./components/animation/HistoricalTrajectory.vue')['default']
    MapLocation: typeof import('./components/map/MapLocation.vue')['default']
    MapScene: typeof import('./components/map/MapScene.vue')['default']
src/components/grid/GridSearch.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
<template>
  <CardDialog
    v-model="dialogVisible"
    title="网格信息"
    draggable
    :modal="false"
    width="300px"
  >
    <template #default>
      <el-form
        :inline="false"
        ref="formRef"
        label-position="right"
        label-width="100px"
      >
        <el-form-item label="网格编号:">
          <div>
            {{ data.cellIndex }}
          </div>
        </el-form-item>
        <el-form-item label="经纬度:">
          <div>
            {{ data.longitude + ', ' + data.latitude }}
          </div>
        </el-form-item>
        <el-form-item label="PM2.5:">
          <div>
            {{ data.pm25 + ' Î¼g/m³' }}
          </div>
        </el-form-item>
        <el-form-item label="四至范围:">
          <div>/</div>
        </el-form-item>
      </el-form>
    </template>
    <template #footer> </template>
  </CardDialog>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
import { useGridStore } from '@/stores/grid-info';
const gridStore = useGridStore();
const dialogVisible = ref(false);
const data = computed(() => {
  if (gridStore.selectedGridCellAndDataDetail) {
    return {
      cellIndex: gridStore.selectedGridCellAndDataDetail.gridCell.cellIndex,
      longitude: gridStore.selectedGridCellAndDataDetail.gridCell.longitude,
      latitude: gridStore.selectedGridCellAndDataDetail.gridCell.latitude,
      pm25: gridStore.selectedGridCellAndDataDetail.gridDataDetail.pm25
    };
  } else {
    return {
      cellIndex: '/',
      longitude: '/',
      latitude: '/',
      pm25: '/'
    };
  }
});
watch(
  () => gridStore.selectedGridCellAndDataDetail,
  (nv, ov) => {
    if (nv != ov) {
      dialogVisible.value = true;
    }
  },
  { deep: true }
);
</script>
src/model/SatelliteGrid.js
@@ -394,20 +394,35 @@
    }
  }
  setGridEvent(name, event) {
  setGridEvent(tags, name, event) {
    const { _mapViewsList, _gridDataDetailList } = this._getMapViews(...tags);
    if (!this.events.has(name)) {
      this.events.set(name, []);
    }
    const list = this.events.get(name);
    if (list.length > 0) {
      const lastEvent = list[list.length - 1];
      this.mapViews.gridViews.forEach((polygon) => {
        polygon.off(name, lastEvent);
      _mapViewsList.forEach((v) => {
        v.gridViews.forEach((polygon) => {
          polygon.off(name, lastEvent);
        });
      });
    }
    this.events.get(name).push(event);
    this.mapViews.gridViews.forEach((polygon) => {
      polygon.on(name, event);
    _mapViewsList.forEach((v, i) => {
      const gridDataDetailList = _gridDataDetailList[i];
      v.gridViews.forEach((polygon) => {
        const { gridCell } = polygon.getExtData();
        const cellIndex = gridCell.cellIndex;
        const gridDataDetail = gridDataDetailList.find(
          (v) => v.cellId == cellIndex
        );
        polygon.on(name, (e) => {
          event(gridCell, gridDataDetail);
        });
      });
    });
  }
@@ -516,7 +531,220 @@
   * @param {string} tag
   */
  drawHeatGrid(tag) {
    if (!this.mapViewsMap.has(tag) || !this.gridDataDetailMap.has(tag)) {
      return;
    }
    const heatTag = `heat-${tag}`;
    if (this.mapViewsMap.has(heatTag)) {
      this.changeVisibility({
        tags: [heatTag],
        showGridViews: true
      });
    } else {
      const _mapViews = this.mapViewsMap.get(tag);
      const _gridDataDetail = this.gridDataDetailMap.get(tag);
      // const groupId = _gridDataDetail[0].groupId;
      // const cellId = _gridDataDetail.cellId;
      const originCellIdList = _gridDataDetail.map((v) => v.cellId);
      let headGridDataDetailList = [];
      const width = 120;
      const height = 90;
      const eachwidth = 10;
      const eachheight = 10;
      const searchLength = 3;
      const _dataMap = new Map();
      _gridDataDetail.forEach((gdd) => {
        const searchRes = this.search(
          gdd,
          width,
          height,
          eachwidth,
          eachheight,
          searchLength
        );
        if (searchRes.find(v=> v.cellId == 1670)) {
          console.log();
        }
        searchRes.forEach((e) => {
          if (originCellIdList.indexOf(e.cellId) == -1) {
            if (!_dataMap.has(e.cellId)) {
              _dataMap.set(e.cellId, {
                source: [],
                res: {}
              });
            }
            _dataMap.get(e.cellId).source.push(e);
          }
        });
      });
      _dataMap.forEach((v, k) => {
        let total = 0,
          count = v.source.length;
        v.source.forEach((s) => {
          total += s.pm25;
        });
        v.res = {
          isHeatData: true,
          groupId: v.source[0].groupId,
          cellId: v.source[0].cellId,
          pm25: count == 0 ? null : Math.round((total / count) * 10) / 10,
          originData: v.source
        };
        headGridDataDetailList.push(v.res);
      });
      headGridDataDetailList = headGridDataDetailList.concat(_gridDataDetail);
      // é‡æ–°æŒ‰ç…§ç›‘测数据排序并标记排名
      headGridDataDetailList.sort((a, b) => {
        return b.pm25 - a.pm25;
      });
      headGridDataDetailList.forEach((gdd, i) => {
        gdd.rank = i + 1;
      });
      this.drawTagGrid({
        tag: heatTag,
        data: headGridDataDetailList,
        // grid: {
        //   style: {
        //     isMixGridHighlight:
        //       isMixGridHighlight == undefined ? true : isMixGridHighlight
        //   }
        // },
        extData: {
          name: `走航热力图 - ${heatTag}`,
          type: 2
        }
      });
    }
    return heatTag;
  }
  search(gdd, width, height, eachwidth, eachheight, searchLength) {
    function getCellWidthRange(cellId, width, height) {
      const total = width * height;
      const x = Math.ceil(cellId / total) - 1;
      let first = 1 + x * total,
        last = width + x * total;
      let scale = 0;
      while (scale < height) {
        const min = first + scale * width;
        const max = last + scale * width;
        if (cellId >= min && cellId <= max) {
          return [min, max];
        }
        scale++;
      }
    }
    const cellId = gdd.cellId;
    // const minData = gdd.pm25 / 2
    const dataOffset = (gdd.pm25 - gdd.pm25 / 2) / 3;
    const hOffset = eachwidth;
    const wOffset = 1;
    const cellIdMin = 1;
    const cellIdMax = width * height;
    let searchWidth = 0 - searchLength,
      searchHeight = 0 - searchLength;
    const result = [];
    const eachRange = getCellWidthRange(cellId, eachwidth, eachheight);
    const groupRange = getCellWidthRange(
      Math.ceil(cellId / (eachwidth * eachheight)),
      width / eachwidth,
      height / eachheight
    );
    for (let w = searchWidth; w <= searchLength; w++) {
      // å…ˆè¿›è¡Œæ¨ªå‘的坐标变换
      let _cellId = cellId + w * wOffset;
      if (_cellId < eachRange[0] || _cellId > eachRange[1]) {
        const cellOffset =
          _cellId < eachRange[0]
            ? _cellId - eachRange[0]
            : _cellId - eachRange[1];
        const groupOffset = Math[cellOffset / eachwidth > 0 ? 'ceil' : 'floor'](
          cellOffset / eachwidth
        );
        const newEachRange = eachRange.map(
          (r) => r + groupOffset * eachwidth * eachheight
        );
        _cellId =
          groupOffset > 0
            ? newEachRange[0] + cellOffset - wOffset
            : newEachRange[1] + cellOffset + wOffset;
        const _groupId = Math.ceil(_cellId / (eachwidth * eachheight));
        if (_groupId < groupRange[0] || _groupId > groupRange[1]) {
          continue;
        }
      }
      for (let h = searchHeight; h <= searchLength; h++) {
        if (w == 0 && h == 0) continue;
        const _eachRange = getCellWidthRange(_cellId, eachwidth, eachheight);
        // if (_eachRange == undefined) {
        //   console.log();
        // }
        const wOffset = _cellId - _eachRange[0];
        let _resCellId = _cellId + h * hOffset;
        if (_resCellId < cellIdMin || _resCellId > cellIdMax) continue;
        const total = eachwidth * eachheight;
        const x = Math.ceil(_cellId / total) - 1;
        const eachCellIdMin = 1 + x * total;
        const eachCellIdMax = total + x * total;
        const topCell = eachCellIdMin + wOffset;
        const bottomCell = eachCellIdMax - eachwidth + 1 + wOffset;
        if (_resCellId < eachCellIdMin || _resCellId > eachCellIdMax) {
          const cellOffset =
            _resCellId < eachCellIdMin
              ? _resCellId - topCell
              : _resCellId - bottomCell;
          const newTopCell =
            cellOffset > 0
              ? topCell + width * eachheight
              : topCell - width * eachheight;
          const newBottomCell =
            cellOffset > 0
              ? bottomCell + width * eachheight
              : bottomCell - width * eachheight;
          _resCellId =
            cellOffset > 0
              ? newTopCell + cellOffset - hOffset
              : newBottomCell + cellOffset + hOffset;
        }
        result.push({
          groupId: gdd.groupId,
          cellId: _resCellId,
          pm25: gdd.pm25 - Math.max(Math.abs(w), Math.abs(h)) * dataOffset
        });
      }
    }
    return result;
  }
  _getMapViews(...tags) {
src/stores/grid-info.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
import { ref } from 'vue';
import { defineStore } from 'pinia';
// èµ°èˆªè®¾å¤‡
export const useGridStore = defineStore('grid', () => {
  const selectedSatelliteProxy = undefined;
  const selectedGridCellAndDataDetail = ref(undefined);
  return { selectedSatelliteProxy, selectedGridCellAndDataDetail };
});
src/views/HomePage.vue
@@ -10,55 +10,14 @@
      <!-- <MapLocation></MapLocation> -->
      <SceneSearch></SceneSearch>
      <MapScene></MapScene>
      <GridSearch></GridSearch>
    </el-row>
    <CoreMenu></CoreMenu>
    <router-view></router-view>
  </div>
</template>
<script setup>
import { map, onMapMounted } from '@/utils/map/index_old';
// let districtPolygon;
// // ç»˜åˆ¶åŒºåŽ¿è¾¹ç•Œ
// function drawDistrict(districtName, isNew) {
//   onMapMounted(() => {
//     if (districtPolygon && !isNew) {
//       map.remove(districtPolygon);
//       map.add(districtPolygon);
//     } else {
//       // eslint-disable-next-line no-undef
//       var district = new AMap.DistrictSearch({
//         extensions: 'all', //返回行政区边界坐标等具体信息
//         level: 'district' //设置查询行政区级别为区
//       });
//       district.search(districtName, function (status, result) {
//         var bounds = result.districtList[0].boundaries; //获取朝阳区的边界信息
//         if (bounds) {
//           for (var i = 0; i < bounds.length; i++) {
//             //生成行政区划 polygon
//             // eslint-disable-next-line no-undef
//             districtPolygon = new AMap.Polygon({
//               map: map, //显示该覆盖物的地图对象
//               strokeWeight: 1, //轮廓线宽度
//               path: bounds[i], //多边形轮廓线的节点坐标数组
//               fillOpacity: 0.6, //多边形填充透明度
//               // fillColor: '#CCF3FF', //多边形填充颜色
//               fillColor: '#0077ff',
//               // strokeColor: '#ffffff' //线条颜色
//               strokeColor: 'white', //线条颜色
//               zIndex: 9
//             });
//           }
//           map.setFitView(); //将覆盖物调整到合适视野
//         }
//       });
//     }
//   });
// }
// drawDistrict('长宁区');
</script>
<script setup></script>
<style scoped>
.overlay-container {
src/views/underwaymix/UnderwayMixMode.vue
@@ -59,6 +59,13 @@
                  @change="handleHeatMapClick"
                >
                </CheckButton>
                <!-- <CheckButton
                  active-text="搜索网格"
                  inactive-text="搜索网格"
                  :default-value="false"
                  @change="handleHeatMapSearchClick"
                >
                </CheckButton> -->
              </el-row>
              <!-- <div class="m-t-8">网格要素</div>
              <el-row class="m-t-8">
@@ -147,9 +154,11 @@
import gridApi from '@/api/gridApi';
import { SatelliteGrid } from '@/model/SatelliteGrid';
import GridStyleTool from './component/GridStyleTool.vue';
import { useGridStore } from '@/stores/grid-info';
const gridStore = useGridStore();
const satelliteGrid = new SatelliteGrid('走航融合');
const gridCtrls = ref([satelliteGrid]);
// å€Ÿç”¨å«æ˜Ÿé¥æµ‹æ¨¡å—中的100米网格
@@ -173,6 +182,7 @@
const gridDataDetailMap = new Map();
const mixActive = ref(false);
const heatActive = ref(false);
const gridVisible = ref(true);
const underwayVisible = ref(false);
const rankVisible = ref(false);
@@ -216,7 +226,32 @@
}
function prepareGrid(gridInfo) {
  satelliteGrid.gridPrepare(gridInfo);
  satelliteGrid.gridPrepare(gridInfo, (polygon) => {
    //鼠标移入事件
    polygon.on('mouseover', () => {
      polygon.setOptions({
        //修改多边形属性的方法
        strokeWeight: 2,
        strokeColor: 'red'
      });
    });
    //鼠标移出事件
    polygon.on('mouseout', () => {
      polygon.setOptions({
        strokeWeight: 1,
        strokeColor: 'white'
      });
    });
  });
  // satelliteGrid.setGridEvent('click', (gridCell, gridDataDetail) => {
  //   // const polygon = e.target
  //   // const { gridCell } = polygon.getExtData();
  //   // const cellIndex = gridCell.cellIndex;
  //   gridStore.selectedGridCellAndDataDetail = {
  //     gridCell,
  //     gridDataDetail
  //   };
  // });
}
// watch(mission, (nV, oV) => {
@@ -263,6 +298,16 @@
            type: 0
          }
        });
        satelliteGrid.setGridEvent(
          [d.id],
          'click',
          (gridCell, gridDataDetail) => {
            gridStore.selectedGridCellAndDataDetail = {
              gridCell,
              gridDataDetail
            };
          }
        );
        gridCtrls.value = [satelliteGrid];
        // gridCtrls.value = Array.from(satelliteGrid.mapViewsMap);
        // console.log(gridCtrls.value);
@@ -271,6 +316,7 @@
  });
}
let mixTag;
function handleMixClick() {
  mixActive.value = !mixActive.value;
  const tags = fusionDataList.value
@@ -282,7 +328,17 @@
    showRankTxt: false
  });
  if (mixActive.value) {
    satelliteGrid.mixGrid(tags);
    mixTag = satelliteGrid.mixGrid(tags);
    satelliteGrid.setGridEvent(
      [mixTag],
      'click',
      (gridCell, gridDataDetail) => {
        gridStore.selectedGridCellAndDataDetail = {
          gridCell,
          gridDataDetail
        };
      }
    );
    gridCtrls.value = [satelliteGrid];
  } else {
    satelliteGrid.changeVisibility({
@@ -292,10 +348,50 @@
  }
}
let heatTag;
function handleHeatMapClick() {
  const tags = fusionDataList.value
    .filter((v, i) => selectedfusionData.value.indexOf(i) != -1)
    .map((v) => v.id);
  heatActive.value = !heatActive.value;
  satelliteGrid.changeVisibility({
    showGridViews: false,
    showDataTxt: false,
    showRankTxt: false
  });
  if (heatActive.value) {
    heatTag = satelliteGrid.drawHeatGrid(mixTag);
    satelliteGrid.setGridEvent(
      [heatTag],
      'click',
      (gridCell, gridDataDetail) => {
        gridStore.selectedGridCellAndDataDetail = {
          gridCell,
          gridDataDetail
        };
      }
    );
    gridCtrls.value = [satelliteGrid];
  } else {
    satelliteGrid.changeVisibility({
      tags: [mixTag],
      showGridViews: true
    });
  }
}
function handleHeatMapSearchClick() {
  const res = satelliteGrid.search(
    {
      groupId: 1,
      cellId: 2893,
      pm25: 50
    },
    120,
    90,
    10,
    10,
    3
  );
  console.log(res);
}
function handleGridClick() {