Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicate points rendered after zooming with vector tiles containing point features #4691

Closed
niklasvincent opened this issue May 9, 2017 · 4 comments

Comments

@niklasvincent
Copy link

niklasvincent commented May 9, 2017

mapbox-gl-js version: 0.37.0 (from https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js)

Steps to Trigger Behavior

  1. Visit this JSFiddle
  2. Zoom in near Oxford, towards the red dot

Expected Behavior

The red dot should get rendered in a single place for each zoom level.

Actual Behavior

The red dot gets rendered in multiple locations as the zoom level changes.

mapbox-bug
Chrome 58.0.3029.96 (64-bit)
(also reproducible in Safari Version 10.1 (11603.1.30.0.34) and Firefox 53.0.2 (64-bit))

Background

The vector tiles are rendered using ElectronicChartCentre/java-vector-tile, which uses the following Protobuf schema that seems to be identical to the latest published one at mapbox/vector-tile-spec.

Using the Python library tilezen/mapbox-vector-tile to decode the same tiles, omitting ones without any data/features, I can confirm that there is only one tile containing a point per zoom level and for each such tile there is only one point feature.

7/63/42.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [146, 148]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

8/127/84.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [35, 41]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

9/254/169.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [70, 82]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

10/508/339.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [141, 164]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

11/1017/678.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [26, 71]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

12/2034/1357.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [51, 143]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

13/4068/2714.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [102, 29]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

14/8136/5429.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [205, 58]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

15/16273/10859.mvt :
 {'points': {'extent': 256, 'version': 2, 'features': [{'geometry': {'type': 'Point', 'coordinates': [154, 116]}, 'properties': {'latitude': 51.757327, 'name': 'Headington Shark', 'longitude': -1.212892}, 'id': 0, 'type': 1}]}}

Full list of tiles used:

10/507/338.mvt 0 bytes
10/507/339.mvt 0 bytes
10/507/340.mvt 0 bytes
10/508/338.mvt 0 bytes
10/508/339.mvt 103 bytes
10/508/340.mvt 0 bytes
10/509/338.mvt 0 bytes
10/509/339.mvt 0 bytes
10/509/340.mvt 0 bytes
11/1016/678.mvt 0 bytes
11/1016/679.mvt 0 bytes
11/1017/678.mvt 102 bytes
11/1017/679.mvt 0 bytes
11/1018/678.mvt 0 bytes
11/1018/679.mvt 0 bytes
12/2033/1356.mvt 0 bytes
12/2033/1357.mvt 0 bytes
12/2033/1358.mvt 0 bytes
12/2034/1356.mvt 0 bytes
12/2034/1357.mvt 102 bytes
12/2034/1358.mvt 0 bytes
12/2035/1356.mvt 0 bytes
12/2035/1357.mvt 0 bytes
12/2035/1358.mvt 0 bytes
13/4067/2714.mvt 0 bytes
13/4067/2715.mvt 0 bytes
13/4068/2714.mvt 103 bytes
13/4068/2715.mvt 0 bytes
13/4069/2714.mvt 0 bytes
13/4069/2715.mvt 0 bytes
14/8135/5429.mvt 0 bytes
14/8135/5430.mvt 0 bytes
14/8136/5429.mvt 103 bytes
14/8136/5430.mvt 0 bytes
14/8137/5429.mvt 0 bytes
14/8137/5430.mvt 0 bytes
15/16272/10859.mvt 0 bytes
15/16272/10860.mvt 0 bytes
15/16273/10859.mvt 103 bytes
15/16273/10860.mvt 0 bytes
15/16274/10859.mvt 0 bytes
15/16274/10860.mvt 0 bytes
7/62/41.mvt 0 bytes
7/62/42.mvt 0 bytes
7/62/43.mvt 0 bytes
7/63/41.mvt 0 bytes
7/63/42.mvt 103 bytes
7/63/43.mvt 0 bytes
7/64/41.mvt 0 bytes
7/64/42.mvt 0 bytes
7/64/43.mvt 0 bytes
8/126/84.mvt 0 bytes
8/126/85.mvt 0 bytes
8/127/84.mvt 102 bytes
8/127/85.mvt 0 bytes
8/128/84.mvt 0 bytes
8/128/85.mvt 0 bytes
9/253/168.mvt 0 bytes
9/253/169.mvt 0 bytes
9/253/170.mvt 0 bytes
9/254/168.mvt 0 bytes
9/254/169.mvt 103 bytes
9/254/170.mvt 0 bytes
9/255/168.mvt 0 bytes
9/255/169.mvt 0 bytes
9/255/170.mvt 0 bytes

@jfirebaugh
Copy link
Contributor

jfirebaugh commented May 9, 2017

Thanks for the detailed issue report! This issue is triggered by tile requests that return HTTP 200 with a content length of 0. Such responses are treated as errors here, in response to which Mapbox GL will attempt to load the parent tile which covers that area. In this case, it winds up loading and tiles covering the area with dots at multiple zoom levels.

We could fix this in several ways:

@davecranwell
Copy link

davecranwell commented May 10, 2017

@nlindblad's colleague here. Thanks for the swift response, that makes a lot of sense. My preference for fixing would be to trust the 200s, but perhaps this is more a discussion for the vector tile spec itself.

@niklasvincent
Copy link
Author

Thank you very much for the prompt reply! I can confirm that returning HTTP status code 204 for zero byte tiles does indeed give me the expected behaviour:

mapbox-working

I'm in favour of the first option of treating empty responses as 204 on the client side. My reasoning is that when tiles are served from a static source such as S3 or nginx, the server doesn't change the HTTP status code to 204 if the content length happens to be zero:

nginx:

$ curl -I http://127.0.0.1:9080/10/508/338.mvt
HTTP/1.1 200 OK
Server: nginx/1.13.0
Date: Wed, 10 May 2017 08:02:01 GMT
Content-Type: application/octet-stream
Content-Length: 0
Last-Modified: Wed, 10 May 2017 07:31:09 GMT
Connection: keep-alive
ETag: "5912c1bd-0"
Accept-Ranges: bytes

AWS S3:

$ curl -I https://s3-eu-west-1.amazonaws.com/mapbox-debug-vector-tiles-20170509/10/508/338.mvt
HTTP/1.1 200 OK
x-amz-id-2: +6we2j40Sy2Hzd5rf0yurLSLX0EaHo+IR+4z6TxZ2L7//gTe0wHDB4RSVRrIaFP6U2pmPEacH6I=
x-amz-request-id: 33FAB966FA6B49D9
Date: Wed, 10 May 2017 08:02:31 GMT
Last-Modified: Tue, 09 May 2017 14:42:37 GMT
ETag: "d41d8cd98f00b204e9800998ecf8427e"
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 0
Server: AmazonS3

Ideally, any empty tiles would not be served by the server in the first place, but by explicitly requiring a HTTP status code of 204, it means a few stray empty tiles can give this kind of undesired and unexpected behaviour.

The current implementation seems to favour dynamic tile servers that have full control over introspecting the content and setting the HTTP status code accordingly, which is not what e.g. nginx and AWS S3 would do when serving static content.

@jfirebaugh
Copy link
Contributor

#6768

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants