Skip to content

Commit

Permalink
Merge pull request #5232 from Jane-Of-Art/multiExpressions
Browse files Browse the repository at this point in the history
Added support for multiple expressions with passing tests
  • Loading branch information
pjcozzi authored May 23, 2017
2 parents 7f3a979 + be3933e commit 6761474
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 155 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
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

0 comments on commit 6761474

Please sign in to comment.