Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
lixun910 committed Sep 28, 2023
1 parent 14d1452 commit a56dd8b
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 21 deletions.
44 changes: 44 additions & 0 deletions src/deckgl-layers/src/geojson-layer/brush-geojson-layer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {Layer, LayerExtension } from '@deck.gl/core';
import {LayerContext} from '@deck.gl/core/lib/layer';

import shaderModule from './brush-shader-module';

const defaultProps = {
};

export type BrushGeoJsonExtensionProps = {
};

// Write an extension to brush geojson layer using the drawn polygon:
// an instanced attribute 'instanceHighlighted' is added to the layer to indicate whether the feature is highlighted
// the shader module is modified to discard the feature if instanceHighlighted is 0
// the accessor getHighlighted is used to get the value of instanceHighlighted based on the search result in GeoJsonlayer
// From a test, deck: Updated attributes for 7314969 instances in azfyr45-polygons-fill in 162ms
export default class BrushGeoJsonExtension extends LayerExtension {
static defaultProps = defaultProps;
static extensionName = 'BrushGeoJsonExtension';

getShaders(extension: any) {
return {
modules: [shaderModule],
defines: {}
};
}

initializeState(this: Layer<BrushGeoJsonExtensionProps>, context: LayerContext, extension: this) {
const attributeManager = this.getAttributeManager();
if (attributeManager) {
attributeManager.addInstanced({
instanceHighlighted: {
size: 1,
accessor: 'getHighlighted'
}
});
}
}
updateState({
props,
oldProps
}) {
}
}
42 changes: 42 additions & 0 deletions src/deckgl-layers/src/geojson-layer/brush-shader-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {project} from '@deck.gl/core';

import type {BrushGeoJsonExtensionProps} from './brush-geojson-layer';

const vs = ``;

const fs = ``;

const inject = {
'vs:#decl': `
attribute float instanceHighlighted;
varying float vHighlighted;
`,
'vs:#main-end': `
if (instanceHighlighted == 0.) {
gl_Position = vec4(0.);
}
vHighlighted = instanceHighlighted;
`,
'fs:#decl': `
varying float vHighlighted;
`,
'fs:DECKGL_FILTER_COLOR': `
if (vHighlighted == 0.) {
discard;
}
`
};

export default {
name: 'brush-geojson',
dependencies: [project],
vs,
fs,
inject,
getUniforms: (opts?: BrushGeoJsonExtensionProps): Record<string, any> => {
if (!opts) {
return {};
}
return {};
}
}
1 change: 1 addition & 0 deletions src/deckgl-layers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {default as EnhancedGridLayer} from './grid-layer/enhanced-cpu-grid-layer
export {default as EnhancedHexagonLayer} from './hexagon-layer/enhanced-hexagon-layer';
export {default as EnhancedLineLayer} from './line-layer/line-layer';
export {default as SvgIconLayer} from './svg-icon-layer/svg-icon-layer';
export {default as BrushGeoJsonExtension} from './geojson-layer/brush-geojson-layer';

export * from './layer-utils/shader-utils';

Expand Down
5 changes: 3 additions & 2 deletions src/layers/src/base-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import keymirror from 'keymirror';
import {DataFilterExtension} from '@deck.gl/extensions';
import {COORDINATE_SYSTEM} from '@deck.gl/core';
import {TextLayer} from '@deck.gl/layers';
import {BrushGeoJsonExtension} from '@kepler.gl/deckgl-layers';

import DefaultLayerIcon from './default-layer-icon';
import {diffUpdateTriggers} from './layer-update';
Expand Down Expand Up @@ -203,7 +204,7 @@ export const LAYER_ID_LENGTH = 6;
const MAX_SAMPLE_SIZE = 5000;
const defaultDomain: [number, number] = [0, 1];
const dataFilterExtension = new DataFilterExtension({filterSize: MAX_GPU_FILTERS});

const brushGeoJsonExtension = new BrushGeoJsonExtension();
const defaultDataAccessor = dc => d => d;
const defaultGetFieldValue = (field, d) => field.valueAccessor(d);

