#geospatial #tile #mvt


A very fast Rust crate for geospatial point clustering

16 stable releases

1.0.16 Feb 6, 2024
1.0.15 Dec 7, 2023
1.0.14 Nov 27, 2023

#17 in Geospatial

Download history 196/week @ 2023-11-01 145/week @ 2023-11-08 32/week @ 2023-11-15 49/week @ 2023-11-22 35/week @ 2023-11-29 78/week @ 2023-12-06 18/week @ 2023-12-13 15/week @ 2023-12-20 17/week @ 2023-12-27 15/week @ 2024-01-03 14/week @ 2024-01-10 8/week @ 2024-01-17 19/week @ 2024-01-24 47/week @ 2024-01-31 10/week @ 2024-02-07 221/week @ 2024-02-14

299 downloads per month

MIT license



A very fast Rust crate for geospatial point clustering.

This crate is deeply inspired by Mapbox's supercluster JS package and blog post.

Reference implementation

test docs crate downloads GitHub



  • load(points): Loads a FeatureCollection Object. Each feature should be a Feature Object.

  • get_clusters(bbox, zoom): For the given bbox array ([west_lng, south_lat, east_lng, north_lat]) and zoom, returns an array of clusters and points as Feature Object objects.

  • get_tile(z, x, y): For a given zoom and x/y coordinates, returns a FeatureCollection Object.

  • get_children(cluster_id): Returns the children of a cluster (on the next zoom level) given its id (cluster_id value from feature properties).

  • get_leaves(cluster_id, limit, offset): Returns all the points of a cluster (given its cluster_id), with pagination support.

  • get_cluster_expansion_zoom(cluster_id): Returns the zoom on which the cluster expands into several children (useful for "click to zoom" feature) given the cluster's cluster_id.


Option Description
min_zoom Minimum zoom level at which clusters are generated.
max_zoom Maximum zoom level at which clusters are generated.
min_points Minimum number of points to form a cluster.
radius Cluster radius, in pixels.
extent (Tiles) Tile extent. Radius is calculated relative to this value.
node_size Size of the KD-tree leaf node. Affects performance.


This crate uses #![forbid(unsafe_code)] to ensure everything is implemented in 100% safe Rust.


For more in-depth details, please refer to the full documentation.

If you encounter any issues or have questions that are not addressed in the documentation, feel free to submit an issue.


Run the following Cargo command in your project directory:

cargo add supercluster
use geojson::FeatureCollection;
use supercluster::{ Supercluster, Options };

fn main() {
  let options = Options {
      max_zoom: 16,
      min_zoom: 0,
      min_points: 2,
      radius: 40.0,
      node_size: 64,
      extent: 512.0,

  // Create a new instance with the specified configuration settings
  let mut cluster = Supercluster::new(options);

  // Load a FeatureCollection Object into the Supercluster instance

  // [GeoJSON Format Specification § 5](https://tools.ietf.org/html/rfc7946#section-5)
  let feature_collection = FeatureCollection {
    bbox: None,
    // [GeoJSON Format Specification § 3.2](https://datatracker.ietf.org/doc/html/rfc7946#section-3.2)
    features: vec![],
    foreign_members: None,
  let index = cluster.load(feature_collection);

  // Retrieve a FeatureCollection Object within a tile at the given zoom level and tile coordinates
  let tile = index.get_tile(0, 0.0, 0.0).expect("cannot get a tile");




cargo build


cargo test

Run clippy:

cargo clippy --all-targets --all-features -- -D warnings

Run rustfmt:

cargo fmt

Generate documentation in HTML format:

cargo doc --open


Chargetrip logo


~54K SLoC