Skip to content

Commit

Permalink
Merge pull request #26 from imec-int/feature/PREC-232-add-bitmap-layer
Browse files Browse the repository at this point in the history
[PREC-232] add bitmap layer
  • Loading branch information
taeymma committed Apr 21, 2023
2 parents ba7962f + d52bcfd commit 6a29eba
Show file tree
Hide file tree
Showing 14 changed files with 14,419 additions and 13,267 deletions.
9 changes: 9 additions & 0 deletions examples/demo-app/floodcast-data/data.json

Large diffs are not rendered by default.

66 changes: 63 additions & 3 deletions examples/demo-app/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,67 @@ class App extends Component {
// this._loadBelAQI();
// Notifications
// this._loadMockNotifications();
this._addWMSLayer();
// this._addWMSLayer();
this._loadBitmapLayer();
}

_loadBitmapLayer() {
const data = require('../floodcast-data/data.json');

this.props.dispatch(
addDataToMap({
datasets: [
{
info: {
label: 'Floodcast',
id: 'floodcast-id'
},
data: processRowObject(data)
}
],
options: {
keepExistingConfig: true,
autoCreateLayers: false
},
config: {
version: 'v1',
config: {
visState: {
layers: [
{
type: 'floatbitmap',
config: {
dataId: 'floodcast-id',
label: 'bitmap layer',
isVisible: true,
visConfig: {
colorRange: {
name: 'BelAQI (PM2.5)',
type: 'standard',
category: 'BelAQI',
ranges: [0, 0.1, 0.2, 0.25, 0.35, 0.4, 0.5, 0.6, 0.7, 1.5],
colors: [
'#1c00ff00',
'#3599ff',
'#2b9900',
'#4dff01',
'#fdff00',
'#f9bb02',
'#f66600',
'#f50b00',
'#990400',
'#660200'
]
}
}
}
}
]
}
}
}
})
);
}

