将 Shapefile (SHP) 建筑底面数据转换为 3D Tiles 1.1 格式的 CLI 工具。
- 3D Tiles 1.1 规范 — 输出
.glb 瓦片,使用 EXT_mesh_features + EXT_structural_metadata 存储要素属性
- 多边形拉伸 — 2D 轮廓 → 3D 建筑网格(墙体/屋顶/地面分离,支持独立纹理)
- 高度灵活控制 — 支持固定数值或 SHP 属性字段作为高度来源,可设缩放系数
- 底面高度控制 — 支持海拔/底面高度字段,解决建筑悬空或贴地问题
- 外轮廓模式 — 可选忽略孔洞,简化回字形等复杂多边形的网格拓扑
- 压缩包输入 — 直接读取
.zip / .rar,自动解压提取 Shapefile
- 纹理贴图 — 侧面/顶面独立纹理,支持 JPG / WebP / KTX2
- 四叉树空间索引 — 自动空间划分,高效组织大规模数据
- Draco 压缩 — 可选顶点压缩,减少传输体积
- 白膜材质 — 无纹理时自动使用
KHR_materials_unlit,纯色无光照
npm install
npm run build
node dist/bin/shp-to-3dtiles.js \
-i ./buildings.shp \
-o ./output \
--building-height height
node dist/bin/shp-to-3dtiles.js \
-i ./buildings.zip \
-o ./output \
--building-height height
# 从属性字段读取高度,楼层×3 转换为米
node dist/bin/shp-to-3dtiles.js \
-i buildings.shp -o output \
--building-height floors --height-scale 3
# 固定高度 15 米,底面从 elevation 字段读取
node dist/bin/shp-to-3dtiles.js \
-i buildings.shp -o output \
--building-height 15 --floor-height elevation
# 侧面贴砖纹理,顶面贴屋顶纹理
node dist/bin/shp-to-3dtiles.js \
-i buildings.shp -o output \
--building-height height \
--wall-texture ./brick.jpg --wall-texture-width 5 \
--roof-texture ./roof.jpg --roof-texture-width 20 \
--texture-format webp
node dist/bin/shp-to-3dtiles.js \
-i ./buildings.zip \
-o ./output \
--building-height height \
--height-scale 3 \
--floor-height elevation \
--floor-scale 1 \
--outer-contour-only \
--wall-texture ./wall.jpg --wall-texture-width 5 \
--roof-texture ./roof.jpg --roof-texture-width 20 \
--texture-format webp \
--draco \
--properties name,type,area \
--verbose
| 参数 |
说明 |
默认值 |
-i, --input <path> |
输入文件路径(.shp 或 .zip/.rar 压缩包) |
必填 |
-o, --output <dir> |
输出目录 |
必填 |
| 参数 |
说明 |
默认值 |
--building-height <value> |
顶面高度:固定数值(如 15)或 SHP 属性字段名(如 height) |
10 |
--height-scale <n> |
顶面高度缩放系数(如楼层→米:--height-scale 3) |
1 |
--floor-height <value> |
底面高度:固定数值(如 0)或 SHP 属性字段名(如 elevation) |
0 |
--floor-scale <n> |
底面高度缩放系数 |
1 |
高度计算公式:
maxHeight = resolve(buildingHeight) × heightScale
minHeight = resolve(floorHeight) × floorScale
resolve 逻辑:数值直接使用,字段名从属性表取值(失败则用默认值)
| 参数 |
说明 |
默认值 |
--outer-contour-only |
仅使用外轮廓,忽略多边形内部孔洞(简化网格拓扑) |
false |
| 参数 |
说明 |
默认值 |
--wall-texture <path> |
侧面(墙体)纹理图片路径 |
无(白膜) |
--wall-texture-width <m> |
侧面纹理平铺宽度(米) |
5 |
--roof-texture <path> |
顶面(屋顶)纹理图片路径 |
无(白膜) |
--roof-texture-width <m> |
顶面纹理平铺宽度(米) |
5 |
--texture-format <type> |
纹理输出格式:jpg、webp、ktx2 |
jpg |
| 参数 |
说明 |
默认值 |
--draco |
启用 Draco 顶点压缩 |
false |
--properties <fields> |
需要保留的 SHP 属性字段,逗号分隔 |
空 |
| 参数 |
说明 |
默认值 |
--spatial-resolution <deg> |
四叉树分割阈值(度),约 0.01° ≈ 1km |
0.01 |
--verbose |
输出详细日志 |
false |
output/
├── tileset.json # 根瓦片集(3D Tiles 1.1)
└── tile/
└── {z}/
└── {x}/
└── {y}/
└── content.glb # GLB 瓦片(含墙体+顶面双 primitive)
每个 GLB 文件包含以下扩展:
- KHR_materials_unlit — 白膜无光照材质(无纹理时自动启用)
- EXT_mesh_features — 为每个顶点分配 feature ID
- EXT_structural_metadata — 定义属性 schema 和 property table
前端可通过 CesiumJS 查询要素属性:
const viewer = new Cesium.Viewer('cesiumContainer');
const tileset = await Cesium.Cesium3DTileset.fromUrl('./output/tileset.json');
viewer.scene.primitives.add(tileset);
// 点击查询属性
viewer.screenSpaceEventHandler.setInputAction((movement) => {
const picked = viewer.scene.pick(movement.position);
if (picked instanceof Cesium.Cesium3DTileFeature) {
console.log(picked.getProperty('name'));
console.log(picked.getProperty('height'));
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
# 开发模式运行
npm run dev -- -i test.shp -o out --building-height height
# 类型检查
npm run typecheck
# 构建
npm run build
| 包名 |
用途 |
shpjs |
SHP 文件解析 |
proj4 |
坐标系转换 |
earcut |
多边形三角化 |
@gltf-transform/core |
glTF 文档构建 |
@gltf-transform/extensions |
Draco / KHR_materials_unlit 扩展 |
sharp |
图片处理 |
commander |
CLI 框架 |
unzipper |
ZIP 解压 |
node-unrar-js |
RAR 解压 |
MIT