maplibre / maplibre-gl-js

MapLibre GL JS - Interactive vector tile maps in the browser
https://maplibre.org/maplibre-gl-js/docs/
Other
6.41k stars 689 forks source link

404 error for tiles in one particular arcgis mapserver #3653

Open CalebPourchot opened 8 months ago

CalebPourchot commented 8 months ago

latest maplibre-gl version

latest chrome version

Steps to Trigger Behavior

  1. Setup simple raster source and layer for this arcgis service: https://geodata.md.gov/imap/rest/services/PlanningCadastre/MD_ParcelBoundaries/MapServer
  2. Open browser dev console and pan the map around. All tile requests get a 404 not found response.

Link to Demonstration

https://codepen.io/calebpourchot/pen/JjzvKgb

Expected Behavior

This same service works fine in other contexts. Esri Leaflet in leaflet: https://codepen.io/calebpourchot/pen/poYVENo (make sure you zoom or pan around)

ArcGIS web viewer https://www.arcgis.com/home/webmap/viewer.html?url=https%3A%2F%2Fgeodata.md.gov%2Fimap%2Frest%2Fservices%2FPlanningCadastre%2FMD_ParcelBoundaries%2FMapServer&source=sd

Actual Behavior

404s on all tile requests - as if the tile ids are not correct for the current viewport or something.

Other MapServer services seem to work fine that appear to have the same parameters (spatial reference, tile size, etc.). Here's an example: https://codepen.io/calebpourchot/pen/oNVdzBG

HarelM commented 8 months ago

I'm not sure I understand the expectations here, 404 means you are requesting tiles from the wrong place, but you knew that already....

CalebPourchot commented 8 months ago

The tile ids that maplibre-gl passes into the url for the raster source are not under my control. My expectation is that it would pass valid tile ids to the service when I pan around the area where I know the data is. Using that very same url in a different map viewer works fine (see links above to other codepens). Somehow they are able to request valid tile ids and yet maplibre-gl doesn't seem to.

I know it is odd (that's why after days i've finally posted here). Other similar services (also linked above) seem to work just fine. I can't figure out why it is requesting tile ids that don't exist. I don't know what other information I can provide. I feel like the linked examples are demonstration enough.

CalebPourchot commented 8 months ago

And just to make it even more obvious - i updated the demo codepen to add an additional mapserver resource that shows imagery but uses the same exact url format. It loads fine but in the same location where the Maryland parcels tiles should be loading - they fail with 404.

HarelM commented 8 months ago

I see 404s also in the leaflet example. I'm not sure I fully understand the problem. Can you please create a minimal reproduction? Also note that maplibre zoom level is not equivalent to leaflet - there's a +1 in general.

In the following example I see a map: https://codepen.io/calebpourchot/pen/oNVdzBG image

I don't know what is the expected vs. actual...

neodescis commented 8 months ago

First off, your demo link has the style set up incorrectly. You have a single raster source that is combining the URLs from satellite imagery and your parcels imagery. Those need to be separate sources, with separate layers pointing to them.

However, even when I separate them, I'm still seeing mostly 404s from the parcels imagery source. In the leaflet example, it appears to be requesting very different zoom levels than what the MapLibre example is requesting. I do not know enough about leaflet to know why that is, but this seems to be a problem with the tile imagery more than anything else.

acalcutt commented 8 months ago

I tried to get your source at https://geodata.md.gov/imap/rest/services/PlanningCadastre/MD_ParcelBoundaries/MapServer to work for a bit, but to me it seems like there is something wrong with it.

In the WMTS file they have it seems like they have two different layers, one 'default028mm' and one 'GoogleMapsCompatible'

I tried to load the wmts in arcgis online and select the 'GoogleMapsCompatible' layer. It loaded but I can see it is still requesting layers from the 'default028mm', which seem to be at different zoom levels to the other tiles it is loading image for example, in this image it is loading 'https://geodata.md.gov/imap/rest/services/PlanningCadastre/MD_ParcelBoundaries/MapServer/WMTS/tile/1.0.0/PlanningCadastre_MD_ParcelBoundaries/default/default028mm/1/48/35' , but on the other layers it is loading an entirely different zoom level pbf 'https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tile/7/48/35.pbf'. I would expect if it was a 'GoogleMapsCompatible' layer the zoom levels would match, but that doesnt seem to be what it is loading

