Skip to content

feat(geojson): serve MVT tiles from a GeoJSON file#2538

Draft
thomfuhrmann wants to merge 66 commits intomaplibre:mainfrom
thomfuhrmann:mvt-from-geojson-issue-2054
Draft

feat(geojson): serve MVT tiles from a GeoJSON file#2538
thomfuhrmann wants to merge 66 commits intomaplibre:mainfrom
thomfuhrmann:mvt-from-geojson-issue-2054

Conversation

@thomfuhrmann
Copy link
Copy Markdown
Contributor

@thomfuhrmann thomfuhrmann commented Feb 3, 2026

Description

This is a first proof-of-concept for GeoJSON integration into Martin tile server. It depends on the geozero crate for MVT tile creation and on geo-index for the spatial Hilbert R-Tree. The clipping depends on the i_overlay crate.

Here is a summary of the processing pipeline:

Steps to pre-process GeoJSON features and create the data source:

  1. Convert from WGS84 EPSG:4326 to Web Mercator EPSG:3857
  2. Create spatial index using a packed Hilbert R-Tree

The following processing steps will be done when a tile request arrives:

  1. Search for geometries that overlap with a given tile bounding box using the R-Tree
  2. Clip geometries with tile bounding box (and optional buffer)
  3. Transform into tile coordinate space and convert to MVT binary format

Related Issue

Addresses #2054

Limitations and open questions

The geozero crate currently does not have an implementation for GeozeroDatasource for the GeoJson datatype. The processing steps are copied from there to avoid unnecessary string conversions.
Currently the buffer is created with a default size of 256 - should we make this configurable?
Testing is done only rudimentary.
Geometries are not cleaned before or after processing, instead it relies on correct geometries.

@thomfuhrmann thomfuhrmann changed the title Mvt from geojson issue #2054 feat: serve Mapbox vector tiles from geojson issue #2054 Feb 3, 2026
@thomfuhrmann thomfuhrmann changed the title feat: serve Mapbox vector tiles from geojson issue #2054 feat: serve Mapbox vector tiles from geojson #2054 Feb 3, 2026
@thomfuhrmann thomfuhrmann changed the title feat: serve Mapbox vector tiles from geojson #2054 feat: serve Mapbox vector tiles from geojson Feb 3, 2026
@thomfuhrmann thomfuhrmann changed the title feat: serve Mapbox vector tiles from geojson feat: serve mapbox vector tiles from geojson Feb 3, 2026
@CommanderStorm
Copy link
Copy Markdown
Member

Interestingly, your approach is a bit different from the one in

I am not sure which is better (I would need advice on this).
I am sure that there are a few things to steal from that PR (docs).
In terms of tests, this needs to be integrted into test.sh and a few more unit tests, for me to really trust that the code is battleproof.

I am fine with marking it as not-battleproof (geojson -> unstable-geojson) similar to rendering or COG.

Comment thread martin-tile-utils/src/lib.rs
Comment thread docs/src/sources-files.md Outdated
@CommanderStorm CommanderStorm changed the title feat: serve MVT tiles from a GeoJSON file feat(geojson): serve MVT tiles from a GeoJSON file Feb 9, 2026
Comment thread docs/src/installation.md
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to find something a bit more minimal than 500k lines / 11 MB.

This curiously does not even seem to be used, so might just be an artefact

Copy link
Copy Markdown
Contributor Author

@thomfuhrmann thomfuhrmann Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course we can remove it, sorry for readding it. I just wanted to test it as an edge case.

Comment thread justfile
Comment on lines +114 to +125
# geos is hard to build on Windows or macos
if [[ "{{target}}" =~ .+-pc-windows-msvc ]]; then
cargo build --release --target {{target}} --package martin --locked \
--no-default-features \
--features fonts,lambda,mbtiles,metrics,pmtiles,postgres,sprites,styles,webui
elif [[ "{{target}}" =~ .+-apple-darwin ]]; then
cargo build --release --target {{target}} --package martin --locked \
--no-default-features \
--features fonts,lambda,mbtiles,metrics,pmtiles,postgres,sprites,styles,webui
else
cargo build --release --target {{target}} --package martin --locked
fi
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really ugly hack and we likely should not merge it as-is.
Geos is just a bit hard to install it seems.

I think making geojson an non-default feature and enabling it in the build here in CI:

  • we are building for musl (aka statically)
  • if packagecfg finds the library

This way, we have a much simpler life and our contributors don't neeed to deal with geos if they want to contribute to martin.

Other oppinions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I also found it hard to build on my Windows machine in the office. At first I wanted to use the geo crate for geometry validation, which would not require a dependency on C++ code. Unfortunately, the geo crate validation routine seems to be much slower than GEOS.

@CommanderStorm
Copy link
Copy Markdown
Member

I think it should now be integrated into our CI, with most issues fixed. Lets see.

@thomfuhrmann
Copy link
Copy Markdown
Contributor Author

I think it should now be integrated into our CI, with most issues fixed. Lets see.

Thank you @CommanderStorm! Sorry for my late reply, I was a little busy at work.

@thomfuhrmann
Copy link
Copy Markdown
Contributor Author

thomfuhrmann commented Feb 21, 2026

I reverted back to geometry validation with the geo crate to simplify the build process. I think the performance is still acceptable even though worse than with GEOS.

Also, I found out that there is an open issue in the geojson crate that would allow much faster parsing and conversion to geo-types geometries. I am planning to integrate this once it will be released:
georust/geojson#263

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants