-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
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