Expand Down Expand Up @@ -1309,7 +1310,7 @@ class Layer {
opacity: this.config.visConfig.opacity,
highlightColor: this.config.highlightColor,
// data filtering
extensions: [dataFilterExtension],
extensions: [dataFilterExtension, brushGeoJsonExtension],
filterRange: gpuFilter ? gpuFilter.filterRange : undefined,

// layer should be visible and if splitMap, shown in to one of panel
Expand Down
28 changes: 17 additions & 11 deletions src/layers/src/geojson-layer/geojson-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import Flatbush from 'flatbush';
import uniq from 'lodash.uniq';
import {DATA_TYPES} from 'type-analyzer';
import {Feature, Polygon} from 'geojson';
import booleanWithin from '@turf/boolean-within';
import {point as turfPoint} from '@turf/helpers';
import Layer, {
Expand Down Expand Up @@ -64,7 +63,6 @@ import {
} from '@kepler.gl/types';
import {KeplerTable} from '@kepler.gl/table';
import {DataContainerInterface} from '@kepler.gl/utils';
import {RowDataContainer} from 'src/utils/src/row-data-container';

const SUPPORTED_ANALYZER_TYPES = {
[DATA_TYPES.GEOMETRY]: true,
Expand Down Expand Up @@ -199,10 +197,12 @@ export default class GeoJsonLayer extends Layer {
centroids: number[][];
static spatialIndex = new Map<string, SpatialIndexProps>();
queryIndexes: Map<number, boolean>;
queryBounds: number[];

constructor(props) {
super(props);

this.queryBounds = [];
this.queryIndexes = new Map();
this.centroids = [];
this.dataToFeature = [];
Expand Down Expand Up @@ -366,19 +366,24 @@ export default class GeoJsonLayer extends Layer {
const dataAccessor = dc => d => ({index: d.properties.index});
const accessors = this.getAttributeAccessors({dataAccessor, dataContainer});

const queryResultAccessor = d => {
// return (this?.queryBounds && this?.queryBounds?.length === 0) || d.properties.selected ? 1 : 0;
return Math.round(Math.random())
};

return {
data,
getFilterValue: gpuFilter.filterValueAccessor(dataContainer)(
indexAccessor,
customFilterValueAccessor
),
getHighlighted: queryResultAccessor,
...accessors
};
}

getSpatialIndex() {
if (!GeoJsonLayer.spatialIndex.get(this.id) && this.centroids.length > 0) {
console.time('create spatial index');
const index = new Flatbush(this.centroids.length);
this.centroids.forEach(c => index?.add(c[0], c[1], c[0], c[1]));
index.finish();
Expand All @@ -387,6 +392,7 @@ export default class GeoJsonLayer extends Layer {
search: (filter: PolygonFilter, layer: GeoJsonLayer): number[] => {
console.time('search');
const [minX, minY, maxX, maxY] = filter.value.properties.bbox;
layer.queryBounds = [minX, minY, maxX, maxY];
const foundIndexes = index?.search(minX, minY, maxX, maxY) || [];
layer.queryIndexes.clear();
if (filter.value.properties?.shape === 'Rectangle') {
Expand All @@ -400,17 +406,16 @@ export default class GeoJsonLayer extends Layer {
}
});
}
layer.queryIndexes.forEach((v, k) => {
const feat = layer.dataToFeature[k];
if (feat?.properties) {
feat.properties.selected = 1;
}
});
// layer.queryIndexes.forEach((v, k) => {
// const feat = layer.dataToFeature[k];
// if (feat?.properties) {
// feat.properties.selected = 1;
// }
// });
console.timeEnd('search');
return foundIndexes;
}
});
console.timeEnd('create spatial index');
}
return GeoJsonLayer.spatialIndex.get(this.id);
}
Expand Down Expand Up @@ -503,7 +508,8 @@ export default class GeoJsonLayer extends Layer {

const updateTriggers = {
...this.getVisualChannelUpdateTriggers(),
getFilterValue: gpuFilter.filterValueUpdateTriggers
getFilterValue: gpuFilter.filterValueUpdateTriggers,
getHighlighted: this.queryBounds
};

const defaultLayerProps = this.getDefaultDeckLayerProps(opts);
Expand Down
22 changes: 15 additions & 7 deletions src/table/src/gpu-filter-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ const defaultGetIndex = d => d.index;
* @param fieldIndex Column index in the data container.
* @returns
*/
const defaultGetData = (dc: DataContainerInterface, d: any, fieldIndex: number) => {
const defaultGetData = (dc: DataContainerInterface, d: any, fieldIndex: number, filter?: Filter) => {
return dc.valueAt(d.index, fieldIndex);
};

Expand All @@ -183,9 +183,9 @@ const getFilterValueAccessor = (
if (!filter) {
return 0;
}
// if (filter.type === FILTER_TYPES.polygon) {
// return getData(dc, d, -1, filter);
// }
if (filter.type === FILTER_TYPES.polygon) {
return getData(dc, d, -1, filter);
}
const fieldIndex = getDatasetFieldIndexForFilter(dataId, filter);
const field = fields[fieldIndex];

Expand Down Expand Up @@ -218,10 +218,18 @@ export function getGpuFilterProps(filters: Filter[], dataId: string, fields: Fie
f.gpuChannel[f.dataId.indexOf(dataId)] === i
);

filterRange[i][0] = filter ? filter.value[0] - filter.domain?.[0] : 0;
filterRange[i][1] = filter ? filter.value[1] - filter.domain?.[0] : 0;
if (filter?.type === FILTER_TYPES.polygon) {
filterRange[i][0] = 1;
// get a number that is larger than 1 and changed when bbox changes
filterRange[i][1] = 1 + Math.abs(filter.value.properties.bbox.reduce((accu, d) => accu + d, 0));
console.log(filterRange)
triggers[`gpuFilter_${i}`] = filter.id;
} else {
filterRange[i][0] = filter ? filter.value[0] - filter.domain?.[0] : 0;
filterRange[i][1] = filter ? filter.value[1] - filter.domain?.[0] : 0;
triggers[`gpuFilter_${i}`] = filter ? filter.name[filter.dataId.indexOf(dataId)] : null;
}

triggers[`gpuFilter_${i}`] = filter ? filter.name[filter.dataId.indexOf(dataId)] : null;
channels.push(filter);
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils/src/filter-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1144,7 +1144,7 @@ export function generatePolygonFilter<
name,
layerId,
value: featureToFilterValue(feature, filter.id, {isVisible: true}),
gpu: false
gpu: true
};
}

Expand Down

0 comments on commit a56dd8b

Please sign in to comment.