From da67648220f86993fac22b8199165995df3d8563 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期五, 21 三月 2025 17:35:51 +0800 Subject: [PATCH] 走航融合(待完成) --- src/model/SatelliteGrid.js | 240 +++++++++++++++++++++++++++++ src/views/underwaymix/UnderwayMixMode.vue | 108 ++++++++++++ src/components/grid/GridSearch.vue | 74 +++++++++ src/components.d.ts | 1 src/views/HomePage.vue | 45 ----- src/stores/grid-info.js | 11 + 6 files changed, 424 insertions(+), 55 deletions(-) diff --git a/src/components.d.ts b/src/components.d.ts index 34b6c69..a0257ee 100644 --- a/src/components.d.ts +++ b/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'] diff --git a/src/components/grid/GridSearch.vue b/src/components/grid/GridSearch.vue new file mode 100644 index 0000000..c9d90a6 --- /dev/null +++ b/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> diff --git a/src/model/SatelliteGrid.js b/src/model/SatelliteGrid.js index 0067b78..cb547e9 100644 --- a/src/model/SatelliteGrid.js +++ b/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) { diff --git a/src/stores/grid-info.js b/src/stores/grid-info.js new file mode 100644 index 0000000..c193329 --- /dev/null +++ b/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 }; +}); diff --git a/src/views/HomePage.vue b/src/views/HomePage.vue index e4cf5d3..b31d689 100644 --- a/src/views/HomePage.vue +++ b/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 { diff --git a/src/views/underwaymix/UnderwayMixMode.vue b/src/views/underwaymix/UnderwayMixMode.vue index 38a403a..c0dbe9b 100644 --- a/src/views/underwaymix/UnderwayMixMode.vue +++ b/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() { -- Gitblit v1.9.3