async _loadH3HData() {
Expand Down Expand Up @@ -239,7 +299,7 @@ class App extends Component {
// name: 'value',
// type: 'real'
// },
// colorScale: 'treshold'
// colorScale: 'threshold'
// }
// }
// ]
Expand Down Expand Up @@ -367,7 +427,7 @@ class App extends Component {
},
visualChannels: {
colorField: {name: 'newState', type: 'integer'},
colorScale: 'treshold'
colorScale: 'threshold'
}
}
]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@imec-int/kepler.gl",
"author": "imec <admin@imec-apt.be>",
"version": "2.5.5-14",
"version": "2.5.5-15",
"description": "kepler.gl is a webgl based application to visualize large scale location data in the browser",
"license": "MIT",
"main": "dist/index.js",
Expand Down
9 changes: 4 additions & 5 deletions src/components/common/color-legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,8 @@ const getQuantLegends = (scale, labelFormat) => {

const labels = scale.range().map(d => {
const invert = scale.invertExtent(d);
return `${labelFormat(invert[0] ? invert[0] : 0)} to ${
invert[1] ? labelFormat(invert[1]) : Infinity
}`;
if (invert[0] === undefined) return '';
return `${labelFormat(invert[0])} to ${invert[1] ? labelFormat(invert[1]) : Infinity}`;
});

return {
Expand Down Expand Up @@ -148,13 +147,13 @@ export default class ColorLegend extends Component {
}

const scaleFunction = SCALE_FUNC[scaleType];
// color scale can only be quantize, quantile, treshold or ordinal
// color scale can only be quantize, quantile, threshold or ordinal
// @ts-ignore fix d3 scale
let scale = scaleFunction()
.domain(domain)
.range(range.colors);

if (scaleType === SCALE_TYPES.treshold && range.ranges) {
if (scaleType === SCALE_TYPES.threshold && range.ranges) {
// @ts-ignore fix d3 scale
scale = scaleFunction()
.domain(range.ranges)
Expand Down
6 changes: 3 additions & 3 deletions src/constants/default-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ export const SCALE_TYPES = keyMirror({

// ordinal domain to linear range
point: null,
treshold: null
threshold: null
});

export const SCALE_FUNC = {
Expand All @@ -320,7 +320,7 @@ export const SCALE_FUNC = {
[SCALE_TYPES.sqrt]: scaleSqrt,
[SCALE_TYPES.log]: scaleLog,
[SCALE_TYPES.point]: scalePoint,
[SCALE_TYPES.treshold]: scaleThreshold
[SCALE_TYPES.threshold]: scaleThreshold
};

export const ALL_FIELD_TYPES = keyMirror({
Expand Down Expand Up @@ -453,7 +453,7 @@ export const AGGREGATION_TYPES = {
};

export const linearFieldScaleFunctions = {
[CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.treshold],
[CHANNEL_SCALES.color]: [SCALE_TYPES.quantize, SCALE_TYPES.quantile, SCALE_TYPES.threshold],
[CHANNEL_SCALES.radius]: [SCALE_TYPES.sqrt],
[CHANNEL_SCALES.size]: [SCALE_TYPES.linear, SCALE_TYPES.sqrt, SCALE_TYPES.log]
};
Expand Down
119 changes: 119 additions & 0 deletions src/deckgl-layers/float-bitmap-layer/float-bitmap-layer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import GL from '@luma.gl/constants';
import {BitmapLayer} from '@deck.gl/layers';
import {Texture2D} from '@luma.gl/webgl';

// Define a new bitmap layer type that can receive binary image data
class FloatBitmapLayer extends BitmapLayer {
initializeState() {
super.initializeState();
const {gl} = this.context;
const {binaryData, colorScale, width, height} = this.props;

// Preallocate the color array (RGBA)
const coloredData = new Uint8Array(binaryData.length * 4);

// Convert color legend colors to rgb
const colorScaleRGB = colorScale.colors.map(color => hexToUnsignedInt(color));

binaryData.forEach((value, index) => {
const i = index * 4;
value = Math.max(0, value);
// Find the index of the value based on the ranges
let colorIndex = colorScale.ranges.findIndex(range => value <= range);

// If the value is out of range, use the first color
colorIndex = colorIndex === -1 ? 0 : colorIndex;

const color = colorScaleRGB[colorIndex];
coloredData[i] = color[0];
coloredData[i + 1] = color[1];
coloredData[i + 2] = color[2];
// If the color has an alpha channel, use it
if (color.length === 4) coloredData[i + 3] = color[3];
else coloredData[i + 3] = 255;
});

const image = new Texture2D(gl, {
data: coloredData,
format: gl.RGBA,
mipmaps: false,
width,
height,
parameters: {
[GL.TEXTURE_MAG_FILTER]: GL.NEAREST,
[GL.TEXTURE_MIN_FILTER]: GL.NEAREST
},
compressed: false
});

this.setState({image});
}

draw(opts) {
const {uniforms, moduleParameters} = opts;
const {model, coordinateConversion, bounds, disablePicking, image} = this.state;

if (moduleParameters.pickingActive && disablePicking) {
return;
}

// Render the image
if (image && model) {
model
.setUniforms(uniforms)
.setUniforms({
bitmapTexture: image,
coordinateConversion,
tintColor: [1, 1, 1],
transparentColor: [0, 0, 0, 0],
desaturate: 0,
bounds
})
.draw();
}
}

finalizeState() {
super.finalizeState(this.context);
const {gl} = this.context;
const {image} = this.state;

// Cleanup the texture when the layer is removed
gl.deleteTexture(image);
}
}

export default FloatBitmapLayer;

function hexToUnsignedInt(input) {
// Drop the # if it exists
if (input[0] === '#') {
input = input.substring(1);
}
const channels = input.length / 2;
var colors = new Uint8Array(channels);
for (var n = 0; n < input.length; n++) {
colors[n] = parseInt(input.substring(n * 2, n * 2 + 2), 16);
}
return colors;
}
4 changes: 2 additions & 2 deletions src/layers/base-layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -736,9 +736,9 @@ class Layer {
return scale;
}

if (colorScale === 'treshold') {
if (colorScale === 'threshold') {
return this.getVisChannelScale(
'treshold',
'threshold',
colorRange.ranges ? colorRange.ranges : colorDomain,
colorRange.colors.map(hexToRgb)
);
Expand Down

0 comments on commit 6a29eba

Please sign in to comment.