Skip to content

Commit

Permalink
Move expressions to a different area
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed May 22, 2017
1 parent 2be73f6 commit 8c84e10
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 124 deletions.
10 changes: 6 additions & 4 deletions Apps/Sandcastle/gallery/3D Tiles Batch Table Hierarchy.html
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,14 @@
});

addStyle('Color features by class name', {
"expressions" : {
"suffix" : "regExp('door(.*)').exec(getExactClassName())"
},
"color" : {
"expression" : "regExp('door(.*)').exec(getExactClassName())",
"conditions" : [
["${expression} === 'knob'", "color('yellow')"],
["${expression} === ''", "color('lime')"],
["${expression} === null", "color('gray')"],
["${suffix} === 'knob'", "color('yellow')"],
["${suffix} === ''", "color('lime')"],
["${suffix} === null", "color('gray')"],
["true", "color('blue'"]
]
}
Expand Down
21 changes: 12 additions & 9 deletions Source/Scene/Cesium3DTileStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ define([
this._show = undefined;
this._pointSize = undefined;
this._meta = undefined;
this._expressions = undefined;

this._colorShaderFunction = undefined;
this._showShaderFunction = undefined;
Expand Down Expand Up @@ -108,33 +109,35 @@ define([
var showExpression = defaultValue(styleJson.show, DEFAULT_JSON_BOOLEAN_EXPRESSION);
var pointSizeExpression = defaultValue(styleJson.pointSize, DEFAULT_JSON_NUMBER_EXPRESSION);

var expressions = styleJson.expressions;

var color;
if (typeof colorExpression === 'string') {
color = new Expression(colorExpression);
color = new Expression(colorExpression, expressions);
} else if (defined(colorExpression.conditions)) {
color = new ConditionsExpression(colorExpression);
color = new ConditionsExpression(colorExpression, expressions);
}

that._color = color;

var show;
if (typeof showExpression === 'boolean') {
show = new Expression(String(showExpression));
show = new Expression(String(showExpression), expressions);
} else if (typeof showExpression === 'string') {
show = new Expression(showExpression);
show = new Expression(showExpression, expressions);
} else if (defined(showExpression.conditions)) {
show = new ConditionsExpression(showExpression);
show = new ConditionsExpression(showExpression, expressions);
}

that._show = show;

var pointSize;
if (typeof pointSizeExpression === 'number') {
pointSize = new Expression(String(pointSizeExpression));
pointSize = new Expression(String(pointSizeExpression), expressions);
} else if (typeof pointSizeExpression === 'string') {
pointSize = new Expression(pointSizeExpression);
pointSize = new Expression(pointSizeExpression, expressions);
} else if (defined(pointSizeExpression.conditions)) {
pointSize = new ConditionsExpression(pointSizeExpression);
pointSize = new ConditionsExpression(pointSizeExpression, expressions);
}

that._pointSize = pointSize;
Expand All @@ -144,7 +147,7 @@ define([
var metaJson = defaultValue(styleJson.meta, defaultValue.EMPTY_OBJECT);
for (var property in metaJson) {
if (metaJson.hasOwnProperty(property)) {
meta[property] = new Expression(metaJson[property]);
meta[property] = new Expression(metaJson[property], expressions);
}
}
}
Expand Down
38 changes: 7 additions & 31 deletions Source/Scene/ConditionsExpression.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ define([
* @constructor
*
* @param {Object} [conditionsExpression] The conditions expression defined using the 3D Tiles Styling language.
* @param {Object} [expressions] Additional expressions defined in the style.
*
* @example
* var expression = new Cesium.Expression({
* expressions : {
* id : "RegEx('^id_(\d+)$').exec(${name})",
* Area : "${length} * ${height}"
* },
* var expression = new Cesium.ConditionsExpression({
* conditions : [
* ['${Area} > 10, 'color("#FF0000")'],
* ['${id} !== "1"', 'color("#00FF00")'],
Expand All @@ -43,16 +40,12 @@ define([
*
* @see {@link https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/Styling|3D Tiles Styling language}
*/
function ConditionsExpression(conditionsExpression) {
function ConditionsExpression(conditionsExpression, expressions) {
this._conditionsExpression = clone(conditionsExpression, true);
this._conditions = conditionsExpression.conditions;

// Insert expressions into conditions
// this._expressions has to stay in prototype for specs to keep passing, but it can be removed in the future.
this._expressions = defaultValue(conditionsExpression.expressions, defaultValue.EMPTY_OBJECT);
this._runtimeConditions = undefined;

setRuntime(this);
setRuntime(this, expressions);
}

defineProperties(ConditionsExpression.prototype, {
Expand All @@ -78,35 +71,18 @@ define([
this.expression = expression;
}

function setRuntime(expression) {
function setRuntime(expression, expressions) {
var runtimeConditions = [];
var conditions = expression._conditions;
if (defined(conditions)) {
var expressions = expression._expressions;
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]);

// Loop over all expressions for replacement
for (var key in expressions) {
if (expressions.hasOwnProperty(key)) {
var expressionPlaceholder = new RegExp('\\$\\{' + key + '\\}', 'g');
var expressionReplace = expressions[key];
if (expression) {
cond = cond.replace(expressionPlaceholder, expressionReplace);
condExpression = condExpression.replace(expressionPlaceholder, expressionReplace);
} else {
cond = cond.replace(expressionPlaceholder, 'undefined');
condExpression = condExpression.replace(expressionPlaceholder, 'undefined');
}
}
}

runtimeConditions.push(new Statement(
new Expression(cond),
new Expression(condExpression)
new Expression(cond, expressions),
new Expression(condExpression, expressions)
));
}
}
Expand Down
22 changes: 21 additions & 1 deletion Source/Scene/Expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ define([
* @constructor
*
* @param {String} [expression] The expression defined using the 3D Tiles Styling language.
* @param {Object} [expressions] Additional expressions defined in the style.
*
* @example
* var expression = new Cesium.Expression('(regExp("^Chest").test(${County})) && (${YearBuilt} >= 1970)');
Expand All @@ -146,14 +147,15 @@ define([
*
* @see {@link https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/Styling|3D Tiles Styling language}
*/
function Expression(expression) {
function Expression(expression, expressions) {
//>>includeStart('debug', pragmas.debug);
if (typeof expression !== 'string') {
throw new DeveloperError('expression must be a string.');
}
//>>includeEnd('debug');

this._expression = expression;
expression = replaceExpressions(expression, expressions);
expression = replaceVariables(removeBackslashes(expression));

// customize jsep operators
Expand Down Expand Up @@ -279,6 +281,24 @@ define([
setEvaluateFunction(this);
}

function replaceExpressions(expression, expressions) {
if (!defined(expressions) || (defined(expressions) && expressions.length === 0)) {
return expression;
}
var result = expression;
var match = variableRegex.exec(expression);
while (match !== null) {
var placeholder = match[0];
var variableName = match[1];
var expressionReplace = expressions[variableName];
if (defined(expressionReplace)) {
result = result.replace(placeholder, expressionReplace);
}
match = variableRegex.exec(result);
}
return result;
}

function removeBackslashes(expression) {
return expression.replace(backslashRegex, backslashReplacement);
}
Expand Down
46 changes: 39 additions & 7 deletions Specs/Scene/Cesium3DTileStyleSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,15 +350,17 @@ defineSuite([

it('applies show style with complex conditional', function() {
var style = new Cesium3DTileStyle({
"expressions": {
"Height" : "${Height} * 1.01"
},
"show" : {
"expression" : "${Height}",
"conditions" : [
["(${expression} >= 1.0) && (${expression} < 10.0)", "true"],
["(${expression} >= 10.0) && (${expression} < 30.0)", "false"],
["(${expression} >= 30.0) && (${expression} < 50.0)", "true"],
["(${expression} >= 50.0) && (${expression} < 70.0)", "false"],
["(${expression} >= 70.0) && (${expression} < 100.0)", "true"],
["(${expression} >= 100.0)", "false"]
["(${Height} >= 1.0) && (${Height} < 10.0)", "true"],
["(${Height} >= 10.0) && (${Height} < 30.0)", "false"],
["(${Height} >= 30.0) && (${Height} < 50.0)", "true"],
["(${Height} >= 50.0) && (${Height} < 70.0)", "false"],
["(${Height} >= 70.0) && (${Height} < 100.0)", "true"],
["(${Height} >= 100.0)", "false"]
]
}
});
Expand Down Expand Up @@ -507,6 +509,36 @@ defineSuite([
expect(style.pointSize.evaluate(frameState, feature2)).toEqual(3);
});

it('applies with additional expressions', function() {
var style = new Cesium3DTileStyle({
"expressions" : {
"halfHeight" : "${Height} / 2",
"quarterHeight" : "${Height} / 4",
"halfVolume" : "${volume} / 2"
},
"color" : {
"conditions" : [
["(${halfHeight} >= 25.0)", "color('red')"],
["(${Height} >= 1.0)", "color('blue')"]
]
},
"show" : "(${quarterHeight} >= 20.0)",
"pointSize" : "${halfVolume} + ${halfHeight}",
"meta" : {
"description" : "'Half height is ' + ${halfHeight}"
}
});

expect(style.color.evaluateColor(frameState, feature1)).toEqual(Color.RED);
expect(style.color.evaluateColor(frameState, feature2)).toEqual(Color.BLUE);
expect(style.show.evaluate(frameState, feature1)).toEqual(true);
expect(style.show.evaluate(frameState, feature2)).toEqual(false);
expect(style.pointSize.evaluate(frameState, feature1)).toEqual(114);
expect(style.pointSize.evaluate(frameState, feature2)).toEqual(44);
expect(style.meta.description.evaluate(frameState, feature1)).toEqual('Half height is 50');
expect(style.meta.description.evaluate(frameState, feature2)).toEqual('Half height is 19');
});

it('return undefined shader functions when the style is empty', function() {
// The default color style is white, the default show style is true, and the default pointSize is 1.0,
// but the generated generated shader functions should just be undefined. We don't want all the points to be white.
Expand Down
81 changes: 9 additions & 72 deletions Specs/Scene/ConditionsExpressionSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,70 +25,33 @@ defineSuite([
]
};

var jsonExpWithExpression = {
expressions : {
halfHeight: '${Height}/2'
},
conditions : [
['${expression} > 50', 'color("blue")'],
['${expression} > 25', 'color("red")'],
['true', 'color("lime")']
]
var additionalExpressions = {
halfHeight: '${Height}/2',
quarterHeight: '${Height}/4'
};

var jsonExpWithMultipleExpressions = {
expressions : {
halfHeight: '${Height}/2',
quarterHeight: '${Height}/4'
},
var jsonExpWithAdditionalExpressions = {
conditions : [
['${halfHeight} > 50 && ${halfHeight} < 100', 'color("blue")'],
['${quarterHeight} > 50 && ${quarterHeight} < 52', 'color("red")'],
['true', 'color("lime")']
]
};

var jsonExpWithUndefinedExpression = {
conditions : [
['${expression} === undefined', 'color("blue")'],
['true', 'color("lime")']
]
};

it('constructs', function() {
var expression = new ConditionsExpression(jsonExp);
expect(expression.conditionsExpression).toEqual(jsonExp);
});

it('constructs with expression', function() {
var expression = new ConditionsExpression(jsonExpWithExpression);
expect(expression._expression).toEqual('${Height}/2');
expect(expression._conditions).toEqual([
['${expression} > 50', 'color("blue")'],
['${expression} > 25', 'color("red")'],
['true', 'color("lime")']
]);
});

it('evaluates undefined expression', function() {
var expression = new ConditionsExpression(jsonExpWithExpression);
expect(expression._expression).toEqual('${Height}/2');
expect(expression._conditions).toEqual([
['${expression} > 50', 'color("blue")'],
['${expression} > 25', 'color("red")'],
['true', 'color("lime")']
]);
});

it('evaluates conditional', function() {
var expression = new ConditionsExpression(jsonExp);
expect(expression.evaluateColor(frameState, new MockFeature(101))).toEqual(Color.BLUE);
expect(expression.evaluateColor(frameState, new MockFeature(52))).toEqual(Color.RED);
expect(expression.evaluateColor(frameState, new MockFeature(3))).toEqual(Color.LIME);
});

it('evaluates conditional with multiple expressions', function() {
var expression = new ConditionsExpression(jsonExpWithMultipleExpressions);
it('evaluates conditional with additional expressions', function() {
var expression = new ConditionsExpression(jsonExpWithAdditionalExpressions, additionalExpressions);
expect(expression.evaluateColor(frameState, new MockFeature(101))).toEqual(Color.BLUE);
expect(expression.evaluateColor(frameState, new MockFeature(52))).toEqual(Color.LIME);
expect(expression.evaluateColor(frameState, new MockFeature(3))).toEqual(Color.LIME);
Expand All @@ -112,42 +75,16 @@ defineSuite([
expect(expression.evaluate(frameState, new MockFeature(3))).toEqual(undefined);
});

it('evaluates conditional with expression', function() {
var expression = new ConditionsExpression(jsonExpWithExpression);
expect(expression.evaluateColor(frameState, new MockFeature(101))).toEqual(Color.BLUE);
expect(expression.evaluateColor(frameState, new MockFeature(52))).toEqual(Color.RED);
expect(expression.evaluateColor(frameState, new MockFeature(3))).toEqual(Color.LIME);
});

it('evaluates undefined conditional expression', function() {
var expression = new ConditionsExpression(jsonExpWithUndefinedExpression);
expect(expression._expression).toEqual(undefined);
expect(expression.evaluateColor(frameState, undefined)).toEqual(Color.BLUE);
});

it('constructs and evaluates conditional expression with multiple expressions', function() {
var expression = new ConditionsExpression(jsonExpWithMultipleExpressions);
expect(expression._expressions).toEqual({halfHeight: '${Height}/2', quarterHeight: '${Height}/4'});
expect(expression._conditions).toEqual([
['${halfHeight} > 50 && ${halfHeight} < 100', 'color("blue")'],
['${quarterHeight} > 50 && ${quarterHeight} < 52', 'color("red")'],
['true', 'color("lime")']
]);
expect(expression.evaluateColor(frameState, new MockFeature(101))).toEqual(Color.BLUE);
expect(expression.evaluateColor(frameState, new MockFeature(52))).toEqual(Color.LIME);
expect(expression.evaluateColor(frameState, new MockFeature(3))).toEqual(Color.LIME);
});

it('gets shader function', function() {
var expression = new ConditionsExpression(jsonExpWithExpression);
var expression = new ConditionsExpression(jsonExp);
var shaderFunction = expression.getShaderFunction('getColor', '', {}, 'vec4');
var expected = 'vec4 getColor() \n' +
'{ \n' +
' if (((Height / 2.0) > 50.0)) \n' +
' if ((Height > 100.0)) \n' +
' { \n' +
' return vec4(vec3(0.0, 0.0, 1.0), 1.0); \n' +
' } \n' +
' else if (((Height / 2.0) > 25.0)) \n' +
' else if ((Height > 50.0)) \n' +
' { \n' +
' return vec4(vec3(1.0, 0.0, 0.0), 1.0); \n' +
' } \n' +
Expand Down
Loading

0 comments on commit 8c84e10

Please sign in to comment.