t-rex icon indicating copy to clipboard operation
t-rex copied to clipboard

Question about tile-grid

Open maxammann opened this issue 3 years ago • 8 comments

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 avatar Nov 30 '21 19:11 maxammann

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 avatar Dec 01 '21 09:12 maxammann

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 avatar Dec 01 '21 16:12 maxammann

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

maxammann avatar Dec 01 '21 18:12 maxammann

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 avatar Dec 02 '21 07:12 pka

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

pka avatar Dec 02 '21 07:12 pka

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.

maxammann avatar Dec 02 '21 10:12 maxammann

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...

pka avatar Dec 02 '21 13:12 pka

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()
}

maxammann avatar Dec 11 '21 10:12 maxammann