Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for multiple expressions with passing tests #5232

Merged
merged 10 commits into from
May 23, 2017
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
16 changes: 16 additions & 0 deletions Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@
pointSize : "${temperature} * 10"
});

addStyle('Multiple expressions', {
expressions : {
length : "length(${POSITION})",
time : "${tiles3d_tileset_time} * 3.0"
},
color : {
conditions : [
["${length} < 0.5", "${length} * color('red')"],
["${length} < 1.0", "vec4(vec3(${temperature} * fract(${time})), 1.0)"],
["true", "${COLOR}"]
]
},
pointSize : "5.0 - ${length} * 2.0",
show : "${length} < 2.0"
});

function setStyle(style) {
return function() {
tileset.style = new Cesium.Cesium3DTileStyle(style);
Expand Down
20 changes: 11 additions & 9 deletions Source/Scene/Cesium3DTileStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,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 @@ -145,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
30 changes: 9 additions & 21 deletions Source/Scene/ConditionsExpression.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ define([
Expression) {
'use strict';

var expressionPlaceholder = /\$\{expression}/g;

/**
* Evaluates a conditions expression defined using the
* {@link https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/Styling|3D Tiles Styling language}.
Expand All @@ -28,28 +26,26 @@ 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({
* expression : 'regExp("^1(\\d)").exec(${id})',
* var expression = new Cesium.ConditionsExpression({
* conditions : [
* ['${expression} === "1"', 'color("#FF0000")'],
* ['${expression} === "2"', 'color("#00FF00")'],
* ['${Area} > 10, 'color("#FF0000")'],
* ['${id} !== "1"', 'color("#00FF00")'],
* ['true', 'color("#FFFFFF")']
* ]
* });
* expression.evaluateColor(frameState, feature, result); // returns a Cesium.Color object
*
* @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;
this._expression = conditionsExpression.expression;

this._runtimeConditions = undefined;

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

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

function setRuntime(expression) {
function setRuntime(expression, expressions) {
var runtimeConditions = [];
var conditions = expression._conditions;
if (defined(conditions)) {
var exp = expression._expression;
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]);
if (defined(exp)) {
cond = cond.replace(expressionPlaceholder, exp);
condExpression = condExpression.replace(expressionPlaceholder, exp);
} 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
20 changes: 19 additions & 1 deletion Source/Scene/Expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,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 @@ -304,12 +305,13 @@ 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);
Check.typeOf.string('expression', expression);
//>>includeEnd('debug');

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

// customize jsep operators
Expand Down Expand Up @@ -435,6 +437,22 @@ define([
setEvaluateFunction(this);
}

function replaceExpressions(expression, expressions) {
if (!defined(expressions)) {
return expression;
}
for (var key in expressions) {
if (expressions.hasOwnProperty(key)) {
var expressionPlaceholder = new RegExp('\\$\\{' + key + '\\}', 'g');
var expressionReplace = expressions[key];
if (defined(expressionReplace)) {
expression = expression.replace(expressionPlaceholder, expressionReplace);
}
}
}
return expression;
}

function removeBackslashes(expression) {
return expression.replace(backslashRegex, backslashReplacement);
}
Expand Down
93 changes: 35 additions & 58 deletions Specs/Scene/Cesium3DTileStyleSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,24 +348,6 @@ defineSuite([
expect(style.color.evaluateColor(frameState, undefined)).toEqual(Color.WHITE);
});

it('applies show style with complex conditional', function() {
var style = new Cesium3DTileStyle({
"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"]
]
}
});
expect(style.show.evaluate(frameState, feature1)).toEqual(false);
expect(style.show.evaluate(frameState, feature2)).toEqual(true);
});

it('applies show style with conditional', function() {
var style = new Cesium3DTileStyle({
"show" : {
Expand Down Expand Up @@ -403,11 +385,13 @@ defineSuite([

it('applies color style that maps id to color', function() {
var style = new Cesium3DTileStyle({
"expressions" : {
"id" : "regExp('^1(\\d)').exec(String(${id}))"
},
"color" : {
"expression" : "regExp('^1(\\d)').exec(String(${id}))",
"conditions" : [
["${expression} === '1'", "color('#FF0000')"],
["${expression} === '2'", "color('#00FF00')"],
["${id} === '1'", "color('#FF0000')"],
["${id} === '2'", "color('#00FF00')"],
["true", "color('#FFFFFF')"]
]
}
Expand All @@ -417,25 +401,6 @@ defineSuite([
expect(style.color.evaluateColor(frameState, feature2)).toEqual(Color.LIME);
});

it('applies color style with complex conditional', function() {
var style = new Cesium3DTileStyle({
"color" : {
"expression" : "${Height}",
"conditions" : [
["(${expression} >= 1.0) && (${expression} < 10.0)", "color('#FF00FF')"],
["(${expression} >= 10.0) && (${expression} < 30.0)", "color('#FF0000')"],
["(${expression} >= 30.0) && (${expression} < 50.0)", "color('#FFFF00')"],
["(${expression} >= 50.0) && (${expression} < 70.0)", "color('#00FF00')"],
["(${expression} >= 70.0) && (${expression} < 100.0)", "color('#00FFFF')"],
["(${expression} >= 100.0)", "color('#0000FF')"]
]
}
});
expect(style.show.evaluate(frameState, feature1)).toEqual(true);
expect(style.color.evaluateColor(frameState, feature1)).toEqual(Color.BLUE);
expect(style.color.evaluateColor(frameState, feature2)).toEqual(Color.YELLOW);
});

it('applies color style with conditional', function() {
var style = new Cesium3DTileStyle({
"color" : {
Expand Down Expand Up @@ -472,24 +437,6 @@ defineSuite([
expect(style.pointSize.evaluate(frameState, feature2)).toEqual(1.0);
});

it('applies pointSize style with complex conditional', function() {
var style = new Cesium3DTileStyle({
"pointSize" : {
"expression" : "${Height}",
"conditions" : [
["(${expression} >= 1.0) && (${expression} < 10.0)", "1"],
["(${expression} >= 10.0) && (${expression} < 30.0)", "2"],
["(${expression} >= 30.0) && (${expression} < 50.0)", "3"],
["(${expression} >= 50.0) && (${expression} < 70.0)", "4"],
["(${expression} >= 70.0) && (${expression} < 100.0)", "5"],
["(${expression} >= 100.0)", "6"]
]
}
});
expect(style.pointSize.evaluate(frameState, feature1)).toEqual(6);
expect(style.pointSize.evaluate(frameState, feature2)).toEqual(3);
});

it('applies pointSize style with conditional', function() {
var style = new Cesium3DTileStyle({
"pointSize" : {
Expand All @@ -507,6 +454,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
Loading