如何轻松加载百万级别的矢量数据?这个方法很实用

内容分享2天前发布
0 0 0

对于矢量数据的渲染显示,一般是以geojson的方式加载,或者直接以shp的形式解析加载,不管哪种方法,对于少量的数据显示还可以满足要求,但是面对百万级别的数据量,直接加载显示的话,会造成严重的卡顿,甚至卡死。这里介绍一种动态切片的方法,轻松加载百万级别的矢量数据。

用到的工具有:postgis + openlayers + springboot

用到的数据有:100万条点数据

数据准备

第一将数据导入到数据库,我这里使用的是测试数据,java连接数据库生成了包括经纬度和时间、类型、UUID等字段的矢量点数据,总共100万条。在后续渲染加载中,通过ptype字段设置不同的点颜色。

如何轻松加载百万级别的矢量数据?这个方法很实用

使用postgis根据参数对数据进行切片。使用到的方法为 st_asmvt()这个方法返回的是mvt格式的切片数据,以二进制数据流的方式返回。

如何轻松加载百万级别的矢量数据?这个方法很实用

其中 st_makeenvelope(118, 30, 120, 32)是切片的范围。在前端是通过XYZ将要切片的行列和级别转换为经纬度,在这里使用。

这样根据返回的二进制数据流,通过一个后端服务传递到前端。

后端服务

后端服务我采用了springboot,主要就是接收二进制数据流,返回给前端。这里具体是通过前端的XYZ参数,将其转换为经纬度,以此为筛选条件,调用切片函数进行切片。

GET方法接收前端请求

    @GetMapping(“reqstream”)

    public byte[] getTileReqStream(@RequestParam(“x”) String x, @RequestParam(“y”) String y, @RequestParam(“z”) String z, HttpServletResponse response) throws IOException {

        x = x.replace(“.pbf”, “”);

        y = y.replace(“.pbf”, “”);

        z = z.replace(“.pbf”, “”);

        //原始流数据

        byte[] b1 = tileReqService.getTileReqStream(x, y, z);

        return b1;

    }

将XYZ转换为经纬度,切片

@Override

    public byte[] getTileReqStream(String x, String y, String z) {

        double [] lonlat = xyz2lonlat(Double.parseDouble(x), Double.parseDouble(y), Double.parseDouble(z));

        double [] lonlat1 = xyz2lonlat(Double.parseDouble(x) + 0.5, Double.parseDouble(y) + 0.5, Double.parseDouble(z));

        List<TileReq> tileReqs = tileReqMapper.getTileReqStream(lonlat[0], lonlat[1], lonlat1[0], lonlat1[1]);

        TileReq tileReq = tileReqs.get(0);

        byte[] s = tileReq.getMvt();

        return s;

    }

    public double[] xyz2lonlat(double x, double y, double z){

        double [] lonlat = {0, 0};

        double n = Math.pow(2, z);

        double lon_deg = (x / n) * 360.0 – 180.0;

        double lat_rad = Math.atan(Math.sinh(Math.PI * (1 – (2 * y) / n)));

        double lat_deg = (180 * lat_rad) / Math.PI;

        lonlat[0] = lon_deg;

        lonlat[1] = lat_deg;

        return lonlat;

    }

前端openlayers加载

前端使用openlayers进行加载渲染。根据字段ptype设置点的颜色。

let vtLayer = new VectorTileLayer({

            source: new VectorTileSource({

                format: new MVT(),

                url: “http://localhost:10001/tile/reqstream?z={z}&x={x}&y={y}.pbf”,

            }),

            style: (evt) => {

                let type = evt.properties_.ptype;

                let style = null;

                switch (type) {

                    case 1:

                        style = styleList[0];

                        break;

                    case 2:

                        style = styleList[1];

                        break;

                    case 3:

                        style = styleList[2];

                        break;

                    case 4:

                        style = styleList[3];

                        break;

                    case 5:

                        style = styleList[4];

                        break;

                    case 6:

                        style = styleList[5];

                        break;

                    case 7:

                        style = styleList[6];

                        break;

                    case 8:

                        style = styleList[7];

                        break;

                    case 9:

                        style = styleList[8];

                        break;

                    case 10:

                        style = styleList[9];

                        break;

                }

                return style;

            },

        });

显示

前端加载效果

如何轻松加载百万级别的矢量数据?这个方法很实用

如何轻松加载百万级别的矢量数据?这个方法很实用

© 版权声明

相关文章

暂无评论

none
暂无评论...