Skip to content

Commit

Permalink
GPU GridLyer Part 6: GPUGridLayer fixes and docs. (#3143)
Browse files Browse the repository at this point in the history
* Fix lighitng when not extruded
* GPUGridLayer: add support for custom color and elevation domains
* GPU GridLayer Part 6: Fix props, update and add docs.
* NewGridLayer/HexagaonLayer: update docs with example usages
  • Loading branch information
1chandu committed May 29, 2019
1 parent 028904a commit ef0b34a
Show file tree
Hide file tree
Showing 12 changed files with 821 additions and 28 deletions.
105 changes: 93 additions & 12 deletions docs/layers/gpu-grid-layer.md
@@ -1,3 +1,5 @@
<!-- INJECT:"GPUGridLayerDemo" -->

<p class="badges">
<img src="https://img.shields.io/badge/@deck.gl/aggregation--layers-lightgrey.svg?style=flat-square" alt="@deck.gl/aggregation-layers" />
<img src="https://img.shields.io/badge/fp64-yes-blue.svg?style=flat-square" alt="64-bit" />
Expand All @@ -14,7 +16,7 @@ GPUGridLayer is a [CompositeLayer](/docs/api-reference/composite-layer.md).

```js
import DeckGL from '@deck.gl/react';
import {GridLayer} from '@deck.gl/aggregation-layers';
import {_GPUGridLayer as GPUGridLayer} from '@deck.gl/aggregation-layers';

const App = ({data, viewport}) => {

Expand All @@ -27,19 +29,28 @@ const App = ({data, viewport}) => {
*/
const layer = new GPUGridLayer({
id: 'gpu-grid-layer',
gpuAggregation: true,
data,
pickable: true,
extruded: true,
cellSize: 200,
elevationScale: 4,
getPosition: d => d.COORDINATES,
onHover: ({object, x, y}) => {
const tooltip = `${object.position.join(', ')}\nCount: ${object.count}`;
/* Update tooltip
http://deck.gl/#/documentation/developer-guide/adding-interactivity?section=example-display-a-tooltip-for-hovered-object
*/
}
});

return (<DeckGL {...viewport} layers={[layer]} />);
};
```

**Note:** This layer is similar to [GridLayer](/docs/layers/grid-layer.md) but supports aggregation on GPU using new prop `gpuAggregation`. Also several features of [GridLayer](/docs/layers/grid-layer.md) are not yet implemented and currently being worked on.
**Note:** The `GridLayer` at the moment only works with `COORDINATE_SYSTEM.LNGLAT`.

**Note:** This layer is similar to [GridLayer](/docs/layers/grid-layer.md) but supports aggregation on GPU when possible. Check below for more detailed differences of this layer compared to `GridLayer`.


## Installation
Expand Down Expand Up @@ -74,7 +85,7 @@ new deck._GPUGridLayer({});

## Properties

Inherits from all [Base Layer](/docs/api-reference/layer.md) properties.
Inherits from all [Base Layer](/docs/api-reference/layer.md) and [CompositeLayer](/docs/api-reference/composite-layer.md) properties.

### Render Options

Expand All @@ -84,13 +95,12 @@ Inherits from all [Base Layer](/docs/api-reference/layer.md) properties.

Size of each cell in meters

##### `gpuAggregation` (bool, optional)

* Default: true
##### `colorRange` (Array, optional)

When set to true and browser supports GPU aggregation, aggregation is performed on GPU. GPU aggregation can be 2 to 3 times faster depending upon number of points and number of cells.
* Default: <img src="/website/src/static/images/colorbrewer_YlOrRd_6.png"/></a>

NOTE: GPU Aggregation requires WebGL2 support by the browser. When `gpuAggregation` is set to true and browser doesn't support WebGL2, aggregation falls back to CPU.
Specified as an array of 6 colors [color1, color2, ... color6]. Each color is an array of 3 or 4 values [R, G, B] or [R, G, B, A], representing intensities of Red, Green, Blue and Alpha channels. Each intensity is a value between 0 and 255. When Alpha not provided a value of 255 is used. By default `colorRange` is set to
[colorbrewer](http://colorbrewer2.org/#type=sequential&scheme=YlOrRd&n=6) `6-class YlOrRd`.

##### `coverage` (Number, optional)

Expand All @@ -100,12 +110,24 @@ Cell size multiplier, clamped between 0 - 1. The final size of cell
is calculated by `coverage * cellSize`. Note: coverage does not affect how points
are binned. Coverage are linear based.

##### `elevationDomain` (Array, optional)

* Default: `[0, max(count)]`

Elevation scale input domain, default is set to the extent of point counts in each cell.

##### `elevationRange` (Array, optional)

* Default: `[0, 1000]`

Elevation scale output range

##### `elevationScale` (Number, optional)

* Default: `1`

Cell elevation multiplier. The elevation of cell is calculated by
`elevationScale * count`. `count` is number of points that fall into the cell.
`elevationScale * getElevation(d)`.
`elevationScale` is a handy property to scale all cells without updating the data.

##### `extruded` (Boolean, optional)
Expand All @@ -118,7 +140,17 @@ Whether to enable cell elevation. Cell elevation scale by count of points in eac

* Default: `false`

Whether the layer should be rendered in high-precision 64-bit mode
Whether the layer should be rendered in high-precision 64-bit mode. Note that since deck.gl v6.1, the default 32-bit projection uses a hybrid mode that matches 64-bit precision with significantly better performance.

##### `gpuAggregation` (bool, optional)

* Default: true

When set to true and browser supports GPU aggregation, aggregation is performed on GPU. GPU aggregation can be 2 to 3 times faster depending upon number of points and number of cells.

**Note:** GPU Aggregation requires WebGL2. When `gpuAggregation` is set to true and browser doesn't support WebGL2, aggregation falls back to CPU.

**Note:** GPU Aggregation is faster only when using large data sets (point count is more than 500K), for smaller data sets GPU Aggregation could be potentially slower than CPU Aggregation.

##### `material` (Object, optional)

Expand All @@ -135,10 +167,59 @@ Check [PhongMaterial](https://github.com/uber/luma.gl/tree/7.0-release/docs/api-

Method called to retrieve the position of each point.

##### `getColorWeight` (Function, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

* Default: `point => 1`

`getColorWeight` is the accessor function to get the weight of a point used to calcuate the color value for a cell.
It takes the data prop array element and returns the weight, for example, to use `SPACE` field, `getColorWeight` should be set to `point => point.SPACES`.
By default `getColorWeight` returns `1`.

Note: similar to `getColorValue`, grid layer compares whether `getColorWeight` has changed to recalculate the value for each bin that its color based on.


##### `colorAggregation` (String, optional)

* Default: 'SUM'

`colorAggregation` defines, operation used to aggregate all data point weights to calculate a cell's color value. Valid values are 'SUM', 'MEAN', 'MIN' and 'MAX'. 'SUM' is used when an invalid value is provided.

Note: `getColorWeight` and `colorAggregation` together define how color value of cell is determined, same can be done by setting `getColorValue` prop. But to enable gpu aggregation, former props must be provided instead of later.


##### `getElevationWeight` (Function, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

* Default: `point => 1`

`getElevationWeight` is the accessor function to get the weight of a point used to calcuate the elevation value for a cell.
It takes the data prop array element and returns the weight, for example, to use `SPACE` field, `getElevationWeight` should be set to `point => point.SPACES`.
By default `getElevationWeight` returns `1`.

Note: similar to `getElevationValue`, grid layer compares whether `getElevationWeight` has changed to recalculate the value for each bin that its color based on.


##### `elevationAggregation` (String, optional)

* Default: 'SUM'

`elevationAggregation` defines, operation used to aggregate all data point weights to calculate a cell's elevation value. Valid values are 'SUM', 'MEAN', 'MIN' and 'MAX'. 'SUM' is used when an invalid value is provided.

Note: `getElevationWeight` and `elevationAggregation` together define how elevation value of cell is determined, same can be done by setting `getColorValue` prop. But to enable gpu aggregation, former props must be provided instead of later.


## Differences compared to GridLayer

### Unsupported props

Due to the nature of GPU Aggregation implementation following GridLayer props are not supported by this layer.

`upperPercentile` `lowerPercentile` `elevationUpperPercentile`, `elevationLowerPercentile`, `getColorValue`, `getElevationValue`, `onSetColorDomain` and `onSetElevationDomain`

Instead of `getColorValue`, `getColorWeight` and `colorAggregation` should be used. Instead of `getElevationValue`, `getElevationWeight` and `elevationAggregation` should be used. There is no alternate for all other unsupported props, if they are needed `GridLayer` should be used instead of this layer.

## The following props of GridLayer are not supported yet
### Picking

`colorDomain`, `colorRange`, `elevationDomain`,`elevationRange`, `upperPercentile` `lowerPercentile` `elevationUpperPercentile`, `elevationLowerPercentile`
When picking mode is `hover`, only the elevation value, color value of selected cell are included in picking result. Array of all points that aggregated into that cell is not provided. For all other modes, picking results match with `GridLayer`, for these cases data is aggregated on CPU to provide array of all points that aggregated to the cell.


## Source
Expand Down
1 change: 1 addition & 0 deletions docs/layers/grid-layer.md
Expand Up @@ -298,6 +298,7 @@ const layer = new GridLayer({

If your use case requires aggregating using an operation that is not one of 'SUM', 'MEAN', 'MAX' and 'MIN', `getColorValue` should be used to define such custom aggregation function. In those cases GPU aggregation is not supported.


##### `getElevationValue` (Function, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

* Default: `points => points.length`
Expand Down
162 changes: 162 additions & 0 deletions docs/layers/hexagon-layer.md
Expand Up @@ -240,6 +240,86 @@ new function on every rendering pass.
}
```

##### `getColorWeight` (Function, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

* Default: `point => 1`

`getColorWeight` is the accessor function to get the weight of a point used to calcuate the color value for a cell.

Note: similar to `getColorValue`, grid layer compares whether `getColorWeight` has changed to recalculate the value for each bin that its color based on.


##### `colorAggregation` (String, optional)

* Default: 'SUM'

`colorAggregation` defines, operation used to aggregate all data point weights to calculate a cell's color value. Valid values are 'SUM', 'MEAN', 'MIN' and 'MAX'. 'SUM' is used when an invalid value is provided.

Note: `getColorWeight` and `colorAggregation` together define how color value of cell is determined, same can be done by setting `getColorValue` prop. But to enable gpu aggregation, former props must be provided instead of later.

###### Example1 : Using count of data elements that fall into a cell to encode the its color
```js
function getCount(points) {
return points.length;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getColorValue: getCount,
...
});
```

####### Using `getColorWeight` and `colorAggregation`
```js
function getWeight(point) {
return 1;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getColorWeight: getWeight,
colorAggregation: 'SUM'
...
});
```

###### Example2 : Using mean value of 'SPACES' field of data elements to encode the color of the cell

####### Using `getColorValue`
```js
function getMean(points) {
return points.reduce((sum, p) => sum += p.SPACES, 0) / points.length;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getColorValue: getMean,
...
});
```

####### Using `getColorWeight` and `colorAggregation`
```js
function getWeight(point) {
return point.SPACES;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getColorWeight: getWeight,
colorAggregation: 'SUM'
...
});
```

If your use case requires aggregating using an operation that is not one of 'SUM', 'MEAN', 'MAX' and 'MIN', `getColorValue` should be used to define such custom aggregation function. In those cases GPU aggregation is not supported.


##### `getElevationValue` (Function, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

* Default: `points => points.length`
Expand All @@ -254,6 +334,88 @@ pass in the function defined outside the render function so it doesn't create a
new function on every rendering pass.


##### `getElevationWeight` (Function, optional) ![transition-enabled](https://img.shields.io/badge/transition-enabled-green.svg?style=flat-square")

* Default: `point => 1`

`getElevationWeight` is the accessor function to get the weight of a point used to calcuate the elevation value for a cell.

Note: similar to `getElevationValue`, grid layer compares whether `getElevationWeight` has changed to recalculate the value for each bin that its color based on.

##### `elevationAggregation` (String, optional)

* Default: 'SUM'

`elevationAggregation` defines, operation used to aggregate all data point weights to calculate a cell's elevation value. Valid values are 'SUM', 'MEAN', 'MIN' and 'MAX'. 'SUM' is used when an invalid value is provided.

Note: `getElevationWeight` and `elevationAggregation` together define how elevation value of cell is determined, same can be done by setting `getColorValue` prop. But to enable gpu aggregation, former props must be provided instead of later.


###### Example1 : Using count of data elements that fall into a cell to encode the its elevation

####### Using `getElevationValue`

```js
function getCount(points) {
return points.length;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getElevationValue: getCount,
...
});
```

####### Using `getElevationWeight` and `elevationAggregation`
```js
function getWeight(point) {
return 1;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getElevationWeight: getWeight,
elevationAggregation: 'SUM'
...
});
```

###### Example2 : Using maximum value of 'SPACES' field of data elements to encode the elevation of the cell

####### Using `getElevationValue`
```js
function getMax(points) {
return points.reduce((max, p) => p.SPACES > max ? p.SPACES : max, -Infinity);
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getElevationValue: getMax,
...
});
```

####### Using `getElevationWeight` and `elevationAggregation`
```js
function getWeight(point) {
return point.SPACES;
}
...
const layer = new HexagonLayer({
id: 'my-hexagon-layer',
...
getElevationWeight: getWeight,
elevationAggregation: 'MAX'
...
});
```

If your use case requires aggregating using an operation that is not one of 'SUM', 'MEAN', 'MAX' and 'MIN', `getElevationValue` should be used to define such custom aggregation function. In those cases GPU aggregation is not supported.

##### `onSetColorDomain` (Function, optional)

* Default: `() => {}`
Expand Down

0 comments on commit ef0b34a

Please sign in to comment.