「AntV」基于众源轨迹数据的三维路网生成与L7可视化

发布时间 2023-06-12 11:07:22作者: 当时明月在曾照彩云归

1. 引言

L7 地理空间数据可视分析引擎是一种基于 WebGL 技术的地理空间数据可视化引擎,可以用于实现各种地理空间数据可视化应用。L7 引擎支持多种数据源和数据格式,包括 GeoJSON、CSV等,可以快速加载和渲染大规模地理空间数据。L7 引擎还提供了丰富的可视化效果和交互功能,包括热力图、等高线图、鼠标交互等,可以帮助用户更好地理解和分析地理空间数据。

L7 官网:蚂蚁地理空间数据可视化 | AntV (antgroup.com)

L7 GitHub 仓库:antvis/L7: ? Large-scale WebGL-powered Geospatial Data Visualization analysis engine (github.com)

L7 官方教程:简介 | L7 (antgroup.com)

L7 官方示例:所有图表 | L7 (antgroup.com)

L7 API文档:场景 Scene | L7 (antgroup.com)

本文描述使用L7对长沙岳麓山景点游客轨迹数据进行可视化并构建三维路网

2. 数据获取

路网数据可以从以下网站下载,数据来源自六只脚:六只脚_GPS轨迹记录_户外自助游_自助游线路 (foooooot.com)

具体的轨迹获取教程可以参考:GPS地图生成03之数据获取 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)

下载好以后可以在QGIS中利用加载XY文件的方式加载all.csv文件,并设置OSM底图,预览GPS轨迹:

图片.png

  • 注:数据量较大,绘制卡顿

数据文件尺寸为47.2 M,有892152条轨迹数据,至此数据获取完成

数据文件内容示例为:

id,lng,lat,ele,track,time
0,112.938652777778,28.1828777777778,52.5862003780718,1448263,1511330079
1,112.936425,28.1837833333333,63.8200589970501,1448263,1511330738
2,112.936280555556,28.1837833333333,64.1105651105651,1448263,1511330800
3,112.93595,28.18385,65.3336643495531,1448263,1511331332
4,112.935691666667,28.1839333333333,66.9243986254296,1448263,1511331794
5,112.932275,28.1840388888889,80.1450980392157,1448263,1511335690
6,112.929519444444,28.1849583333333,179.382636655949,1448263,1511336583
7,112.929244444444,28.1849777777778,185.630363036304,1448263,1511336714
8,112.928458333333,28.1860111111111,228.579710144928,1448263,1511337087
9,112.931161111111,28.1911555555556,285.57196969697,1448263,1511339434
10,112.931288888889,28.1910944444444,288.503448275862,1448263,1511339460
......

3. L7可视化

可参考官方亮度图样例:亮度图 | L7 (antgroup.com)

3.1 加载底图

加载Mapbox地图

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script>
  <link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' />
  <script src='https://unpkg.com/@antv/l7'></script>
</head>

<body>
  <div id="map"></div>
  <script>
    const scene = new L7.Scene({
      id: 'map',
      map: new L7.Mapbox({
        style: 'dark',
        center: [112.9448, 28.1708],
        zoom: 12,
        token: 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA'
      }),
    });
      
  </script>
</body>

</html>

image-20230609025100248

3.2 加载数据并解析

加载数据,L7内置CSV格式解析器,只需指定字段名即可:

scene.on('loaded', () => {
    fetch('./all.csv')
        .then(res => res.text())
        .then(data => {
        const pointLayer = new L7.PointLayer({})
        .source(data, {
            parser: {
                type: 'csv',
                y: 'lat',
                x: 'lng'
            }
        })

        scene.addLayer(pointLayer);
    });
});

image-20230609025533852

3.3 绘制样式

绘制点图层,并设置样式:

scene.on('loaded', () => {
    fetch('./all.csv')
        .then(res => res.text())
        .then(data => {
        const pointLayer = new L7.PointLayer({})
        .source(data, {
            parser: {
                type: 'csv',
                y: 'lat',
                x: 'lng'
            }
        })
        .size(0.5)
        .color('#080298');

        scene.addLayer(pointLayer);
    });
});

image-20230609025659772

从图中可以看出主要的路线,即高亮部分

3.4 路网叠加

以下对景点及附近的路网数据可视化

路网数据获取与可视化步骤可参考:「AntV」路网数据获取与L7可视化 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)

image-20230609030907412

叠加图层:

image-20230609031947991

可以看到,在景区的轨迹信息比路网信息更为完善和直观

3.5 路网提取

