做数字孪生项目时我经常被问到同一个问题场景里要放几千上万个业务点位怎么办最开始是摄像头点位接着是传感器、门禁、路灯、井盖、充电桩……几十个点的时候还没有感觉等数据源一次性接入了上万条 POI 记录画面就开始掉帧点位标签互相遮挡鼠标点击也经常选不中目标。这个问题的常规解法就是“点聚合”。网上关于 CIMPro POI 点聚合的用法资料比较零散很多文章只提到平台有“聚合”功能却没有把数据格式、API 调用、样式配置、动态刷新和排错讲完整。本文将围绕 CIMPro 平台整理一套 POI 点聚合的完整使用方案覆盖从数据准备、接口联调到脚本调用、性能优化的全过程适合正在做智慧园区、智慧城市、交通态势等数字孪生项目的开发者参考。1. 什么是 POI 点聚合它解决了什么问题1.1 先理解 POIPOI 全称 Point of Interest即“兴趣点”。在地理信息系统GIS和数字孪生场景中POI 通常指带有空间坐标的业务点位。比如一个智慧园区项目里摄像头、门禁、烟感传感器、路灯控制器、地磁车位检测器都可以看成 POI。这里要提醒一句我们讨论的 POI 是 Point of Interest兴趣点不是 Apache POI 那个操作 Office 文档的 Java 工具库。虽然英文缩写相同但在数字孪生、地图可视化领域POI 指的是业务空间点位。POI 与普通模型对象的区别在于它必须有明确的坐标信息并且通常挂接业务属性。一份最小可用的 POI 数据一般包含以下字段{ id: CAM-001, name: 园区东门摄像头, lng: 121.4737, lat: 31.2304, type: camera, status: 1 }这里id是唯一标识name是显示名称lng和lat是经纬度坐标type是业务分类status是状态字段。实际项目中还会扩展出设备厂商、安装时间、负责人、在线状态等字段但这些并不是点聚合功能关注的核心字段。点聚合只关心“这个点在哪、属于哪一类”其他字段更多是为了点击后的详情展示。1.2 什么是点聚合点聚合Marker Cluster / Point Aggregation是一种空间数据的可视化处理方式当地图或三维场景处于远景视角时距离较近的多个 POI 会被合并成一个聚合点并显示该聚合点覆盖范围内的 POI 数量当地图放大、视野拉近后聚合点又会自动拆解为更小范围的聚合点直到恢复为单个 POI。在 CIMPro 这类数字孪生平台中点聚合通常以“聚合图层”的形式存在。你可以把聚合图层理解成一个容器它会持续计算当前视角下所有 POI 在屏幕上的投影位置并按设定规则把相邻的点合并展示。最终呈现出来的效果是场景缩到最小的时候可能只有十几个带数字的聚合点场景逐步放大的过程中聚合点不断拆解放到足够大时每个点都恢复成独立的业务图标。这种“先聚合、后下钻”的交互模式和地图 App 里的餐馆聚合、手机相册按日期聚合是同一个思路。它不是简单地把点藏起来而是通过分层展示让用户先看到空间分布趋势再按需查看细节。1.3 点聚合解决了什么问题先对比一下不做聚合会出现什么问题问题表现原因渲染性能下降场景掉帧、操作卡顿上万图标/模型同时参与绘制GPU 和 CPU 压力大标签互相遮挡名字叠在一起看不清点在屏幕上距离过近标签没有避让策略点击难以命中选不中目标点小目标在屏幕上只有几个像素很难点准信息过载大屏内容杂乱用户第一眼看不到空间分布趋势点聚合直接把“逐点渲染”变成“按区域聚合渲染”画面元素数量从几万降低到几十几百个性能和可读性同时提升。用户先通过聚合点看到整体分布再逐级下钻到具体点位符合“从宏观到微观”的浏览逻辑。你可能会有疑问既然点聚合是平台自带能力那是不是所有项目都直接把开关打开就行其实不是。点聚合适合数据量大、空间分布密集的场景如果只有几十个点且点之间有明确的空间意义就不需要开聚合普通图标点反而更直观。做项目时先想清楚数据量和用户交互目标再决定是否启用点聚合。1.4 常见应用场景行业典型 POI关注点智慧园区摄像头、门禁、烟感设备分布、离线统计智慧城市井盖、路灯、垃圾桶设施覆盖、告警密度交通车辆、公交站、充电桩实时位置、热点区域商业地产商铺、客流点位客流热力、业态分布能源光伏面板、电表、管道监测点设备健康度、告警聚合可以这么说凡是需要在地图上展示大量点位的数字孪生项目点聚合基本是必选方案。例如智慧园区项目里几千个设备点全部平铺显示大屏根本没法看而聚合后用户先看到哪片区域设备密集再点击下钻看具体设备交互体验会好很多。2. 环境准备与数据准备2.1 平台环境说明本文以 CIMPro 平台为基础进行讲解。CIMPro 是一款面向数字孪生场景的三维可视化开发平台用于搭建智慧园区、智慧城市等可视化项目。实际使用中你需要先在 CIMPro 编辑器中创建项目或打开已有项目然后通过“数据接入 图层 脚本”的方式完成点聚合功能。有一点需要特别说明CIMPro 不同版本的界面布局、脚本 API 名称会略有差异。本文的重点是讲清楚实现思路和数据协议具体的方法名、属性名请以你当前版本编辑器的代码提示和官方文档为准。你可以在脚本编辑器中输入图层对象名看 IDE 自动补全了哪些方法再按提示调用这比在网上搜旧资料更可靠。2.2 POI 数据从哪来在实际项目中POI 数据通常来自以下几个渠道业务系统数据库设备表、点位表中已经有坐标字段通过后端接口返回。地图开放平台的兴趣点数据需要申请对应平台的开发者权限并严格遵守平台的调用条款和数据使用范围。手工整理项目前期没有现成数据时可以用 Excel、CSV 整理一批测试点。程序生成开发联调阶段用脚本随机生成几千条测试 POI方便快速验证聚合效果。这里需要提醒一点从第三方地图平台获取 POI 数据时不要使用爬虫批量抓取数据也不要将数据用于超出授权范围的商业用途。联调阶段自己生成一份模拟数据是最安全、最可控的方式。2.3 用 Python 生成 POI 测试数据为了验证点聚合效果我们需要一份数量足够大的 POI 数据。下面是生成测试数据的 Python 脚本它会在某个中心点附近随机生成指定数量的点位然后保存为 JSON 文件# -*- coding: utf-8 -*- # 文件路径generate_poi.py import json import math import random def generate_poi_data(count5000, center_lng121.4737, center_lat31.2304, radius0.02): 在中心点附近随机生成 POI 数据。 :param count: 生成点数 :param center_lng: 中心经度 :param center_lat: 中心纬度 :param radius: 生成半径约为经纬度增量0.02 大约对应 2 公里左右 data [] types [camera, sensor, gate, light] for i in range(count): angle random.uniform(0, 2 * math.pi) dist random.uniform(0, radius) # 经度方向需要考虑纬度造成的比例差异 lng center_lng dist * math.cos(angle) / math.cos(math.radians(center_lat)) lat center_lat dist * math.sin(angle) data.append({ id: fDEV-{i:05d}, name: f设备点位{i:05d}, lng: round(lng, 6), lat: round(lat, 6), type: random.choice(types), status: random.choice([0, 1]) }) return data if __name__ __main__:
