maplibre reduce xyz vector tile requests - mapbox-gl-js

I'm fairly new to maplibre/mapbox. I've about 40,000 polygons in my PostGIS database. That's just too much data to load it all at once into the maplibre map as a geojson source when the webapp starts. Thus I implemented a simple rest server which returns the polygons compiled into X/Y/Z MVT Vector tiles, so I can use it as a "vector" source in my maplibre style file. This works fine, polygons start showing up at zoom-level 10.
The question is... for the sake of performance and server load I would like to reduce the amount of tile requests.
At the moment when I change the zoom level from 10 to 11, maplibre requests new tiles, which actually isn't necessary, as all needed data already was included in the tile it got for zoom-level 10. Is there a way to tell maplibre to request tiles not for the current zoom-level, but for the higher zoom level instead? e.g. instead of requesting 1/1/12, request 1/1/10.
In other words, I would like to tell maplibre to always use the data from the z10 tile, even for greater zoom levels. And to load the z10 tile if it hasn't been loaded yet.
Thanks

I may be misinterpreting your question, but yes, you can tell the client library to never request tiles above zoom 10, and always to overzoom them, by setting maxzoom on your source:
map.addSource('polys', { type: 'vector', /*...*/, maxzoom: 10 });

Related

How can I generate mbtiles with a smaller extent with openmaptiles?

I'm using OpenMapTiles to download OSM data and create a mbtiles with mapbox vector tiles. This all works great, except I'm targeting an embedded platform.
At zoom level 14 with the default extent of 4096, a single tile can be over 1MB and cover an entire city. Not only is that a huge file to process for an embedded platform, it also means you're potentially sifting through every house in an entire city. I went as far as writing a streaming protobuf parser, but it takes 10 minutes to just parse such a file.
How can I generate mapbox vector tiles with a smaller extent?
I found there appears to be a parameter for it, but can't figure out where it actually gets used to generate tiles and how to modify it: https://github.com/openmaptiles/openmaptiles-tools/blob/4cc6e88dfdef83de69bd49845e0f23908d9edecc/openmaptiles/sqltomvt.py#L25
I'm not married to openmaptiles, but it's what I'm currently using to download and process openstreetmap data.
in case others need it, use https://github.com/mapbox/tilelive and specify maxzoom you want
bin/tilelive-copy --minzoom=0 --maxzoom=10 ~/Apps/tileserver/tiles/osm-2017-07-03-v3.6.1-planet.mbtiles ~/Apps/tileserver/tiles/small-osm-2017-07-03-v3.6.1-planet.mbtiles

Optimizing and tracking Mapbox mapviews

