/
ConditionsExpression.js
187 lines (173 loc) · 7.39 KB
/
ConditionsExpression.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
define([
'../Core/clone',
'../Core/defined',
'../Core/defineProperties',
'./Expression'
], function(
clone,
defined,
defineProperties,
Expression) {
'use strict';
/**
* An expression for a style applied to a {@link Cesium3DTileset}.
* <p>
* Evaluates a conditions expression defined using the
* {@link https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/Styling|3D Tiles Styling language}.
* </p>
* <p>
* Implements the {@link StyleExpression} interface.
* </p>
*
* @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(frameState, 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);
}
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/AnalyticalGraphicsInc/3d-tiles/tree/master/Styling|3D Tiles Styling language}
* is of type <code>Boolean</code>, <code>Number</code>, or <code>String</code>, the corresponding JavaScript
* primitive type will be returned. If the result is a <code>RegExp</code>, a Javascript <code>RegExp</code>
* object will be returned. If the result is a <code>Cartesian2</code>, <code>Cartesian3</code>, or <code>Cartesian4</code>,
* a {@link Cartesian2}, {@link Cartesian3}, or {@link Cartesian4} object will be returned. If the <code>result</code> argument is
* a {@link Color}, the {@link Cartesian4} value is converted to a {@link Color} and then returned.
*
* @param {FrameState} frameState The frame state.
* @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(frameState, 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(frameState, feature)) {
return statement.expression.evaluate(frameState, feature, result);
}
}
};
/**
* Evaluates the result of a Color expression, using the values defined by a feature.
* <p>
* This is equivalent to {@link ConditionsExpression#evaluate} but always returns a {@link Color} object.
* </p>
* @param {FrameState} frameState The frame state.
* @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(frameState, 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(frameState, feature)) {
return statement.expression.evaluateColor(frameState, 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} attributePrefix Prefix that is added to any variable names to access vertex attributes.
* @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, attributePrefix, 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(attributePrefix, shaderState);
var expression = statement.expression.getShaderExpression(attributePrefix, 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;
};
return ConditionsExpression;
});