Skip to content

[Feat] RFC: Filter by category in DataFilterExtension #7827

@felixpalmer

Description

@felixpalmer

Target Use Case

deck.gl includes the DataFilterExtension which allows GPU filtering of a dataset via an accessor:

new GeoJsonLayer({
  ...
  extensions: [new DataFilterExtension({filterSize: 1})]
  getFilterValue: f => f.properties.timeOfDay,  // in seconds
  filterRange: [43200, 46800],  // 12:00 - 13:00
});

A limitation of this approach that is that it only works for filters which can be represented as a continuous numeric range. There is no way to construct a filter which filters based on discrete categories.

Proposal

A new accessor, getFilterCategory and prop, filterCategories, are added to the extension which allows the user to filter by a set of discrete values.

new GeoJsonLayer({
  ...
  extensions: [new DataFilterExtension()]
  getFilterCategory: f => f.properties.country,
  filterCategories: ['spain', 'usa']
});

The above example will only display features where the country property matches any one of the values in the filterCategories array.

Implementation

Consider first the implementation where each category is represented as an unsigned integer. We can then form a mask from these values by taking each value (n) and setting the nth mask bit to 1. So filterCategories: [1, 3, 7] => 100 0101 => 69. Thus we can encode these 3 categories as the value of 69 which is passed to shader as a uniform. The shader then decodes the mask and compares it to the attribute value that is populated via getFilterCategory.

Maximum number of categories

In WebGL we can represent uniforms are represented as 32 bit integer which are 32 bit values. Thus we can exactly represent integers in the range 0 -> 2 ** 32 which gives support for up to 32 categories.

If this uniform is declared as vec4 we get 4 times as many categories: 128.

String categories

To support strings as categories, the extension maintains a mapping between string and integers internally and only passes the integer values to the GPU. This is transparent to the user.

Compound category filters

In order to filter by category on multiple properties, an array can be returned like with the getFilterValue accessor:

new GeoJsonLayer({
  getFilterCategory: f => [f.properties.country, f.properties.type],
  filterCategories: [['spain', 'usa'], ['school', 'airport']]
});

In order to specify the number of category filters, the constructor is extended to include the categorySize parameter, which is analagous to filterSize. The maximum value is 4

Usage with filterRange

As the category filtering has its own dedicated accessor & filter definition it can be used together with the existing filtering by numerical range.

Interaction with other props

As the category filtering is discrete in nature, filterTransformSize & filterTransformColor are not supported

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions