Java implements air pollution emission transmission path simulation (iClientOpenlayer front-end rendering)

At the beginning, let's look at the simulation implementation effect diagram

 

1. Technical application and background description

Understanding air pollution transport path simulations can help us better understand where air pollution comes from and how it spreads, allowing for more effective control measures. This simulation technology can simulate the transmission path and influence range of pollutants in the atmosphere according to the atmospheric environment and meteorological conditions, and provide scientific basis to guide the formulation and implementation of environmental protection policies.

Using scientific and technological means to explore the transmission path of air pollution is an important research work. Through simulation analysis, we can more fully understand the flow of pollutants in the air, and provide strong support for environmental protection and governance.

Air pollution has become a ubiquitous problem in modern society. Although this is a complex issue, there are various means we can use to reduce the impact of air pollution, such as raising environmental awareness, using clean energy, building green cities, etc.

Beyond our individual and corporate efforts, technology can also help us better understand and respond to air pollution. For example, air pollution transmission path simulation technology can help us understand the propagation rules and sources of pollutants in the atmosphere, and formulate corresponding control measures. The application of this technology can not only improve our environmental governance capabilities, but also provide scientists with data and information to promote the development of environmental science research.

At the same time, the application of air pollution transmission path simulation technology also requires government support and supervision. The government can formulate stricter environmental regulations and standards to regulate the production behavior of enterprises and reduce the emission of air pollutants. In addition, the government can also promote environmental scientific research and technological innovation through capital investment and scientific and technological support, and provide more means and resources for environmental governance.

Two air pollution emission scenarios

pollutant emission

3. Technical realization

1. Wind field data capture can refer to

Wind field data capture program implementation (java+python implementation) - Xingcheng's Blog - CSDN Blog

2. Java interface code writing and implementation

//http://localhost:8945/api/TrajectoryTracking/TrajectoryTrackingForward?lon=126&lat=45
@ApiOperation(value = "TrajectoryTracking")
@GetMapping(value = "/TrajectoryTrackingForward")
public String TrajectoryTrackingForward(double lon,double lat) {
    JSONArray datalist = JSON.parseArray(HttpUtils.sendGet("http://localhost:8213/wind/windresult/20230412/2023041202.json",""));
    String geoStr = InterpolationTraceUtils.calForwardPoints(lon,lat,datalist);
    return geoStr;
}

3. iClientOpenlayer realizes code configuration of part of visual code

<template> 
  <div class="layerPanel"> 
    <div v-if="isPanelShow" class="layerPanel-content"> 
      <el-container> 
        <el-header style="height: 30px"> Air pollution transmission trajectory simulation Calculate</el-header> 
        <el-main> 
          <div> 
            <div style="margin: 3px"> 
              <span>Start coordinates:</span> 
              <el-input v-model= 'startLonLat' style="width : 90%;" clearable></el-input> 
            </div> 
            <div style="margin: 3px"> 
              <span>Simulation calculation:</span>
              <el-button type="primary" round @click="simulationCalculate">计算</el-button>
            </div>
          </div>
        </el-main>
      </el-container>
    </div>
    <div class="layer-collapse" @click="layersPanelCollapse">
      <i class="layerlist"></i>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      layers: 11,
      isPanelShow: false,
      clayersInfo: [],
      opacityValue: 100,
      dh: 40,
      dz: 60,
      u: 3,
      q: 300000,
      gRows: 25,
      gColums: 50,
      gScale: 8,
      windOptions: [{
        value: '0',
        label: '北风'
      }, {
        value: '45',
        label:'Northeast wind' 
        value: '90',
      }, { 
        label: 'East Wind' 
      }, { 
        value: '135', 
        label: 'Southeast Wind' 
      }, { 
        value: '180', 
        label: 'South Wind' 
      },{ 
        value: '225', 
        label: 'Southwest Wind' 
      }, { 
        value: '270', 
        label: 'West Wind' 
      }, { 
        value: '315', 
        label: 'Northwest Wind' 
      }], 
      windValue: '225', 
      airStableOptions: [{ 
        value: 'A', 
        label: 'Strong unstable' 
      }, { 
        value: 'B',
        label: 'unstable' 
      }, { 
        value: 'C', 
        label: 'weakly unstable' 
      }, {
        value: 'D',
        label: '中性'
      }, {
        value: 'E',
        label: '较稳定'
      },{
        value: 'F',
        label: '稳定'
      }],
      airStableValue: 'F'
    }
  },
  mounted () {

  },
  methods: {
    layersPanelCollapse () {
      this.isPanelShow = !this.isPanelShow
    },
    simulationCalculate(){
      this.$emit("GaussPlumeSimulation", this.windValue,this.dz,this.dh,this.u,this.q,this.startLonLat.split(',')[0], this.startLonLat.split(',')[1],this.gColums,this.gRows,this.gScale,this.airStableValue)
    },
    locationToItem () {
      this.$emit("zoomToC", this.startLonLat.split(',')[0], this.startLonLat.split(',')[1], 14.2)
    }
  },
  props: {
    startLonLat: Object
  }
}
</script>

