1

I have a leaflet map that loads a vector tile set from Maptiler. I would like the map to fit the bounds of the tile set's content when the user selects the overlay check box to display this tile set. For example, I'm working with the zip codes in Illinois. Each zip code is a polygon.

How can I get the minimum and maximum latitude and longitude of this tile set? The tiles are saved in a protobuf (protocol buffer). If this is impossible, is it at least possible to get the x and y coordinates of the centroid of a single tile? Or at least the tile's z, x and y indices? Then I can use those values to calculate latitude and longitude.

I am using the leaflet.vectorGrid library.

  var ILZipTileOptions = {
    interactive: true,
    vectorTileLayerStyles: {
      ILZipCodes: properties => {
        //maybe I can add a line here that gets the coordinates?
        return getColor(
          [properties.ZCTA5CE10]
        );
      }
    }
  };

  var ILZips = L.vectorGrid
    .protobuf(IL_ZIP_CODES_PBF, ILZipTileOptions)
    .on("click", function(e) {
      L.popup()
        .setContent(
          "Zip Code: " +
            e.layer.properties.<zip code variable>
        )
        .setLatLng(e.latlng)
        .openOn(myMap);
    });

After poking around some more, I see it is possible to get the x, y and z indices of the tiles as they load.

  var ILZips = L.vectorGrid
    .protobuf(IL_ZIP_CODES_PBF, ILZipTileOptions)
    .on("load", function(e) {
      console.log("e.target._tiles: " + JSON.stringify(e.target._tiles));
    });

Here is an example printed out in the console...

e.target._tiles: {"3:6:4":{"el":{"_leaflet_pos":{"x":153,"y":200}},"coords":{"x":3,"y":6,"z":4},"current":true,"retain":true,"loaded":1579817242542,"active":true},"4:6:4":..... 

But I cannot yet figure out how to programatically grab the x and y values from this object.

Update: I figured out how to programatically grab the x and y values. The way I'm accessing the variable that has colons in the variable name is ugly. Maybe there is a better way.

  var ILZips = L.vectorGrid
    .protobuf(IL_ZIP_CODES_PBF, ILZipTileOptions)
    .on("load", function(e) {
      console.log(
        "tile_x_coordinate: " +
          e.target._tiles[Object.keys(e.target._tiles)[0]].coords.x
      );
      console.log(
        "tile_y_coordinate: " +
          e.target._tiles[Object.keys(e.target._tiles)[0]].coords.y
      );
      console.log(
        "tile_z_coordinate: " +
          e.target._tiles[Object.keys(e.target._tiles)[0]].coords.z
      );
      console.log("e.target._tileZoom: " + e.target._tileZoom);
    });

The next step I took was to convert these tile indices to latitude and longitude degrees like this...

  function tileIndicesToDegrees(tile_x, tile_y, zoomLevel) {
    var n = Math.pow(2, zoomLevel);
    var lon_deg = (tile_x / n) * 360.0 - 180.0;
    var lat_rad = Math.atan(Math.sinh(Math.PI * (1 - (2 * tile_y) / n)));
    var lat_deg = (lat_rad * 180.0) / Math.PI;
    return [lon_deg, lat_deg];
  }

At the end of all this work I realized that the MapTiler tile set covers the entire world and not strictly the area of interest (i.e. the area covered by the geojson I uploaded to MapTiler). Therefore, this task of using the tile set indices to find the boundaries of the original geojson features is pointless.

How can I get the boundaries of the geojson features I used to create this tile set? Or is this impossible?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.