前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >高质量编码-克里金插值地图可视化(前端代码)

高质量编码-克里金插值地图可视化(前端代码)

原创
作者头像
MiaoGIS
修改2021-07-16 14:47:58
7990
修改2021-07-16 14:47:58
举报
文章被收录于专栏:Python in AI-IOTPython in AI-IOT

下面介绍一下前端JavaScript代码各函数的逻辑功能:

在介绍js函数前,首先介绍一下后台web接口的数据结构:

数据接口:

1.GET方法的/api/stations

使用$.parseJSON将result反序列化为JSON对象,表示包含经纬度坐标的全国空气站点信息的数组。

2.POST方法的/api/stations?date=20210501&hour=15&type=PM2.5

根据date,hour,type从后台查询指定日期指定小时的指定监测因子(AQI,PM2.5,PM10,O3,CO,NO2,SO2等)的全国空气站点的数据

使用$.parseJSON将result反序列化为JSON对象,用字典表示各个空气站点的数据(字典键为空气站点编码,字典值为数值)。

格网划分

如下图,将地图范围沿着纵向和横向划分为多个网格,对应每个网格单独生成canvas叠加到了地图上。

代码说明

初始化百度地图
初始化百度地图
遍历点位数组,每一个点位都在地图上对应添加位置图标,以及绑定弹窗内容
遍历点位数组,每一个点位都在地图上对应添加位置图标,以及绑定弹窗内容
从后台获取点位基本信息(必须包含经度,纬度,编号三列,其他列任意添加)
从后台获取点位基本信息(必须包含经度,纬度,编号三列,其他列任意添加)
关联点位基本信息(经度,纬度)和监测值(value),并且根据分级标准生成value2
关联点位基本信息(经度,纬度)和监测值(value),并且根据分级标准生成value2
将地图切分成格网时的格网单元大小,四周填充大小,分级颜色以及分级标准
将地图切分成格网时的格网单元大小,四周填充大小,分级颜色以及分级标准
使用国界作为克里金插值的轮廓多边形
使用国界作为克里金插值的轮廓多边形
将canvas叠加到地图上
将canvas叠加到地图上

前端html和js代码如下:

代码语言:javascript
复制
<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        html,
        body,
        #allmap {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            overflow: hidden;
        }

        #allmap img {
            height: 100%;
        }

    </style>

    <script type="text/javascript" src="https://underscorejs.net/js/jquery-1.11.0.min.js"></script>
    <script type="text/javascript" src="https://underscorejs.net/js/underscore.js"></script>
    <script type="text/javascript" src="static/lib/kriging.js"></script>

    <script type="text/javascript" src="static/js/china.js"></script>
    <script type="text/javascript" src="//api.map.baidu.com/api?v=2.0&ak=wWy2A8K94nhntYTYUHS19RXW"></script>
    <title>空气质量空间插值可视化</title>

</head>

