Skip to content

Commit

Permalink
update unit tests, fix point within polygon
Browse files Browse the repository at this point in the history
  • Loading branch information
zmiao committed Feb 28, 2020
1 parent e9fc60a commit 5bc9c76
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 82 deletions.
2 changes: 1 addition & 1 deletion src/data/feature_index.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ class FeatureIndex {

const sourceLayerName = this.sourceLayerCoder.decode(sourceLayerIndex);
const sourceLayer = this.vtLayers[sourceLayerName];

const feature = sourceLayer.feature(featureIndex);

if (!filter.filter(new EvaluationParameters(this.tileID.overscaledZ), feature))
return;

Expand Down
18 changes: 14 additions & 4 deletions src/style-spec/expression/definitions/within.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ function getLngLatPoints(line, canonical) {
return coords;
}

function onBoundary(p, p1, p2) {
const x1 = p[0] - p1[0];
const y1 = p[1] - p1[1];
const x2 = p[0] - p2[0];
const y2 = p[1] - p2[1];
return (x1 * y2 - x2 * y1 === 0) && (x1 * x2 <= 0) && (y1 * y2 <= 0);
}

function rayIntersect(p, p1, p2) {
return ((p1[1] > p[1]) !== (p2[1] > p[1])) && (p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0]);
}
Expand All @@ -80,8 +88,9 @@ function pointWithinPolygon(point, rings) {
let inside = false;
for (let i = 0, len = rings.length; i < len; i++) {
const ring = rings[i];
for (let j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) {
if (rayIntersect(point, ring[j], ring[k])) inside = !inside;
for (let j = 0, len2 = ring.length; j < len2 - 1; j++) {
if (onBoundary(point, ring[j], ring[j + 1])) return false;
if (rayIntersect(point, ring[j], ring[j + 1])) inside = !inside;
}
}
return inside;
Expand Down Expand Up @@ -173,8 +182,9 @@ function pointsWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPo
const lngLatPoints = [];
for (const points of ctx.geometry()) {
for (const point of points) {
lngLatPoints.push(getLngLatPoint(point, ctx.canonicalID()));
updateBBox(pointBBox, point);
const p = getLngLatPoint(point, ctx.canonicalID());
lngLatPoints.push(p);
updateBBox(pointBBox, p);
}
}
if (!boxWithinBox(pointBBox, polyBBox)) return false;
Expand Down
3 changes: 1 addition & 2 deletions src/style-spec/feature_filter/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ export default function convertFilter(filter: FilterSpecification): mixed {
* produce a `false` result.
*/
function _convertFilter(filter: FilterSpecification, expectedTypes: ExpectedTypes): mixed {
const needGeo = false;
if (isExpressionFilter(filter, needGeo)) { return filter; }
if (isExpressionFilter(filter)) { return filter; }

if (!filter) return true;
const op = filter[0];
Expand Down
27 changes: 17 additions & 10 deletions src/style-spec/feature_filter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import type {GlobalProperties, Feature} from '../expression';
import type {CanonicalTileID} from '../../source/tile_id';

type FilterExpression = (globalProperties: GlobalProperties, feature: Feature, canonical?: CanonicalTileID) => boolean;
export type FeatureFilter ={filter: FilterExpression,
needGeometry: boolean};
export type FeatureFilter ={filter: FilterExpression, needGeometry: boolean};

export default createFilter;
export {isExpressionFilter};

function isExpressionFilter(filter: any, needGeometry: boolean) {
function isExpressionFilter(filter: any) {
if (filter === true || filter === false) {
return true;
}
Expand Down Expand Up @@ -41,14 +40,12 @@ function isExpressionFilter(filter: any, needGeometry: boolean) {
case 'any':
case 'all':
for (const f of filter.slice(1)) {
if (!isExpressionFilter(f, needGeometry) && typeof f !== 'boolean') {
if (!isExpressionFilter(f) && typeof f !== 'boolean') {
return false;
}
}
return true;
case 'within':
needGeometry = true;
return true;

default:
return true;
}
Expand Down Expand Up @@ -79,18 +76,28 @@ function createFilter(filter: any): FeatureFilter {
return {filter: () => true, needGeometry: false};
}

const withinExpr = false;
if (!isExpressionFilter(filter, withinExpr)) {
if (!isExpressionFilter(filter)) {
filter = convertFilter(filter);
}

const compiled = createExpression(filter, filterSpec);
if (compiled.result === 'error') {
throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
} else {
const needGeometry = filterNeedGeometry(filter);
return {filter: (globalProperties: GlobalProperties, feature: Feature, canonical?: CanonicalTileID) => compiled.value.evaluate(globalProperties, feature, {}, canonical),
needGeometry: withinExpr};
needGeometry};
}
}

function filterNeedGeometry(filter) {
if (filter === true || filter === false) {
return false;
}
if (!Array.isArray(filter) || filter.length === 0) {
return false;
}
return filter[0] === 'within';
}

// Comparison function to sort numbers and strings
Expand Down
2 changes: 1 addition & 1 deletion src/style/properties.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// @flow

import assert from 'assert';
import type {CanonicalTileID} from '../source/tile_id';
import {clone, extend, easeCubicInOut} from '../util/util';
import * as interpolate from '../style-spec/util/interpolate';
import {normalizePropertyExpression} from '../style-spec/expression';
import Color from '../style-spec/util/color';
import {register} from '../util/web_worker_transfer';
import EvaluationParameters from './evaluation_parameters';

import type {CanonicalTileID} from '../source/tile_id';
import type {StylePropertySpecification} from '../style-spec/style-spec';
import type {
TransitionSpecification,
Expand Down
1 change: 1 addition & 0 deletions src/style/style_layer/fill_extrusion_style_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class FillExtrusionStyleLayer extends StyleLayer {
this.paint.get('fill-extrusion-translate'),
this.paint.get('fill-extrusion-translate-anchor'),
transform.angle, pixelsToTileUnits);

const height = this.paint.get('fill-extrusion-height').evaluate(feature, featureState);
const base = this.paint.get('fill-extrusion-base').evaluate(feature, featureState);

Expand Down
Loading

0 comments on commit 5bc9c76

Please sign in to comment.