import clone from "../Core/clone.js"; import defined from "../Core/defined.js"; import Expression from "./Expression.js"; /** * An expression for a style applied to a {@link Cesium3DTileset}. *
* Evaluates a conditions expression defined using the * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/Styling|3D Tiles Styling language}. *
** Implements the {@link StyleExpression} interface. *
* * @alias ConditionsExpression * @constructor * * @param {Object} [conditionsExpression] The conditions expression defined using the 3D Tiles Styling language. * @param {Object} [defines] Defines in the style. * * @example * var expression = new Cesium.ConditionsExpression({ * conditions : [ * ['${Area} > 10, 'color("#FF0000")'], * ['${id} !== "1"', 'color("#00FF00")'], * ['true', 'color("#FFFFFF")'] * ] * }); * expression.evaluateColor(feature, result); // returns a Cesium.Color object */ function ConditionsExpression(conditionsExpression, defines) { this._conditionsExpression = clone(conditionsExpression, true); this._conditions = conditionsExpression.conditions; this._runtimeConditions = undefined; setRuntime(this, defines); } Object.defineProperties(ConditionsExpression.prototype, { /** * Gets the conditions expression defined in the 3D Tiles Styling language. * * @memberof ConditionsExpression.prototype * * @type {Object} * @readonly * * @default undefined */ conditionsExpression: { get: function () { return this._conditionsExpression; }, }, }); function Statement(condition, expression) { this.condition = condition; this.expression = expression; } function setRuntime(expression, defines) { var runtimeConditions = []; var conditions = expression._conditions; if (!defined(conditions)) { return; } var length = conditions.length; for (var i = 0; i < length; ++i) { var statement = conditions[i]; var cond = String(statement[0]); var condExpression = String(statement[1]); runtimeConditions.push( new Statement( new Expression(cond, defines), new Expression(condExpression, defines) ) ); } expression._runtimeConditions = runtimeConditions; } /** * Evaluates the result of an expression, optionally using the provided feature's properties. If the result of * the expression in the * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/Styling|3D Tiles Styling language} * is of typeBoolean
, Number
, or String
, the corresponding JavaScript
* primitive type will be returned. If the result is a RegExp
, a Javascript RegExp
* object will be returned. If the result is a Cartesian2
, Cartesian3
, or Cartesian4
,
* a {@link Cartesian2}, {@link Cartesian3}, or {@link Cartesian4} object will be returned. If the result
argument is
* a {@link Color}, the {@link Cartesian4} value is converted to a {@link Color} and then returned.
*
* @param {Cesium3DTileFeature} feature The feature whose properties may be used as variables in the expression.
* @param {Object} [result] The object onto which to store the result.
* @returns {Boolean|Number|String|RegExp|Cartesian2|Cartesian3|Cartesian4|Color} The result of evaluating the expression.
*/
ConditionsExpression.prototype.evaluate = function (feature, result) {
var conditions = this._runtimeConditions;
if (!defined(conditions)) {
return undefined;
}
var length = conditions.length;
for (var i = 0; i < length; ++i) {
var statement = conditions[i];
if (statement.condition.evaluate(feature)) {
return statement.expression.evaluate(feature, result);
}
}
};
/**
* Evaluates the result of a Color expression, using the values defined by a feature.
* * This is equivalent to {@link ConditionsExpression#evaluate} but always returns a {@link Color} object. *
* @param {Cesium3DTileFeature} feature The feature whose properties may be used as variables in the expression. * @param {Color} [result] The object in which to store the result * @returns {Color} The modified result parameter or a new Color instance if one was not provided. */ ConditionsExpression.prototype.evaluateColor = function (feature, result) { var conditions = this._runtimeConditions; if (!defined(conditions)) { return undefined; } var length = conditions.length; for (var i = 0; i < length; ++i) { var statement = conditions[i]; if (statement.condition.evaluate(feature)) { return statement.expression.evaluateColor(feature, result); } } }; /** * Gets the shader function for this expression. * Returns undefined if the shader function can't be generated from this expression. * * @param {String} functionName Name to give to the generated function. * @param {String} propertyNameMap Maps property variable names to shader attribute names. * @param {Object} shaderState Stores information about the generated shader function, including whether it is translucent. * @param {String} returnType The return type of the generated function. * * @returns {String} The shader function. * * @private */ ConditionsExpression.prototype.getShaderFunction = function ( functionName, propertyNameMap, shaderState, returnType ) { var conditions = this._runtimeConditions; if (!defined(conditions) || conditions.length === 0) { return undefined; } var shaderFunction = ""; var length = conditions.length; for (var i = 0; i < length; ++i) { var statement = conditions[i]; var condition = statement.condition.getShaderExpression( propertyNameMap, shaderState ); var expression = statement.expression.getShaderExpression( propertyNameMap, shaderState ); // Build the if/else chain from the list of conditions shaderFunction += " " + (i === 0 ? "if" : "else if") + " (" + condition + ") \n" + " { \n" + " return " + expression + "; \n" + " } \n"; } shaderFunction = returnType + " " + functionName + "() \n" + "{ \n" + shaderFunction + " return " + returnType + "(1.0); \n" + // Return a default value if no conditions are met "} \n"; return shaderFunction; }; export default ConditionsExpression;