Skip to content

Instantly share code, notes, and snippets.

@springmeyer
Last active October 2, 2017 13:38
Show Gist options
  • Save springmeyer/3522514c85443b57e338 to your computer and use it in GitHub Desktop.
Save springmeyer/3522514c85443b57e338 to your computer and use it in GitHub Desktop.

VT compositing and named layers

Currently VT rendering works like:

-> for each layer in project.yml/mapnik XML
----> find matching layer in vtile, break on first matched (so order only matters in vtile if duplicately named layers)
----------> render all styles for that matched layer

Currently VT compositing works by combining multiple VT's into a single vtile, then rendering that. So VT compositing increases the likelyhood that a VT might have duplicately named layers, but they could exist already if encoded that way.

Therefore which layer wins when rendered (in the case of duplicates) is currently controlled by the VT producer or compositor, which feels like the wrong place for control to be.

More discussion at mapbox/mapnik-vector-tile#20.

A better way?

Ideally we rename or alias duplicates. Details below on ideas for doing this. The key question is whether this happens at vtile creation/compositing time or whether the renderer should be able to handle duplicates, or both. For serverside rendering/TM2 both are easy. For GL rendering, it might make sense to not have to handle dupes at render time and therefore think of vtile sources in GL as only coming from a single uri/source and having a promise of unique names. But this feels limiting - being able to pull in multiple sources to GL could be be a nice thing to support (assuming equal z/x/y and low latency http)

The following ideas are within the context of TM2 rendering:

Lazy layer aliasing

mapnik.VectorTile.names() could dynamically find duplicate names and report them as aliased. TM2 could hook into this and report those names and make them both available for styling in the UI (related mapbox/mapbox-studio-classic#112). So, if there are two dean layers then they could be aliased as dean-1 and dean-2 (or something more creative). If a stylesheet tries to reference dean nothing would happen: this could happen if a stylesheet started off using only a single VT source and later added another one that conflicted: the layer would simply dissapear until the cartographer fixed the references.

Whether in the context of TM2 or clientside/GL rendering, doing a loop over all layers in a VT protobuf to detect duplicates before rendering should not be expensive, as long as your parsing is lazy (node-mapnik is now lazy this way). The argument against this is that the rendering code can be simplier if unique layers are promised.

Composite time renaming

This would require giving each source some name when compositing. So instead of just blindly compositing VT's like:

v1.setData(buf);
vtile.composite([vt1,vt2]);

The compositing API could look like:

vtile.composite([{name:'enf':source:vt1},{name:'springmeyer':source:vt2}]);

Any duplicate dean layers found during compositing in each tile could be renamed as dean-enf and dean-springmeyer.

Render all vtile layers matching a named layer

Easy to do (change would be in node-mapnik) but I can't see a strong usecase other than if composited layers represented different spatial extents - e.g. if a composited vtile was the result of "underzooming" where only tiles from higher zooms were available when compositing was done.

But this case is odd and not fully supported (yet) anyway because if layer geometries are buffered at all you will see rendering artifacts from shapes drawn with alpha because of overlaps.

@yhahn
Copy link

yhahn commented Feb 14, 2014

Hrm, what I recall from the last time we discussed this was some

  • Render all vtile layers matching a named layer, plus
  • Some pseudo or actual property on features that can be further used to scope styles

I think we had tossed around the idea of a mapnik-geometry-type like pseudo-property but with GL renderers in mind as well it seems more like an actual property is what would be needed for this approach.

@springmeyer
Copy link
Author

This is explicit in the vector tile spec now: A Vector Tile MUST NOT contain two or more layers whose name values are byte-for-byte identical. Prior to appending a layer to an existing Vector Tile, an encoder MUST check the existing name fields in order to prevent duplication.: https://github.com/mapbox/vector-tile-spec/blob/master/2.1/README.md#41-layers. So, decoders should expect non-duplicate layer names. And the encoder (like always) will handle preventing dupes.

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