-
-
Notifications
You must be signed in to change notification settings - Fork 306
feat(geojson): add mvt tiles generation from GeoJSON #2098
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
this is great, thank you! One of us will definitely review it shortly. Being a fairly complex feature, i'm sure there will be some back and forth about it, so please don't be dissuaded if it doesn't get merged right away :) |
CommanderStorm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Firstly, this is nice work 👍🏻
Thanks for tackling this!
This is very straightforward code you wrote.
I needed access to some of the internals from geozero's mvt, which were not public
Instead of effectively forking, let's try to just make the fields public that we need.
For an experimental impl, current version is fine.
For getting merged, I would like to see a PR to make the values we need pub in geozero.
In my initial testing, the tile endpoint was abnormally slow. I did not yet get around to why that is the case.
Just throwing it out there: did you run it in release mode?. This burnt me once 😉
To benchmark things, we have the following two functionalities. If you think performance could be an issue, benchmarking it is probably a good idea.
Lines 41 to 59 in 872a0e7
| # Run benchmark tests | |
| bench: | |
| cargo bench --bench bench | |
| open target/criterion/report/index.html | |
| # Run HTTP requests benchmark using OHA tool. Use with `just bench-server` | |
| bench-http: (cargo-install 'oha') | |
| @echo "ATTENTION: Make sure Martin was started with just bench-server" | |
| @echo "Warming up..." | |
| oha --latency-correction -z 5s --no-tui http://localhost:3000/function_zxy_query/18/235085/122323 > /dev/null | |
| oha --latency-correction -z 60s http://localhost:3000/function_zxy_query/18/235085/122323 | |
| oha --latency-correction -z 5s --no-tui http://localhost:3000/png/0/0/0 > /dev/null | |
| oha --latency-correction -z 60s http://localhost:3000/png/0/0/0 | |
| oha --latency-correction -z 5s --no-tui http://localhost:3000/stamen_toner__raster_CC-BY-ODbL_z3/0/0/0 > /dev/null | |
| oha --latency-correction -z 60s http://localhost:3000/stamen_toner__raster_CC-BY-ODbL_z3/0/0/0 | |
| # Start release-compiled Martin server and a test database | |
| bench-server: start | |
| cargo run --release -- tests/fixtures/mbtiles tests/fixtures/pmtiles |
I would like to get guidance on how to move forward with this PR.
Let me know what works and what does not.
There are three larger aspects:
Testing. We try to test what we can. This prevents unwanted surprises later on and makes working generally more pleasant. Lets
-
add integration tests in
test.sh- add a minimal GeoJSON fixture with a polygons, points, and lines (each with one over tile border, one in tile border)
- test if it does the splitting at tile borders works as expected
- if the options (see inline comment) are correctly passed.
-
add unit tests for that
file.geojsonCLI argument parsing works as expected- the config file is serialised as expected
- since there is not much "actual code" (= code which can have bugs without the dependency having a bug), I don't think we need much in terms of unit testing
Upstreaming the geozero-pub change necessary.
Vendoring (=forking) is a last resort, and we should not do this, unless as a last resort.
You can change where a dependency points to via git = "..", branch = "..".
Adjusting the existing documentation (README and /docs, for the individual source and the config file respectively)
=> we should tell people about the capability you are adding 😉
martin/src/geojson/mod.rs
Outdated
| .map_err(|e| FileError::InvalidFilePath(path.clone()))?; | ||
|
|
||
| // TODO: see if options default is goood enough | ||
| let inner = GeoJSONVT::from_geojson(&geojson, &Options::default()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a few options which might be nice to have not hard-coded => added to GeoJsonConfig and passed to GeoJsonSource::new.
We can just expose these options in the config file.
I am not sure if index_max_points works like our existing option, or what that index is.
Options {
max_zoom: 18, // max zoom to preserve detail on; can't be higher than 24
index_max_zoom: 5, // max zoom in the tile index
index_max_points: 100000, // max number of points per tile in the tile index
generate_id: false, // whether to generate feature ids, overriding existing ids
tile: TileOptions {
tolerance: 3., // simplification tolerance (higher means simpler)
extent: 4096, // tile extent
buffer: 64, // tile buffer on each side
line_metrics: false, // enable line metrics tracking for LineString/MultiLineString features
}
}More a personal interest:
I would be interested if this changes the performance of the code as the compiler now can no longer constant-fold things.
martin/src/geojson/mod.rs
Outdated
| let tilejson = tilejson! { | ||
| tiles: vec![], | ||
| minzoom: 0, | ||
| maxzoom: 18, | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a bit sparse. I am not sure if this tilejson works, as it does not specify what is contained features.. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at the cog module's one and took that as an example. That's just like this let tilejson = tilejson! { tiles: vec![], minzoom: min_zoom, maxzoom: max_zoom };
I'll look into this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the required vector_layers field as per https://github.com/mapbox/tilejson-spec/blob/master/3.0.0/README.md#332-fields. I viewed it in Maputnik editor and it seems to be working. We should probably add bbox etc. some time.
|
Thanks for the quick review. I've taken out |
|
@CommanderStorm I've replaced the GeoJSONVT struct with the function. geojson_to_tile reprojects the entire dataset on every call, which might be a significant overhead. Maybe we could do a PR to that crate so that we can project once and keep that as state in |
|
Yea, reprojecting on every tile would not be great for performance |
|
Current TODOs for this PR
|
I would prefer option 1 of using I would prefer I know that this is a big ask. |
I fully understand and agree with your point, though
I agree with you on the ecosystem advantages part. I've briefly looked over some
Thank you so much! I really appreciate the help. I’ll stay in touch as I put together a basic plan to move forward. |
|
Since writing docs is something that takes iterations, I thought you might appreciate me doing the legwork and writing up a first rough draft to iterate on later => c3b1728 |
|
I'm currently waiting on two PRs: geozero MVT feature-writing georust/geozero#264 and geojson-vt-rs preprocessed geojson maxammann/geojson-vt-rs#3. I will update this PR as those PRs move forward. |
…outputting layers (#264) - [x] I agree to follow the project's [code of conduct](https://github.com/georust/.github/blob/main/CODE_OF_CONDUCT.md). - [x] I added an entry to the project's change log file if knowledge of this change could be valuable to users. - Usually called `CHANGES.md` or `CHANGELOG.md` - Prefix changelog entries for breaking changes with "BREAKING: " --- This is an implementation of feature writing for MVTs, as discussed in #263. This PR builds upon @nyurik's previous WIP reimplementation #181. It passes all of the `mvt_writer` tests. I am not sure if I understood the API exactly correctly but this seems to be a pretty good starting point, as individual feature/geom can be converted to a MVT feature with the `ToMvt` trait as well as `MvtWriter` can process multiple feature and output them to a layer. [Here is an example](https://github.com/maplibre/martin/blob/20ff5e36cc89bb07aefaf39a6f513df6b65a38cc/martin/src/geojson/mod.rs#L124) of feature writing and layer output with MvtWriter (from GeoJSON to MVT tiles PR, maplibre/martin#2098) Let me know how we can move forward with this PR. --------- Co-authored-by: Yuri Astrakhan <[email protected]>
|
Both of those PRs got merged, so I'll try to continue work on this again. |
|
We have done a bit of light refactoring to support the v1 release via |
|
Thanks Frank. I just pushed a few (rough) commits to show how the code is with the new PRs. I still have to test, add fixtures, and improve error handling. The function naming is a bit rough too. Looking forward to what you think. |
|
I rebased it again as our changes (should now be mostly done) in main were kind of touching this code. I and @nyurik discussed this offline and came to the conclusion that
The current path that we all hoped/assumed we can get geozero to make a release via internal chanels is apparently more a longer term plan 😞 We can also rename the feature |
|
My academic term has finished, so I have more time to work on this PR. I merged the main branch and did some refactoring. Let me know how can I continue, or whether we should shelve the PR. |
This is a quickly hacked PR to implement MVT tile generation from GeoJSON files (#2054). I used geojson-vt-rs to slice GeoJSON into tiles and integrated the
mvtmodule from geozero for encoding those tiles in MVT format. I needed access to some of the internals fromgeozero'smvt, which were not public -- that's why I decided to vendor in the module independently.There are still rough edges and lots of TODOs left on this PR. In my initial testing, the tile endpoint was abnormally slow. I did not yet get around to why that is the case.
I also had to remove
#![forbid(unsafe_code)]from the library for an unsafe trait impl in themvtmodule. It might be a better idea to just break out that module into a seperate crate.I would like to get guidance on how to move forward with this PR. Let me know what works and what does not. Thank you for your time.