1

I am using the following map for India (https://data.maptiler.com/downloads/tileset/osm/asia/india/) and serving it via a server to send pbf files. The map shape is rendering correctly, and I want to display the names received in the places layer. However, the x, y values I receive are very weird and none of the functions suggested online (map.unproject, map.LayertoLatLng etc.) seem to work. What should I do?

const MapComponent = () => {
    const map = useMap();

    const countriesWithMarkers = new Set();

    const vectorTileOptions = {
        rendererFactory: L.canvas.tile,
        interactive: false, // Whether the vector tiles are interactive
        getFeatureId: function (e:any) {
            const originPixel = map.getPixelOrigin();
            const stationName = e.properties.name;
            //console.log(map.getZoom());
            if(e.properties.class === 'state' && map.getZoom() == 6 ) {
                if (!countriesWithMarkers.has(stationName)) 
                    const latlng = map.layerPointToLatLng([e.geometry[0][0].x, e.geometry[0][0].y]);
                    
                    // const marker = L.marker(latlng, {
                    //     icon: L.divIcon({ className: 'text-label', html: stationName }),
                    // });
                    // marker.addTo(map);
                    countriesWithMarkers.add(stationName);
                }
            }
            return '0';
        },
        vectorTileLayerStyles: {
            water: {
                fill: true,
                fillColor: '#a6cbe1', // Light blue
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              waterway: {
                stroke: true,
                color: '#6699cc', // Blue
                weight: 1
              },
              landcover: {
                fill: true,
                fillColor: '#b5e3a6', // Light green
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              landuse: {
                fill: true,
                fillColor: '#e8dab2', // Beige
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              mountain_peak: {
                radius: 5,
                fillColor: '#ffffff', // White
                color: '#000000', // Black
                weight: 1,
                opacity: 1,
                fillOpacity: 0.8
              },
              park: {
                fill: true,
                fillColor: '#c2e0b3', // Light green
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              boundary: {
                stroke: true,
                color: '#ff0000', // Red
                weight: 1
              },
              aeroway: {
                stroke: true,
                color: '#999999', // Grey
                weight: 1
              },
              transportation: {
                stroke: true,
                color: '#999999', // Grey
                weight: 1
              },
              building: {
                fill: true,
                fillColor: '#cccccc', // Grey
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              water_name: {
                fill: true,
                fillColor: '#6699cc', // Blue
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              transportation_name: {
                fill: true,
                fillColor: '#999999', // Grey
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              place: { // Customize the rendering for the 'place' layer
                fill: false,
                stroke: false,
            },
              housenumber: {
                fill: true,
                fillColor: '#ffffff', // White
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              poi: {
                fill: true,
                fillColor: '#ff0000', // Red
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
              aerodrome_label: {
                fill: true,
                fillColor: '#999999', // Grey
                fillOpacity: 0.7,
                weight: 0 // No outline
              },
        },
    };

    useEffect(() => {
        const ok = L.vectorGrid.protobuf('http://localhost:3650/api/tiles/osm-2020-02-10-v3.11_asia_india/{z}/{x}/{y}', vectorTileOptions);
        console.log(ok);
        ok.addTo(map);
    }, [map]);

    return null;
};
6
  • Read github.com/mapbox/vector-tile-spec/tree/master/2.1 , section 3 and the last two paragraphs of section 4.1. Commented Apr 12 at 8:42
  • Even if you happen do decipher meaning of x,y values, it won't help you much, since you don't have access to tile coordinates within getFeatureId function (at least to my knowledge). Simple edit of one line in vector tile plugin can give you access to tile coordinates within that function.
    – TomazicM
    Commented Apr 12 at 9:18
  • Thanks @IvanSanchez is there any way to get latlng coordinate of a vector tile? The extent of my tiles are 4096 so I think I can decode the place coordinates from that Commented Apr 13 at 11:10
  • Thanks @TomazicM ! The extent of all my tiles are 4096. How can I get coordinates for a tile though? Its not present anywhere in the pbf I receive. Commented Apr 13 at 11:10
  • If you can live with modifying Leaflet vector tile plugin, I can post a solution.
    – TomazicM
    Commented Apr 13 at 12:35

1 Answer 1

0

On possible solution requires a slight, one line modification of Leaflet.VectorGrid plugin. If you take code from https://unpkg.com/[email protected]/dist/Leaflet.VectorGrid.bundled.js, then line 1295:

id = this.options.getFeatureId(feat);

has to be changed to:

id = this.options.getFeatureId(feat, coords);

This allows access to tile number [x, y, z] in option getFeatureId through second parameter. First parameter has handy method .toGeoJSON which returns GeoJSON representation of features in the tile for given [x, y, z] tile.

Code to retrieve GeoJSON for a tile could then look something like:

getFeatureId: function(f, coords) {
  var geoJSON = f.toGeoJSON(coords.x, coords.y, coords.z);
  console.log(geoJSON);
  return(f.properties.id);
}
1
  • Thanks a lot!!! Its really slow but serves my purpose Commented Apr 14 at 9:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.