Skip to content

Getting Started

Installation

CLI (Cargo)

cargo install gpq-tiles

Prerequisites: Rust 1.75+, protoc

# macOS
brew install protobuf

# Ubuntu/Debian
apt install protobuf-compiler

Python

pip install gpq-tiles

From Source

git clone https://github.com/geoparquet-io/gpq-tiles.git
cd gpq-tiles
cargo build --release

Input Requirements

gpq-tiles requires WGS84 (EPSG:4326) coordinates. If your GeoParquet file uses a projected CRS (e.g., UTM, British National Grid), you must reproject first using geoparquet-io:

# Reproject to WGS84 with geoparquet-io (recommended)
gpio convert reproject input.parquet output.parquet -d EPSG:4326

# Optimize for streaming performance at the same time
gpio convert reproject input.parquet output.parquet -d EPSG:4326 --hilbert --row-group-size 100000

If you forget, gpq-tiles will error with a helpful message showing the detected CRS and the reprojection command.

Why gpio? Unlike generic tools, gpio produces optimized GeoParquet with Hilbert sorting and proper row group sizing, which dramatically improves gpq-tiles performance on large files.

Basic Usage

CLI

# Basic conversion
gpq-tiles input.parquet output.pmtiles --min-zoom 0 --max-zoom 14

# Property filtering (matches tippecanoe -y/-x/-X)
gpq-tiles input.parquet output.pmtiles --include name --include population
gpq-tiles input.parquet output.pmtiles --exclude internal_id
gpq-tiles input.parquet output.pmtiles --exclude-all  # geometry only

# Compression options (gzip is default for compatibility)
gpq-tiles input.parquet output.pmtiles                       # gzip (default)
gpq-tiles input.parquet output.pmtiles --compression zstd    # faster encoding
gpq-tiles input.parquet output.pmtiles --compression brotli  # best ratio
gpq-tiles input.parquet output.pmtiles --compression none    # debugging only

# Verbose progress (useful for large files)
gpq-tiles input.parquet output.pmtiles --verbose

# Suppress optimization warnings
gpq-tiles input.parquet output.pmtiles --quiet

Compression tradeoffs:

Algorithm Notes
gzip Default. Maximum compatibility with PMTiles viewers (pmtiles.io, MapLibre, etc.)
zstd Faster encoding, larger files. Use when your viewer supports it
brotli Slowest encoding, best compression ratio
none No compression (debugging only)

Based on benchmark: 3.3GB GeoParquet, zoom 0-8. Gzip: 3:04 (175MB output), Zstd: 2:59 (254MB output).

Python

Current API (basic conversion only):

from gpq_tiles import convert

convert(
    input="buildings.parquet",
    output="buildings.pmtiles",
    min_zoom=0,
    max_zoom=14,
    compression="gzip",          # "gzip" | "zstd" | "brotli" | "none"
    drop_density="medium",       # "low" | "medium" | "high"
)

Coming soon: Property filtering, streaming modes, progress callbacks. Track progress in #45.

Rust

Low-level API (full control):

use gpq_tiles_core::pipeline::{generate_tiles, TilerConfig};
use gpq_tiles_core::PropertyFilter;
use std::path::Path;

let config = TilerConfig::new(0, 14)
    .with_density_drop(true)
    .with_property_filter(PropertyFilter::Include(vec!["name".into(), "population".into()]))
    .with_layer_name("buildings");

let tiles = generate_tiles(Path::new("input.parquet"), &config)?;
for tile in tiles {
    let tile = tile?;
    println!("Tile z={} x={} y={}: {} bytes",
             tile.coord.z, tile.coord.x, tile.coord.y, tile.data.len());
}

High-level API (convenience wrapper):

use gpq_tiles_core::{Converter, Config, Compression, PropertyFilter};

let config = Config {
    min_zoom: 0,
    max_zoom: 14,
    compression: Compression::Gzip,  // Default, maximum compatibility
    property_filter: PropertyFilter::Exclude(vec!["internal_id".into()]),
    ..Default::default()
};

let converter = Converter::new(config);
converter.convert("input.parquet", "output.pmtiles")?;

Optimizing Input Files

For best performance, optimize your GeoParquet files first:

# Check and fix GeoParquet formatting with geoparquet-io
gpio check all --fix input.parquet

gpq-tiles warns if input files lack optimization. See geoparquet-io for details.

Property Filtering

Control which attributes are included in output tiles (matches tippecanoe's -y/-x/-X flags):

Include only specific fields (whitelist):

gpq-tiles input.parquet output.pmtiles \
  --include name \
  --include population \
  --include area_sqkm

Exclude specific fields (blacklist):

gpq-tiles input.parquet output.pmtiles \
  --exclude internal_id \
  --exclude temp_field \
  --exclude debug_info

Exclude all properties (geometry only):

gpq-tiles input.parquet output.pmtiles --exclude-all

Why filter properties? - Reduce tile size — Remove unnecessary attributes - Optimize performance — Less data to encode/decode - Privacy — Strip sensitive fields before publishing

Large Files

For files larger than available memory, use streaming mode:

# Fast mode (default): Single pass, processes row groups sequentially
gpq-tiles large.parquet output.pmtiles --streaming-mode fast

# Low-memory mode: External sort, bounded memory (slower)
gpq-tiles large.parquet output.pmtiles --streaming-mode low-memory

Mode comparison:

Mode Memory Speed Notes
fast Row-group based Fastest Memory bounded by largest row group (~100-200MB typical)
low-memory External sort Slower Sorts to disk, guaranteed low memory

Row-group streaming works best with properly formatted files. Use gpio check all --fix for optimal performance.