云原生的 3D 建筑 —— 把 PLATEAU 从下载变成数据服务
PLATEAU 是日本的开放 3D 城市模型计划,到 2025 年度已经有 329 个市町村的模型开放下载。我 2022 年起的本职工作,就是在 Eukarya 做它的官方 viewer 和 CMS。下载很容易,用起来不容易:我住的柏市,光建筑物就是 143 个文件、1.6 GB 的 CityGML。门户本身没有问题——目录整齐、许可清晰、规格标准——问题出在「先下载、再整个解析」这个模式。影视行业有力气硬啃下来,日常的 GIS 工作大多被弹开。
于是做了个个人实验:如果这些建筑物是 cloud-native 的呢?不下载整座城市,从对象存储直接读需要的那个街区,语义完整保留,什么工具都能读。
查了一圈现有方案,「3D 几何 × 语义面 × 云原生范围读取 × 列式分析」这个交叉点是空的。最接近的先行工作 FLATEAU 只保留了 LOD0 的 footprint,理由是 GeoParquet 没有 3D 几何类型——这个被放弃的台阶,正是这次实验站的地方。要说清楚:我什么都没发明,每一块砖都是现成的。
做法是分层,而不是把 Solid 硬塞进 GeoParquet:GeoParquet 放 2D footprint 和属性,44 MB,是发现层,DuckDB 和 QGIS 直接 SQL over HTTP;嵌套 Parquet 放 LOD1 实体和 LOD2 语义面;FlatCityBuf 放完整的 3D 对象——文件内部自带 Hilbert R-tree,和 COG、COPC 是同一个思路,可以叫它「建筑物的 COPC」。结果:同一座城市小了 13 倍,169,223 栋建筑转换零失败;取一个街区的完整 3D,只碰 141 MB 文件的 2.2%,9 次 range 请求。两层还互相跑了基准:投递偏爱面向对象的那层,分析偏爱列式的那层——所以两个都留。整套数据挂在一个合法的 STAC 1.1 目录下,用的全是社区扩展,没有发明方言。
结尾说了句实话:3D 真的值得吗?我自己的模拟跑在 2.5D 棱柱上,精心保留的 LOD2 面一次都没碰。文献的结论是,分水岭在于高度是否准确,而不在屋顶形状。所以默认 2.5D,只在划算的地方按需读 3D——分层恰好让这件事变得便宜。想试的话,DuckDB 里贴一句 SQL 就能直接跑:不用下载,不用 key。
--- layout: talk.njk title_zh: "云原生的 3D 建筑 —— 把 PLATEAU 从下载变成数据服务" title_ja: "クラウドネイティブな 3D 建物 — PLATEAU をダウンロードからデータサービスへ" title_en: "Cloud-Native 3D Buildings — PLATEAU, from Downloads to Data Services" year: 2026 event: STAC Japan 2026 eventUrl: https://cloudnativegeo.org/events/stac-japan-2026/ role: speaker location: JAXA 筑波宇宙中心 location_ja: JAXA 筑波宇宙センター location_en: JAXA Tsukuba Space Center cover: /images/talks/stac-japan-2026-cloud-native-buildings/cover.jpg description: "A personal experiment in making PLATEAU's 3D buildings cloud-native: GeoParquet + FlatCityBuf under one STAC catalog, the same city 13× smaller, one block's full 3D for 2.2% of the file — and an honest ending about when 3D even pays." slides: https://stac.surreal.red workTags: - talk --- <div lang="zh"> PLATEAU 是日本的开放 3D 城市模型计划,到 2025 年度已经有 329 个市町村的模型开放下载。我 2022 年起的本职工作,就是在 Eukarya 做它的官方 viewer 和 CMS。下载很容易,用起来不容易:我住的柏市,光建筑物就是 143 个文件、1.6 GB 的 CityGML。门户本身没有问题——目录整齐、许可清晰、规格标准——问题出在「先下载、再整个解析」这个模式。影视行业有力气硬啃下来,日常的 GIS 工作大多被弹开。 于是做了个个人实验:如果这些建筑物是 cloud-native 的呢?不下载整座城市,从对象存储直接读需要的那个街区,语义完整保留,什么工具都能读。 查了一圈现有方案,「3D 几何 × 语义面 × 云原生范围读取 × 列式分析」这个交叉点是空的。最接近的先行工作 FLATEAU 只保留了 LOD0 的 footprint,理由是 GeoParquet 没有 3D 几何类型——这个被放弃的台阶,正是这次实验站的地方。要说清楚:我什么都没发明,每一块砖都是现成的。 做法是分层,而不是把 Solid 硬塞进 GeoParquet:GeoParquet 放 2D footprint 和属性,44 MB,是发现层,DuckDB 和 QGIS 直接 SQL over HTTP;嵌套 Parquet 放 LOD1 实体和 LOD2 语义面;FlatCityBuf 放完整的 3D 对象——文件内部自带 Hilbert R-tree,和 COG、COPC 是同一个思路,可以叫它「建筑物的 COPC」。结果:同一座城市小了 13 倍,169,223 栋建筑转换零失败;取一个街区的完整 3D,只碰 141 MB 文件的 2.2%,9 次 range 请求。两层还互相跑了基准:投递偏爱面向对象的那层,分析偏爱列式的那层——所以两个都留。整套数据挂在一个合法的 STAC 1.1 目录下,用的全是社区扩展,没有发明方言。 结尾说了句实话:3D 真的值得吗?我自己的模拟跑在 2.5D 棱柱上,精心保留的 LOD2 面一次都没碰。文献的结论是,分水岭在于高度是否准确,而不在屋顶形状。所以默认 2.5D,只在划算的地方按需读 3D——分层恰好让这件事变得便宜。想试的话,DuckDB 里贴一句 SQL 就能直接跑:不用下载,不用 key。 </div> <div lang="ja"> PLATEAU は日本のオープンな 3D 都市モデルのプロジェクトで、2025 年度時点で 329 の市区町村のモデルが公開されている。私の 2022 年からの本業は、Eukarya でその公式ビューアと CMS を作ることだ。ダウンロードは簡単。使うのは簡単ではない。私の住む柏市は、建物だけで 143 ファイル・1.6 GB の CityGML になる。ポータル自体に問題はない——目録は整い、ライセンスは明確で、仕様は標準的だ。問題は「まずダウンロードして、全部パースする」というモデルのほうにある。映像業界は力技で乗り越えるが、日常の GIS 業務はだいたい弾き返される。 そこで個人的な実験をした。この建物たちが cloud-native だったら? 都市をまるごとダウンロードするのではなく、必要な街区だけをオブジェクトストレージから直接読む。セマンティクスは保ったまま、どのツールからでも。 既存の手法を調べると、「3D ジオメトリ × セマンティックサーフェス × クラウドネイティブな範囲読み取り × 列指向の分析」という交差点は空白だった。一番近い先行例の FLATEAU は LOD0 のフットプリントだけを残していて、理由は GeoParquet に 3D ジオメトリ型がないこと。その諦められた一段が、ちょうどこの実験の立ち位置だ。はっきり言っておくと、私は何も発明していない——レンガは全部、既製品である。 やり方は、Solid を GeoParquet に押し込むのではなく、層に分けること。GeoParquet には 2D フットプリントと属性(44 MB の発見レイヤー。DuckDB や QGIS から SQL over HTTP でそのまま引ける)。ネストした Parquet には LOD1 のソリッドと LOD2 のセマンティックサーフェス。FlatCityBuf には完全な 3D オブジェクト——ファイルの中に Hilbert R-tree を持っていて、COG や COPC と同じ発想だ。「建物のための COPC」と呼んでいい。結果:同じ都市が 13 分の 1 に、169,223 棟の変換は失敗ゼロ。ある街区の完全な 3D を取り出すのに、141 MB のファイルのうち触るのは 2.2%、レンジリクエスト 9 回。2 つの層はベンチマークで突き合わせもした——配信はフィーチャー指向が、分析は列指向が勝つ。だから両方残す。全体は正規の STAC 1.1 カタログにぶら下がっていて、使ったのはコミュニティ拡張だけ。方言は発明していない。 最後に正直な話をした。3D は本当に割に合うのか? 私自身のシミュレーションは 2.5D の角柱で走っていて、丁寧に保存した LOD2 サーフェスには一度も触れなかった。文献の結論は、分水嶺は屋根の形ではなく高さの正確さにある、というものだ。だからデフォルトは 2.5D。3D は割に合う場所でだけレンジ読みする——層に分けたおかげで、それが安くできる。試したければ、DuckDB に SQL を 1 行貼るだけでそのまま動く。ダウンロードもキーも要らない。 </div> <div lang="en"> Project PLATEAU is Japan's open 3D city model programme — 329 municipalities published as of FY2025 — and my day job since 2022 has been building its official viewer and CMS at Eukarya. Downloading is easy. Using it is not: my own city, Kashiwa, is 1.6 GB of CityGML in 143 files for the buildings alone. The portal is not the problem — tidy catalog, clear licence, standard spec. The problem is the download-first, parse-everything model. The film industry powers through; everyday GIS work mostly bounces off. So, a personal experiment: what if these buildings were cloud-native? Don't download the city — read just the block you need, straight from object storage, semantics intact, from any tool. Surveying what exists, the intersection of 3D geometry × semantic surfaces × cloud-native range reads × columnar analysis turned out to be empty. The nearest prior work, FLATEAU, kept LOD0 footprints only, citing GeoParquet's lack of 3D geometry types — and that abandoned step is exactly where this experiment lives. To be clear: I invented nothing. Every brick is off the shelf. The answer is layering, not forcing solids into GeoParquet: GeoParquet for 2D footprints and attributes (a 44 MB discovery layer — SQL over HTTP from DuckDB or QGIS), nested Parquet for LOD1 solids and LOD2 semantic surfaces, and FlatCityBuf for complete 3D objects — a packed Hilbert R-tree lives inside the file, the same idea as COG and COPC. Call it the COPC for buildings. Results: the same city 13× smaller, 169,223 buildings converted with zero failures; one block's full 3D for 2.2% of a 141 MB file in 9 range requests. The two layers were benchmarked against each other — delivery favours feature-oriented, analytics favours columnar, so keep both. Everything hangs off a valid STAC 1.1 catalog using community extensions only; no invented dialect. The honest ending: is 3D even worth it? My own simulations ran on 2.5D prisms and never touched the LOD2 surfaces I so carefully preserved. The literature says the watershed is height accuracy, not roof shape. So default to 2.5D, and range-read the 3D only where it pays — the layers make that cheap. If you want to poke at it, one SQL statement pasted into DuckDB runs as-is: no download, no key. </div>