Skip to content

Commit 2793a9d

Browse files
zmiaokarimnaaji
authored andcommitted
Fix using within expression with complex filter (#9611)
* Fix within usage with othere expressions in the same filter * Add render tests * Fix filter operator checking for nested condition
1 parent 8de5d36 commit 2793a9d

File tree

5 files changed

+124
-3
lines changed

5 files changed

+124
-3
lines changed

src/style-spec/feature_filter/index.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function createFilter(filter: any): FeatureFilter {
8585
if (compiled.result === 'error') {
8686
throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
8787
} else {
88-
const needGeometry = Array.isArray(filter) && filter.length !== 0 && filter[0] === 'within';
88+
const needGeometry = geometryNeeded(filter);
8989
return {filter: (globalProperties: GlobalProperties, feature: Feature, canonical?: CanonicalTileID) => compiled.value.evaluate(globalProperties, feature, {}, canonical),
9090
needGeometry};
9191
}
@@ -96,6 +96,15 @@ function compare(a, b) {
9696
return a < b ? -1 : a > b ? 1 : 0;
9797
}
9898

99+
function geometryNeeded(filter) {
100+
if (!Array.isArray(filter)) return false;
101+
if (filter[0] === 'within') return true;
102+
for (let index = 1; index < filter.length; index++) {
103+
if (geometryNeeded(filter[index])) return true;
104+
}
105+
return false;
106+
}
107+
99108
function convertFilter(filter: ?Array<any>): mixed {
100109
if (!filter) return true;
101110
const op = filter[0];
@@ -114,6 +123,7 @@ function convertFilter(filter: ?Array<any>): mixed {
114123
op === '!in' ? convertNegation(convertInOp(filter[1], filter.slice(2))) :
115124
op === 'has' ? convertHasOp(filter[1]) :
116125
op === '!has' ? convertNegation(convertHasOp(filter[1])) :
126+
op === 'within' ? filter :
117127
true;
118128
return converted;
119129
}

src/style-spec/reference/v8.json

+3
Original file line numberDiff line numberDiff line change
@@ -2450,6 +2450,9 @@
24502450
},
24512451
"!has": {
24522452
"doc": "`[\"!has\", key]` `feature[key]` does not exist"
2453+
},
2454+
"within": {
2455+
"doc": "`[\"within\", object]` feature geometry is within object geometry"
24532456
}
24542457
},
24552458
"doc": "The filter operator."

src/style-spec/validate/validate_filter.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,14 @@ function validateNonExpressionFilter(options) {
104104
errors.push(new ValidationError(`${key}[1]`, value[1], `string expected, ${type} found`));
105105
}
106106
break;
107-
107+
case 'within':
108+
type = getType(value[1]);
109+
if (value.length !== 2) {
110+
errors.push(new ValidationError(key, value, `filter array for "${value[0]}" operator must have 2 elements`));
111+
} else if (type !== 'object') {
112+
errors.push(new ValidationError(`${key}[1]`, value[1], `object expected, ${type} found`));
113+
}
114+
break;
108115
}
109-
110116
return errors;
111117
}
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
{
2+
"version": 8,
3+
"metadata": {
4+
"test": {
5+
"width": 64,
6+
"height": 64
7+
}
8+
},
9+
"zoom": 3,
10+
"center": [2.5, 2.5],
11+
"sources": {
12+
"points": {
13+
"type": "geojson",
14+
"data": {
15+
"type": "FeatureCollection",
16+
"features": [
17+
{
18+
"type": "Feature",
19+
"properties": {
20+
"number": [5]
21+
},
22+
"geometry": {
23+
"type": "Point",
24+
"coordinates": [
25+
1.9775390625,
26+
2.3284603685731593
27+
]
28+
}
29+
},
30+
{
31+
"type": "Feature",
32+
"properties": {
33+
"number": [5]
34+
},
35+
"geometry": {
36+
"type": "Point",
37+
"coordinates": [
38+
1.7138671875,
39+
-1.7136116598836224
40+
]
41+
}
42+
}
43+
]
44+
}
45+
},
46+
"polygon": {
47+
"type": "geojson",
48+
"data": {
49+
"type": "FeatureCollection",
50+
"features": [
51+
{
52+
"type": "Feature",
53+
"properties": {},
54+
"geometry": {
55+
"type": "Polygon",
56+
"coordinates": [
57+
[[0, 0],
58+
[0, 5],
59+
[5, 5],
60+
[5, 0],
61+
[0, 0]]
62+
]
63+
}
64+
}
65+
]
66+
}
67+
}
68+
},
69+
"layers": [
70+
{
71+
"id": "border",
72+
"type": "fill",
73+
"source": "polygon",
74+
"paint": {
75+
"fill-color": "black",
76+
"fill-opacity": 0.5
77+
}
78+
},
79+
{
80+
"id": "circle",
81+
"type": "circle",
82+
"source": "points",
83+
"filter": ["all", ["in", 5, ["get", "number"]], ["==", ["within", {
84+
"type": "Polygon",
85+
"coordinates": [
86+
[
87+
[0, 0],
88+
[0, 5],
89+
[5, 5],
90+
[5, 0],
91+
[0, 0]
92+
]
93+
]
94+
}], true]
95+
],
96+
"paint": {
97+
"circle-radius": 5,
98+
"circle-color": "red"
99+
}
100+
}
101+
]
102+
}

0 commit comments

Comments
 (0)