From f95f06c55f57bb93f16e93768c263a6ec44894fc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 27 Oct 2017 10:31:48 -0700 Subject: [PATCH] Split "curve" into "step" and "interpolate" --- debug/circles.html | 2 +- debug/expressions.html | 2 +- debug/heatmap.html | 2 +- docs/components/expression-metadata.js | 8 +- docs/pages/style-spec.js | 52 ++++++--- .../expression/definitions/index.js | 6 +- .../definitions/{curve.js => interpolate.js} | 78 +++---------- src/style-spec/expression/definitions/step.js | 110 ++++++++++++++++++ src/style-spec/expression/index.js | 32 ++--- src/style-spec/expression/stops.js | 34 ++++++ src/style-spec/function/convert.js | 41 ++++--- src/style-spec/function/index.js | 9 +- src/style-spec/reference/v8.json | 12 +- src/style/style_declaration.js | 8 +- .../evaluation-error/test.json | 5 +- .../heatmap-density/basic/test.json | 2 +- .../cubic-bezier-3-args/test.json | 2 +- .../cubic-bezier-5-args/test.json | 2 +- .../test.json | 2 +- .../cubic-bezier/test.json | 2 +- .../exponential-number-array/test.json | 2 +- .../exponential-single-stop/test.json | 2 +- .../exponential-string-array/test.json | 4 +- .../test.json | 4 +- .../exponential/test.json | 2 +- .../infer-array-type/test.json | 3 +- .../linear-color/test.json | 2 +- .../linear-many-stops/test.json | 2 +- .../{curve => interpolate}/linear/test.json | 2 +- .../expression-tests/let/zoom/test.json | 2 +- .../{curve/step => step/basic}/test.json | 2 +- .../expression-tests/zoom/basic/test.json | 2 +- .../heatmap-color/expression/style.json | 2 +- .../line-opacity/step-curve/style.json | 2 +- .../text-font/camera-function/style.json | 2 +- .../text-size/composite-expression/style.json | 2 +- test/unit/style-spec/expression.test.js | 6 +- .../style-spec/fixture/functions.input.json | 4 +- .../style-spec/fixture/functions.output.json | 6 +- 39 files changed, 292 insertions(+), 172 deletions(-) rename src/style-spec/expression/definitions/{curve.js => interpolate.js} (74%) create mode 100644 src/style-spec/expression/definitions/step.js create mode 100644 src/style-spec/expression/stops.js rename test/integration/expression-tests/{curve => interpolate}/cubic-bezier-3-args/test.json (95%) rename test/integration/expression-tests/{curve => interpolate}/cubic-bezier-5-args/test.json (95%) rename test/integration/expression-tests/{curve => interpolate}/cubic-bezier-invalid-control-point/test.json (95%) rename test/integration/expression-tests/{curve => interpolate}/cubic-bezier/test.json (97%) rename test/integration/expression-tests/{curve => interpolate}/exponential-number-array/test.json (96%) rename test/integration/expression-tests/{curve => interpolate}/exponential-single-stop/test.json (82%) rename test/integration/expression-tests/{curve => interpolate}/exponential-string-array/test.json (67%) rename test/integration/expression-tests/{curve => interpolate}/exponential-uninterpolatable-numeric-array/test.json (70%) rename test/integration/expression-tests/{curve => interpolate}/exponential/test.json (85%) rename test/integration/expression-tests/{curve => interpolate}/infer-array-type/test.json (93%) rename test/integration/expression-tests/{curve => interpolate}/linear-color/test.json (87%) rename test/integration/expression-tests/{curve => interpolate}/linear-many-stops/test.json (98%) rename test/integration/expression-tests/{curve => interpolate}/linear/test.json (89%) rename test/integration/expression-tests/{curve/step => step/basic}/test.json (87%) diff --git a/debug/circles.html b/debug/circles.html index 530f64aa18d..832e3ee19d0 100644 --- a/debug/circles.html +++ b/debug/circles.html @@ -42,7 +42,7 @@ "source": "circles", "paint": { "circle-radius": [ - "curve", + "interpolate", ["exponential", 2.0], ["zoom"], 0, 5, diff --git a/debug/expressions.html b/debug/expressions.html index 2a1cadce160..260db31a838 100644 --- a/debug/expressions.html +++ b/debug/expressions.html @@ -59,7 +59,7 @@ "source": "circles", "paint": { "circle-radius": [ - "curve", + "interpolate", ["exponential", 2.0], ["zoom"], 0, 5, diff --git a/debug/heatmap.html b/debug/heatmap.html index 7e2768f2d08..f8f26bca04a 100644 --- a/debug/heatmap.html +++ b/debug/heatmap.html @@ -48,7 +48,7 @@ }, "heatmap-intensity": 0.9, "heatmap-color": [ - "curve", + "interpolate", ["linear"], ["heatmap-density"], 0, "rgba(0, 0, 255, 0)", diff --git a/docs/components/expression-metadata.js b/docs/components/expression-metadata.js index 76540c9902f..b7f345d8b45 100644 --- a/docs/components/expression-metadata.js +++ b/docs/components/expression-metadata.js @@ -64,20 +64,20 @@ const types = { type: 'OutputType', parameters: [{repeat: ['OutputType']}] }], - curve: [{ + step: [{ type: 'OutputType', parameters: [ 'input: number', - '["step"]', 'stop_output_0: OutputType', 'stop_input_1: number, stop_output_1: OutputType', 'stop_input_n: number, stop_output_n: OutputType, ...' ] - }, { + }], + interpolate: [{ type: 'OutputType (number, array, or Color)', parameters: [ - 'input: number', 'interpolation: ["linear"] | ["exponential", base] | ["cubic-bezier", x1, y1, x2, y2 ]', + 'input: number', 'stop_input_1: number, stop_output_1: OutputType', 'stop_input_n: number, stop_output_n: OutputType, ...' ] diff --git a/docs/pages/style-spec.js b/docs/pages/style-spec.js index 14a317afd35..d78314269f4 100644 --- a/docs/pages/style-spec.js +++ b/docs/pages/style-spec.js @@ -361,11 +361,7 @@ class Item extends React.Component { {this.props.function === "interpolated" && - Supports all curve types. } - - {this.props.function === "piecewise-constant" && - - Supports step curves only. } + Supports interpolate expressions. } {this.props.transition && Transitionable. } @@ -1218,7 +1214,7 @@ export default class extends React.Component { {highlightJSON(` { "circle-radius": [ - "curve", ["linear"], ["zoom"], + "interpolate", ["linear"], ["zoom"], // zoom is 5 (or less) -> circle radius will be 1px 5, 1, // zoom is 10 (or greater) -> circle radius will be 2px @@ -1227,17 +1223,34 @@ export default class extends React.Component { }`)} -

This example uses a 'curve' expression to +

This example uses an interpolate expression to define a linear relationship between zoom level and circle size using a set of input-output pairs. In this case, the expression indicates that the circle radius should be 1 pixel when the zoom level is 5, and 2 pixels when the zoom is 10. (See the 'curve' documentation for more + href="#expressions-interpolate">the interpolate documentation for more details.)

-

Note that any zoom expression used in a layout or paint property must be of the following form:

+

Note that any zoom expression used in a layout or paint property must be of the following forms:

- {highlightJSON(`[ "curve", interpolation, ["zoom"], ... ]`)} + {highlightJSON(`[ "interpolate", interpolation, ["zoom"], ... ]`)} +
+ +

Or:

+ +
+ {highlightJSON(`[ "step", ["zoom"], ... ]`)} +
+ +

Or:

+ +
+ {highlightJSON(` + [ + "let", + ... variable bindings..., + [ "interpolate", interpolation, ["zoom"], ... ] + ]`)}

Or:

@@ -1247,13 +1260,14 @@ export default class extends React.Component { [ "let", ... variable bindings..., - [ "curve", interpolation, ["zoom"], ... ] + [ "step", ["zoom"], ... ] ]`)} -

That is, in layout or paint properties, ["zoom"] may only appear as the - input to an outer curve, and may not appear anywhere - else in the expression.

+

That is, in layout or paint properties, ["zoom"] may appear only as the + input to an outer interpolate or + step expression, or such an expression within a + let expression.

Example: a zoom-and-property expression

Combining zoom and property expressions allows a layer's appearance to change with @@ -1263,11 +1277,11 @@ export default class extends React.Component { {highlightJSON(` { "circle-radius": [ - "curve", ["linear"], ["zoom"], - // when zoom is 0, set each feature's circle radius to the value of its "rating" property - 0, ["get", "rating"], - // when zoom is 0, set each feature's circle radius to four times the value of its "rating" property - 10, ["*", 4, ["get", "rating"]] + "interpolate", ["linear"], ["zoom"], + // when zoom is 0, set each feature's circle radius to the value of its "rating" property + 0, ["get", "rating"], + // when zoom is 0, set each feature's circle radius to four times the value of its "rating" property + 10, ["*", 4, ["get", "rating"]] ] }`)} diff --git a/src/style-spec/expression/definitions/index.js b/src/style-spec/expression/definitions/index.js index ea5ea3782a4..078814c5f4b 100644 --- a/src/style-spec/expression/definitions/index.js +++ b/src/style-spec/expression/definitions/index.js @@ -25,7 +25,8 @@ const Coercion = require('./coercion'); const At = require('./at'); const Match = require('./match'); const Case = require('./case'); -const Curve = require('./curve'); +const Step = require('./step'); +const Interpolate = require('./interpolate'); const Coalesce = require('./coalesce'); import type { Expression } from '../expression'; @@ -46,7 +47,8 @@ const expressions: { [string]: Class } = { 'case': Case, 'match': Match, 'coalesce': Coalesce, - 'curve': Curve, + 'step': Step, + 'interpolate': Interpolate }; function rgba(ctx, [r, g, b, a]) { diff --git a/src/style-spec/expression/definitions/curve.js b/src/style-spec/expression/definitions/interpolate.js similarity index 74% rename from src/style-spec/expression/definitions/curve.js rename to src/style-spec/expression/definitions/interpolate.js index e7e6314b9bf..11c1c6fc9cd 100644 --- a/src/style-spec/expression/definitions/curve.js +++ b/src/style-spec/expression/definitions/interpolate.js @@ -4,21 +4,20 @@ const UnitBezier = require('@mapbox/unitbezier'); const interpolate = require('../../util/interpolate'); const { toString, NumberType } = require('../types'); const { Color } = require('../values'); +const { findStopLessThanOrEqualTo } = require("../stops"); +import type { Stops } from '../stops'; import type { Expression } from '../expression'; import type ParsingContext from '../parsing_context'; import type EvaluationContext from '../evaluation_context'; import type { Type } from '../types'; export type InterpolationType = - { name: 'step' } | { name: 'linear' } | { name: 'exponential', base: number } | { name: 'cubic-bezier', controlPoints: [number, number, number, number] }; -type Stops = Array<[number, Expression]>; - -class Curve implements Expression { +class Interpolate implements Expression { key: string; type: Type; @@ -62,9 +61,7 @@ class Curve implements Expression { return context.error(`Expected an interpolation type expression.`, 1); } - if (interpolation[0] === 'step') { - interpolation = { name: 'step' }; - } else if (interpolation[0] === 'linear') { + if (interpolation[0] === 'linear') { interpolation = { name: 'linear' }; } else if (interpolation[0] === 'exponential') { const base = interpolation[1]; @@ -91,15 +88,12 @@ class Curve implements Expression { return context.error(`Unknown interpolation type ${String(interpolation[0])}`, 1, 0); } - const isStep = interpolation.name === 'step'; - - const minArgs = isStep ? 5 : 4; - if (args.length - 1 < minArgs) - return context.error(`Expected at least ${minArgs} arguments, but found only ${args.length - 1}.`); + if (args.length - 1 < 4) { + return context.error(`Expected at least 4 arguments, but found only ${args.length - 1}.`); + } - const parity = minArgs % 2; - if ((args.length - 1) % 2 !== parity) { - return context.error(`Expected an ${parity === 0 ? 'even' : 'odd'} number of arguments.`); + if ((args.length - 1) % 2 !== 0) { + return context.error(`Expected an even number of arguments.`); } input = context.parse(input, 2, NumberType); @@ -112,23 +106,19 @@ class Curve implements Expression { outputType = context.expectedType; } - if (isStep) { - rest.unshift(-Infinity); - } - for (let i = 0; i < rest.length; i += 2) { const label = rest[i]; const value = rest[i + 1]; - const labelKey = isStep ? i + 2 : i + 3; - const valueKey = isStep ? i + 3 : i + 4; + const labelKey = i + 3; + const valueKey = i + 4; if (typeof label !== 'number') { - return context.error('Input/output pairs for "curve" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey); + return context.error('Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey); } if (stops.length && stops[stops.length - 1][0] > label) { - return context.error('Input/output pairs for "curve" expressions must be arranged with input values in strictly ascending order.', labelKey); + return context.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.', labelKey); } const parsed = context.parse(value, valueKey, outputType); @@ -137,8 +127,7 @@ class Curve implements Expression { stops.push([label, parsed]); } - if (interpolation.name !== 'step' && - outputType.kind !== 'number' && + if (outputType.kind !== 'number' && outputType.kind !== 'color' && !( outputType.kind === 'array' && @@ -146,10 +135,10 @@ class Curve implements Expression { typeof outputType.N === 'number' ) ) { - return context.error(`Type ${toString(outputType)} is not interpolatable, and thus cannot be used as a ${interpolation.name} curve's output type.`); + return context.error(`Type ${toString(outputType)} is not interpolatable.`); } - return new Curve(context.key, outputType, interpolation, input, stops); + return new Interpolate(context.key, outputType, interpolation, input, stops); } evaluate(ctx: EvaluationContext) { @@ -171,13 +160,9 @@ class Curve implements Expression { } const index = findStopLessThanOrEqualTo(labels, value); - if (this.interpolation.name === 'step') { - return outputs[index].evaluate(ctx); - } - const lower = labels[index]; const upper = labels[index + 1]; - const t = Curve.interpolationFactor(this.interpolation, value, lower, upper); + const t = Interpolate.interpolationFactor(this.interpolation, value, lower, upper); const outputLower = outputs[index].evaluate(ctx); const outputUpper = outputs[index + 1].evaluate(ctx); @@ -246,31 +231,4 @@ function exponentialInterpolation(input, base, lowerValue, upperValue) { } } -module.exports = Curve; - -/** - * Returns the index of the last stop <= input, or 0 if it doesn't exist. - * @private - */ -function findStopLessThanOrEqualTo(stops, input) { - const n = stops.length; - let lowerIndex = 0; - let upperIndex = n - 1; - let currentIndex = 0; - let currentValue, upperValue; - - while (lowerIndex <= upperIndex) { - currentIndex = Math.floor((lowerIndex + upperIndex) / 2); - currentValue = stops[currentIndex]; - upperValue = stops[currentIndex + 1]; - if (input === currentValue || input > currentValue && input < upperValue) { // Search complete - return currentIndex; - } else if (currentValue < input) { - lowerIndex = currentIndex + 1; - } else if (currentValue > input) { - upperIndex = currentIndex - 1; - } - } - - return Math.max(currentIndex - 1, 0); -} +module.exports = Interpolate; diff --git a/src/style-spec/expression/definitions/step.js b/src/style-spec/expression/definitions/step.js new file mode 100644 index 00000000000..d52c37d5a27 --- /dev/null +++ b/src/style-spec/expression/definitions/step.js @@ -0,0 +1,110 @@ +// @flow + +const { NumberType } = require('../types'); +const { findStopLessThanOrEqualTo } = require("../stops"); + +import type { Stops } from '../stops'; +import type { Expression } from '../expression'; +import type ParsingContext from '../parsing_context'; +import type EvaluationContext from '../evaluation_context'; +import type { Type } from '../types'; + +class Step implements Expression { + key: string; + type: Type; + + input: Expression; + labels: Array; + outputs: Array; + + constructor(key: string, type: Type, input: Expression, stops: Stops) { + this.key = key; + this.type = type; + this.input = input; + + this.labels = []; + this.outputs = []; + for (const [label, expression] of stops) { + this.labels.push(label); + this.outputs.push(expression); + } + } + + static parse(args: Array, context: ParsingContext) { + let [ , input, ...rest] = args; + + if (args.length - 1 < 4) { + return context.error(`Expected at least 4 arguments, but found only ${args.length - 1}.`); + } + + if ((args.length - 1) % 2 !== 0) { + return context.error(`Expected an even number of arguments.`); + } + + input = context.parse(input, 1, NumberType); + if (!input) return null; + + const stops: Stops = []; + + let outputType: Type = (null: any); + if (context.expectedType && context.expectedType.kind !== 'value') { + outputType = context.expectedType; + } + + rest.unshift(-Infinity); + + for (let i = 0; i < rest.length; i += 2) { + const label = rest[i]; + const value = rest[i + 1]; + + const labelKey = i + 1; + const valueKey = i + 2; + + if (typeof label !== 'number') { + return context.error('Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey); + } + + if (stops.length && stops[stops.length - 1][0] > label) { + return context.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.', labelKey); + } + + const parsed = context.parse(value, valueKey, outputType); + if (!parsed) return null; + outputType = outputType || parsed.type; + stops.push([label, parsed]); + } + + return new Step(context.key, outputType, input, stops); + } + + evaluate(ctx: EvaluationContext) { + const labels = this.labels; + const outputs = this.outputs; + + if (labels.length === 1) { + return outputs[0].evaluate(ctx); + } + + const value = ((this.input.evaluate(ctx): any): number); + if (value <= labels[0]) { + return outputs[0].evaluate(ctx); + } + + const stopCount = labels.length; + if (value >= labels[stopCount - 1]) { + return outputs[stopCount - 1].evaluate(ctx); + } + + const index = findStopLessThanOrEqualTo(labels, value); + return outputs[index].evaluate(ctx); + } + + eachChild(fn: (Expression) => void) { + fn(this.input); + for (const expression of this.outputs) { + fn(expression); + } + } +} + +module.exports = Step; diff --git a/src/style-spec/expression/index.js b/src/style-spec/expression/index.js index 9a9cda455e8..158a0945776 100644 --- a/src/style-spec/expression/index.js +++ b/src/style-spec/expression/index.js @@ -5,7 +5,8 @@ const ParsingError = require('./parsing_error'); const ParsingContext = require('./parsing_context'); const EvaluationContext = require('./evaluation_context'); const {CompoundExpression} = require('./compound_expression'); -const Curve = require('./definitions/curve'); +const Step = require('./definitions/step'); +const Interpolate = require('./definitions/interpolate'); const Coalesce = require('./definitions/coalesce'); const Let = require('./definitions/let'); const definitions = require('./definitions'); @@ -15,7 +16,6 @@ const {unwrap} = require('./values'); import type {Type} from './types'; import type {Value} from './values'; import type {Expression} from './expression'; -import type {InterpolationType} from './definitions/curve'; export type Feature = { +type: 1 | 2 | 3 | 'Unknown' | 'Point' | 'MultiPoint' | 'LineString' | 'MultiLineString' | 'Polygon' | 'MultiPolygon', @@ -51,7 +51,7 @@ export type StyleDeclarationExpression = ZoomConstantExpression | { isFeatureConstant: boolean, evaluate: (globals: GlobalProperties, feature?: Feature) => any, // parsed: Expression, - interpolation: InterpolationType, + interpolationFactor: (input: number, lower: number, upper: number) => number, zoomStops: Array }; @@ -195,17 +195,17 @@ function createExpression(expression: mixed, if (!zoomCurve) { return { result: 'error', - errors: [new ParsingError('', '"zoom" expression may only be used as input to a top-level "curve" expression.')] + errors: [new ParsingError('', '"zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.')] }; - } else if (!(zoomCurve instanceof Curve)) { + } else if (!(zoomCurve instanceof Step || zoomCurve instanceof Interpolate)) { return { result: 'error', errors: [new ParsingError(zoomCurve.key, zoomCurve.error)] }; - } else if (zoomCurve.interpolation.name !== 'step' && propertySpec['function'] === 'piecewise-constant') { + } else if (zoomCurve instanceof Interpolate && propertySpec['function'] === 'piecewise-constant') { return { result: 'error', - errors: [new ParsingError(zoomCurve.key, 'interpolation type must be "step" for this property')] + errors: [new ParsingError(zoomCurve.key, '"interpolate" expressions cannot be used with this property')] }; } @@ -220,7 +220,9 @@ function createExpression(expression: mixed, // capture metadata from the curve definition that's needed for // our prepopulate-and-interpolate approach to paint properties // that are zoom-and-property dependent. - interpolation: zoomCurve.interpolation, + interpolationFactor: zoomCurve instanceof Interpolate ? + Interpolate.interpolationFactor.bind(undefined, zoomCurve.interpolation) : + () => 0, zoomStops: zoomCurve.labels }; } @@ -228,11 +230,11 @@ function createExpression(expression: mixed, module.exports.createExpression = createExpression; module.exports.isExpression = isExpression; -// Zoom-dependent expressions may only use ["zoom"] as the input to a -// 'top-level' "curve" expression. (The curve may be wrapped in one or more -// "let" or "coalesce" expressions.) -function findZoomCurve(expression: Expression): null | Curve | {key: string, error: string} { - if (expression instanceof Curve) { +// Zoom-dependent expressions may only use ["zoom"] as the input to a top-level "step" or "interpolate" +// expression (collectively referred to as a "curve"). The curve may be wrapped in one or more "let" or +// "coalesce" expressions. +function findZoomCurve(expression: Expression): null | Step | Interpolate | {key: string, error: string} { + if (expression instanceof Step || expression instanceof Interpolate) { const input = expression.input; if (input instanceof CompoundExpression && input.name === 'zoom') { return expression; @@ -249,12 +251,12 @@ function findZoomCurve(expression: Expression): null | Curve | {key: string, err continue; } else if (e.error) { return e; - } else if (e instanceof Curve && !result) { + } else if ((e instanceof Step || e instanceof Interpolate) && !result) { result = e; } else { return { key: e.key, - error: 'Only one zoom-based curve may be used in a style function.' + error: 'Only one zoom-based "step" or "interpolate" subexpression may be used in an expression.' }; } } diff --git a/src/style-spec/expression/stops.js b/src/style-spec/expression/stops.js new file mode 100644 index 00000000000..3e047cce1aa --- /dev/null +++ b/src/style-spec/expression/stops.js @@ -0,0 +1,34 @@ +// @flow + +import type { Expression } from './expression'; + +export type Stops = Array<[number, Expression]>; + +/** + * Returns the index of the last stop <= input, or 0 if it doesn't exist. + * @private + */ +function findStopLessThanOrEqualTo(stops: Array, input: number) { + const n = stops.length; + let lowerIndex = 0; + let upperIndex = n - 1; + let currentIndex = 0; + let currentValue, upperValue; + + while (lowerIndex <= upperIndex) { + currentIndex = Math.floor((lowerIndex + upperIndex) / 2); + currentValue = stops[currentIndex]; + upperValue = stops[currentIndex + 1]; + if (input === currentValue || input > currentValue && input < upperValue) { // Search complete + return currentIndex; + } else if (currentValue < input) { + lowerIndex = currentIndex + 1; + } else if (currentValue > input) { + upperIndex = currentIndex - 1; + } + } + + return Math.max(currentIndex - 1, 0); +} + +module.exports = {findStopLessThanOrEqualTo}; diff --git a/src/style-spec/function/convert.js b/src/style-spec/function/convert.js index f89aa4b898b..57e5d76a6e6 100644 --- a/src/style-spec/function/convert.js +++ b/src/style-spec/function/convert.js @@ -109,24 +109,27 @@ function convertZoomAndPropertyFunction(parameters, propertySpec, stops, default // for which it's being used: linear for interpolatable properties, step // otherwise. const functionType = getFunctionType({}, propertySpec); - let interpolationType; - let isStep = false; if (functionType === 'exponential') { - interpolationType = ['linear']; + const expression = ['interpolate', ['linear'], ['zoom']]; + + for (const z of zoomStops) { + const output = convertPropertyFunction(featureFunctionParameters[z], propertySpec, featureFunctionStops[z], defaultExpression); + appendStopPair(expression, z, output, false); + } + + return expression; } else { - interpolationType = ['step']; - isStep = true; - } - const expression = ['curve', interpolationType, ['zoom']]; + const expression = ['step', ['zoom']]; - for (const z of zoomStops) { - const output = convertPropertyFunction(featureFunctionParameters[z], propertySpec, featureFunctionStops[z], defaultExpression); - appendStopPair(expression, z, output, isStep); - } + for (const z of zoomStops) { + const output = convertPropertyFunction(featureFunctionParameters[z], propertySpec, featureFunctionStops[z], defaultExpression); + appendStopPair(expression, z, output, true); + } - fixupDegenerateStepCurve(expression); + fixupDegenerateStepCurve(expression); - return expression; + return expression; + } } function convertPropertyFunction(parameters, propertySpec, stops, defaultExpression) { @@ -158,11 +161,11 @@ function convertPropertyFunction(parameters, propertySpec, stops, defaultExpress } else if (type === 'categorical') { expression = ['match', input]; } else if (type === 'interval') { - expression = ['curve', ['step'], input]; + expression = ['step', input]; isStep = true; } else if (type === 'exponential') { const base = parameters.base !== undefined ? parameters.base : 1; - expression = ['curve', ['exponential', base], input]; + expression = ['interpolate', ['exponential', base], input]; } else { throw new Error(`Unknown property function type ${type}`); } @@ -185,11 +188,11 @@ function convertZoomFunction(parameters, propertySpec, stops, input = ['zoom']) let expression; let isStep = false; if (type === 'interval') { - expression = ['curve', ['step'], input]; + expression = ['step', input]; isStep = true; } else if (type === 'exponential') { const base = parameters.base !== undefined ? parameters.base : 1; - expression = ['curve', ['exponential', base], input]; + expression = ['interpolate', ['exponential', base], input]; } else { throw new Error(`Unknown zoom function type "${type}"`); } @@ -205,7 +208,7 @@ function convertZoomFunction(parameters, propertySpec, stops, input = ['zoom']) function fixupDegenerateStepCurve(expression) { // degenerate step curve (i.e. a constant function): add a noop stop - if (expression[0] === 'curve' && expression[1][0] === 'step' && expression.length === 4) { + if (expression[0] === 'step' && expression.length === 3) { expression.push(0); expression.push(expression[3]); } @@ -213,7 +216,7 @@ function fixupDegenerateStepCurve(expression) { function appendStopPair(curve, input, output, isStep) { // step curves don't get the first input value, as it is redundant. - if (!(isStep && curve.length === 3)) { + if (!(isStep && curve.length === 2)) { curve.push(input); } curve.push(output); diff --git a/src/style-spec/function/index.js b/src/style-spec/function/index.js index bbad53de1d2..36fb734aeb9 100644 --- a/src/style-spec/function/index.js +++ b/src/style-spec/function/index.js @@ -4,6 +4,7 @@ const parseColor = require('../util/parse_color'); const extend = require('../util/extend'); const getType = require('../util/get_type'); const interpolate = require('../util/interpolate'); +const Interpolate = require('../expression/definitions/interpolate'); function isFunction(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); @@ -112,7 +113,7 @@ function createFunction(parameters, propertySpec, name) { return { isFeatureConstant: false, - interpolation: {name: 'linear'}, + interpolationFactor: Interpolate.interpolationFactor.bind(undefined, {name: 'linear'}), zoomStops: featureFunctionStops.map(s => s[0]), evaluate({zoom}, properties) { return outputFunction(evaluateExponentialFunction({ @@ -131,9 +132,9 @@ function createFunction(parameters, propertySpec, name) { return { isFeatureConstant: true, isZoomConstant: false, - interpolation: type === 'exponential' ? - {name: 'exponential', base: parameters.base !== undefined ? parameters.base : 1} : - {name: 'step'}, + interpolationFactor: type === 'exponential' ? + Interpolate.interpolationFactor.bind(undefined, {name: 'exponential', base: parameters.base !== undefined ? parameters.base : 1}) : + () => 0, zoomStops: parameters.stops.map(s => s[0]), evaluate }; diff --git a/src/style-spec/reference/v8.json b/src/style-spec/reference/v8.json index f76fa96c805..72212e8422a 100644 --- a/src/style-spec/reference/v8.json +++ b/src/style-spec/reference/v8.json @@ -1895,8 +1895,12 @@ "doc": "Evaluates each expression in turn until the first non-null value is obtained, and returns that value.", "group": "Decision" }, - "curve": { - "doc": "Interpolates an output value based on a set of input/output pairs using the specified interpolation strategy. A set of one input and one output value is known as a \"stop.\" \n\nThe `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`). Stop inputs must be numeric literals in strictly ascending order.\n\nInterpolation types:\n- `[\"step\"]`: returns the output value of the stop just less than the input , or the first input if the input is less than the first stop.\n- `[\"linear\"]`: interpolates linearly between the pair of stops just less than and just greater than the input .\n- `[\"exponential\", base]`: interpolates exponentially between the stops just less than and just greater than the input . `base` controls the rate at which the output increases: higher values make the output increase more towards the high end of the range. With values close to 1 the output increases linearly.\n- `[\"cubic-bezier\", x1, y2, x2, y2]`: interpolates using the cubic bezier curve defined by the given control points\n\nNote that interpolation types other that \"step\" are only supported when the output type is `number`, `array`, or `Color`.", + "step": { + "doc": "Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`). Stop inputs must be numeric literals in strictly ascending order. Returns the output value of the stop just less than the input, or the first input if the input is less than the first stop.", + "group": "Ramps, scales, curves" + }, + "interpolate": { + "doc": "Produces continuous, smooth results by interpolating between pairs of input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`). Stop inputs must be numeric literals in strictly ascending order. The output type must be `number`, `array`, or `color`.\n\nInterpolation types:\n- `[\"linear\"]`: interpolates linearly between the pair of stops just less than and just greater than the input.\n- `[\"exponential\", base]`: interpolates exponentially between the stops just less than and just greater than the input. `base` controls the rate at which the output increases: higher values make the output increase more towards the high end of the range. With values close to 1 the output increases linearly.\n- `[\"cubic-bezier\", x1, y2, x2, y2]`: interpolates using the cubic bezier curve defined by the given control points.", "group": "Ramps, scales, curves" }, "ln2": { @@ -1984,7 +1988,7 @@ "group": "Feature data" }, "zoom": { - "doc": "Gets the current zoom level. Note that in style layout and paint properties, [\"zoom\"] may only appear as the input to a top-level [\"curve\"] expression.", + "doc": "Gets the current zoom level. Note that in style layout and paint properties, [\"zoom\"] may only appear as the input to a top-level \"step\" or \"interpolate\" expression.", "group": "Zoom" }, "heatmap-density": { @@ -3110,7 +3114,7 @@ [1, "red"] ] }, - "doc": "Defines the color of each pixel based on its density value in a heatmap. Should be either a stop function with input values ranging from `0` to `1`, or a curve expression with a special `[\"heatmap-density\"]` keyword as the input.", + "doc": "Defines the color of each pixel based on its density value in a heatmap. Should be either a stop function with input values ranging from `0` to `1`, or an expression which uses `[\"heatmap-density\"]`.", "function": "interpolated", "zoom-function": true, "property-function": false, diff --git a/src/style/style_declaration.js b/src/style/style_declaration.js index f69c87f2877..fc5c0072522 100644 --- a/src/style/style_declaration.js +++ b/src/style/style_declaration.js @@ -4,7 +4,6 @@ const parseColor = require('../style-spec/util/parse_color'); const {isFunction, createFunction} = require('../style-spec/function'); const {isExpression, createExpression} = require('../style-spec/expression'); const util = require('../util/util'); -const Curve = require('../style-spec/expression/definitions/curve'); import type {StyleDeclarationExpression, Feature, GlobalProperties} from '../style-spec/expression'; @@ -74,12 +73,7 @@ class StyleDeclaration { if (this.expression.isZoomConstant) { return 0; } else { - return Curve.interpolationFactor( - this.expression.interpolation, - zoom, - lower, - upper - ); + return this.expression.interpolationFactor(zoom, lower, upper); } } } diff --git a/test/integration/expression-tests/constant-folding/evaluation-error/test.json b/test/integration/expression-tests/constant-folding/evaluation-error/test.json index dfa27b43783..53b7e30ec48 100644 --- a/test/integration/expression-tests/constant-folding/evaluation-error/test.json +++ b/test/integration/expression-tests/constant-folding/evaluation-error/test.json @@ -1,8 +1,7 @@ { "propertySpec": {"type": "color"}, "expression": [ - "curve", - ["step"], + "step", ["get", "x"], "black", 0, @@ -21,7 +20,7 @@ "compiled": { "result": "error", "errors": [ - {"key": "[5]", "error": "Could not parse color from value 'invalid'"} + {"key": "[4]", "error": "Could not parse color from value 'invalid'"} ] } } diff --git a/test/integration/expression-tests/heatmap-density/basic/test.json b/test/integration/expression-tests/heatmap-density/basic/test.json index fc2c4f4917a..832ea900465 100644 --- a/test/integration/expression-tests/heatmap-density/basic/test.json +++ b/test/integration/expression-tests/heatmap-density/basic/test.json @@ -12,7 +12,7 @@ ] } }, - "expression": ["curve", ["linear"], ["heatmap-density"], 0, "#000000", 1, "#ff0000"], + "expression": ["interpolate", ["linear"], ["heatmap-density"], 0, "#000000", 1, "#ff0000"], "inputs": [[{"heatmapDensity": 0.5}, {}]], "expected": { "compiled": { diff --git a/test/integration/expression-tests/curve/cubic-bezier-3-args/test.json b/test/integration/expression-tests/interpolate/cubic-bezier-3-args/test.json similarity index 95% rename from test/integration/expression-tests/curve/cubic-bezier-3-args/test.json rename to test/integration/expression-tests/interpolate/cubic-bezier-3-args/test.json index 8f5d8ff5cf2..b7155f43e7c 100644 --- a/test/integration/expression-tests/curve/cubic-bezier-3-args/test.json +++ b/test/integration/expression-tests/interpolate/cubic-bezier-3-args/test.json @@ -2,7 +2,7 @@ "expression": [ "number", [ - "curve", + "interpolate", ["cubic-bezier", 0, 0, 1], ["number", ["get", "x"]], 0, diff --git a/test/integration/expression-tests/curve/cubic-bezier-5-args/test.json b/test/integration/expression-tests/interpolate/cubic-bezier-5-args/test.json similarity index 95% rename from test/integration/expression-tests/curve/cubic-bezier-5-args/test.json rename to test/integration/expression-tests/interpolate/cubic-bezier-5-args/test.json index e8862ee9397..fa6a1c2d5e7 100644 --- a/test/integration/expression-tests/curve/cubic-bezier-5-args/test.json +++ b/test/integration/expression-tests/interpolate/cubic-bezier-5-args/test.json @@ -2,7 +2,7 @@ "expression": [ "number", [ - "curve", + "interpolate", ["cubic-bezier", 0, 0, 1, 1, 1], ["number", ["get", "x"]], 0, diff --git a/test/integration/expression-tests/curve/cubic-bezier-invalid-control-point/test.json b/test/integration/expression-tests/interpolate/cubic-bezier-invalid-control-point/test.json similarity index 95% rename from test/integration/expression-tests/curve/cubic-bezier-invalid-control-point/test.json rename to test/integration/expression-tests/interpolate/cubic-bezier-invalid-control-point/test.json index db8070eee96..d61d2c096f8 100644 --- a/test/integration/expression-tests/curve/cubic-bezier-invalid-control-point/test.json +++ b/test/integration/expression-tests/interpolate/cubic-bezier-invalid-control-point/test.json @@ -2,7 +2,7 @@ "expression": [ "number", [ - "curve", + "interpolate", ["cubic-bezier", 0, 1.75, 1, 1], ["number", ["get", "x"]], 0, diff --git a/test/integration/expression-tests/curve/cubic-bezier/test.json b/test/integration/expression-tests/interpolate/cubic-bezier/test.json similarity index 97% rename from test/integration/expression-tests/curve/cubic-bezier/test.json rename to test/integration/expression-tests/interpolate/cubic-bezier/test.json index ddd1207840b..9bcdb15e78e 100644 --- a/test/integration/expression-tests/curve/cubic-bezier/test.json +++ b/test/integration/expression-tests/interpolate/cubic-bezier/test.json @@ -2,7 +2,7 @@ "expression": [ "number", [ - "curve", + "interpolate", ["cubic-bezier", 0.42, 0, 0.58, 1], ["number", ["get", "x"]], 0, diff --git a/test/integration/expression-tests/curve/exponential-number-array/test.json b/test/integration/expression-tests/interpolate/exponential-number-array/test.json similarity index 96% rename from test/integration/expression-tests/curve/exponential-number-array/test.json rename to test/integration/expression-tests/interpolate/exponential-number-array/test.json index 5e76771665e..ad67aa16817 100644 --- a/test/integration/expression-tests/curve/exponential-number-array/test.json +++ b/test/integration/expression-tests/interpolate/exponential-number-array/test.json @@ -1,6 +1,6 @@ { "expression": [ - "curve", + "interpolate", ["exponential", 2], ["number", ["get", "x"]], 1, diff --git a/test/integration/expression-tests/curve/exponential-single-stop/test.json b/test/integration/expression-tests/interpolate/exponential-single-stop/test.json similarity index 82% rename from test/integration/expression-tests/curve/exponential-single-stop/test.json rename to test/integration/expression-tests/interpolate/exponential-single-stop/test.json index 00ba81ded44..355c1336c0f 100644 --- a/test/integration/expression-tests/curve/exponential-single-stop/test.json +++ b/test/integration/expression-tests/interpolate/exponential-single-stop/test.json @@ -1,7 +1,7 @@ { "expression": [ "number", - ["curve", ["exponential", 2], ["number", ["get", "x"]], 1, 2] + ["interpolate", ["exponential", 2], ["number", ["get", "x"]], 1, 2] ], "inputs": [ [{}, {"properties": {"x": 0}}], diff --git a/test/integration/expression-tests/curve/exponential-string-array/test.json b/test/integration/expression-tests/interpolate/exponential-string-array/test.json similarity index 67% rename from test/integration/expression-tests/curve/exponential-string-array/test.json rename to test/integration/expression-tests/interpolate/exponential-string-array/test.json index 92572b784a8..e0264e1ede2 100644 --- a/test/integration/expression-tests/curve/exponential-string-array/test.json +++ b/test/integration/expression-tests/interpolate/exponential-string-array/test.json @@ -1,6 +1,6 @@ { "expression": [ - "curve", + "interpolate", ["exponential", 2], ["number", ["get", "x"]], 1, @@ -15,7 +15,7 @@ "errors": [ { "key": "", - "error": "Type array is not interpolatable, and thus cannot be used as a exponential curve's output type." + "error": "Type array is not interpolatable." } ] } diff --git a/test/integration/expression-tests/curve/exponential-uninterpolatable-numeric-array/test.json b/test/integration/expression-tests/interpolate/exponential-uninterpolatable-numeric-array/test.json similarity index 70% rename from test/integration/expression-tests/curve/exponential-uninterpolatable-numeric-array/test.json rename to test/integration/expression-tests/interpolate/exponential-uninterpolatable-numeric-array/test.json index c67eb550aea..8aa48c51f0a 100644 --- a/test/integration/expression-tests/curve/exponential-uninterpolatable-numeric-array/test.json +++ b/test/integration/expression-tests/interpolate/exponential-uninterpolatable-numeric-array/test.json @@ -1,6 +1,6 @@ { "expression": [ - "curve", + "interpolate", ["exponential", 2], ["number", ["get", "x"]], 1, @@ -15,7 +15,7 @@ "errors": [ { "key": "", - "error": "Type array is not interpolatable, and thus cannot be used as a exponential curve's output type." + "error": "Type array is not interpolatable." } ] } diff --git a/test/integration/expression-tests/curve/exponential/test.json b/test/integration/expression-tests/interpolate/exponential/test.json similarity index 85% rename from test/integration/expression-tests/curve/exponential/test.json rename to test/integration/expression-tests/interpolate/exponential/test.json index 2652399e65c..4f416810708 100644 --- a/test/integration/expression-tests/curve/exponential/test.json +++ b/test/integration/expression-tests/interpolate/exponential/test.json @@ -1,7 +1,7 @@ { "expression": [ "number", - ["curve", ["exponential", 2], ["number", ["get", "x"]], 1, 2, 3, 6] + ["interpolate", ["exponential", 2], ["number", ["get", "x"]], 1, 2, 3, 6] ], "inputs": [ [{}, {"properties": {"x": 0}}], diff --git a/test/integration/expression-tests/curve/infer-array-type/test.json b/test/integration/expression-tests/interpolate/infer-array-type/test.json similarity index 93% rename from test/integration/expression-tests/curve/infer-array-type/test.json rename to test/integration/expression-tests/interpolate/infer-array-type/test.json index b305dd8ef00..bcedac352cc 100644 --- a/test/integration/expression-tests/curve/infer-array-type/test.json +++ b/test/integration/expression-tests/interpolate/infer-array-type/test.json @@ -1,8 +1,7 @@ { "propertySpec": {"type": "array", "value": "string"}, "expression": [ - "curve", - ["step"], + "step", ["number", ["get", "x"]], ["literal", ["one"]], 10, diff --git a/test/integration/expression-tests/curve/linear-color/test.json b/test/integration/expression-tests/interpolate/linear-color/test.json similarity index 87% rename from test/integration/expression-tests/curve/linear-color/test.json rename to test/integration/expression-tests/interpolate/linear-color/test.json index 38368da2b83..4f542c3ad2d 100644 --- a/test/integration/expression-tests/curve/linear-color/test.json +++ b/test/integration/expression-tests/interpolate/linear-color/test.json @@ -1,7 +1,7 @@ { "expression": [ "to-rgba", - ["curve", ["exponential", 1], ["get", "x"], 1, "red", 11, ["get", "color"]] + ["interpolate", ["exponential", 1], ["get", "x"], 1, "red", 11, ["get", "color"]] ], "inputs": [ [{}, {"properties": {"x": 0, "color": "blue"}}], diff --git a/test/integration/expression-tests/curve/linear-many-stops/test.json b/test/integration/expression-tests/interpolate/linear-many-stops/test.json similarity index 98% rename from test/integration/expression-tests/curve/linear-many-stops/test.json rename to test/integration/expression-tests/interpolate/linear-many-stops/test.json index 5745fb1f1e6..0bb687ec099 100644 --- a/test/integration/expression-tests/curve/linear-many-stops/test.json +++ b/test/integration/expression-tests/interpolate/linear-many-stops/test.json @@ -2,7 +2,7 @@ "expression": [ "number", [ - "curve", + "interpolate", ["exponential", 1], ["number", ["get", "x"]], 2, diff --git a/test/integration/expression-tests/curve/linear/test.json b/test/integration/expression-tests/interpolate/linear/test.json similarity index 89% rename from test/integration/expression-tests/curve/linear/test.json rename to test/integration/expression-tests/interpolate/linear/test.json index 47d4fa16ea1..365fe6516e7 100644 --- a/test/integration/expression-tests/curve/linear/test.json +++ b/test/integration/expression-tests/interpolate/linear/test.json @@ -1,6 +1,6 @@ { "propertySpec": {"type": "number"}, - "expression": ["curve", ["linear"], ["get", "x"], 0, 100, 10, 200], + "expression": ["interpolate", ["linear"], ["get", "x"], 0, 100, 10, 200], "inputs": [ [{}, {"properties": {"x": 0}}], [{}, {"properties": {"x": 5}}], diff --git a/test/integration/expression-tests/let/zoom/test.json b/test/integration/expression-tests/let/zoom/test.json index 51cfeb67a03..31d7f796d03 100644 --- a/test/integration/expression-tests/let/zoom/test.json +++ b/test/integration/expression-tests/let/zoom/test.json @@ -6,7 +6,7 @@ "z20_value", 30, [ - "curve", + "interpolate", ["linear"], ["zoom"], 0, diff --git a/test/integration/expression-tests/curve/step/test.json b/test/integration/expression-tests/step/basic/test.json similarity index 87% rename from test/integration/expression-tests/curve/step/test.json rename to test/integration/expression-tests/step/basic/test.json index a3796343269..eb6c459b6cc 100644 --- a/test/integration/expression-tests/curve/step/test.json +++ b/test/integration/expression-tests/step/basic/test.json @@ -1,7 +1,7 @@ { "expression": [ "number", - ["curve", ["step"], ["number", ["get", "x"]], 11, 0, 111, 1, 1111] + ["step", ["number", ["get", "x"]], 11, 0, 111, 1, 1111] ], "inputs": [ [{}, {"properties": {"x": -1.5}}], diff --git a/test/integration/expression-tests/zoom/basic/test.json b/test/integration/expression-tests/zoom/basic/test.json index 199477e72b1..c65208dd4bb 100644 --- a/test/integration/expression-tests/zoom/basic/test.json +++ b/test/integration/expression-tests/zoom/basic/test.json @@ -1,5 +1,5 @@ { - "expression": ["curve", ["linear"], ["zoom"], 0, 0, 30, 30], + "expression": ["interpolate", ["linear"], ["zoom"], 0, 0, 30, 30], "inputs": [[{"zoom": 5}, {}]], "expected": { "compiled": { diff --git a/test/integration/render-tests/heatmap-color/expression/style.json b/test/integration/render-tests/heatmap-color/expression/style.json index 9143984b3af..a95bde7d7a5 100644 --- a/test/integration/render-tests/heatmap-color/expression/style.json +++ b/test/integration/render-tests/heatmap-color/expression/style.json @@ -35,7 +35,7 @@ "source-layer": "poi_label", "paint": { "heatmap-color": [ - "curve", + "interpolate", ["linear"], ["heatmap-density"], 0, "rgba(0, 0, 255, 0)", diff --git a/test/integration/render-tests/line-opacity/step-curve/style.json b/test/integration/render-tests/line-opacity/step-curve/style.json index 5f365af23f7..a649864026b 100644 --- a/test/integration/render-tests/line-opacity/step-curve/style.json +++ b/test/integration/render-tests/line-opacity/step-curve/style.json @@ -69,7 +69,7 @@ "paint": { "line-width": 10, "line-opacity": [ - "curve", ["step"], ["zoom"], + "step", ["zoom"], ["match", ["string", ["get", "class"]], "motorway", 1, "trunk", 0.25, diff --git a/test/integration/render-tests/text-font/camera-function/style.json b/test/integration/render-tests/text-font/camera-function/style.json index 186f4bfd67c..5ac3962a1e7 100644 --- a/test/integration/render-tests/text-font/camera-function/style.json +++ b/test/integration/render-tests/text-font/camera-function/style.json @@ -40,7 +40,7 @@ "layout": { "text-field": "Test", "text-font": [ - "curve", ["step"], ["zoom"], + "step", ["zoom"], [ "literal", [ "Open Sans Semibold", "Arial Unicode MS Bold" ]], 1, ["literal", [ "Open Sans Semibold", "Arial Unicode MS Bold" ]] diff --git a/test/integration/render-tests/text-size/composite-expression/style.json b/test/integration/render-tests/text-size/composite-expression/style.json index 087e805b900..55ea38f5607 100644 --- a/test/integration/render-tests/text-size/composite-expression/style.json +++ b/test/integration/render-tests/text-size/composite-expression/style.json @@ -64,7 +64,7 @@ "Arial Unicode MS Bold" ], "text-size": [ - "curve", + "interpolate", ["cubic-bezier", 0, 0.9, 0.1, 1], ["zoom"], 0, diff --git a/test/unit/style-spec/expression.test.js b/test/unit/style-spec/expression.test.js index 5e5afafe84a..8f6f9973f88 100644 --- a/test/unit/style-spec/expression.test.js +++ b/test/unit/style-spec/expression.test.js @@ -4,16 +4,16 @@ const test = require('mapbox-gl-js-test').test; const {createExpression} = require('../../../src/style-spec/expression'); test('createExpression', (t) => { - test('require piecewise-constant zoom curves to use "step" interpolation', (t) => { + test('prohibits piecewise-constant properties from using an "interpolate" expression', (t) => { const expression = createExpression([ - 'curve', ['linear'], ['zoom'], 0, 0, 10, 10 + 'interpolate', ['linear'], ['zoom'], 0, 0, 10, 10 ], { type: 'number', function: 'piecewise-constant' }); t.equal(expression.result, 'error'); t.equal(expression.errors.length, 1); - t.equal(expression.errors[0].message, 'interpolation type must be "step" for this property'); + t.equal(expression.errors[0].message, '"interpolate" expressions cannot be used with this property'); t.end(); }); diff --git a/test/unit/style-spec/fixture/functions.input.json b/test/unit/style-spec/fixture/functions.input.json index 0c74abf54f3..2dcc168ce23 100644 --- a/test/unit/style-spec/fixture/functions.input.json +++ b/test/unit/style-spec/fixture/functions.input.json @@ -913,7 +913,7 @@ "source": "source", "source-layer": "layer", "paint": { - "fill-opacity": ["+", 0.5, ["curve", ["linear"], ["zoom"], 0, 0, 1, 1]] + "fill-opacity": ["+", 0.5, ["interpolate", ["linear"], ["zoom"], 0, 0, 1, 1]] } }, { @@ -940,7 +940,7 @@ "source": "source", "source-layer": "layer", "paint": { - "line-dasharray": ["curve", ["linear"], ["zoom"], 0, ["literal", [1, 2]], 1, ["literal", [3, 4]]] + "line-dasharray": ["interpolate", ["linear"], ["zoom"], 0, ["literal", [1, 2]], 1, ["literal", [3, 4]]] } } ] diff --git a/test/unit/style-spec/fixture/functions.output.json b/test/unit/style-spec/fixture/functions.output.json index 1e6dc98ad08..54df086dcb8 100644 --- a/test/unit/style-spec/fixture/functions.output.json +++ b/test/unit/style-spec/fixture/functions.output.json @@ -172,7 +172,7 @@ "line": 907 }, { - "message": "layers[49].paint.fill-opacity: \"zoom\" expression may only be used as input to a top-level \"curve\" expression.", + "message": "layers[49].paint.fill-opacity: \"zoom\" expression may only be used as input to a top-level \"step\" or \"interpolate\" expression.", "line": 916 }, { @@ -184,7 +184,7 @@ "line": 934 }, { - "message": "layers[52].paint.line-dasharray: Type array is not interpolatable, and thus cannot be used as a linear curve's output type.", + "message": "layers[52].paint.line-dasharray: Type array is not interpolatable.", "line": 943 } -] \ No newline at end of file +]