<style lang="less" scoped>
@import "./assets/css/index";
</style>
<template>
  <div>
    <div id="map" style="width: 100%;">
      <popHover :popHoverInfo="popHoverInfo" :popHoverScreenPoint="popHoverScreenPoint" :popHoverVisible="popHoverVisible"></popHover>
      <popClick :popAspect="popAspect" :popClickScreenPoint="popClickScreenPoint" :popClickVisible="popClickVisible" :popClickTitleInfo="popClickTitleInfo" :popClickContentInfo="popClickContentInfo"></popClick>
    </div>
    <div id="gisToolPopoup">
      <GisTool :sMap="smap" @tdtSwitchBase="tdtSwitchBase"></GisTool>
    </div>
    <div id="layersPanel">
      <layerPanel :layersInfo="layersInfo" @setLayerVisible="setLayerVisible" @setLayerOpacity="setLayerOpacity" @zoomToC="zoomToC"></layerPanel>
    </div>
    <div id="GaussPlumeCalculate">
      <GaussPlumePanel :startLonLat="startLonLat" @zoomToC="zoomToC" @GaussPlumeSimulation="GaussPlumeSimulation"></GaussPlumePanel>
    </div>
  </div>
</template>
<script>
import GisTool from './gisTool'
import layerPanel from './widgets/layerPanel/index'
import GaussPlumePanel from './widgets/GaussPlumePanel/index'
import Map from 'ol/Map'
import View from 'ol/View'
import * as control from 'ol/control'
// import { Logo,ScaleLine } from '@supermap/iclient-ol'
import {Logo} from '@supermap/iclient-ol/control/Logo'
import {ScaleLine} from '@supermap/iclient-ol/control/ScaleLine'
import {iCOLMapConfig} from './Store/iCOLMapConfig'
import {layersInfo} from './LayersInfo/LayersInfo'
import {layerMsgClick} from './layerMsg/LayerMsgClick'
import {layerMsgMouseOver} from './layerMsg/LayerMsgMouseOver'
import popHover from './widgets/popHover/index'
import popClick from './widgets/popClick/index'
import {WindyUtil} from './gisUtils/WindyUtil.js'
import {
  initTdtBaseMap,
  CommonCreateLayers,
  getLayerByCode,
  tdtSwitchBase,
  MapMouseoverEvent,
  MapClick,
  addElementToMap,
  getGeojsonByLayerCode,
  setLayersVisible,
  setLayersVisibleByCode,
  zoomC,
  commonRefreshVectorGeojsonLayer,
  CommonCreateVectorLayerGroup,
  refreshCv, CommonRemoveLayers, commonCreatePoint
} from './MapCommon'
import $ from 'jquery'
import {windData} from './data/windData'
import {LayersRenderSet} from "@/components/iClientOpenLayers/RendersInfo/LayersRenderSet";
let icolMap,_this
export default {
  components: {
    GisTool,
    layerPanel,
    GaussPlumePanel,
    popHover,
    popClick
  },
  name: 'iCOLMapCommon',
  data () {
    return {
      smap: null,
      startLonLat: '115.76745223366264,34.40937666512325',
      layersInfo: layersInfo,
      baseLayerArr:[],
      popHoverScreenPoint: {x: null, y: null},
      popHoverInfo: '',
      popHoverVisible: false,
      popClickScreenPoint: {x: null, y: null},
      popAspect: {cWidth: 600, cHeight: 400},
      popClickPoint: null,
      windyUtil: null,
      popClickTitleInfo: '',
      popClickContentInfo: '',
      popClickVisible: false,
    }
  },
  methods: {
    initMap: function () {
      $('#map').css('height', window.innerHeight)
      icolMap = new Map({
        target: 'map',
        controls: control.defaults({attributionOptions: {collapsed: true}})
            .extend([new Logo()]),
        view: new View({
          center: iCOLMapConfig.defaultMapViewCenter,
          zoom: iCOLMapConfig.defaultMapViewLevel,
          minZoom: iCOLMapConfig.minZoom,
          maxZoom: iCOLMapConfig.maxZoom,
          projection: iCOLMapConfig.projection,
          multiWorld: true
        })
      })
      this.smap = icolMap
      initTdtBaseMap(icolMap)
      icolMap.addControl(new ScaleLine())
      CommonCreateLayers(icolMap, layersInfo,_this)
      tdtSwitchBase(icolMap, 'img', true)
      // let windyUtil = new WindyUtil(this.smap)
      // windyUtil.addWindyLayer(windData)
      // windyUtil.clearWindyLayer()
      // debugger
      // var detail=windyUtil.getWindyDetail([103,45])

      let source = getLayerByCode(icolMap, 'CRegion').getSource()
      let vector = getLayerByCode(icolMap, 'CRegion')
      source.layer = vector
      // icolMap.addLayer(vector);
      // console.log(new Modify({source: source}))
      // let modify = new Modify({source: source})
      // icolMap.addInteraction(modify);
      let displayFeatureInfo = function (coordinate) {
        let pixel = icolMap.getPixelFromCoordinate(coordinate)
        console.log('longitude: ' + icolMap.getView().getCenter()[0].toString() + ', latitude: '+ icolMap.getView().getCenter()[1].toString() + ', level: '+ icolMap.getView().getZoom().toString())

        // var details = windyUtil.getWindyDetail(coordinate);
        // console.log(details);
        // alert(' 风向:' + details.direction + '\n 风级:' + details.level + '\n 风速:' + details.speed)
        let features = {length: 0}
        icolMap.forEachFeatureAtPixel(pixel, function (feature, layer) {
          if (layer == null){
            return
          }
          // debugger
          features.length = features.length + 1
          let code = layer.get('code')
          let obj = features[code]
          if (!obj) {
            obj = []
          }
          obj.push(feature)

          features[code] = obj
        })
        //console.log(features.length);

        let laysers = Object.keys(features)
        if (laysers.length > 1) {
          features[laysers[1]][0]["code"] = laysers[1]
          MapClick(_this,layerMsgClick,features[laysers[1]][0], laysers[1])
          if (layersInfo[laysers[1]].CustomPopupTemplate) {
            _this.popHoverVisible = false
            _this.popClickTitleInfo = features[laysers[1]][0].values_.values_[layersInfo[laysers[1]].CustomPopupTemplate.titleField]
            _this.popClickContentInfo = layersInfo[laysers[1]].CustomPopupTemplate.content
            let attrs = Object.keys(features[laysers[1]][0].values_.values_)
            for (let i = 0; i < attrs.length; i++) {
              _this.popClickContentInfo = _this.popClickContentInfo.replaceAll('{' + attrs[i] + '}', features[laysers[1]][0].values_.values_[attrs[i]])
            }
            _this.popAspect.cWidth = layersInfo[laysers[1]].CustomPopupTemplate.width
            _this.popAspect.cHeight = layersInfo[laysers[1]].CustomPopupTemplate.height
            _this.popClickVisible = true
          }
        }
        return features.length > 0
      }
      let displayFeatureInfoOver = function (coordinate) {
        let pixel = icolMap.getPixelFromCoordinate(coordinate)
        let features = {length: 0}
        icolMap.forEachFeatureAtPixel(pixel, function (feature, layer) {
          if (layer == null){
            return
          }
          features.length = features.length + 1
          let code = layer.get('code')
          let obj = features[code]
          if (!obj) {
            obj = []
          }
          obj.push(feature)

          features[code] = obj
        })
        //console.log(features.length);

        let laysers = Object.keys(features)
        if (laysers.length > 1) {
          features[laysers[1]][0]["code"] = laysers[1]
          features[laysers[1]][0]["pixel"] = pixel
          MapMouseoverEvent(_this,layerMsgMouseOver,features[laysers[1]][0], laysers[1])
          if (layersInfo[laysers[1]] && layersInfo[laysers[1]].floatLabelInfo) {
            _this.popHoverScreenPoint.x = pixel[0] + layersInfo[laysers[1]].floatLabelInfo.offsetX
            _this.popHoverScreenPoint.y = pixel[1] + layersInfo[laysers[1]].floatLabelInfo.offsetY
            _this.popHoverInfo = features[laysers[1]][0].values_.values_[layersInfo[laysers[1]].floatLabelInfo.floatLabelField]
            _this.popHoverVisible = true
          } else {
            _this.popHoverVisible = false
          }
        } else { 
          _this.popHoverVisible = false 
        } 
        return features.length > 0 
      } 

      /** 
       * Add a click handler to the map to render the popup. 
       */ 
      icolMap.on('click', function(optional) { 
        // let geojson=getGeojsonByLayerCode(icolMap,'Measure') 

        // if(opt.dragging) { 
        // //Specify the default settings and 
        // return ; 
        // } 
        let coordinate = possible coordinate 
        _this .startLonLat = possible coordinate[0]+','+possible coordinate[1] commonCreatePoint
        commonCreatePoint(icolMap,layersInfo,"LS",LayersRenderSet,[{id:1,lon:evt.coordinate[0],lat:evt.coordinate[1]}],"lon","lat") // var 
        // return; 
        // } 
      })
        // var details = _this.getWindyDetail(coordinate); 
        // console.log(details); 
        // alert('wind direction:' + details.direction + '\n wind level:' + details.level + '\n wind speed :' + details.speed); 
        //console.log(coordinate); 
        //click event 
        if (displayFeatureInfo(coordinate)) { 
          return 
        } 
      }) 
      icolMap.on('dblclick', function (evt) { 
        // if ( evt.dragging) { 
        // //Under the polygon query tool operation 
      icolMap.on('moveend', function (evt) { 
        //Zoom level control parser 
        let layers = Object.keys(layersInfo); 
        let cZoom = icolMap. getView().getZoom()
        for (let i = 0; i < laysers.length; i++) {
          if (layersInfo[laysers[i]].sourceType === "Overlay" && layersInfo[laysers[i]].visible == true ) {
            if(layersInfo[laysers[i]].minZoom < cZoom && cZoom <= layersInfo[laysers[i]].maxZoom){
              _this.setLayerVisibleOverly(laysers[i],true)
            }else {
              _this.setLayerVisibleOverly(laysers[i],false)
            }
          }
          if((layersInfo[laysers[i]].isGroupLayer||false == true)&&layersInfo[laysers[i]].visible == true) {
            if(layersInfo[laysers[i]].minZoom < cZoom && cZoom <= layersInfo[laysers[i]].maxZoom && layersInfo[laysers[i]].outRes.length>0) {
              refreshCv(layersInfo[laysers[i]].outRes,icolMap,layersInfo,laysers[i])
            }
          }
        }


        // var pixel = icolMap.getPixelFromCoordinate([115.783878,34.308761])
      })
      icolMap.on('pointermove', function (evt) {
        if (evt.dragging) {
          return
        }
        let coordinate = evt.coordinate
        displayFeatureInfoOver(coordinate)
      })
      // let el = document.createElement('div')
      // el.innerHTML = "<span style='color: red;font-size: larger;font-weight: bold'>gis创造美好未来</span>"
      // addElementToMap(this.smap,el,115.783878,34.308761,'popoupid')
      // let echartsLayerUtil = new EchartsLayerUtil(this.smap)
      // echartsLayerUtil.createTransferLayer(transferData,'code','entName')
      // let info = new control.Control({element: document.getElementById('popup')})
      // info.setMap(icolMap)
      // icolMap.addControl(info)

      // debugger
    },
    tdtSwitchBase (type, isLabel) {
      tdtSwitchBase(this.smap,type,isLabel)
    },
    refreshXZQH(regionCode){
      commonRefreshVectorGeojsonLayer('/image/duoyuanronghe/'+regionCode+'/XZQH.json',layersInfo,'XZQHRegion',this.smapm)
    },
    setLayerVisibleOverly (layerId, visible) {
      if(layersInfo[layerId].sourceType == 'Overlay'){
        for(let i = 0; i < layersInfo[layerId].overlays.length; i++){
          layersInfo[layerId].overlays[i].setVisible(visible)
        }
      }
    },
    setLayerVisible (layerId, visible) {
      let _this = this
      // debugger
      // CommonCreateVectorLayerGroup(_this.smap,layersInfo,'point1')
      // setInterval(function () {
      //   debugger
      //   CommonCreateVectorLayerGroup(_this.smap,layersInfo,'point1')
      // },13000)
      if(layersInfo[layerId].sourceType == 'Overlay'){
        for(let i = 0; i < layersInfo[layerId].overlays.length; i++){
          layersInfo[layerId].overlays[i].setVisible(visible)
        }
        // layersInfo[layerId].visible = visible
      }else {
        setLayersVisibleByCode(this.smap, [layerId], visible)
      }
      (layersInfo[layerId]||{}).visible = visible

    },
    setLayerOpacity (layerId, opacity) {
      getLayerByCode(this.smap, layerId).setOpacity(opacity)
    },
    GaussPlumeSimulation(wd,z,h,u,q,lon,lat,colums,rows,scale,airStable){
      let lyifs = {
        geoJsonFeP: {
          layerCode: 'geoJsonFeP',
          isRLayerPanel: true,
          sourceType: 'Vector',
          title: '轨迹点',
          url: '/api/TrajectoryTracking/TrajectoryTrackingForward?lon='+lon+'&lat='+lat,
          dataPath:'',
          floatLabelInfo: {floatLabelField: 'val', offsetX: 8, offsetY: -16},
          geoType: 'geojson',
          maxZoom: Infinity,
          minZoom: -Infinity,
          wrapX: false,
          opacity: 1,
          location: {longitude: 116.11704458402367, latitude: 34.25804927841997, level: 9.808516864898834},
          visible: layersInfo['geoJsonFeP'].visible
        },
      }
      CommonRemoveLayers(icolMap, lyifs)
      CommonCreateLayers(icolMap, lyifs,this)
    },
    zoomToC (x, y, level) {
      zoomC(this.smap, x, y, level, false)
    },
    getGeojsonByLayerCode(layerCode){
      return getGeojsonByLayerCode(this.smap,layerCode)
    }
  },
  updated () {

  },
  mounted () {
    _this = this
    this.initMap()
  }
}
</script>
<style>
@import url('../../../public/static/gis/css/ol.css');
@import url('../../../public/static/css/css/mapoperatestyle.css');
#popup1 {
  position: absolute;
  top: 50px;
  right: 20px;
}
.ol-zoom{
  display: none;
}
#gisToolPopoup{
  position: absolute;
  top: 50px;
  left: 20px;
}
#layersPanel{
  position: absolute;
  top: 50px;
  right: 300px;
}
#GaussPlumeCalculate{
  position: absolute;
  bottom: 20px;
  right: 30px;
}
.ol-attribution{
  display: none;
}
.ol-control-logo{
  display: none;
}
.ol-rotate{
  display: none;
}
.ol-scale-line{
  display: none;
}
</style>

//If it is helpful to you, please like and support!

//Technical cooperation exchange qq: 2401315930     

4. Interface call and geojson data result return

5. Front-end visual simulation effect 

         

Guess you like

Origin blog.csdn.net/weixin_42496466/article/details/130535141