@csi-foxbyte/cityjson-to-3d-tiles
v0.0.22
Published
A Node.js library that converts CityJSON files into Cesium 3D Tiles—complete with automatic texture atlas packing, Basis compression, three LOD levels, and customizable threading.
Readme
cityjson-to-3d-tiles
A Node.js library for converting CityJSON files into Cesium 3D Tiles with automatic texture packing and Basis compression. Supports generating three levels of detail (LODs) for different distance ranges.
Table of Contents
- Features
- Installation
- Usage
- API
- Options Overview
- CLI Wrapper Example
- Docker Job
- Airflow DAG Example
- Building from source
- Contributing
- License
Features
- 🏙️ CityJSON to Tile Database: Parses CityJSON files and builds a tile database optimized for 3D Tiles generation. 🛠️
- 🗺️ 3D Tiles Generation: Converts the tile database into Cesium 3D Tiles, including geometry, textures, and metadata. 🎨
- 🖼️ Automatic Texture Packing: Packs textures into atlases and compresses them with Basis for efficient streaming. ⚡
- 📏 Multiple LODs: Generates three LODs (LOD0, LOD1, LOD2) to balance detail and performance based on camera distance. 🔍
- 🧵 Customizable Threading: Control the number of worker threads for CPU-bound tasks. 🛡️
Installation
npm install @csi-foxbyte/cityjson-to-3d-tilesUsage
import { generate3DTilesFromTileDatabase } from "cityjson-to-3d-tiles/3dtiles/index.js";
import { generateTileDatabaseFromCityJSON } from "cityjson-to-3d-tiles/cityjson/index.js";
const inputFolder = "D:\\generator_test\\src"; // Folder containing CityJSON files 📂
const appearance = "rgbTexture"; // Texture appearance (e.g., "rgbTexture", "vertexColor") 🎨
const outputFolder = "D:\\generator_test"; // Base output folder for the tile database and tiles 📁
(async () => {
// Step 1: Convert CityJSON to an on-disk tile database 🏗️
const { dbFilePath } = await generateTileDatabaseFromCityJSON(
inputFolder, // Source folder
outputFolder, // Destination folder
appearance, // Appearance mode
console.log, // Progress callback 📊
{ threadCount: 1 }, // Options: number of worker threads 🧵
);
// Step 2: Generate Cesium 3D Tiles from the tile database 🛠️
await generate3DTilesFromTileDatabase(
dbFilePath, // Path to the generated tile database
"D:\\generator_test\\tiles", // Output folder for 3D Tiles 🗂️
console.log, // Progress callback 📈
{ threadCount: 1 }, // Options: number of worker threads 🔧
);
})();
export { generate3DTilesFromTileDatabase, generateTileDatabaseFromCityJSON };API
generateTileDatabaseFromCityJSON(inputFolder, outputFolder, appearance, progressCallback, options)
- inputFolder
(string)– Path to a directory containing CityJSON files. 📂 - outputFolder
(string)– Directory where the tile database will be created. 📁 - appearance
(string)– Appearance: e.g."rgbTexture"-> which appearence to use. 🌈 - progressCallback
(function)– Function called with log messages or progress updates. 📢 - options
(object):threadCount(number)– Number of worker threads to use (default: number of CPU cores). 🧵
Returns: A promise that resolves with an object containing:
dbFilePath(string)– File path to the generated tile database (.db file). 📜
generate3DTilesFromTileDatabase(dbFilePath, tilesOutputFolder, progressCallback, options)
- dbFilePath
(string)– Path to the tile database generated in the previous step. 📂 - tilesOutputFolder
(string)– Directory where the Cesium 3D Tiles will be written. 🗂️ - progressCallback
(function)– Function called with log messages or progress updates. 🔔 - options
(object):threadCount(number)– Number of worker threads for tile generation (default: number of CPU cores). 🧵
Returns: A promise that resolves when 3D Tiles generation is complete. ✅
Options Overview
| Option | Default | Description |
| ------------------- | ------------------ | -------------------------------------------------------------------------- |
| appearance | "rgbTexture" | Which CityGML appearance to use. 🎨 |
| threadCount | os.cpus().length | Number of parallel worker threads. 🧵 |
| simplifyAddresses | false | Whether to simplify addresses or not (From multiple to first address only) |
CLI Wrapper Example
Wrap the functions in a simple CLI script:
#!/usr/bin/env node
import path from "path";
import { generateTileDatabaseFromCityJSON } from "cityjson-to-3d-tiles/cityjson/index.js";
import { generate3DTilesFromTileDatabase } from "cityjson-to-3d-tiles/3dtiles/index.js";
const [, , src, out, appearance] = process.argv;
(async () => {
const { dbFilePath } = await generateTileDatabaseFromCityJSON(
path.resolve(src),
path.resolve(out),
appearance || "rgbTexture",
console.log,
{ threadCount: 4 },
);
await generate3DTilesFromTileDatabase(
dbFilePath,
path.join(out, "tiles"),
console.log,
{ threadCount: 4 },
);
})();Docker Job
The repository provides a Docker-based job runner.
What it does:
- Runs
citygml-tools to-cityjson -o cityjson .in/work(skippable viaSKIP_CONVERSION) - Converts CityJSON files from
INPUT_DIR(default:/work) - Creates the temporary SQLite DB in container-local storage (
/tmp) for better performance on Windows mounts - Writes final 3D Tiles to
OUTPUT_DIR(default:/work/tiles)
Build Image
docker build -t cityjson-to-3d-tiles .Run on Windows (PowerShell)
Run this from your data folder:
docker run --rm -v "${PWD}:/work" cityjson-to-3d-tilesRun on Linux (bash/zsh)
Run this from your data folder:
docker run --rm -v "$(pwd):/work" cityjson-to-3d-tilesOptional Environment Variables
APPEARANCE=rgbTexture
THREAD_COUNT=4
HAS_ALPHA_ENABLED=true
SIMPLIFY_ADDRESSES=false
SKIP_CONVERSION=false
INPUT_DIR=/work
OUTPUT_DIR=/work/tiles
INTERNAL_DB_DIR=/tmp/cityjson-to-3d-tiles
SRC_SRS=<proj string>
DEST_SRS=<proj string>
SHOW_STACK_TRACE=falseFind Proj4 strings:
- PROJ documentation: https://proj.org/
- EPSG search (incl. Proj4): https://epsg.io/
Example (PowerShell):
docker run --rm -v "${PWD}:/work" -e THREAD_COUNT=8 -e APPEARANCE=rgbTexture cityjson-to-3d-tilesExample (Linux):
docker run --rm -v "$(pwd):/work" -e THREAD_COUNT=8 -e APPEARANCE=rgbTexture cityjson-to-3d-tilesAirflow DAG Example
An example DAG is available in:
examples/airflow/cityjson_to_3d_tiles_dag.py
It uses DockerOperator, runs the GHCR image, and mounts one host folder to /work.
Building from source
pnpm is required to build this library.
pnpm install
pnpm run buildContributing
Contributions are welcome! Please open issues or pull requests on the GitHub repository. 🙌
License
This library is licensed under the GNU Lesser General Public License.
