From 02c9bcf89d37cce3113208e870c290aaed8078a5 Mon Sep 17 00:00:00 2001 From: elenatorro Date: Thu, 23 May 2019 15:39:36 +0200 Subject: [PATCH 1/9] First PoC to improve getLegendData with several operators --- debug/advanced/bivariate-legends.html | 109 ++++++++++++++++++ src/renderer/viz/expressions.js | 3 +- src/renderer/viz/expressions/Ramp.js | 1 + src/renderer/viz/expressions/basic/List.js | 5 + src/renderer/viz/expressions/binary.js | 26 ++++- .../viz/expressions/binary/BinaryOperation.js | 85 ++++++++++++++ src/renderer/viz/expressions/binary/Mul.js | 69 +++++++++++ .../expressions/classification/Classifier.js | 2 +- .../classification/ClassifierGLSLHelper.js | 4 +- 9 files changed, 299 insertions(+), 5 deletions(-) create mode 100644 debug/advanced/bivariate-legends.html create mode 100644 src/renderer/viz/expressions/binary/BinaryOperation.js create mode 100644 src/renderer/viz/expressions/binary/Mul.js diff --git a/debug/advanced/bivariate-legends.html b/debug/advanced/bivariate-legends.html new file mode 100644 index 000000000..aece012bb --- /dev/null +++ b/debug/advanced/bivariate-legends.html @@ -0,0 +1,109 @@ + + + + + + + + + + + +
+ +
+
+ + + +
+
+ + + + + diff --git a/src/renderer/viz/expressions.js b/src/renderer/viz/expressions.js index ff672880d..4962af5d1 100644 --- a/src/renderer/viz/expressions.js +++ b/src/renderer/viz/expressions.js @@ -451,7 +451,8 @@ import { Nin } from './expressions/belongs'; import Between from './expressions/between'; -import { Mul } from './expressions/binary'; +// import { Mul } from './expressions/binary'; +import { Mul } from './expressions/binary/Mul'; import { Div } from './expressions/binary'; import { Add } from './expressions/binary'; import { Sub } from './expressions/binary'; diff --git a/src/renderer/viz/expressions/Ramp.js b/src/renderer/viz/expressions/Ramp.js index ce7142c3c..2e6f37d75 100644 --- a/src/renderer/viz/expressions/Ramp.js +++ b/src/renderer/viz/expressions/Ramp.js @@ -129,6 +129,7 @@ export default class Ramp extends BaseExpression { super({ input, palette }); this.palette = palette; this.others = others; + this.type = palette.type; this._defaultOthers = others === DEFAULT_RAMP_OTHERS; } diff --git a/src/renderer/viz/expressions/basic/List.js b/src/renderer/viz/expressions/basic/List.js index e08fd9930..927f23f0e 100644 --- a/src/renderer/viz/expressions/basic/List.js +++ b/src/renderer/viz/expressions/basic/List.js @@ -63,6 +63,7 @@ export default class List extends Base { super(elems); this.elems = elems; + this.type = elems[0].type; } get value () { @@ -73,6 +74,10 @@ export default class List extends Base { return this.elems.map(elem => elem.eval(feature)); } + inlineMaker () { + return f => 'hellow'; + } + _bindMetadata (metadata) { super._bindMetadata(metadata); this._setTypes(); diff --git a/src/renderer/viz/expressions/binary.js b/src/renderer/viz/expressions/binary.js index 084f950ed..e115c7502 100644 --- a/src/renderer/viz/expressions/binary.js +++ b/src/renderer/viz/expressions/binary.js @@ -40,6 +40,26 @@ export const Mul = genBinaryOp('mul', (x, y) => `(${x} * ${y})` ); +Mul.prototype.eval = function (featureA, featureB) { + const valueA = this.a.eval(featureA); + const valueB = this.b.eval(featureB); + + if (this.a.type === 'color' && this.b.type === 'color') { + return _evalColors(valueA, valueB); + } + + return valueA * valueB; +}; + +function _evalColors (colorA, colorB) { + return { + r: colorA.r * colorB.r / 255, + g: colorA.g * colorB.g / 255, + b: colorA.b * colorB.b / 255, + a: colorA.a * colorB.a + }; +} + /** * Divide two numeric expressions. * @@ -464,8 +484,10 @@ function genBinaryOp (name, allowedSignature, jsFn, glsl) { return jsFn(this.a.value, this.b.value); } - eval (feature) { - return jsFn(this.a.eval(feature), this.b.eval(feature)); + eval (featureA, featureB) { + const valueA = this.a.eval(featureA); + const valueB = this.b.eval(featureB); + return jsFn(valueA, valueB); } _bindMetadata (meta) { diff --git a/src/renderer/viz/expressions/binary/BinaryOperation.js b/src/renderer/viz/expressions/binary/BinaryOperation.js new file mode 100644 index 000000000..3d0956786 --- /dev/null +++ b/src/renderer/viz/expressions/binary/BinaryOperation.js @@ -0,0 +1,85 @@ +import BaseExpression from '../base'; + +import CartoValidationError, { CartoValidationErrorTypes } from '../../../../errors/carto-validation-error'; + +export const UNSUPPORTED_SIGNATURE = 0; +export const NUMBERS_TO_NUMBER = 1; +export const NUMBER_AND_COLOR_TO_COLOR = 2; +export const COLORS_TO_COLOR = 4; +export const CATEGORIES_TO_NUMBER = 8; +export const IMAGES_TO_IMAGE = 16; + +export class BinaryOperation extends BaseExpression { + constructor (a, b, allowedSignature) { + super({ a, b }); + this._allowedSignature = allowedSignature; + } + + _resolveAliases () { + } + + _getMinimumNeededSchema () { + return {}; + } + + loadImages () {} + + _getDependencies () { + return [ this.a, this.b ]; + } + + _bindMetadata (metadata) { + // super._bindMetadata(metadata); + const [a, b] = [this.a, this.b]; + + const signature = getSignature(a, b); + if (signature === UNSUPPORTED_SIGNATURE || !(signature && this._allowedSignature)) { + throw new CartoValidationError( + `${this.expressionName}(): invalid parameter types\n'a' type was ${a.type}, 'b' type was ${b.type}`, + CartoValidationErrorTypes.INCORRECT_TYPE + ); + } + + this.type = getReturnTypeFromSignature(signature); + } +} + +function getSignature (a, b) { + if (!a.type || !b.type) { + return undefined; + } else if (a.type === 'number' && b.type === 'number') { + return NUMBERS_TO_NUMBER; + } else if (a.type === 'number' && b.type === 'color') { + return NUMBER_AND_COLOR_TO_COLOR; + } else if (a.type === 'color' && b.type === 'number') { + return NUMBER_AND_COLOR_TO_COLOR; + } else if (a.type === 'color' && b.type === 'color') { + return COLORS_TO_COLOR; + } else if (a.type === 'category' && b.type === 'category') { + return CATEGORIES_TO_NUMBER; + } else if ((a.type === 'image' && b.type === 'color') || + (a.type === 'image' && b.type === 'color') || + (a.type === 'image' && b.type === 'image') || + (a.type === 'color' && b.type === 'image')) { + return IMAGES_TO_IMAGE; + } else { + return UNSUPPORTED_SIGNATURE; + } +} + +function getReturnTypeFromSignature (signature) { + switch (signature) { + case NUMBERS_TO_NUMBER: + return 'number'; + case NUMBER_AND_COLOR_TO_COLOR: + return 'color'; + case COLORS_TO_COLOR: + return 'color'; + case CATEGORIES_TO_NUMBER: + return 'number'; + case IMAGES_TO_IMAGE: + return 'image'; + default: + return undefined; + } +} diff --git a/src/renderer/viz/expressions/binary/Mul.js b/src/renderer/viz/expressions/binary/Mul.js new file mode 100644 index 000000000..14f99dd97 --- /dev/null +++ b/src/renderer/viz/expressions/binary/Mul.js @@ -0,0 +1,69 @@ +import { number } from '../../expressions'; +import { + BinaryOperation, + NUMBERS_TO_NUMBER, + NUMBER_AND_COLOR_TO_COLOR, + COLORS_TO_COLOR, + IMAGES_TO_IMAGE +} from './BinaryOperation'; + +import { implicitCast, checkMaxArguments } from '../utils'; + +export class Mul extends BinaryOperation { + constructor (a, b) { + checkMaxArguments(arguments, 2); + + if (Number.isFinite(a) && Number.isFinite(b)) { + return number(a * b); + } + + const allowedSignature = NUMBERS_TO_NUMBER | + NUMBER_AND_COLOR_TO_COLOR | + COLORS_TO_COLOR | + IMAGES_TO_IMAGE; + + a = implicitCast(a); + b = implicitCast(b); + + super(a, b, allowedSignature); + this.expressionName = 'mul'; + } + + eval (featureA, featureB) { + const valueA = this.a.eval(featureA); + const valueB = this.b.eval(featureB); + + if (this.a.type === 'color' && this.b.type === 'color') { + return this._evalColors(valueA, valueB); + } + + return valueA * valueB; + } + + getLegendData (options) { + const legendDataA = this.a.getLegendData(options); + const legendDataB = this.b.getLegendData(options); + + return { a: legendDataA, b: legendDataB }; + } + + _evalColors (colorA, colorB) { + return { + r: colorA.r * colorB.r / 255, + g: colorA.g * colorB.g / 255, + b: colorA.b * colorB.b / 255, + a: colorA.a * colorB.a + }; + } + + _setGenericGLSL (inlineMaker, preface) { + this.inlineMaker = inlineMaker; + this.preface = (preface || ''); + } + + _bindMetadata (meta) { + super._bindMetadata(meta); + + this.inlineMaker = inline => `(${inline.a} * ${inline.b})`; + } +} diff --git a/src/renderer/viz/expressions/classification/Classifier.js b/src/renderer/viz/expressions/classification/Classifier.js index 8a77fb5b0..3571fdd3d 100644 --- a/src/renderer/viz/expressions/classification/Classifier.js +++ b/src/renderer/viz/expressions/classification/Classifier.js @@ -100,7 +100,7 @@ export default class Classifier extends BaseExpression { _genBreakpoints () { } _applyToShaderSource (getGLSLforProperty) { - return this._GLSLhelper.applyToShaderSource(getGLSLforProperty); + return this._GLSLhelper ? this._GLSLhelper.applyToShaderSource(getGLSLforProperty) : null; } _preDraw (program, drawMetadata, gl) { diff --git a/src/renderer/viz/expressions/classification/ClassifierGLSLHelper.js b/src/renderer/viz/expressions/classification/ClassifierGLSLHelper.js index 39bc32ae0..759531f4b 100644 --- a/src/renderer/viz/expressions/classification/ClassifierGLSLHelper.js +++ b/src/renderer/viz/expressions/classification/ClassifierGLSLHelper.js @@ -18,7 +18,9 @@ export default class ClassifierGLSLHelper { `${index > 0 ? 'else' : ''} if (x<(${childInlines[`arg${index}`]})){ return ${(index / divisor).toFixed(20)}; }`; - const funcBody = this.classifier.breakpoints.map(elif).join(''); + const funcBody = this.classifier.breakpoints + ? this.classifier.breakpoints.map(elif).join('') + : ''; const preface = `float ${funcName}(float x){ ${funcBody} From 3c3f84b138a8381a708a7e849177e426c7a77e81 Mon Sep 17 00:00:00 2001 From: elenatorro Date: Fri, 21 Jun 2019 16:48:02 +0200 Subject: [PATCH 2/9] PoC bivariate legends --- src/renderer/viz/expressions.js | 4 +- src/renderer/viz/expressions/basic/List.js | 4 - src/renderer/viz/expressions/binary.js | 65 +++- src/renderer/viz/expressions/binary/Mul.js | 19 +- .../renderer/viz/expressions/binary.test.js | 305 +++++++++++------- 5 files changed, 257 insertions(+), 140 deletions(-) diff --git a/src/renderer/viz/expressions.js b/src/renderer/viz/expressions.js index 4962af5d1..c7799d513 100644 --- a/src/renderer/viz/expressions.js +++ b/src/renderer/viz/expressions.js @@ -451,8 +451,8 @@ import { Nin } from './expressions/belongs'; import Between from './expressions/between'; -// import { Mul } from './expressions/binary'; -import { Mul } from './expressions/binary/Mul'; +import { Mul } from './expressions/binary'; +// import { Mul } from './expressions/binary/Mul'; import { Div } from './expressions/binary'; import { Add } from './expressions/binary'; import { Sub } from './expressions/binary'; diff --git a/src/renderer/viz/expressions/basic/List.js b/src/renderer/viz/expressions/basic/List.js index 927f23f0e..9ba0d44e3 100644 --- a/src/renderer/viz/expressions/basic/List.js +++ b/src/renderer/viz/expressions/basic/List.js @@ -74,10 +74,6 @@ export default class List extends Base { return this.elems.map(elem => elem.eval(feature)); } - inlineMaker () { - return f => 'hellow'; - } - _bindMetadata (metadata) { super._bindMetadata(metadata); this._setTypes(); diff --git a/src/renderer/viz/expressions/binary.js b/src/renderer/viz/expressions/binary.js index e115c7502..bb1691793 100644 --- a/src/renderer/viz/expressions/binary.js +++ b/src/renderer/viz/expressions/binary.js @@ -1,5 +1,5 @@ import { number } from '../expressions'; -import { implicitCast, checkMaxArguments } from './utils'; +import { implicitCast, checkMaxArguments, mix } from './utils'; import BaseExpression from './base'; import CartoValidationError, { CartoValidationErrorTypes } from '../../../errors/carto-validation-error'; @@ -40,25 +40,40 @@ export const Mul = genBinaryOp('mul', (x, y) => `(${x} * ${y})` ); -Mul.prototype.eval = function (featureA, featureB) { +Mul.prototype.eval = function (features) { + const featureA = features[0]; + const featureB = features[1]; + const valueA = this.a.eval(featureA); const valueB = this.b.eval(featureB); - if (this.a.type === 'color' && this.b.type === 'color') { - return _evalColors(valueA, valueB); + switch (this._signature) { + case NUMBERS_TO_NUMBER: + return valueA * valueB; + case NUMBER_AND_COLOR_TO_COLOR: + return mix(valueA, valueB); + case COLORS_TO_COLOR: + return multiplyColors(valueA, valueB); + default: + return valueA * valueB; } - - return valueA * valueB; }; -function _evalColors (colorA, colorB) { - return { - r: colorA.r * colorB.r / 255, - g: colorA.g * colorB.g / 255, - b: colorA.b * colorB.b / 255, - a: colorA.a * colorB.a - }; -} +Mul.prototype.getLegendData = function (options) { + const legendDataA = this.a.getLegendData(options); + const legendDataB = this.b.getLegendData(options); + const SIZE = legendDataA.data.length; + const data = []; + + for (let i = 0; i < SIZE; i++) { + for (let j = 0; j < SIZE; j++) { + const value = multiplyColors(legendDataA.data[i].value, legendDataB.data[j].value); + data.push({ value }); + } + } + + return { data }; +}; /** * Divide two numeric expressions. @@ -490,18 +505,25 @@ function genBinaryOp (name, allowedSignature, jsFn, glsl) { return jsFn(valueA, valueB); } + getLegendData (options) { + const legendDataA = this.a.getLegendData(options); + const legendDataB = this.b.getLegendData(options); + + return { a: legendDataA, b: legendDataB }; + } + _bindMetadata (meta) { super._bindMetadata(meta); const [a, b] = [this.a, this.b]; - const signature = getSignature(a, b); - if (signature === UNSUPPORTED_SIGNATURE || !(signature & allowedSignature)) { + this._signature = getSignature(a, b); + if (this._signature === UNSUPPORTED_SIGNATURE || !(this._signature & allowedSignature)) { throw new CartoValidationError( `${name}(): invalid parameter types\n'x' type was ${a.type}, 'y' type was ${b.type}`, CartoValidationErrorTypes.INCORRECT_TYPE ); } - this.type = getReturnTypeFromSignature(signature); + this.type = getReturnTypeFromSignature(this._signature); } }; } @@ -545,3 +567,12 @@ function getReturnTypeFromSignature (signature) { return undefined; } } + +function multiplyColors (colorA, colorB) { + return { + r: Math.round(colorA.r * colorB.r / 255), + g: Math.round(colorA.g * colorB.g / 255), + b: Math.round(colorA.b * colorB.b / 255), + a: colorA.a + }; +} diff --git a/src/renderer/viz/expressions/binary/Mul.js b/src/renderer/viz/expressions/binary/Mul.js index 14f99dd97..36d52897c 100644 --- a/src/renderer/viz/expressions/binary/Mul.js +++ b/src/renderer/viz/expressions/binary/Mul.js @@ -43,16 +43,25 @@ export class Mul extends BinaryOperation { getLegendData (options) { const legendDataA = this.a.getLegendData(options); const legendDataB = this.b.getLegendData(options); + const SIZE = legendDataA.data.length; + const data = []; - return { a: legendDataA, b: legendDataB }; + for (let i = 0; i < SIZE; i++) { + for (let j = 0; j < SIZE; j++) { + const value = this._evalColors(legendDataA.data[i].value, legendDataB.data[j].value); + data.push({ value }); + } + } + + return { data }; } _evalColors (colorA, colorB) { return { - r: colorA.r * colorB.r / 255, - g: colorA.g * colorB.g / 255, - b: colorA.b * colorB.b / 255, - a: colorA.a * colorB.a + r: Math.round(colorA.r * colorB.r / 255), + g: Math.round(colorA.g * colorB.g / 255), + b: Math.round(colorA.b * colorB.b / 255), + a: colorA.a }; } diff --git a/test/unit/renderer/viz/expressions/binary.test.js b/test/unit/renderer/viz/expressions/binary.test.js index 229ddd850..4bb732fc7 100644 --- a/test/unit/renderer/viz/expressions/binary.test.js +++ b/test/unit/renderer/viz/expressions/binary.test.js @@ -75,134 +75,215 @@ describe('src/renderer/viz/expressions/binary', () => { }); }); - describe('eval', () => { - describe('and', () => { - test('and', s.TRUE, s.TRUE, 1); - test('and', s.TRUE, s.FALSE, 0); - test('and', s.FALSE, s.FALSE, 0); - test('and', 0.5, s.TRUE, 0.5); - test('and', 0.5, 0.5, 0.25); - }); + describe('.eval', () => { + describe('mul', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('mul', 0, 0, 0); + testValue('mul', 1, 0, 0); + testValue('mul', 1, 1, 1); + testValue('mul', 1, 2, 2); + testValue('mul', -1, 2, -2); + }); - describe('or', () => { - test('or', 0, 0, 0); - test('or', 0, 1, 1); - test('or', 1, 1, 1); - test('or', 0.5, 1, 1); - }); + describe('NUMBER_AND_COLOR_TO_COLOR', () => { - describe('mul', () => { - test('mul', 0, 0, 0); - test('mul', 1, 0, 0); - test('mul', 1, 1, 1); - test('mul', 1, 2, 2); - test('mul', -1, 2, -2); + }); + + describe('COLORS_TO_COLOR', () => { + + }); + + describe('IMAGES_TO_IMAGE', () => { + + }); }); describe('div', () => { - test('div', 1, 0, Infinity); - test('div', -1, 0, -Infinity); - test('div', 0, 0, NaN); - test('div', 0, 1, 0); - test('div', 4, 2, 2); - test('div', -4, 2, -2); + describe('NUMBERS_TO_NUMBER', () => { + testValue('div', 1, 0, Infinity); + testValue('div', -1, 0, -Infinity); + testValue('div', 0, 0, NaN); + testValue('div', 0, 1, 0); + testValue('div', 4, 2, 2); + testValue('div', -4, 2, -2); + }); + + describe('NUMBER_AND_COLOR_TO_COLOR', () => { + + }); + + describe('COLORS_TO_COLOR', () => { + + }); + + describe('IMAGES_TO_IMAGE', () => { + + }); }); describe('add', () => { - test('add', 0, 0, 0); - test('add', 0, 1, 1); - test('add', 2, 2, 4); - test('add', -2, 2, 0); - test('add', -2, -3, -5); + describe('NUMBERS_TO_NUMBER', () => { + testValue('add', 0, 0, 0); + testValue('add', 0, 1, 1); + testValue('add', 2, 2, 4); + testValue('add', -2, 2, 0); + testValue('add', -2, -3, -5); + }); + + describe('COLORS_TO_COLOR', () => { + + }); + + describe('IMAGES_TO_IMAGE', () => { + + }); }); describe('sub', () => { - test('sub', 0, 0, 0); - test('sub', 0, 1, -1); - test('sub', 2, 2, 0); - test('sub', -2, 2, -4); - test('sub', -2, -3, 1); + describe('NUMBERS_TO_NUMBER', () => { + testValue('sub', 0, 0, 0); + testValue('sub', 0, 1, -1); + testValue('sub', 2, 2, 0); + testValue('sub', -2, 2, -4); + testValue('sub', -2, -3, 1); + }); + + describe('COLORS_TO_COLOR', () => { + + }); + + describe('IMAGES_TO_IMAGE', () => { + + }); }); describe('mod', () => { - test('mod', 0, 1, 0); - test('mod', 2, 1, 0); - test('mod', 2, 2, 0); - test('mod', 6, 4, 2); - test('mod', -6, 4, -2); + describe('NUMBERS_TO_NUMBER', () => { + testValue('mod', 0, 1, 0); + testValue('mod', 2, 1, 0); + testValue('mod', 2, 2, 0); + testValue('mod', 6, 4, 2); + testValue('mod', -6, 4, -2); + }); }); describe('pow', () => { - test('pow', 0, 0, 1); - test('pow', 0, 1, 0); - test('pow', 2, 2, 4); - test('pow', -2, 2, 4); - test('pow', -2, -3, -0.125); - }); - - describe('gt', () => { - test('gt', 0, 0, 0); - test('gt', 0, 1, 0); - test('gt', 1, 0, 1); - test('gt', 2, 2, 0); - test('gt', 2, 3, 0); - test('gt', 3, 2, 1); - test('gt', -3, 2, 0); - }); - - describe('gte', () => { - test('gte', 0, 0, 1); - test('gte', 0, 1, 0); - test('gte', 1, 0, 1); - test('gte', 2, 2, 1); - test('gte', 2, 3, 0); - test('gte', 3, 2, 1); - test('gte', -3, 2, 0); - }); - - describe('lt', () => { - test('lt', 0, 0, 0); - test('lt', 0, 1, 1); - test('lt', 1, 0, 0); - test('lt', 2, 2, 0); - test('lt', 2, 3, 1); - test('lt', 3, 2, 0); - test('lt', -3, 2, 1); - }); - - describe('lte', () => { - test('lte', 0, 0, 1); - test('lte', 0, 1, 1); - test('lte', 1, 0, 0); - test('lte', 2, 2, 1); - test('lte', 2, 3, 1); - test('lte', 3, 2, 0); - test('lte', -3, 2, 1); - }); - - describe('eq', () => { - test('eq', 0, 0, 1); - test('eq', 0, 1, 0); - test('eq', 1, 0, 0); - test('eq', 2, 2, 1); - test('eq', 2, 3, 0); - }); - - describe('neq', () => { - test('neq', 0, 0, 0); - test('neq', 0, 1, 1); - test('neq', 1, 0, 1); - test('neq', 2, 2, 0); - test('neq', 2, 3, 1); - }); - - function test (fn, param1, param2, expected) { - it(`${fn}(${param1}, ${param2}) should return ${expected}`, () => { - let actual = s[fn](param1, param2).value; - expect(actual).toEqual(expected); - actual = s[fn](param1, param2).value; - expect(actual).toEqual(expected); - }); - } + describe('NUMBERS_TO_NUMBER', () => { + testValue('pow', 0, 0, 1); + testValue('pow', 0, 1, 0); + testValue('pow', 2, 2, 4); + testValue('pow', -2, 2, 4); + testValue('pow', -2, -3, -0.125); + }); + }); + + describe('or', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('or', 0, 0, 0); + testValue('or', 0, 1, 1); + testValue('or', 1, 1, 1); + testValue('or', 0.5, 1, 1); + }); + }); + + describe('and', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('and', s.TRUE, s.TRUE, 1); + testValue('and', s.TRUE, s.FALSE, 0); + testValue('and', s.FALSE, s.FALSE, 0); + testValue('and', 0.5, s.TRUE, 0.5); + testValue('and', 0.5, 0.5, 0.25); + }); + }); + + describe('greaterThan', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('gt', 0, 0, 0); + testValue('gt', 0, 1, 0); + testValue('gt', 1, 0, 1); + testValue('gt', 2, 2, 0); + testValue('gt', 2, 3, 0); + testValue('gt', 3, 2, 1); + testValue('gt', -3, 2, 0); + }); + }); + + describe('greaterThanOrEqualTo', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('gte', 0, 0, 1); + testValue('gte', 0, 1, 0); + testValue('gte', 1, 0, 1); + testValue('gte', 2, 2, 1); + testValue('gte', 2, 3, 0); + testValue('gte', 3, 2, 1); + testValue('gte', -3, 2, 0); + }); + }); + + describe('lessThan', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('lt', 0, 0, 0); + testValue('lt', 0, 1, 1); + testValue('lt', 1, 0, 0); + testValue('lt', 2, 2, 0); + testValue('lt', 2, 3, 1); + testValue('lt', 3, 2, 0); + testValue('lt', -3, 2, 1); + }); + }); + + describe('lessThanOrEqualTo', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('lte', 0, 0, 1); + testValue('lte', 0, 1, 1); + testValue('lte', 1, 0, 0); + testValue('lte', 2, 2, 1); + testValue('lte', 2, 3, 1); + testValue('lte', 3, 2, 0); + testValue('lte', -3, 2, 1); + }); + }); + + describe('equals', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('eq', 0, 0, 1); + testValue('eq', 0, 1, 0); + testValue('eq', 1, 0, 0); + testValue('eq', 2, 2, 1); + testValue('eq', 2, 3, 0); + }); + + describe('CATEGORIES_TO_NUMBER', () => { + + }); + }); + + describe('notEquals', () => { + describe('NUMBERS_TO_NUMBER', () => { + testValue('neq', 0, 0, 0); + testValue('neq', 0, 1, 1); + testValue('neq', 1, 0, 1); + testValue('neq', 2, 2, 0); + testValue('neq', 2, 3, 1); + }); + + describe('CATEGORIES_TO_NUMBER', () => { + + }); + }); }); + + function testValue (fn, param1, param2, expected) { + it(`${fn}(${param1}, ${param2}) should return ${expected}`, () => { + const actual = s[fn](param1, param2).value; + expect(actual).toEqual(expected); + }); + } + + function testEval (fn, param1, param2, expected, featureA, featureB) { + it(`${fn}(${param1}, ${param2}).eval(featureA, featureB) should return ${expected}`, () => { + const actual = s[fn](param1, param2).eval(featureA, featureB); + expect(actual).toEqual(expected); + }); + } }); From 78cc532c0ac695cd70a0ed98007d233f9ff93a4b Mon Sep 17 00:00:00 2001 From: elenatorro Date: Fri, 21 Jun 2019 16:48:12 +0200 Subject: [PATCH 3/9] Fix eval --- src/interactivity/featureVizProperty.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/interactivity/featureVizProperty.js b/src/interactivity/featureVizProperty.js index 115c91816..7349ea375 100644 --- a/src/interactivity/featureVizProperty.js +++ b/src/interactivity/featureVizProperty.js @@ -22,6 +22,17 @@ export default class FeatureVizProperty { } get value () { - return this._viz[this._propertyName].eval(this._properties); + return this._viz[this._propertyName].value; + } + + eval (...properties) { + const props = []; + properties.forEach((property) => { + const prop = {}; + prop[property] = this._properties[property]; + props.push(prop); + }); + + return this._viz[this._propertyName].eval(props); } } From f775bc816d7e6ef78ecba3940f8882ea491ccfed Mon Sep 17 00:00:00 2001 From: elenatorro Date: Fri, 21 Jun 2019 16:48:23 +0200 Subject: [PATCH 4/9] Update example --- debug/advanced/bivariate-legends.html | 53 +++++++++++++-------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/debug/advanced/bivariate-legends.html b/debug/advanced/bivariate-legends.html index aece012bb..567ce5808 100644 --- a/debug/advanced/bivariate-legends.html +++ b/debug/advanced/bivariate-legends.html @@ -13,13 +13,14 @@