@csi-foxbyte/cityjson-to-3d-tiles
Version:
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.
240 lines (168 loc) β’ 7.94 kB
Markdown
# cityjson-to-3d-tiles
A Node.js library for converting [CityJSON](https://www.cityjson.org/) files into [Cesium 3D Tiles](https://cesium.com/3d-tiles/) with automatic texture packing and Basis compression. Supports generating three levels of detail (LODs) for different distance ranges.
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [API](#api)
- [Options Overview](#options-overview)
- [CLI Wrapper Example](#cli-wrapper-example)
- [Docker Job](#docker-job)
- [Airflow DAG Example](#airflow-dag-example)
- [Building from source](#building-from-source)
- [Contributing](#contributing)
- [License](#license)
<a id="features" />
## 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](https://github.com/BinomialLLC/basis_universal) 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. π‘οΈ
<a id="installation" />
## Installation
```bash
npm install @csi-foxbyte/cityjson-to-3d-tiles
```
<a id="usage" />
## Usage
```js
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 };
```
<a id="api" />
## 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. β
<a id="options-overview" />
## 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) |
<a id="cli-wrapper-example" />
## CLI Wrapper Example
Wrap the functions in a simple CLI script:
```js
#!/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 },
);
})();
```
<a id="docker-job" />
## Docker Job
The repository provides a Docker-based job runner.
What it does:
- Runs `citygml-tools to-cityjson -o cityjson .` in `/work` (skippable via `SKIP_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
```bash
docker build -t cityjson-to-3d-tiles .
```
### Run on Windows (PowerShell)
Run this from your data folder:
```powershell
docker run --rm -v "${PWD}:/work" cityjson-to-3d-tiles
```
### Run on Linux (bash/zsh)
Run this from your data folder:
```bash
docker run --rm -v "$(pwd):/work" cityjson-to-3d-tiles
```
### Optional Environment Variables
```text
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=false
```
Find Proj4 strings:
- PROJ documentation: https://proj.org/
- EPSG search (incl. Proj4): https://epsg.io/
Example (PowerShell):
```powershell
docker run --rm -v "${PWD}:/work" -e THREAD_COUNT=8 -e APPEARANCE=rgbTexture cityjson-to-3d-tiles
```
Example (Linux):
```bash
docker run --rm -v "$(pwd):/work" -e THREAD_COUNT=8 -e APPEARANCE=rgbTexture cityjson-to-3d-tiles
```
<a id="airflow-dag-example" />
## Airflow 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`.
<a id="building-from-source" />
## Building from source
[pnpm](https://pnpm.io/) is required to build this library.
```bash
pnpm install
pnpm run build
```
<a id="contributing" />
## Contributing
Contributions are welcome! Please open issues or pull requests on the GitHub repository. π
<a id="license" />
## License
This library is licensed under the [GNU Lesser General Public License](https://www.gnu.org/licenses/#LGPL).