question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Retaining custom properties on a TileLayer and BitMap to enable redrawing

See original GitHub issue

Hi there,

I’m working on kind-of a custom TileLayer with BitMap layer setup.

In my approach I’m retrieving an array of integer values which I’m then converting into an image in the browser using a particular colour ramp (Edit: perhaps similar to this issue which I found after posting this).

What I’d like to be able to do is reuse my original array of data to regenerate my image based on a new colour ramp without having to redownload the tiles. From example switching from the viridis colour ramp to using a a magma colour ramp. ChangingRamps The first hurdle I’ve got is that I don’t seem to be able to hold onto my original array.

new TileLayer({
  data: 'http://tiles:3000/{z}/{x}/{y}.pbf',
  tileSize: 256,

  getTileData: async function (tile) {
    const someBuffer = await makeRequest("GET", tile.url);

    tile._rawData = someBuffer <--- I want to save the original array

    const out = new ImageData(256, 256);
    for (let i = 0; i < this.data.length / 4; i++) {
      if (someBuffer.values[i] !== 999) {
        const rgba = d3.interpolateViridis(someBuffer.values[i])
        out.data[i * 4] = rgba[0];
        out.data[(i * 4) + 1] = rgba[1];
        out.data[(i * 4) + 2] = rgba[2];
        out.data[(i * 4) + 3] = 255;
      }
    };
    return out
  },

  renderSubLayers: props => {
    const {
    bbox: {west, south, east, north}
    } = props.tile;

    return new BitmapLayer(props, {
      data: null,
      image: props.tile.data,
      bounds: [west, south, east, north]
    });
}

I’m new to deckgl so just poking around the edges at the moment so this may not be the best way to go around this things so I’m open to suggestions, but hopefully you can make sense of the request 😃

Thanks, Rowan

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9

github_iconTop GitHub Comments

2reactions
Pessimistresscommented, Jul 4, 2020

I do not recommend accessing the layer instance via this in getTileData - this may break in the future if we change the TileLayer implementation.

You can simply return the raw data in getTileData:

new TileLayer({
  data: 'http://tiles:3000/{z}/{x}/{y}.pbf',
  
  // Changing a TileLayer prop will re-evaluate `renderSubLayers` for each tile
  colorScheme: d3.interpolateViridis,

  getTileData: tile => makeRequest("GET", tile.url),

  renderSubLayers: props => {
    const {
	  data,
      bbox: {west, south, east, north}
    } = props.tile;

	// Convert buffer to image
    const image = new ImageData(256, 256);
    for (let i = 0; i < data.length / 4; i++) {
      if (data.values[i] !== 999) {
        const rgba = props.colorScheme(data.values[i])
        image.data[i * 4] = rgba[0];
        image.data[(i * 4) + 1] = rgba[1];
        image.data[(i * 4) + 2] = rgba[2];
        image.data[(i * 4) + 3] = 255;
      }
    };

    return new BitmapLayer(props, {
      data: null,
      image,
      bounds: [west, south, east, north]
    });
}

renderSubLayers is only called once for each tile until some TileLayer props change. If you want to introduce other props and avoid recreating the ImageData, wrap the buffer to image conversion in a memoized function.

0reactions
rowanwinscommented, Jul 7, 2020

So just jotting a final note on this - I’m fairly happy with where I’ve handed.

Ignore the dodgy gif quality - was just trying to keep under the github limits 😃 Sample

One thing I did notice was that when I changed by props, such as my color ramp, the more I’d browsed around previously the slower the re-rendering would take. From what I could tell it looked like the renderSubLayers method was being called for every tile that had been visited previously, irrespective of whether that tile was currently visible or not, I’m not sure if this is expected behaviour or not… So I’ve hacked around it by doing

this.deck.layerManager.layers = []
Read more comments on GitHub >

github_iconTop Results From Across the Web

What's New - deck.gl
Starting from v8.8, the TileLayer supports custom indexing systems. Applications can now supply a custom implementation of Tileset2D to the TilesetClass prop.
Read more >
Custom TileLayer | ArcGIS Maps SDK for JavaScript 4.25
Using the custom tile layer in JavaScript application​​ Once the custom layer is created, you can add it to the layers of the...
Read more >
User's Manual - LightningChart
This document is a brief User's Manual, reference of Arction LightningChart® .NET. Only essential key features are explained.
Read more >
3ds Max 2023 Developer Help | Custom Bitmap Properties
You may use the BitmapManager::ImageInputOptions() method to allow the user to specify these options via the standard 3ds Max Input Image Options dialog....
Read more >
CHANGELOG.md ... - GitLab
BitmapData has a new property frameData which is a Phaser. ... The Physics Manager will now throw a console warning if you try...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found