<body>
    <div id="allmap"></div>

    <script type="text/javascript">
        // 百度地图API功能
        var map = new BMap.Map("allmap");
        map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5);
        map.enableScrollWheelZoom();

        function loadMarkers(points) {

            map.clearOverlays();
            $.each(points, (i, x) => {
                //console.log(x);
                var position = new BMap.Point(x['经度'], x['纬度']);
                var marker1 = new BMap.Marker(position);
                dictMarker[x['编号']] = marker1;
                map.addOverlay(marker1);
                marker1.addEventListener("click", function() {

                    var attrs = _.omit(x, ['编号', '经度', '纬度','value2']);
                    var content = _.map(attrs, (x, i) => `${i}:${x}`).join('<br>');
                    var infoWindow = new BMap.InfoWindow(content);
                    marker1.openInfoWindow(infoWindow);

                });

            })

        }
        dictMarker = {};
        $.get('api/stations', function(data) {

            data = JSON.parse(data['result']);
            window.points = data;

            dictPoints = _.indexBy(points, '编号');
            //loadMarkers(data);
            refreshCanvas();
        })

        function refreshCanvas() {
            var date = location.search.match(/date=([^&]*)/i);
            var hour = location.search.match(/hour=([^&]*)/i);
            if (!!date) {
                date = date[1];
            } else {
                date = "20210610";
            }
            if (!!hour) {
                hour = hour[1];
            } else {
                hour = "0";
            }
            var type = "PM2.5";
           
            $.post('api/stations', {
                date: date,
                hour: hour,
                type: type

            }, function(data) {

                data = JSON.parse(data['result']);
                var airData = _.find(data, {
                    hour: parseInt(hour),
                    type: type
                });

                airData = _.omit(airData, ['date', 'hour', 'type']);

                var trainData = _.compact(_.map(airData, function(item, index) {
                    if (!item) {
                        return null;
                    }
                    result = _.result(dictPoints, index, null);
                    if (!!result) {
                        result['value']=item;
                        result['value2'] = _.sortedIndex(standards, item);
                    }
                    return result;
                }));
                window.data1 = trainData;
                window.canvas = getCanvas(trainData);
            })
        }
        var [width, height] = [10, 5];
        var [offsetX, offsetY] = [10, 5];
        let canvas = null; //画布
        let colors = ["green", "#82D827", "yellow", "#FFDF00", "orange", "#FF5E00",
            "red", "#B71850", "purple", "#952E81","brown"];
        var standards = [25, 50, 75, 100, 125, 150, 175, 200, 250, 300];

        function getCanvas(data) {
            var values = _.pluck(data, 'value2');
            var lngs = _.pluck(data, '经度');
            var lats = _.pluck(data, '纬度');
            var indexes = _.unique(values);
            var colors0 = colors.slice(_.min(indexes), _.max(indexes) + 1);
       
            var [minX, minY, maxX, maxY] = [_.min(lngs), _.min(lats), _.max(lngs), _.max(lats)];
            var bounds = [
                [
                    [minX, minY],
                    [minX, maxY],
                    [maxX, maxY],
                    [maxX, minY]
                ]
            ];
            console.log(bounds);
            bounds = _.flatten(china.geometry.coordinates,true);
            console.time();
            window.variogram = kriging.train(values, lngs, lats, 'exponential', 0, 100);
            console.timeEnd();
            console.time();
            window.grid = kriging.grid(bounds, variogram, (maxY - minY) / 500);
            console.timeEnd();
            console.time();

            var lngs = _.range(minX - offsetX, maxX + offsetX, width);
            var lats = _.range(minY - offsetY, maxY + offsetY, height);
            _.map(lngs, function(m) {
                canvas = document.createElement('canvas');
                canvas.width = width * 5;
                canvas.height = height * 5;
                canvas.style.display = 'block';
                canvas.getContext('2d').globalAlpha = 0.75;

                [minX, maxX] = [m, m + width]
                _.map(lats, function(n) {
                    [minY, maxY] = [n, n + height]

                    kriging.plot(canvas, grid, [minX, maxX], [minY, maxY], colors0);

                    addOverlay([minX, minY], [maxX, maxY], canvas);
                })
            })
            console.timeEnd();

        }

        function addOverlay(west_south, east_north, canvasSource) {
            var west_south = new BMap.Point(west_south[0], west_south[1]);
            var east_north = new BMap.Point(east_north[0], east_north[1]);
            var bounds = new BMap.Bounds(west_south, east_north);
            var canvasOverlay = new BMap.GroundOverlay(bounds, {

                imageURL: canvasSource.toDataURL(),
                opacity: 0.6
            });
            map.addOverlay(canvasOverlay);
        }

    </script>
</body>


</html>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据接口:
    • 1.GET方法的/api/stations
      • 2.POST方法的/api/stations?date=20210501&hour=15&type=PM2.5
      • 格网划分
      • 代码说明
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档