mapbox / geojson-vt

Slice GeoJSON into vector tiles on the fly in the browser

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Document / enforce a maximum zoom of 24 because of toID

deanm opened this issue · comments

toID is currently implemented as:

function toID(z, x, y) {
    return (((1 << z) * y + x) * 32) + z;
}

The first part of the expression calculates a tile index, which will be in the range of 2^(z*2) because the tile grid is 2^z x 2^z, for example zoom 3 is 64 tiles (8x8).

JavaScript represents numbers as doubles, which can represent integers exactly up to 53 bits. The * 32 is effectively a shift by 5 (I believe this is a multiplication and not a shift because JavaScript bit ops work on 32-bits so to use the full double it can't be a shift), reserving 5 bits (values 0..31) for the zoom level. This means from this perspective the max zoom representable by the ID scheme is 31. However, because of the 53 bit integer representation the max zoom level is actually 24 (24 * 2 + 5 == 53).

This means the ID scheme will break down at z=25, but I don't see anything in the code or documentation that checks or mentions this limitation.

PS: Since the ID space is going to be sparse the object is going to be in dictionary mode anyway, in which case I'm not sure what the benefits of sometimes SMI keys are... Anyway, SMIs I believe are 31-bit signed, which means only up to z=10 will be SMI. I am not sure if using a double as the key is such a great idea then, I don't know enough about the JavaScript spec but something tells me it probably defines the key as converted to a string, so maybe in the end it would just be better to directly build a string key and then anyway improve the above limitations.

Another thing you could do, although I'm not sure it's a better idea, is just to support collisions. Then you could truncate the IDs / etc, and then you just need to keep the actual coordinate values and check them, and support multiple tiles in a single "bucket" (id), probably easy just to do a linked list. I'm not sure if that would be more performant than string keys for typical usage, but should be something you could measure.

Thank you for such a nice, thorough issue report! Really appreciate the effort of explaining it so clearly.

I think we should explicitly limit the zoom to 24 and throw an error on higher values. I haven't seen any practical reasons to support z25+ — a z25 tile will be roughly 1x1m, and even assuming the default extent of 4096, coordinates would have ~0.2mm precision.

I think setting a limit of 24 makes good sense. I wasn't hoping to use it above, I was just trying to understand what the limits were and why.

I think there is probably a separate issue to possibly look at the current performance of using doubles as the cache keys, but that should at least be something just affecting performance and not correctness when z <= 24.