第17章 - 点云可视化与三维发布
PDAL 自己不渲染点云。它没有 viewer、没有着色器、没有相机。这句话听起来像限制,实际是它的设计选择:PDAL 负责把点云整理成”能被渲染器高效消费”的几种形态,剩下的交给 Potree、Cesium、QGIS、Blender 或自研 WebGL 客户端。
所以这一章不是讲”怎么用 PDAL 看图”,而是讲发布的四种产物以及各自的生成方式:
| 产物 | 生成工具 | 消费方 | 典型场景 |
|---|---|---|---|
| COPC 单文件 | writers.copc |
Potree、Cesium、viewer.copc.io | 在线浏览、按需取数 |
| EPT 目录 | entwine build |
Potree、Cesium(3D Tiles 转换) | 大规模发布、增量更新 |
| glTF/GLB 网格 | filters.poisson/filters.greedyprojection + writers.gltf |
three.js、Blender、Cesium | 三维模型展示、地形网格 |
| 栅格 / 矢量 | writers.gdal、writers.ogr、writers.raster |
QGIS、GeoServer | 2.5D 视图、报告用图 |
选哪条路取决于数据量与交互需求:给业务人员看图用 COPC + Potree;给别人一个模型文件用 GLB;要做分析出图用栅格。
17.1 先决条件:点云得先”可索引”
浏览器渲染点云的难点不在着色,而在一次不能传太多点。1000 万点按 tiled 结构分块,每块几千到几万点,随视距加载——这就是 COPC 与 EPT 的价值。
17.1.1 COPC:单文件八叉树
writers.copc 把 LAS 1.4 写成带内部层级索引的 LAZ,单个文件既是”完整数据”也是”可随机访问的瓦片集合”。这是目前最省事的发布形态:
[
{ "type": "readers.las", "filename": "input.laz" },
{ "type": "filters.assign", "assignment": "Red[:]=Red" },
{
"type": "writers.copc",
"filename": "output.copc.laz",
"forward": "all",
"scale_x": 0.01, "scale_y": 0.01, "scale_z": 0.01,
"offset_x": "auto", "offset_y": "auto", "offset_z": "auto"
}
]
写完后可以直接用官方在线查看器验证:https://viewer.copc.io 支持把 COPC 文件拖进浏览器(Chrome/Edge 下走 File System Access API),不需要上传服务器。
17.1.2 EPT:目录形式的发布层
EPT 把数据拆成 ept.json + 瓦片目录,适合放对象存储 + CDN。构建用 Entwine(第 14 章):
entwine build -i ./classified.laz -o ./ept/classified
EPT 的强项是”看着像一张无限大的底图”:浏览器先取 ept.json 拿到八叉树结构,再按视锥与视距取节点。PDAL 官方文档里直接给出 Potree 的示例(纽约 47 亿点),并说明 readers.ept 可以做空间与分辨率查询——这也是 Web 端取数的服务化基础。
17.1.3 先降采样再发布
原始点云常有每平方米几十到几百点,浏览器端并不需要。用 filters.decimation 或 readers.copc 的 resolution 先降采样:
[
{ "type": "readers.copc", "filename": "raw.copc.laz", "resolution": 0.05 },
{ "type": "writers.copc", "filename": "web.copc.laz" }
]
resolution 的单位与数据坐标系一致,米制下 0.05 表示约 400 点/m² 的上限;Web 展示通常 0.2–1.0 就足够,文件能小一到两个数量级。
17.2 导出可渲染的网格
点云在 WebGL 里要靠 splat/point 材质渲染;如果要”实体表面”,就得先三角化。
17.2.1 三角化:poisson 还是 greedyprojection
| 过滤器 | 算法 | 适合 | 注意 |
|---|---|---|---|
filters.poisson |
泊松重建 | 封闭/完整的表面,噪声较多的扫描数据 | 计算重、内存高;depth 默认 8,越大越精细 |
filters.greedyprojection |
贪心三角化 | 有序、较干净的机载数据 | 对噪声敏感,可能产生孔洞 |
17.2.2 导出 GLB
writers.gltf 输出二进制 glTF(.glb),并且要求 point view 里已经有 mesh(否则没有可写的三角形):
[
"input.las",
{ "type": "filters.poisson", "depth": 12 },
{
"type": "writers.gltf",
"filename": "output.glb",
"red": 0.8, "green": 0.75, "blue": 0.7,
"metallic": 0.0, "roughness": 0.9,
"colors": false, "normals": true
}
]
参数(默认值都来自官方文档):
| 参数 | 默认 | 说明 |
|---|---|---|
metallic |
0 | 金属度 |
roughness |
0 | 粗糙度;0 是镜面,实物表面一般设 0.8–1.0 |
red/green/blue |
0 | 面的基础色,0–1 |
alpha |
1.0 | 透明度 |
double_sided |
false |
是否双面着色 |
colors |
false |
写顶点色,要求存在 Red/Green/Blue 维度 |
normals |
false |
写顶点法向,要求存在 NormalX/Y/Z |
colors: true 要配合 filters.normal 先算法向量,否则 normals: true 会因为缺维度而失败。
17.2.3 PLY:给桌面软件的中间格式
writers.ply 同时支持点与面,storage_mode 可选 ascii/little endian/big endian(默认 ascii)。CloudCompare、MeshLab、Blender 都能直接打开。对不需要 GLB 的场景,PLY 比 glTF 更省事。
17.3 2.5D 与制图输出
17.3.1 栅格产品
writers.gdal(第 10 章详述)把点云插值成 GeoTIFF,配 gdaldem 出山体阴影、坡度;writers.raster 输出原始栅格。这是给 QGIS/GeoServer 用的最直接产物,也是报告里”一张图”的来源。
17.3.2 矢量产品
writers.ogr 把点云按维度写成 OGR 矢量(点图层)。适合把稀疏的样点、检查点导出成 GeoPackage/Shapefile,在 GIS 里叠加底图检查位置是否正确。
17.4 三维发布的性能账
发布形态的选择本质上是一道带宽与内存的算术题。
17.4.1 数据量估算
| 形态 | 单点字节 | 1000 万点 | 说明 |
|---|---|---|---|
| LAS 1.4(格式 7) | 36 | 360 MB | 未压缩 |
| LAZ/COPC | 约 8–15 | 80–150 MB | 压缩率取决于数据 |
| EPT 瓦片 | 同上 + 目录开销 | 同上 | 碎片多,请求数多 |
| GLB 网格 | 每三角形约 36–60 | 取决于面数 | 面数由 poisson depth 决定 |
发布前用 pdal info --summary 看 count 和文件大小,按上表估算首屏加载量,再决定降采样参数。
17.4.2 首屏时间怎么压
- 降采样:
resolution或filters.decimation把首屏数据控制在 100–300 万点。 - 控制层级:COPC 的八叉树层级数量与文件体积相关,不是越多越好。
- 就近部署:CDN 或与计算同区域的对象存储,跨洲访问的 RTT 会抵消一切压缩优化。
- 避免服务端实时处理:Web 请求打到
readers.copc+ 一堆过滤器上,延迟不可控;正确做法是离线处理好,线上只做 Range 读。
17.5 从点云到 Web 三维:链路拆解
把 PDAL 产物接到浏览器,中间通常还有一步格式转换。三条现实链路:
17.5.1 链路 A:COPC + Potree
原始 LAS/LAZ
│ pdal translate(分类、降采样)
▼
COPC (.copc.laz) ──► 静态文件服务 / CDN
│
└─ Potree 前端按视锥请求 Range
Potree 原生支持 COPC,前端按节点请求 HTTP Range,服务端只需要能响应 Range 请求的静态文件服务(Nginx 默认支持)。这条链路没有中间格式、没有服务端处理,是当前最省事的方案。
17.5.2 链路 B:EPT + Potree/Cesium
LAZ 清单
│ entwine build
▼
EPT 目录(ept.json + ept-data/)
│ 上传对象存储(保持目录结构)
▼
CDN ──► Potree(原生 EPT)/ Cesium(经 3D Tiles 转换)
Cesium 消费的是 3D Tiles,不是 EPT 本身。EPT → 3D Tiles 需要外部转换工具(如 py3dtiles 生态里的转换器),PDAL 不提供这一步。如果你只需要浏览器看图,优先选链路 A。
17.5.3 链路 C:网格 + GLB
点云 ─► filters.poisson ─► writers.gltf ─► .glb
│
├─ three.js / Babylon.js 直接加载
├─ Blender 编辑后再导出
└─ Cesium glTF 模型
适合”给一个模型”而不是”给一整片点云”的场景:单栋建筑、一段地形、一个设备的三维模型。GLB 是自包含的二进制格式,单文件可拖入任何支持 glTF 的引擎。
17.5.4 三条链路怎么选
| 需求 | 链路 | 理由 |
|---|---|---|
| 在线浏览原始点云 | A(COPC) | 单文件、Range 请求、无服务端处理 |
| 百亿点级、需增量更新 | B(EPT) | 目录发布、可加 addon |
| 只要一个三维模型 | C(GLB) | 单文件、任何引擎都能开 |
| 要在浏览器里做拾取/量测 | A 或 B | 保留点云才能量测,网格只能看 |
17.6 发布前的检查清单
一份点云发布出去之前,至少确认下面几项——每一项都对应过真实故障:
| 检查项 | 命令 / 方法 | 失败后果 |
|---|---|---|
| 点数与文件大小符合预期 | pdal info --summary |
首屏加载过慢 |
| SRS 已声明 | pdal info --summary 看 metadata.srs |
前端无法定位、叠加错位 |
| 范围正确 | 对比 bounds 与测区范围 |
相机初始位置飞到别处 |
| 压缩生效 | 文件扩展名 .laz/.copc.laz,大小约为 LAS 的 1/4–1/8 |
带宽成本翻倍 |
| 分层完整 | COPC 可用 pdal info 读;EPT 检查 ept-data/ 与 entwine-files.json |
局部区域空白 |
| 颜色/强度归一化 | 抽样看 Red/Green/Blue 的取值范围 |
显示过曝或全黑 |
| 版本与生成参数留档 | 保存 pipeline JSON | 无法复现与增量更新 |
17.7 排错清单
| 现象 | 原因 | 修法 |
|---|---|---|
writers.gltf 报没有 mesh |
直接写点云,没有三角化 | 前置 filters.poisson 或 filters.greedyprojection |
| GLB 里没有颜色 | colors 默认 false,或没有 Red/Green/Blue |
设 colors: true 并确认维度存在 |
| GLB 里没有法向 | normals 默认 false,或没有 NormalX/Y/Z |
前置 filters.normal,设 normals: true |
| 模型全黑 | red/green/blue 默认都是 0 |
显式给基础色或开 colors |
| poisson 内存爆掉 | depth 过大 |
从 8–9 起调,配合降采样 |
| COPC 在 viewer 里加载慢 | 点数过多、未降采样 | 用 resolution 重新导出 |
| EPT 请求 404 | 目录上传不完整 | 校验 ept-data/ 与 entwine-files.json 的完整性 |
17.8 生产建议
发布与处理分离。 生产端离线跑完整 pipeline 产出 COPC/EPT;线上只做静态文件服务,不要在前端请求时动态执行 PDAL。延迟和成本都可控。
COPC 优先于 EPT。 单文件便于分发、校验和缓存,viewer.copc.io 与 Potree 都直接支持;只有在需要增量更新、或数据量到百亿级必须拆目录时才用 EPT。
网格只是展示层。 filters.poisson 的结果不能替代点云做量测——三角化的精度取决于点密度和算法,用它算体积、坡度会引入系统误差。量测一律回到点云。
给三维模型配”轻量元数据”。 发布时同时导出 bounds、点数、SRS、生成参数(pipeline JSON 全文)。下游在 Cesium/Potree 里定位、配准、叠图都依赖这几个值。
17.9 本章小结
| 主题 | 结论 |
|---|---|
| PDAL 的定位 | 不渲染,只产出可渲染格式 |
| COPC | writers.copc 单文件八叉树,配 resolution 降采样,viewer.copc.io 可直接验证 |
| EPT | Entwine 构建,目录发布,适合 CDN 与增量更新 |
| 网格 | filters.poisson/filters.greedyprojection 三角化后导出 |
| glTF | writers.gltf 只写 .glb,默认无顶点色、无法向,需显式开启 |
| PLY | writers.ply 支持点与面,默认 ascii |
| 2.5D | writers.gdal/writers.raster 出栅格,writers.ogr 出矢量 |
| 发布原则 | 离线处理、线上静态服务、首屏 100–300 万点 |