t-rex-tileserver / t-rex

t-rex is a vector tile server specialized on publishing MVT tiles from your own data
https://t-rex.tileserver.ch/
MIT License
556 stars 69 forks source link

Question about tile-grid #275

Open maxammann opened 2 years ago

maxammann commented 2 years ago

Hello, I'm using the tile-grid library outside of t-rex for determining Slippy map tilenames.

I'm a bit confused about the values which are returned by the library. For example:

  1. On zoom level 0, there is only a single tile, which covers the whole world. This means that the extend in WSG84 of the tile z=0,x=0,y=0 should be:
    Extent { minx: -180.0, miny: -90.0, maxx: 180, maxy: 90.0 }

But Grid::wgs84().tile_extent_xyz(0, 0, 0) returns Extent { minx: -180.0, miny: -90.0, maxx: 0.0, maxy: 90.0 }. I belive this is not correct or at least I do not understand the result. The implementation in mapcache is equal: https://github.com/mapserver/mapcache/blob/main/lib/grid.c#L51

  1. I want to iterate over a few map tiles in Germany. Therefore, I'm doing:
    let grid = Grid::web_mercator();
    let tile_limits = grid.tile_limits(
        extent_wgs84_to_merc(&Extent {
            minx: 10.0,
            miny: 48.0,
            maxx: 12.0,
            maxy: 50.0,
        }),
        0,
    );
    let griditer = GridIterator::new(6, 6, tile_limits);
    griditer.collect()

If I fetch the tiles which have been collected, then I'm not able to fetch them from my hosted tile server (nginx with pbf files): https://maps.tuerantuer.org/europe_germany/tiles.json

maxammann commented 2 years ago

My goal is to actually render vector tiles. For that I want to get a list of xyz coordinates which need to be fetched in order to render an arbitrary bounding box defined in geographic coordinates. I think that the GridIterator is actually the perfect fit here.

maxammann commented 2 years ago

I found a cool tool which describes what the correct values are which I'm looking for: https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection/#6/11.17/49.81

So it actually seems like GridIterator returns tiles coordinates in TMS format.

maxammann commented 2 years ago

I think I found the solution: The "Google" grid starts from the TopLeft instead of BottomLeft.

pka commented 2 years ago

Hallo Max, Seems the same issue as #55 Not sure, how to improve on that. The Iterator API could be nicer, too. Input welcome!

pka commented 2 years ago

I think, we should follow the OGC Two Dimensional Tile Matrix Set specification http://docs.opengeospatial.org/is/17-083r2/17-083r2.html

maxammann commented 2 years ago

Not sure, how to improve on that. The Iterator API could be nicer, too. Input welcome!

I'm not absolutely sure what you mean, but probably it would be "cleaner" to just iterate over the grid struct :) Yes, maybe I could refactor this!

Seems the same issue as #55 Not sure, how to improve on that.

yes, in fact I was able to modify the Grid definition and it is working now :) I think the crate should contain a google projection additionalyl to web_mercator

I think, we should follow the OGC Two Dimensional Tile Matrix Set specification http://docs.opengeospatial.org/is/17-083r2/17-083r2.html

Maybe in a few months I can understand such a document :D Just starting to write a graphical tile rendering and starting to grasp the complexity of GIS.

pka commented 2 years ago

Not sure, how to improve on that. The Iterator API could be nicer, too. Input welcome!

I'm not absolutely sure what you mean, but probably it would be "cleaner" to just iterate over the grid struct :) Yes, maybe I could refactor this!

I mean something like:

let grid = Grid::web_mercator();
let iter = grid.iterator(0, 10, &grid.extent);

Seems the same issue as #55 Not sure, how to improve on that.

yes, in fact I was able to modify the Grid definition and it is working now :) I think the crate should contain a google projection additionalyl to web_mercator

So you did change origin to Origin::TopLeft and then grid.tile_extent_xyz(0, 0, 0) did return what you're expecting?

I think, we should follow the OGC Two Dimensional Tile Matrix Set specification http://docs.opengeospatial.org/is/17-083r2/17-083r2.html

Maybe in a few months I can understand such a document :D Just starting to write a graphical tile rendering and starting to grasp the complexity of GIS.

Yes, it's a pity that OGC specs are so complicated...

maxammann commented 2 years ago

So you did change origin to Origin::TopLeft and then grid.tile_extent_xyz(0, 0, 0) did return what you're expecting?

Here is an example:

use tile_grid::{extent_wgs84_to_merc, Extent, Grid, GridIterator, Origin, Unit};

pub fn google_mercator() -> Grid {
    Grid::new(
        256,
        256,
        Extent {
            minx: -20037508.3427892480,
            miny: -20037508.3427892480,
            maxx: 20037508.3427892480,
            maxy: 20037508.3427892480,
        },
        3857,
        Unit::Meters,
        vec![
            156543.0339280410,
            78271.5169640205,
            39135.75848201025,
            19567.879241005125,
            9783.939620502562,
            4891.969810251281,
            2445.9849051256406,
            1222.9924525628203,
            611.4962262814101,
            305.7481131407051,
            152.87405657035254,
            76.43702828517627,
            38.218514142588134,
            19.109257071294067,
            9.554628535647034,
            4.777314267823517,
            2.3886571339117584,
            1.1943285669558792,
            0.5971642834779396,
            0.2985821417389698,
            0.1492910708694849,
            0.07464553543474245,
            0.037322767717371225,
        ],
        Origin::TopLeft,
    )
}

///
/// Returns coordinates for tiles within bavaria according to the specified grid.
/// The grid is responsible for defining the coordinate system. For example whether
/// [Slippy map tilenames](https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames) (also known as
/// XYZ) or [TMS](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#TileMap_Diagram) is
/// used.
///
/// ## Additional Resources:
///
/// * https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection
/// * https://gist.github.com/maptiler/fddb5ce33ba995d5523de9afdf8ef118
pub fn tile_coordinates_bavaria(grid: &Grid, zoom: u8) -> Vec<(u8, u32, u32)> {
    let tile_limits = grid.tile_limits(
        extent_wgs84_to_merc(&Extent {
            minx: 8.9771580802,
            miny: 47.2703623267,
            maxx: 13.8350427083,
            maxy: 50.5644529365,
        }),
        0,
    );

    GridIterator::new(zoom, zoom, tile_limits).collect()
}