Skip to content

Commit

Permalink
Evaluate query results
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanhamley committed Feb 10, 2020
1 parent ccae2ba commit e16da16
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 13 deletions.
13 changes: 9 additions & 4 deletions src/data/feature_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class FeatureIndex {
}

// Finds non-symbol features in this tile at a particular position.
query(args: QueryParameters, styleLayers: {[string]: StyleLayer}, sourceFeatureState: SourceFeatureState): {[string]: Array<{ featureIndex: number, feature: GeoJSONFeature }>} {
query(args: QueryParameters, styleLayers: {[string]: StyleLayer}, serializedLayers: {[string]: Object}, sourceFeatureState: SourceFeatureState): {[string]: Array<{ featureIndex: number, feature: GeoJSONFeature }>} {
this.loadVTLayers();

const params = args.params || {},
Expand Down Expand Up @@ -146,6 +146,7 @@ class FeatureIndex {
filter,
params.layers,
styleLayers,
serializedLayers,
(feature: VectorTileFeature, styleLayer: StyleLayer, id: string | number | void) => {
if (!featureGeometry) {
featureGeometry = loadGeometry(feature);
Expand All @@ -171,6 +172,7 @@ class FeatureIndex {
filter: FeatureFilter,
filterLayerIDs: Array<string>,
styleLayers: {[string]: StyleLayer},
serializedLayers: {[string]: Object},
intersectionTest?: (feature: VectorTileFeature, styleLayer: StyleLayer, id: string | number | void) => boolean | number) {

const layerIDs = this.bucketLayerIDs[bucketIndex];
Expand Down Expand Up @@ -202,19 +204,21 @@ class FeatureIndex {
continue;
}

const serializedLayer = serializedLayers[layerID];
const geojsonFeature = new GeoJSONFeature(feature, this.z, this.x, this.y, id);
(geojsonFeature: any).layer = styleLayer.serialize();
(geojsonFeature: any).layer = serializedLayer;
let layerResult = result[layerID];
if (layerResult === undefined) {
layerResult = result[layerID] = [];
}
layerResult.push({featureIndex, feature: geojsonFeature, intersectionZ});
layerResult.push({featureIndex, feature: geojsonFeature, vtFeature: feature, intersectionZ});
}
}

// Given a set of symbol indexes that have already been looked up,
// return a matching set of GeoJSONFeatures
lookupSymbolFeatures(symbolFeatureIndexes: Array<number>,
serializedLayers: {[string]: Object},
bucketIndex: number,
sourceLayerIndex: number,
filterSpec: FilterSpecification,
Expand All @@ -233,7 +237,8 @@ class FeatureIndex {
symbolFeatureIndex,
filter,
filterLayerIDs,
styleLayers
styleLayers,
serializedLayers
);

}
Expand Down
4 changes: 4 additions & 0 deletions src/source/query_features.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function queryIncludes3DLayer(layers?: Array<string>, styleLayers: {[string]: St

export function queryRenderedFeatures(sourceCache: SourceCache,
styleLayers: {[string]: StyleLayer},
serializedLayers: {[string]: Object},
queryGeometry: Array<Point>,
params: { filter: FilterSpecification, layers: Array<string> },
transform: Transform) {
Expand All @@ -57,6 +58,7 @@ export function queryRenderedFeatures(sourceCache: SourceCache,
wrappedTileID: tileIn.tileID.wrapped().key,
queryResults: tileIn.tile.queryRenderedFeatures(
styleLayers,
serializedLayers,
sourceCache._state,
tileIn.queryGeometry,
tileIn.cameraQueryGeometry,
Expand Down Expand Up @@ -86,6 +88,7 @@ export function queryRenderedFeatures(sourceCache: SourceCache,
}

export function queryRenderedSymbols(styleLayers: {[string]: StyleLayer},
serializedLayers: {[string]: Object},
sourceCaches: {[string]: SourceCache},
queryGeometry: Array<Point>,
params: { filter: FilterSpecification, layers: Array<string> },
Expand All @@ -102,6 +105,7 @@ export function queryRenderedSymbols(styleLayers: {[string]: StyleLayer},
for (const queryData of bucketQueryData) {
const bucketSymbols = queryData.featureIndex.lookupSymbolFeatures(
renderedSymbols[queryData.bucketInstanceId],
serializedLayers,
queryData.bucketIndex,
queryData.sourceLayerIndex,
params.filter,
Expand Down
3 changes: 2 additions & 1 deletion src/source/tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ class Tile {
// Queries non-symbol features rendered for this tile.
// Symbol features are queried globally
queryRenderedFeatures(layers: {[string]: StyleLayer},
serializedLayers: {[string]: Object},
sourceFeatureState: SourceFeatureState,
queryGeometry: Array<Point>,
cameraQueryGeometry: Array<Point>,
Expand All @@ -285,7 +286,7 @@ class Tile {
transform,
params,
queryPadding: this.queryPadding * maxPitchScaleFactor
}, layers, sourceFeatureState);
}, layers, serializedLayers, sourceFeatureState);
}

querySourceFeatures(result: Array<GeoJSONFeature>, params: any) {
Expand Down
55 changes: 47 additions & 8 deletions src/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import PauseablePlacement from './pauseable_placement';
import ZoomHistory from './zoom_history';
import CrossTileSymbolIndex from '../symbol/cross_tile_symbol_index';
import {validateCustomStyleLayer} from './style_layer/custom_style_layer';
import {PossiblyEvaluated} from './properties';

// We're skipping validation errors with the `source.canvas` identifier in order
// to continue to allow canvas sources to be added at runtime/updated in
Expand Down Expand Up @@ -1055,6 +1056,38 @@ class Style extends Evented {
return features;
}

evaluateQueryResults(queryResults, featureState) {
const availableImages = this.imageManager.listImages();
if (Object.keys(queryResults).length) {
for (const layerName in queryResults) {
const layer = this._layers[layerName];
const layoutValues = layer.layout._values;
const paintValues = layer.paint._values;

queryResults[layerName].forEach(result => {
if (layoutValues) {
const evaluatedLayout = {};
Object.getOwnPropertyNames(layoutValues).forEach(property => {
const possiblyEvaluatedProperty = layoutValues[property];
evaluatedLayout[property] = possiblyEvaluatedProperty && possiblyEvaluatedProperty.evaluate ? possiblyEvaluatedProperty.evaluate(result.vtFeature, featureState, availableImages) : possiblyEvaluatedProperty;
});
result.feature.layer.layout = evaluatedLayout;
}

if (paintValues) {
const evaluatedPaint = {};
Object.getOwnPropertyNames(paintValues).forEach(property => {
const possiblyEvaluatedProperty = paintValues[property]
evaluatedPaint[property] = possiblyEvaluatedProperty && possiblyEvaluatedProperty.evaluate ? possiblyEvaluatedProperty.evaluate(result.vtFeature, featureState, availableImages) : possiblyEvaluatedProperty;
});
result.feature.layer.paint = evaluatedPaint;
}
});
}
}
return queryResults;
}

queryRenderedFeatures(queryGeometry: any, params: any, transform: Transform) {
if (params && params.filter) {
this._validate(validateStyle.filter, 'queryRenderedFeatures.filter', params.filter, null, params);
Expand All @@ -1078,17 +1111,22 @@ class Style extends Evented {
}

const sourceResults = [];
const serializedLayers = {};
for (const layer in this._layers) {
serializedLayers[layer] = this._layers[layer].serialize();
}

for (const id in this.sourceCaches) {
if (params.layers && !includedSources[id]) continue;
sourceResults.push(
queryRenderedFeatures(
this.sourceCaches[id],
this._layers,
queryGeometry,
params,
transform)
);
let queryResults = queryRenderedFeatures(
this.sourceCaches[id],
this._layers,
serializedLayers,
queryGeometry,
params,
transform);
queryResults = this.evaluateQueryResults(queryResults, this.sourceCaches[id]._state);
sourceResults.push(queryResults);
}

if (this.placement) {
Expand All @@ -1097,6 +1135,7 @@ class Style extends Evented {
sourceResults.push(
queryRenderedSymbols(
this._layers,
serializedLayers,
this.sourceCaches,
queryGeometry,
params,
Expand Down

0 comments on commit e16da16

Please sign in to comment.