Then I tried to load that same WMTS layerer into QGIS, In qgis again I can see the 'default028mm' layer works, image image

but when I try use the 'GoogleMapsCompatible' layer it is just blank and revieves errors

image image image

I would think to you would want to use the 'GoogleMapsCompatible' url with maplibre for the right zoom levels, tiles: ['https://geodata.md.gov/imap/rest/services/PlanningCadastre/MD_ParcelBoundaries/MapServer/WMTS/tile/1.0.0/PlanningCadastre_MD_ParcelBoundaries/default/GoogleMapsCompatible/{z}/{x}/{y}'], but after my testing I'm not sure the 'GoogleMapsCompatible' url actually works

CalebPourchot commented 8 months ago

@acalcutt Thanks for looking at this, but i'm not trying to use the WMTS server, so i'm not sure if that is relevant.

There may very well be an issue with the maryland parcels service. However, the point i'm trying to make is that from the maplibre point of view - it is just a url replacement with tile ids that maplibre generates, right? It doesn't know anything about the service details. The tile ids are generated based on the current zoom and viewport, right?

So, why is it that 2 different service urls using the same backend technology behave differently? It looks to me like maplibre is passing the same tile ids to both services.

The updated example below splits the two raster sources out (as pointed out above). As you can see, only the imagery source is displayed even though the maryland parcels service is in the same geographic location. All the calls to the mdparcels service result in 404s. The tile ids passed to each service appear to be identical. https://codepen.io/calebpourchot/pen/JjzvKgb

Does maplibre require some special knowledge about the service to adjust the tile ids it sends? Is that why it works in the esri leaflet and arcgis map viewer examples?

At this point i'm not trying to fix it, I just would like to understand it.

neodescis commented 8 months ago

It is expected behavior for MapLibre to send the same z/x/y parameters for each layer of tiles it is requesting. As I noted above, I'm not sure why leaflet is issuing requests for entirely different zoom levels for the two different layers... that seems strange to me.

acalcutt commented 8 months ago

I think the tiles maplibre requests are based on TileSize and https://github.com/mapbox/sphericalmercator . There is a 1 zoom level difference between 512px tiles and 256px tiles.

My testing was somewhat based on recently adding 512px tile support to tileserver GL. When I first implemented them I had just upsized the 256px tiles we had, and that seemed like it worked fine with leaflet. However when I tried to use those new 512px tiles in maplibre, they were a zoom level off and maplibre was requesting tiles that didn't exist. I had the same issue with wmts in arcgis, and all the zoom levels were off by one.

In reading I had found that in leaflet, mapbox 512px tiles are usually set with a zoomOffset -1, which makes leaflet request a zoom level lower. Because I had set up the server so that zoomOffset wasn't needed, my tiles were a zoom level off in maplibre. Once I fixed this 1 zoom level difference my tiles worked in maplire, and with leaflet if I used zoomOffset of -1

In tileserver-gl wmts, the GoogleComplatible endpoint is is the same as the xyz url maplibre expects, which is why I tried to use it as an alternative.

In this sources case it doesn't seem like the tiles they are listing match what maplibre would request based on https://github.com/mapbox/sphericalmercator . the zoom levels seem more than the typical 1 zoom level off. They say it is web mercator but i wonder if the default is something else, like that default028mm mentioned in wmts

acalcutt commented 8 months ago

For example, one thing that seems off about the source, is there should only be one tile at zoom level 0 https://wiki.openstreetmap.org/wiki/Zoom_levels . something like 0/0/0 that covers the full planet https://tiles.wifidb.net/data/gebco_color_releif_pmtiles/0/0/0.png

but in your source their zoom 0 starts at 0/24/17 , which usually wouldn't be a zoom 0 tile. https://geodata.md.gov/imap/rest/services/PlanningCadastre/MD_ParcelBoundaries/MapServer/tile/0/24/17

farney9 commented 6 months ago

Hi people. I'm playing with maplibre-gl in angular 17 App. I get these errors when I fly on markers locations.

image

image

image