Dc62ce9df760873945a45b106be7bbfb
Cesium项目实战(5)-城市各类POI数据制作、加工、展示

百度百科关于POI是这样解释的。POI是"Point of Interest"的缩写,中文可以翻译为"兴趣点"。在地理信息系统中,一个POI可以是一栋房子、一个商铺、一个邮筒、一个公交站等。每个POI包含四方面信息,名称、类别、坐标、分类,全面的POI讯息是丰富导航地图的必备资讯,及时的POI兴趣点能提醒用户路况的分支及周边建筑的详尽信息,也能方便导航中查到你所需要的各个地方,选择最为便捷和通畅的道路来进行路径规划,因此,无论是车载导航还是手机导航,导航地图POI多少状况直接影响到导航的好用程度,导航地图中POI信息点的多少以及信息的准确程度和信息更新速度,都严重影响到一款导航的使用情况。

我们可以理解为POI在任何一个GIS系统中,都占据了非常重要的地位。因此,如何收集POI信息,以及如何在三维场景中显示这些POI信息也是非常重要的。很幸运的是,我们获取到了一份北京市较全的POI数据,大概15万条记录,本篇文章就这个数据着重介绍一下,如何加载POI信息。

笔者获取到的数据为SHP格式,classify为分类属性,本文中,提炼了4s店、餐饮、地铁站、汽车站、超市5个种类,作为示例。

在本篇“城市各类POI数据制作、加工、展示”中我们主要包括如下几个可视化内容。

  1. 普通直接加载
  2. 默认启用聚合加载
  3. 自定义聚合加载

1. 普通直接加载

普通直接加载,主要是针对于POI数量比较少的情况下。笔者把shp文件转换成了geojson格式,方便使用,同时,可便于模拟真实情况下的,后台API返回的数据格式。

1、构造数据结构

// 构造数据对象
var poiDataSource = {
  // 数据类别:{对应的加载地址,icon显示的图片,icon的大小(相对于原始图片大小)}
  "4s": {url: "../../data/4s.geojson", pic: "images/4s.png", size: 0.5},
  "food": {url: "../../data/food.geojson", pic: "images/food.png", size: 0.5},
  "metro": {url: "../../data/metro.geojson", pic: "images/metro.png", size: 0.5},
  "station": {url: "../../data/station.geojson", pic: "images/station.png", size: 0.5},
  "supermarket": {url: "../../data/supermarket.geojson", pic: "images/supermarket.png", size: 0.5},
};

2、遍历数据,直接加载

for (let key in poiDataSource) {
  // 遍历每一种poi分类
  let data = poiDataSource[key];
  // 使用GeoJsonDataSource接口进行加载
  Cesium.GeoJsonDataSource.load(data.url).then((dataSource) => {
    // 获取dataSource并绑定到数据对象中,用于poi图层控制显示/隐藏用
    data.dataSource = dataSource;
    // 根据页面上的控制状态设置(这里默认都不显示)
    dataSource.show = false;
    // 加载数据源到viewer中
    viewer.dataSources.add(dataSource).then(() => {
      var entities = dataSource.entities.values;
      for (var i = 0; i < entities.length; i++) {
        // 处理每个加载的entity,并设置billboard的image属性和scale属性
        var entity = entities[i];
        entity.billboard.image = data.pic;
        entity.billboard.scale = data.size;
      }
    });
  });
}





如果你觉得上面的效果已经满足了你的要求的话,下面的内容可以忽略了。


2. 默认启用聚合加载

聚合处理一般是针对数据量比较大的情况,如果你的POI信息点过多,可能直接按照上面的方式浏览器就直接崩溃了。

我们可以使用dataSource的clustering属性来开启聚合。默认是不启用的。首先定义几个聚合要用到的参数变量。

var pixelRange = 15; // 定义群集的屏幕像素尺寸(默认为80,自定义)
var minimumClusterSize = 3; // 定义最少群集的个数(默认为2,自定义)
var enabled = true; // 是否开启群集(默认不开启)

当加载完成后,得到dataSource对象,开启聚合,并设置相关参数。

dataSource.clustering.enabled = enabled;
dataSource.clustering.pixelRange = pixelRange;
dataSource.clustering.minimumClusterSize = minimumClusterSize;

使用PinBuilder来做群集的显示效果,也是默认的聚合效果。

// 定义pinBuilder对象
var pinBuilder = new Cesium.PinBuilder();

// 定义分类(通过PinBuilder的方法函数fromText构造一个Canvas对象,可以转换为图片资源)
var pin50 = pinBuilder.fromText('50+', Cesium.Color.RED, 48).toDataURL();
var pin40 = pinBuilder.fromText('40+', Cesium.Color.ORANGE, 48).toDataURL();
var pin30 = pinBuilder.fromText('30+', Cesium.Color.YELLOW, 48).toDataURL();
var pin20 = pinBuilder.fromText('20+', Cesium.Color.GREEN, 48).toDataURL();
var pin10 = pinBuilder.fromText('10+', Cesium.Color.BLUE, 48).toDataURL();

// 定义在小于10大于3(这里的3是因为上面定义了最少群集的个数为3)
var singleDigitPins = new Array(8);
for (var i = 0; i < singleDigitPins.length; ++i) {
  singleDigitPins[i] = pinBuilder.fromText('' + (i + 2), Cesium.Color.VIOLET, 48).toDataURL();
}

定义相机在运动时,聚合的动态改变事件。
```
dataSource.clustering.clusterEvent.addEventListener(function (entities, cluster) {

// 不显示默认的label群集样式

top Created with Sketch.