从上图不难看出,虽然有的地方在路网上不显示,这些道路可能只是景区小道,但它确实也是一种特殊的道路,尤其是对于行人、旅行者而言

当足够数量的轨迹点显示在一起时,这些亮度图似乎就是路网图,更进一步的,可以从这些轨迹数据中提取去路网

这里不做具体研究阐述,可以参考下列文章:

这里使用的是《Map Inference in the Face of Noise and Disparity》中所提出的算法进行提取路网,并提取GPS轨迹数据中的三维信息,构建为三维路网

《Map Inference in the Face of Noise and Disparity》中所提出的算法可以在以下地址下载:

另外,还有多种路网提取算法,可以在下列网站中查看并使用:

3.6 二维路网可视化

经过一系列的数据预处理、路网提取、数据后处理,从上述的轨迹数据得到了以下路网数据:

image-20230610023340968

其中,海拔渐变色带由低到高为:image-20230610023425852

由图中可以看出岳麓山景点路网数据的相对高度

绘制的代码如下:

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script>
  <link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' />
  <script src='https://unpkg.com/@antv/l7'></script>
  <style>
    body,
    #map {
      height: 100vh;
      width: 100vw;
      margin: 0;
    }
  </style>
</head>

<body>
  <div id="map"></div>
  <script>
    const scene = new L7.Scene({
      id: 'map',
      map: new L7.Mapbox({
        style: 'dark',
        center: [112.9448, 28.1708],
        zoom: 12,
        token: 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA'
      })
    });

    scene.on('loaded', () => {
      fetch('./Yuelushan.geojson')
        .then(res => res.json())
        .then(data => {
          const layer = new L7.LineLayer({
            zIndex: 2,
          })
            .source(data)
            .size(0.5)
            .active(true)
            .color('z1', ['#0b8040', '#f2b90c', '#751304', '#8c644c', '#b8b8b8']);
          scene.addLayer(layer);
        });
    });

  </script>
</body>

3.7 三维路网可视化

路网数据的格式如下:

{
  "type": "FeatureCollection",
  "name": "Yuelushan",
  "crs": {
    "type": "name",
    "properties": {
      "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
    }
  },
  "features": [
    {
      "type": "Feature",
      "properties": {
        "id": 0,
        "z1": 74.72296906,
        "z2": 74.72296906
      },
      "geometry": {
        "type": "MultiLineString",
        "coordinates": [
          [
            [
              112.918952568856085,
              28.182139289691705,
              74.72296906
            ],
            [
              112.918964283127451,
              28.182139382193309,
              74.72296906
            ]
          ]
        ]
      }
    },
    ......

由示例数据可知,每个点坐标是由经纬度和高程组成,而L7默认支持路网数据高程显示:

image

3.8 坡度信息图

利用高程信息,可以制作出坡度信息图

image-20230610025330643

利用坡度信息,可以帮助行人选择道路,实现代码如下:

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

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js'></script>
  <link href='https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css' rel='stylesheet' />
  <script src='https://unpkg.com/@antv/l7'></script>
  <style>
    body,
    #map {
      height: 100vh;
      width: 100vw;
      margin: 0;
    }
  </style>
</head>

<body>
  <div id="map"></div>
  <script>
    const scene = new L7.Scene({
      id: 'map',
      map: new L7.Mapbox({
        style: 'dark',
        center: [112.9448, 28.1708],
        zoom: 12,
        token: 'pk.eyJ1IjoieWFuZ2ppYW4iLCJhIjoiY2phaG1neno0MXFkNDMzbWhwNWw0bWM4aiJ9.CFmrh0LVWAbmVeed-Xr7wA'
      })
    });

    scene.on('loaded', () => {
      fetch('./Yuelushan.geojson')
        .then(res => res.json())
        .then(data => {
          data.features.forEach(element => {
            element.properties.slope = Math.abs(element.properties.z1 - element.properties.z2);
          });
          const layer = new L7.LineLayer({
            zIndex: 2,
          })
            .source(data)
            .size(1)
            .active(true)
            .color('slope', ['#0b8040', '#f2b90c', '#751304', '#8c644c', '#b8b8b8']);
          scene.addLayer(layer);
        });
    });

  </script>
</body>

4. 参考资料

[1] 简介 | L7 (antgroup.com)

[2] 所有图表 | L7 (antgroup.com)

[3] 场景 Scene | L7 (antgroup.com)

[4] Map Inference in the Face of Noise and Disparity

[5] haidaoxiaofei/mapinference-gis12-upgrade (github.com)