{"version":3,"file":"index.mjs","names":[],"sources":["../../src/function/index.ts"],"sourcesContent":["import {Color, isSupportedInterpolationColorSpace} from '../expression/types/color';\nimport {extendBy} from '../util/extend';\nimport {getType} from '../util/get_type';\nimport {Interpolate, interpolateFactory} from '../expression/definitions/interpolate';\nimport {Formatted} from '../expression/types/formatted';\nimport {ResolvedImage} from '../expression/types/resolved_image';\nimport {supportsInterpolation} from '../util/properties';\nimport {findStopLessThanOrEqualTo} from '../expression/stops';\nimport {Padding} from '../expression/types/padding';\nimport {ColorArray} from '../expression/types/color_array';\nimport {NumberArray} from '../expression/types/number_array';\nimport {typeOf} from '../expression/values';\nimport {ObjectType} from '../expression/types';\nimport {StylePropertySpecification} from '..';\nimport type {InterpolationType} from '../expression/definitions/interpolate';\nimport type {Feature, GlobalProperties} from '../expression/index';\n\nexport type StyleFunction = {\n kind: 'source' | 'camera' | 'composite';\n interpolationType?: InterpolationType | null;\n interpolationFactor?: (input: number, lower: number, upper: number) => number;\n zoomStops?: Array;\n evaluate: (globals: GlobalProperties, feature?: Partial) => any;\n};\n\nexport function isFunction(value) {\n return (\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(value) &&\n typeOf(value) === ObjectType\n );\n}\n\nfunction identityFunction(x) {\n return x;\n}\n\nfunction getParseFunction(propertySpec: StylePropertySpecification) {\n switch (propertySpec.type) {\n case 'color':\n return Color.parse;\n case 'padding':\n return Padding.parse;\n case 'numberArray':\n return NumberArray.parse;\n case 'colorArray':\n return ColorArray.parse;\n default:\n return null;\n }\n}\n\nfunction getInnerFunction(type: string) {\n switch (type) {\n case 'exponential':\n return evaluateExponentialFunction;\n case 'interval':\n return evaluateIntervalFunction;\n case 'categorical':\n return evaluateCategoricalFunction;\n case 'identity':\n return evaluateIdentityFunction;\n default:\n throw new Error(`Unknown function type \"${type}\"`);\n }\n}\n\nexport function createFunction(parameters, propertySpec): StyleFunction {\n const zoomAndFeatureDependent = parameters.stops && typeof parameters.stops[0][0] === 'object';\n const featureDependent = zoomAndFeatureDependent || parameters.property !== undefined;\n const zoomDependent = zoomAndFeatureDependent || !featureDependent;\n const type =\n parameters.type || (supportsInterpolation(propertySpec) ? 'exponential' : 'interval');\n\n const parseFn = getParseFunction(propertySpec);\n if (parseFn) {\n parameters = extendBy({}, parameters);\n\n if (parameters.stops) {\n parameters.stops = parameters.stops.map((stop) => {\n return [stop[0], parseFn(stop[1])];\n });\n }\n\n if (parameters.default) {\n parameters.default = parseFn(parameters.default);\n } else {\n parameters.default = parseFn(propertySpec.default);\n }\n }\n\n if (parameters.colorSpace && !isSupportedInterpolationColorSpace(parameters.colorSpace)) {\n throw new Error(`Unknown color space: \"${parameters.colorSpace}\"`);\n }\n\n const innerFun = getInnerFunction(type);\n let hashedStops;\n let categoricalKeyType;\n if (type === 'categorical') {\n // For categorical functions, generate an Object as a hashmap of the stops for fast searching\n hashedStops = Object.create(null);\n for (const stop of parameters.stops) {\n hashedStops[stop[0]] = stop[1];\n }\n\n // Infer key type based on first stop key-- used to encforce strict type checking later\n categoricalKeyType = typeof parameters.stops[0][0];\n }\n\n if (zoomAndFeatureDependent) {\n const featureFunctions = {};\n const zoomStops = [];\n for (let s = 0; s < parameters.stops.length; s++) {\n const stop = parameters.stops[s];\n const zoom = stop[0].zoom;\n if (featureFunctions[zoom] === undefined) {\n featureFunctions[zoom] = {\n zoom,\n type: parameters.type,\n property: parameters.property,\n default: parameters.default,\n stops: []\n };\n zoomStops.push(zoom);\n }\n featureFunctions[zoom].stops.push([stop[0].value, stop[1]]);\n }\n\n const featureFunctionStops = [];\n for (const z of zoomStops) {\n featureFunctionStops.push([\n featureFunctions[z].zoom,\n createFunction(featureFunctions[z], propertySpec)\n ]);\n }\n\n const interpolationType: InterpolationType = {name: 'linear'};\n return {\n kind: 'composite',\n interpolationType,\n interpolationFactor: Interpolate.interpolationFactor.bind(undefined, interpolationType),\n zoomStops: featureFunctionStops.map((s) => s[0]),\n evaluate({zoom}, properties) {\n return evaluateExponentialFunction(\n {\n stops: featureFunctionStops,\n base: parameters.base\n },\n propertySpec,\n zoom\n ).evaluate(zoom, properties);\n }\n };\n } else if (zoomDependent) {\n const interpolationType: InterpolationType | null =\n type === 'exponential'\n ? {name: 'exponential', base: parameters.base !== undefined ? parameters.base : 1}\n : null;\n return {\n kind: 'camera',\n interpolationType,\n interpolationFactor: Interpolate.interpolationFactor.bind(undefined, interpolationType),\n zoomStops: parameters.stops.map((s) => s[0]),\n evaluate: ({zoom}) =>\n innerFun(parameters, propertySpec, zoom, hashedStops, categoricalKeyType)\n };\n } else {\n return {\n kind: 'source',\n evaluate(_, feature) {\n const value =\n feature && feature.properties\n ? feature.properties[parameters.property]\n : undefined;\n if (value === undefined) {\n return coalesce(parameters.default, propertySpec.default);\n }\n return innerFun(parameters, propertySpec, value, hashedStops, categoricalKeyType);\n }\n };\n }\n}\n\nfunction coalesce(a, b, c?) {\n if (a !== undefined) return a;\n if (b !== undefined) return b;\n if (c !== undefined) return c;\n}\n\nfunction evaluateCategoricalFunction(parameters, propertySpec, input, hashedStops, keyType) {\n const evaluated = typeof input === keyType ? hashedStops[input] : undefined; // Enforce strict typing on input\n return coalesce(evaluated, parameters.default, propertySpec.default);\n}\n\nfunction evaluateIntervalFunction(parameters, propertySpec, input) {\n // Edge cases\n if (getType(input) !== 'number') return coalesce(parameters.default, propertySpec.default);\n const n = parameters.stops.length;\n if (n === 1) return parameters.stops[0][1];\n if (input <= parameters.stops[0][0]) return parameters.stops[0][1];\n if (input >= parameters.stops[n - 1][0]) return parameters.stops[n - 1][1];\n\n const index = findStopLessThanOrEqualTo(\n parameters.stops.map((stop) => stop[0]),\n input,\n ''\n );\n\n return parameters.stops[index][1];\n}\n\nfunction evaluateExponentialFunction(parameters, propertySpec, input) {\n const base = parameters.base !== undefined ? parameters.base : 1;\n\n // Edge cases\n if (getType(input) !== 'number') return coalesce(parameters.default, propertySpec.default);\n const n = parameters.stops.length;\n if (n === 1) return parameters.stops[0][1];\n if (input <= parameters.stops[0][0]) return parameters.stops[0][1];\n if (input >= parameters.stops[n - 1][0]) return parameters.stops[n - 1][1];\n\n const index = findStopLessThanOrEqualTo(\n parameters.stops.map((stop) => stop[0]),\n input,\n ''\n );\n const t = interpolationFactor(\n input,\n base,\n parameters.stops[index][0],\n parameters.stops[index + 1][0]\n );\n\n const outputLower = parameters.stops[index][1];\n const outputUpper = parameters.stops[index + 1][1];\n const interp = interpolateFactory[propertySpec.type] || identityFunction;\n\n if (typeof outputLower.evaluate === 'function') {\n return {\n evaluate(...args) {\n const evaluatedLower = outputLower.evaluate.apply(undefined, args);\n const evaluatedUpper = outputUpper.evaluate.apply(undefined, args);\n // Special case for fill-outline-color, which has no spec default.\n if (evaluatedLower === undefined || evaluatedUpper === undefined) {\n return undefined;\n }\n return interp(evaluatedLower, evaluatedUpper, t, parameters.colorSpace);\n }\n };\n }\n\n return interp(outputLower, outputUpper, t, parameters.colorSpace);\n}\n\nfunction evaluateIdentityFunction(parameters, propertySpec, input) {\n switch (propertySpec.type) {\n case 'color':\n input = Color.parse(input);\n break;\n case 'formatted':\n input = Formatted.fromString(input.toString());\n break;\n case 'resolvedImage':\n input = ResolvedImage.fromString(input.toString());\n break;\n case 'padding':\n input = Padding.parse(input);\n break;\n case 'colorArray':\n input = ColorArray.parse(input);\n break;\n case 'numberArray':\n input = NumberArray.parse(input);\n break;\n default:\n if (\n getType(input) !== propertySpec.type &&\n (propertySpec.type !== 'enum' || !propertySpec.values[input])\n ) {\n input = undefined;\n }\n }\n return coalesce(input, parameters.default, propertySpec.default);\n}\n\n/**\n * Returns a ratio that can be used to interpolate between exponential function\n * stops.\n *\n * How it works:\n * Two consecutive stop values define a (scaled and shifted) exponential\n * function `f(x) = a * base^x + b`, where `base` is the user-specified base,\n * and `a` and `b` are constants affording sufficient degrees of freedom to fit\n * the function to the given stops.\n *\n * Here's a bit of algebra that lets us compute `f(x)` directly from the stop\n * values without explicitly solving for `a` and `b`:\n *\n * First stop value: `f(x0) = y0 = a * base^x0 + b`\n * Second stop value: `f(x1) = y1 = a * base^x1 + b`\n * => `y1 - y0 = a(base^x1 - base^x0)`\n * => `a = (y1 - y0)/(base^x1 - base^x0)`\n *\n * Desired value: `f(x) = y = a * base^x + b`\n * => `f(x) = y0 + a * (base^x - base^x0)`\n *\n * From the above, we can replace the `a` in `a * (base^x - base^x0)` and do a\n * little algebra:\n * ```\n * a * (base^x - base^x0) = (y1 - y0)/(base^x1 - base^x0) * (base^x - base^x0)\n * = (y1 - y0) * (base^x - base^x0) / (base^x1 - base^x0)\n * ```\n *\n * If we let `(base^x - base^x0) / (base^x1 base^x0)`, then we have\n * `f(x) = y0 + (y1 - y0) * ratio`. In other words, `ratio` may be treated as\n * an interpolation factor between the two stops' output values.\n *\n * (Note: a slightly different form for `ratio`,\n * `(base^(x-x0) - 1) / (base^(x1-x0) - 1) `, is equivalent, but requires fewer\n * expensive `Math.pow()` operations.)\n *\n * @private\n */\nfunction interpolationFactor(input, base, lowerValue, upperValue) {\n const difference = upperValue - lowerValue;\n const progress = input - lowerValue;\n\n if (difference === 0) {\n return 0;\n } else if (base === 1) {\n return progress / difference;\n } else {\n return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);\n }\n}\n"],"mappings":"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"}