UNPKG

s2maps-gpu

Version:

S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.

110 lines (109 loc) 4.16 kB
import coalesceField from './coalesceField.js'; /** * Parse a filter into a filter function * @param filter - input user defined filter * @returns a filter function that represents the user defined filter */ export default function parseFilter(filter) { if (filter === undefined) return () => true; // case 1: AND if ('and' in filter) { const { and } = filter; const filterLambdas = and.map(parseFilter); return (properties = {}) => { for (const filterLambda of filterLambdas) { if (!filterLambda(properties)) return false; } return true; }; } else if ('or' in filter) { // case 2: OR const { or } = filter; const filterLambdas = or.map(parseFilter); return (properties = {}) => { for (const filterLambda of filterLambdas) { if (filterLambda(properties)) return true; } return false; }; } else { // case 3: Condition const { key, comparator, value } = filter; const filterLambda = parseFilterCondition(comparator, value); return (properties = {}) => { return filterLambda(coalesceField(key, properties, true), properties); }; } } /** * Parse a filter condition * Note: We disable the eslint rule here because we want to allow the use of * `==` and `!=` instead of `===` and `!==` because we want to allow * comparasons between strings and numbers. * @param comparator - comparator operator * @param value - input value * @returns Condition function result */ function parseFilterCondition(comparator, value) { // manage multiple comparators if (comparator === '==') return (input, properties) => // eslint-disable-next-line eqeqeq input == buildValue(value, properties); // ['class', '==', 'ocean'] OR ['elev', '==', 50] else if (comparator === '!=') return (input, properties) => // eslint-disable-next-line eqeqeq input != buildValue(value, properties); // ['class', '!=', 'ocean'] OR ['elev', '!=', 50] else if (comparator === '>') return (input, properties) => input > buildValue(value, properties); // ['elev', '>', 50] else if (comparator === '>=') return (input, properties) => input >= buildValue(value, properties); // ['elev', '>=', 50] else if (comparator === '<') return (input, properties) => input < buildValue(value, properties); // ['elev', '<', 50] else if (comparator === '<=') return (input, properties) => input <= buildValue(value, properties); // ['elev', '<=', 50] else if (comparator === 'has') return (input, properties) => Array.isArray(value) || typeof value === 'string' ? buildValue(value, properties).includes(input) : false; // ['class', 'has', ['ocean', 'river']] OR ['elev', 'in', [2, 3, 4, 5]] else if (comparator === '!has') return (input, properties) => Array.isArray(value) || typeof value === 'string' ? !buildValue(value, properties).includes(input) : true; // ['class', '!has', ['ocean', 'river']] OR ['elev', '!in', [2, 3, 4, 5]] else if (comparator === 'in') return (input) => Array.isArray(input) && typeof value === typeof input[0] ? input.includes(value) : false; // ['elev', 'in', 50] else if (comparator === '!in') return (input) => Array.isArray(input) && typeof value === typeof input[0] ? !input.includes(value) : true; // ['class', '!in', 'ocean'] OR ['elev', '!in', 50] else return () => false; } /** * Build a value from a string or an array of strings * @param value - input value * @param properties - properties to coalesce * @returns the built value */ function buildValue(value, properties = {}) { if (typeof value === 'string' || (Array.isArray(value) && typeof value[0] === 'string')) return coalesceField(value, properties); return value; }