leaflet 使用kriging-contour.js 与 turf.js生成等值面

效果如下:

leaflet生成等值面网上搜索了好多资料但测试感觉都有点瑕疵,kriging.js 生成的canvas图片每个都是小方格影响美感,turf.js会有非法Polygon且有白色缝隙。就想着可不可以使用kriging.js生成等值面,turf,js进行裁剪。

但kriging.js返回的是栅格图片,偶然间查看到kriging-contour.js 可以返回矢量数据。(https://github.com/FreeGIS/kriging-contour

具体代码如下:

 kriging-contour.js 生成等值面的边界是根据传入的点坐标最大值最小值计算的,但按照我的点位数据,最后生成的等值面不能填充满geojson边界数据,我又在源码修改下,传个边界参数,如果有需要的可以自己加一下。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>leaflet克里金空间加插值turf.js</title>
    <style>
        html,
        body,
        #map {
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
            overflow: hidden;
            cursor: default;
        }
    </style>

    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin="" />
    <!-- Make sure you put this AFTER Leaflet's CSS -->

    <script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>
    <script src="./js/truf.js"></script>
    <script src="./js/kriging-contour.js"></script>

    <script src="./json/clip.js"></script>
    <script src="./json/clippoint.js"></script>

</head>

<body>
  
    <div id="map"></div>
    <script>
        var map = L.map('map', {
            center: [38.65953686, 120.8696333],
            zoom: 9
        });
        let name = L.tileLayer(
            "http://wprd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7",
        ).addTo(map);
        // 计算边界范围
        let dd1 = turf.bbox(boundaries);
        let points1 = {
            type: "FeatureCollection",
            features: []
        }
        pointvalue.map(item => {
                points1.features.push({
                    geometry: {
                        coordinates: [item.lng, item.lat],
                        type: 'Point'
                    },
                    properties: {
                        value: item.value
                    },
                    type: 'Feature'
                })
            })
            //计算克里金等值面

        let levelV = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 250, 260, 270, 280, 290, 300, 400];
        let colors = [{
                fill: "#ffdc84"
            }, {
                fill: "#ffd782"
            }, {
                fill: "#ffd281"
            }, {
                fill: "#ffcd7f"
            }, {
                fill: "#ffc87e"
            }, {
                fill: "#ffc37c"
            }, {
                fill: "#ffbe7a"
            }, {
                fill: "#ffb979"
            }, {
                fill: "#feb477"
            }, {
                fill: "#feaf76"
            }, {
                fill: "#feaa74"
            }, {
                fill: "#fea573"
            }, {
                fill: "#fea071"
            }, {
                fill: "#fe9b6f"
            }, {
                fill: "#fe966e"
            }, {
                fill: "#fe906c"
            }, {
                fill: "#fe8b6b"
            }, {
                fill: "#fe8669"
            }, {
                fill: "#fe8167"
            }, {
                fill: "#fe7c66"
            }, {
                fill: "#fe7764"
            }, {
                fill: "#fe7263"
            }, {
                fill: "#fd6d61"
            }, {
                fill: "#fd6860"
            }, {
                fill: "#fd635e"
            }, {
                fill: "#fd5e5c"
            }, {
                fill: "#fd595b"
            }, {
                fill: "#fd5459"
            }, {
                fill: "#fd4f58"
            }, {
                fill: "#fd4a56"
            }]
            
        let kriging_contours = kriging.getVectorContour(points1, 'value', {
            model: 'exponential',
            sigma2: 0,
            alpha: 100
        }, levelV, dd1);


        function hotColor(d) {

            let index = levelV.findIndex((item) => item >= d);
            if (index > -1) {
                return colors[index].fill
            } else {
                return colors[colors.length - 1].fill
            }
        }

        function sortArea(a, b) {
            return turf.area(b) - turf.area(a);
        }
        //按照面积对图层进行排序,规避turf的一个bug
        kriging_contours.features.sort(sortArea)

        //后面使用要求输入的参数为Feature<Polygon> ,而turf.isobands的是 MultiPolygon,需要先 flatten() 处理一下,同时去掉图形为空的记录
        boundaries = turf.flatten(boundaries); //行政边界

        kriging_contours = turf.flatten(kriging_contours); //等值面边界
        //console.log('kriging_contours:'+JSON.stringify(kriging_contours));
        //根据行政边界裁剪图形,
        //现在放大一些区域边界还是没有充满  后面可以封装成一个插件,在源码里面进行canvas  clip 剪辑只显示的geojson区域,其余的栅格部分不显示
        let features = []; //裁剪后的结果集
        kriging_contours.features.forEach(function(feature1) {
            boundaries.features.forEach(function(feature2) {
                let intersection = null;
                try {

                    intersection = turf.intersect(feature1, feature2);

                } catch (e) {

                    try {
                        //色斑图绘制之后,可能会生成一些非法 Polygon 
                        //解决的方法通常就是做一次 turf.buffer() 操作,这样可以把一些小的碎片 Polygon 清理掉。
                        feature1 = turf.buffer(feature1, 0);
                        intersection = turf.intersect(feature1, feature2);
                    } catch (e) {

                        intersection = feature1; //实在裁剪不了就不裁剪了,根据业务需求自行决定

                    }

                }
                if (intersection != null) {
                    intersection.properties = feature1.properties;
                    intersection.id = (Math.random() * 100000).toFixed(0);
                    features.push(intersection);
                }
            });
        });

        let intersection = turf.featureCollection(features);

        L.geoJSON(intersection, {
            style: function(feature) {
                return {

                    fillColor: hotColor(feature.properties.value),
                    weight: 0,
                    fillOpacity: 0.3,

                };
            }
        }).addTo(map);
    </script>
</body>

</html>

  clip.js 是geojson 边界数据,

     clippoint.js是插值点数据,部分格式如下:

   

[{
    "lat": 34.42,
    "lng": 115.66,
    "value": 299,
  },
  {
    "lat": 36.53,
    "lng": 118.44,
    "value": 312,
  },
  {
    "lat": 36.4,
    "lng": 117,
    "value": 321,
  },
........
]

 

参考文档:https://segmentfault.com/a/1190000022293641?utm_source=tag-newest

posted @ 2022-12-14 18:32  风紧了  阅读(2883)  评论(4编辑  收藏  举报
/* 点击爆炸效果*/
/* 鼠标点击求赞文字特效 */ /*鼠标跟随效果*/