Mapbox GL JS Image Overlay Coordinates Precision Issue - mapbox

I'm facing a precision issue with Mapbox GL JS when placing an image overlay on the map with 4 corners coordinates, there is a shift from the expected position by 50-250 m. To reach this conclusion and find this bug, the projection of the image was compared to Leaflet and QGIS, both of them shows the same position of the image but Mapbox GL JS is showing a shift.
I think this may be a bug in the framework that needs to be fixed. I'm using React Mapbox GL JS and was able to recreate this issue using Mapbox GL JS library within a normal html file. So most probably it's not being caused by React.
To recreate the issue try to overlay an image on the map using Mapbox, Leaflet and QGIS and then compare the results.
mapbox-gl-js version: 1.4.0
browser: Google Chrome Version 79.0.3945.88 (Official Build) (64-bit)
Steps to Trigger Behavior
Add an image overlay to Mapbox GL JS using 4 coordinates
map.addSource("imageTest", {
"type": "image",
"url": "/DIR/TO/IMAGE",
"coordinates": [
[LON1,LAT1],
[LON2,LAT2],
[LON3,LAT3],
[LON4,LAT4]
]
})
map.addLayer({
"id": "overlay",
"source": "imageTest",
"type": "raster"
})
Geo reference the same image using GDAL Georeferencer on QGIS with the same coordinates and use QGIS to load the resulting GeoTIFF.
Overlay the image using Leaflet Distortable Image https://github.com/publiclab/Leaflet.DistortableImage
Compare the 3 projections, a shift shall be observed only with the Mapbox projection and on the y axis most probably.
Expected Behavior
All of these methods should yield the same results.
Actual Behavior
Mapbox is showing a major shift sometimes up to 250 meters for an image with a swath of 3 km.
Check this screenshot: (QGIS left, Mapbox center, Leaflet right)