I have a Mapbox mapping application that gets a LOT of map views per user — on the order of 30 per hit. Which seems kind of high! (And expensive!)
(The application tries to use MapboxGL by default and falls back to Mapbox.js if it can't. All versions also use Leaflet for whatever that is worth.)
I've been trying to debug this, but it's been hard for me to measure how different changes affect the overall number of map views.
Is there any way one can imagine that will allow me to get a realtime count of how many map views my application is generating? I am reasonably sure there isn't some kind of simple variable to query (that I have found), but maybe there is some way to count/keep track either in JS or the developer console? Any thoughts would be appreciated.
Are you using a Mapbox Studio style or your own tiles? In both cases you can count the tiles being requested by your app using the data event:
map.on('data', event => {
if (event.tile) tileCount++;
});
That's a very simple example. AFAIK one map view is consists of four tile requests.
If you got a lot different tile sources loading in parallel you end up with a lot of requests hence map views. If possible you could merge multiple sources into a single tile set (if you are using vector tiles).
If you use your own tiles, e.g. raster tiles, you can increase your tile size from 256px to 512px, which should result in less requests. For vector tiles the size is fixed to 256.

Mapbox not able to change the style of vector tiles at run time

I am using tippecanoe command line utility to create my application vector tileset. This is creating a directory structure as per the z/x/y coordinates which is perfectly fine. I have a certain group of features(allocated with a layer) which do not need z to be up to 21 zoom level so it's creating the tiles up to zoom-level 14. It is critical in my case to not to waste the memory space by increasing the max-zoom to 21 for certain layer of features.
As per my understanding, mapbox gl-js queries for the vector tiles as per its coordinate space.
So during my zoom-in from 6 to 21, although zoom-level > 14 tile queries are responding with 404, gl-js is adopting the same tile which is available at 14.
The problem is,
For example, If I click on any feature, I need that feature to be highlighted. I am doing it by filtering out the layers as :
//hiding the current layer
mapBox.setFilter(currentLayer, ["==",'gid', "_none_"]);
//showing only the clicked feature by filtering it out with a unique id it has
mapBox.setFilter(highlightedLayer, ["==",'gid', feature_gid]);
This works as expected for zoom-level < 14 but if zoom-level exceeds 14 (the max-zoom while tile creation) then it is not able to render the tile with applied layer style as it tries to fetch a tile which is not there on my server. So my question is if a source tile at particular zoom level is giving 404 then why not apply the layer style to whichever tile is available at zoom level 14 ?
Any help to solve this problem?
This functionality is not supported by mapbox-gl. You need to go back to Tippecanoe and generate the tiles for this zoom level.
Note that you those new tiles can be similar in terms of data as the other zoom levels.
Remember that tiles are like images generated at a precise zoom level. If you zoom in, one tile will be divided in many tiles.

Leaflet + geojson datas

I'm working on a project using Leaflet. For this project I've created an interface to draw all the roofs of a large city as polygons. A lot of scripts calculate the surfaces, the addresses, the orientation and so on... I'll store each roof's datas in a geojson file (or files). We expect to get about 10 000 roofs or more. I don't know if Leaflet displays only visibles polygons depending window's boundaries or if all the polygons are drawn, and my problem is to find the better way to do this storage.
In one geojson file. It may be a problem because the 10 000 roofs are computed in the same time and waiting for polygons loading may be very boring for users.
In separated geojson files: for each roof I can approximatively calculate the coordinates of its center and put this roof in the right geojson file depending the lat/lng. By this way I can create (say 20 or 50) differents geojson files and call the right one depending boundaries. Then the question is: to create all the polygons, is it better to call the 6 (or 8 or 10) geojson usefull files for the area on screen, or is it better to create a new dynamic geojson file?
All the roof's datas are stored in a database or in a XML file and I have to detect boundaries and automatically create a dynamic geojson file. But each time user scroll or darg or zoom the map I'm supposed to recreate this unique geojson file...
Do you ever have a similar problem to solve and how do you solve it ? Thx.
I think the second scenario is the most robust, you need tiled GeoJSON tiles. Have a look at Leaflet Plugins. There is one called TileLayer.GeoJSON. Some links on how to create these tiles are on OpenStreetMap wiki.

Mapbox.js - Fallback tile image from lower zoom level, when missing in requested zoom level

I serve map png files from disk and I have tile pngs for whole city in zoom level 15. I have also tiles in zoom levels 16-18 but only for certain areas.
I would like to set up the tile Layer, so that when the user is in zoom level 18 the map will display scaled tiles from level 15 as a fallback.
I tried setting option maxNativeZoom, but didn't work for me.
Here is my code:
offlineLayer = L.mapbox.tileLayer(tileJSON, {
minZoom: 8,
maxZoom: 18,
maxNativeZoom: 15
});
map.addLayer(offlineLayer, 'Offline', 1);
Can I make it work, that way using some options or do I need to hack it some way? Or is there some example code for that?
Just to let people know that I wrote Leaflet.TileLayer.Fallback plugin some time ago to address this exact use case:
Replaces missing Tiles (404 error) by scaled lower zoom Tiles.
Demo page
In OP's situation, you would just specify the maxZoom Tile Layer option as usual, and whenever a tile is found missing at the current zoom level, the plugin will try to replace it by the "parent" tile at the previous zoom level (scaled and clipped appropriately so that it fits the missing tile), and so on until a tile is found or minZoom is reached.
L.tileLayer.fallback(urlTemplate, {
minZoom: 8,
maxZoom: 18
});
Disclaimer: I am the author of that plugin.
When you say that it didn't work for you, I'm guessing that what you're seeing with the code above is level 15 tiles for everywhere even when at zoom levels 16-18 in the areas where you have tiles at those levels? That's the expected behavior of maxNativeZoom. TileLayer creates all of the tiles for a given zoom level and map bounds and sets the "src" to a URL containing the current zoom level. If the current zoom level is greater than "maxNativeZoom" then the zoom level in the URL is set to "maxNativeZoom". For example, src="http://a.tile.openstreetmap.org/15/16368/10896.png" would be used for zoom levels 16-18 if "maxNativeZoom" is set to 15.
There is no logic in the code that checks to see if an image actually exists for that tile at that zoom level.
If your tiles are in a single data set then you could modify the code in TileLayer to check for a HTTP 404 return code for the generated URL and if one is received then create a new URL using "maxNativeZoom". If your tiles are in multiple data sets (i.e. one for zoom level 15 and less, and another for zoom levels 16-18) then I think you'd have to write a TileLayer that supports multiple data sets.