npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

  • 🏙️ 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-tiles

Usage

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 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

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-tiles

Run on Linux (bash/zsh)

Run this from your data folder:

docker run --rm -v "$(pwd):/work" cityjson-to-3d-tiles

Optional 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=false

Find 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-tiles

Example (Linux):

docker run --rm -v "$(pwd):/work" -e THREAD_COUNT=8 -e APPEARANCE=rgbTexture cityjson-to-3d-tiles

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.

Building from source

pnpm is required to build this library.

pnpm install
pnpm run build

Contributing

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.