The problem does have to do with projection. Images can be sliced and diced exactly by coordinates but they must match the projection of the map they are being overlaid on. In the case of Mapbox, it uses web mercator and images must be reprojected to EPSG:3857.
A utility to convert images (such as geoTIF) to this projection is GDAL (https://gdal.org/). A command using GDAL tools to convert an image would be something like :
gdalwarp -t_srs EPSG:3857 input.tif input-projected.tif
Hopefully this clears things up.

Related

Custom DEM for 3D Terrain in Mapbox GL JS V2

Is there a way to use a custom DEM for 3D viewing in the new mapbox release? I can use custom 2D rasters tiled using MapTiler, so I was wondering if the same option is available for "raster-dem" then setTerrain. The goal is to create something like this, but with my own elevation data:
https://docs.mapbox.com/mapbox-gl-js/example/add-terrain/
Thanks
Good question. In theory, you ought to be able to produce your own raster tileset following the same Terrain RGB format like this:
map.addSource('mapbox-dem', {
'type': 'raster-dem',
'url': 'mapbox://yourusername.yourtilesetid',
'tileSize': 512,
'maxzoom': 14
});
map.setTerrain({ 'source': 'mapbox-dem', 'exaggeration': 1.5 });
However, the documentation does say:
Only supports Mapbox Terrain RGB (mapbox://mapbox.terrain-rgb):
It's unclear if they mean it only supports that format (seems more likely), or is somehow hardcoded to only support data from that exact data source (which seems a very strange choice).
Based on my very basic testing, Mapbox GL JS does attempt to fetch tiles from whatever source you provide, and doesn't give any weird error messages, but I haven't gone as far as actually producing such a tileset.

GeoServer Vector Tiles show tile boundary issue in Mapbox GL JS

I use GeoServer to provide Vector Tiles (based on the GeoServer Vector Tile Extension) of my biking trails as .pbf.
The data are added as vector source and visualized using Mapbox GL JS.
Additionally, I use the GeoServer perpendicularOffset to offset the lines (as I always have two directions of the biking trail).
A problem occurs when visualizing the data within Mapbox. The lines are cut at the tile edges, although they are visualized correctly using the layer preview on GeoServer.
The further I zoom in the map, the less the clipping of the lines happens and at a very detailed zoom, the lines are drawn correctly.
I already tried to use a large enough buffer and modify the tile size, as these were suggestions when researching the problem. Unfortunately, these settings had no effect.
I have another vector source layer for the base map, there I have no problems.
It seems to me, that offsetting the lines might be a problem.
Any idea what I can try?
the tile size of Geoserver's tile grid is 256x256 , but mapbox need 512x512, add a custom tile grid, set the tile size to 512x512, generate your vector tile with the custom tile grid should be ok.

Mapbox geometries get degraded when exported to tilesets

I'm trying out Mapbox for the first time, and playing around with drawing some polygons in the dataset editor for export to a tileset. However, the polygons in the resulting tileset are not the same as what I create in the editor. The polygons are only very rough, simplified approximations of the originals.
In dataset editor:
In map layer as tileset export:
I understand that Mapbox does vector simplification at certain zoom levels, but these changes are not zoom-dependent. I zoom in all the way and the shapes are still like this.
Moreover, such extreme degredation of the geometries makes tilesets essentially useless for features that require any sort of accuracy, like property lot lines.
Am I missing something, or is this really the expected behavior? Is there really no way to get accurate geometries into a tileset?
UPDATE: It appears this is only happening with shapes I create by drawing in the Mapbox data editor. So far the geometries that I've uploaded as geojson files have gotten converted to tilesets accurately...
I suspect this is because the maxzoom is too low.
When you create a Mapbox Tileset, either by uploading GeoJSON directly as a new Tileset, or by exporting your your Dataset to a Tileset, Mapbox will try to guess an appropriate minzoom and maxzoom of the Tileset.
Sometimes the min/max zoom's used aren't suitable for the map you're trying to create. Since there is no way to specify a maxzoom in either of the two approaches the only alternative is to create your Tileset locally with https://github.com/mapbox/tippecanoe specifying an appropriate maxzoom for your data and then uploading the resulting .mbtiles as a Mapbox Tileset.

Mapbox vector tile MVT is missing data

I'm trying to make my own renderer for Mapbox MVT vector tiles, but I have hit the obstacle and couldn't find the answer. My problem is that MVT tile downloaded form Mapbox server contains all roads, but only a few bulding numbers (should be much more for given area) and no land types (grean area on map) and buildings.
Anyone had same problem or know the answer?
link I use to download tile is:
https://api.mapbox.com/v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v7/18/143415/87627.mvt?access_token={access_token}
Below raster tile for the same area:
The trick is in decoding MVT tiles (using mapbox-vector-tile-java), to parse it properly MvtReader.RING_CLASSIFIER_V1 needs to be used:
final JtsMvt result = MvtReader.loadMvt(f, new GeometryFactory(), new TagKeyValueMapConverter(), MvtReader.RING_CLASSIFIER_V1);
Resolved thanks to boldtrn commit on mapsforge/vtm

Converting GeoJSON to Vector Tiles on the fly w/ MapBox GL JS?

My map's source file is GeoJSON, but it is very large and very slow. Is there a way to convert this to vector tiles on the fly using MapBox GL JS? (Load the GeoJSON, pre-process the file into vector tiles, and show use the vector tiles as the base map.) It seems that vector tiles are much faster.
I've tried all the GeoJSON-VT tutorials and examples that I could, like the one on MapBox's site, but it just says that GeoJSON-VT works under the hood, so it isn't much help. The others mostly apply to Leaflet, not MapBox GL JS.
Meanwhile, every example I find that uses a large dataset always does so via vector tiles:
map.addSource('x', {
"type": "vector",
"url": "url"
});
For reference, I am loading my file using this method:
map.addSource('x', {
type: 'geojson',
data: 'file.geojson'
});
In case your GeoJSON file is static, you could use mapbox/tippecanoe to convert the GeoJSON to an .mbtiles file. You could then either upload the file to Mapbox as a tileset (about tilesets) or you could serve your own vector tile source from a web server using the .mbtiles file (reference implementation).
If your GeoJSON file is more dynamic, things get a little bit more complicated. I have never used it, but Mapbox Dataset API might be a good solution for that.
To the best of my knowledge, Mapbox-GL-JS uses GeoJSON-VT to automatically convert client-side-loaded GeoJSON files into vector tiles within the browser - so it's already doing what you're asking for.
If this is still "slow", probably the problem is the actual loading and processing - so pre-generating and serving vector tiles is the right answer.