Deck.gl: Render MVTLayer using TextLayer

Created on 9 Apr 2020  路  9Comments  路  Source: visgl/deck.gl

Description

I've been using MVTLayer with the default renderSubLayers and it works perfectly. Aside that, I've created a layer that extends from CompositeLayer to show a TextLayer above the GeoJsonLayer following this deck.gl tutorial. It works but it repeats the TextLayer inside each geometry.

Repro Steps

I've made an example that reproduces the problem.

As you can see in this screenshot, the word Illinois is repeated four times inside the state polygon.

Environment

  • Framework Version: deck.gl 8.1.1
  • Browser Version: Chrome 80.0.3987.163
  • OS: macOS 10.14.6

All 9 comments

What tile service are you using? Are you creating your own MVT tiles?

Polygons naturally get split into multiple tiles when you use a tiled data source. Because tiles do not talk to each other, each tile's renderSubLayers will try to create their own labels. The way Mapbox etc. handle this is to create one or more label layer of point features. These layers are computed when you generate the MVT tiles. At runtime, you can use the TextLayer directly to render them.

Thanks for your answer @Pessimistress, I'm using deck MVTLayer with CARTO Maps API to generate the MVT tiles.

I've achieved what I wanted creating two different MVTLayer: the first one uses the default renderSubLayers to draw the polygons. The second one uses the same query to generate the MVTs, but instead of the default geometry of the polygons they are converted to the centroids of each one using ST_Centroid, and in renderSubLayers it uses a TextLayer.

image

I understand why it's working but I think it's a disadvantages of MVTLayer that both things cannot be done together because I had to make two requests to generate MVTs.

You should be able to subclass MVTLayer to render both sets of sub layers with one network request per tile.

Hello, I'm interested in this too.
Are you saying is posible to subclass MVTLayer to create an "adaptor layer" like in the icon-cluster example or the labeled-geosjon example ??

Polygon data will still be split into multiple tiles, so can we merge them back at the client-side to find the anchor point of the labels or should we change the part that does the MVT generation ?

I think previous versions of the MVTLayer did this client-side polygon merging but stopped it because it was not the best alternative, so it is okay to do it here ?

Are you saying is posible to subclass MVTLayer to create an "adaptor layer"

Yes, I think the icon-cluster-layer is actually a good reference point. You'll have to play around with it a bit. For example you can see that the MVTLayer currently subclasses the TileLayer I believe. So you might have to copy some code from the MVTLayer so that you can render both geometry layers and a TextLayer.

Along the same lines, a Text/Symbol layer that handles symbol collisions is of interest to me personally. It might be out of scope for the main Deck.gl repository, since Deck.gl isn't in the game of creating a basemap, but it could be a separate open source repo. I've started reading through relevant code in Mapbox GL JS, but haven't gotten around to extracting it for an implementation that might work with Deck.gl.

Polygon data will still be split into multiple tiles, so can we merge them back at the client-side to find the anchor point of the labels or should we change the part that does the MVT generation ?

Currently there's no merging that happens in the MVTLayer client side. This would be non-trivial since the number of tiles necessary to merge a polygon is unknown before retrieving the tiles.

Personally, I think you'd have much better luck pre-generating anchor points for text labels and storing them as a point layer in the MVT, so that you aren't finding points client side.

I think previous versions of the MVTLayer did this client-side polygon merging but stopped it because it was not the best alternative, so it is okay to do it here ?

I don't think polygon merging was ever implemented, but it was discussed here: https://github.com/uber/deck.gl/pull/3704#issuecomment-535613783

Wow, thanks a lot for your comments @kylebarron !!

Following up on this, another idea I'm having is to use the backend to generate two properties in every feature, centroid_x and centroid_y, group them by feature id client-side and feed those positions to the symbol/text layer

You generally don't want to put labels at centroids. Using the pole of accessibility is more standard and gives better results for weird polygons. https://github.com/mapbox/polylabel and https://blog.mapbox.com/a-new-algorithm-for-finding-a-visual-center-of-a-polygon-7c77e6492fbc

Ah yes, I've been told that many times but I never remeber it, thanks for the tip. It think there is a PostGIS function that also does that called ST_PointOnSurface

Is this still an issue? I can't find it now, but there was a similar issue in Mapbox GL JS, and the recommendation there was the same as Pessimistress's above.

Generate point anchors for labels before encoding into MVT, so that there's only one anchor per label.

Was this page helpful?
0 / 5 - 0 ratings