Add abs, round, floor, ceil operators (#11653)
* Add abs, round, floor, ceil operators Port of https://github.com/mapbox/mapbox-gl-js/pull/6496 * [ios, macos] Simplified abs, ceiling, floor expressions * [ios, macos] Added rounding expression function * [android] - binding integration for round, ceil, floor and abs expressions * Update mapbox-gl-js to include non-integer rounding test * Drop extra braces * mapbox-gl-js -> master * Update style-spec docs -> PropertyFactory.java
This commit is contained in:
Submodule mapbox-gl-js updated: b01859294f...6b96d69ab5
@@ -81,7 +81,6 @@ import java.util.List;
|
||||
* )
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class Expression {
|
||||
|
||||
@@ -1061,6 +1060,7 @@ public class Expression {
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-properties">Style specification</a>
|
||||
*/
|
||||
@@ -1081,6 +1081,7 @@ public class Expression {
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-geometry-types">Style specification</a>
|
||||
*/
|
||||
@@ -2294,6 +2295,185 @@ public class Expression {
|
||||
return max(numberExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the input to the nearest integer.
|
||||
* Halfway values are rounded away from zero.
|
||||
* For example `[\"round\", -1.5]` evaluates to -2.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(round(pi()))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param expression number expression to round
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-round">Style specification</a>
|
||||
*/
|
||||
public static Expression round(Expression expression) {
|
||||
return new Expression("round", expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the input to the nearest integer.
|
||||
* Halfway values are rounded away from zero.
|
||||
* For example `[\"round\", -1.5]` evaluates to -2.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(round(3.14159265359f))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param number number to round
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-round">Style specification</a>
|
||||
*/
|
||||
public static Expression round(Number number) {
|
||||
return round(literal(number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of the input.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(abs(subtract(pi())))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param expression number expression to get absolute value from
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
|
||||
*/
|
||||
public static Expression abs(Expression expression) {
|
||||
return new Expression("abs", expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of the input.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(abs(-3.14159265359f))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param number number to get absolute value from
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
|
||||
*/
|
||||
public static Expression abs(Number number) {
|
||||
return abs(literal(number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smallest integer that is greater than or equal to the input.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(ceil(pi()))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param expression number expression to get value from
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
|
||||
*/
|
||||
public static Expression ceil(Expression expression) {
|
||||
return new Expression("ceil", expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the smallest integer that is greater than or equal to the input.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(ceil(3.14159265359))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
* @param number number to get value from
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
|
||||
*/
|
||||
public static Expression ceil(Number number) {
|
||||
return ceil(literal(number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest integer that is less than or equal to the input.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(floor(pi()))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param expression number expression to get value from
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
|
||||
*/
|
||||
public static Expression floor(Expression expression) {
|
||||
return new Expression("floor", expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the largest integer that is less than or equal to the input.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
|
||||
* circleLayer.setProperties(
|
||||
* circleRadius(floor(pi()))
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param number number to get value from
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
|
||||
*/
|
||||
public static Expression floor(Number number) {
|
||||
return floor(literal(number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the input string converted to uppercase.
|
||||
* <p>
|
||||
@@ -3128,6 +3308,7 @@ public class Expression {
|
||||
* );
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param expression base number expression
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
|
||||
|
||||
@@ -1856,7 +1856,7 @@ public class PropertyFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of image in sprite to use for drawing an image background. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
|
||||
* Name of image in sprite to use for drawing an image background.
|
||||
*
|
||||
* @param value a String value
|
||||
* @return property wrapper around String
|
||||
@@ -1866,7 +1866,7 @@ public class PropertyFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of image in sprite to use for drawing an image background. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
|
||||
* Name of image in sprite to use for drawing an image background.
|
||||
*
|
||||
* @param value a String value
|
||||
* @return property wrapper around String
|
||||
@@ -2036,7 +2036,7 @@ public class PropertyFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Value to use for a text label. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
|
||||
* Value to use for a text label.
|
||||
*
|
||||
* @param value a String value
|
||||
* @return property wrapper around String
|
||||
@@ -2046,7 +2046,7 @@ public class PropertyFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Value to use for a text label. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
|
||||
* Value to use for a text label.
|
||||
*
|
||||
* @param value a String value
|
||||
* @return property wrapper around String
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.abs;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.acos;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.any;
|
||||
@@ -14,6 +15,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.asin;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.at;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.atan;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.bool;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.ceil;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.coalesce;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
|
||||
@@ -24,6 +26,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.downcase;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.e;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.floor;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.geometryType;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.gt;
|
||||
@@ -56,6 +59,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.properties;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.round;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.sin;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.sqrt;
|
||||
import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
|
||||
@@ -1105,4 +1109,60 @@ public class ExpressionTest {
|
||||
);
|
||||
expression.toArray();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRound() {
|
||||
Object[] expected = new Object[] {"round", 2.2f};
|
||||
Object[] actual = round(2.2f).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundLiteral() {
|
||||
Object[] expected = new Object[] {"round", 2.2f};
|
||||
Object[] actual = round(literal(2.2f)).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbs() {
|
||||
Object[] expected = new Object[] {"abs", -2.2f};
|
||||
Object[] actual = abs(-2.2f).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbsLiteral() {
|
||||
Object[] expected = new Object[] {"abs", -2.2f};
|
||||
Object[] actual = abs(literal(-2.2f)).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCeil() {
|
||||
Object[] expected = new Object[] {"ceil", 2.2f};
|
||||
Object[] actual = ceil(2.2f).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCeilLiteral() {
|
||||
Object[] expected = new Object[] {"ceil", 2.2f};
|
||||
Object[] actual = ceil(literal(2.2f)).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFloor() {
|
||||
Object[] expected = new Object[] {"floor", 2.2f};
|
||||
Object[] actual = floor(2.2f).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFloorLiteral() {
|
||||
Object[] expected = new Object[] {"floor", 2.2f};
|
||||
Object[] actual = floor(literal(2.2f)).toArray();
|
||||
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
|
||||
}
|
||||
}
|
||||
@@ -379,11 +379,14 @@ In style specification | Method, function, or predicate type | Format string syn
|
||||
`%` | `modulus:by:` |
|
||||
`^` | `raise:toPower:` | `2 ** 2`
|
||||
`+` | `add:to:` | `1 + 2`
|
||||
`abs` | `abs:` | `abs(-1)`
|
||||
`acos` | |
|
||||
`asin` | |
|
||||
`atan` | |
|
||||
`ceil` | `ceiling:` | `ceiling(0.99999)`
|
||||
`cos` | |
|
||||
`e` | | `%@` representing `NSNumber` containing `M_E`
|
||||
`floor` | `floor:` | `floor(-0.99999)`
|
||||
`ln` | `ln:` | `ln(2)`
|
||||
`ln2` | | `%@` representing `NSNumber` containing `M_LN2`
|
||||
`log10` | `log:` | `log(1)`
|
||||
@@ -391,6 +394,7 @@ In style specification | Method, function, or predicate type | Format string syn
|
||||
`max` | `max:` | `max({1, 2, 2, 3, 4, 7, 9})`
|
||||
`min` | `min:` | `min({1, 2, 2, 3, 4, 7, 9})`
|
||||
`pi` | | `%@` representing `NSNumber` containing `M_PI`
|
||||
`round` | `mgl_round:` | `mgl_round(1.5)`
|
||||
`sin` | |
|
||||
`sqrt` | `sqrt:` | `sqrt(2)`
|
||||
`tan` | |
|
||||
|
||||
@@ -196,6 +196,7 @@ Initializer parameter | Format string syntax | Description
|
||||
`mgl_interpolate:withCurveType:parameters:stops:` | `mgl_interpolate:withCurveType:parameters:stops:(x, 'linear', nil, %@)` | Produces continuous, smooth results by interpolating between pairs of input and output values (“stops”). Compared to the `mgl_interpolateWithCurveType:parameters:stops:` custom function, the input expression (that function’s target) is instead passed in as the first argument to this function.
|
||||
`mgl_step:from:stops:` | `mgl_step:from:stops:(x, 11, %@)` | Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of input and output values ("stops"). Compared to the `mgl_stepWithMinimum:stops:` custom function, the input expression (that function’s target) is instead passed in as the first argument to this function.
|
||||
`mgl_join:` | `mgl_join({'Old', 'MacDonald'})` | Returns the result of concatenating together all the elements of an array in order. Compared to the `stringByAppendingString:` custom function, this function takes only one argument, which is an aggregate expression containing the strings to concatenate.
|
||||
`mgl_round:` | `mgl_round(1.5)` | Returns the number rounded to the nearest integer. If the number is halfway between two integers, this function rounds it away from zero.
|
||||
`mgl_coalesce:` | `mgl_coalesce({x, y, z})` | Returns the first non-`nil` value from an array of expressions.
|
||||
`MGL_LET` | `MGL_LET('age', uppercase('old'), 'name', uppercase('MacDonald'), mgl_join({$age, $name}))` | Any number of variable names interspersed with their assigned `NSExpression` values, followed by an `NSExpression` that may contain references to those variables. Compared to the `mgl_expressionWithContext:` custom function, this function takes the variable names and values inline before the expression that contains references to those variables.
|
||||
`MGL_MATCH` | `MGL_MATCH(x, 0, 'zero match', 1, 'one match', 'two match', 'default')` | Evaluates the first expression and returns the value that matches the initial condition. After the first expression condition a pair of matching/return value should be added and a default value.
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
// Install method-like functions, taking the number of arguments implied by
|
||||
// the selector name.
|
||||
INSTALL_METHOD(mgl_join:);
|
||||
INSTALL_METHOD(mgl_round:);
|
||||
INSTALL_METHOD(mgl_interpolate:withCurveType:parameters:stops:);
|
||||
INSTALL_METHOD(mgl_step:from:stops:);
|
||||
INSTALL_METHOD(mgl_coalesce:);
|
||||
@@ -83,6 +84,14 @@
|
||||
return [components componentsJoinedByString:@""];
|
||||
}
|
||||
|
||||
/**
|
||||
Rounds the given number to the nearest integer. If the number is halfway
|
||||
between two integers, this method rounds it away from zero.
|
||||
*/
|
||||
- (NSNumber *)mgl_round:(NSNumber *)number {
|
||||
return @(round(number.doubleValue));
|
||||
}
|
||||
|
||||
/**
|
||||
A placeholder for a method that evaluates an interpolation expression.
|
||||
*/
|
||||
@@ -487,6 +496,10 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
|
||||
@"sqrt": @"sqrt:",
|
||||
@"log10": @"log:",
|
||||
@"ln": @"ln:",
|
||||
@"abs": @"abs:",
|
||||
@"round": @"mgl_round:",
|
||||
@"floor": @"floor:",
|
||||
@"ceil": @"ceiling:",
|
||||
@"^": @"raise:toPower:",
|
||||
@"upcase": @"uppercase:",
|
||||
@"downcase": @"lowercase:",
|
||||
@@ -720,9 +733,13 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
|
||||
@"log:": @"log10",
|
||||
@"ln:": @"ln",
|
||||
@"raise:toPower:": @"^",
|
||||
@"ceiling:": @"ceil",
|
||||
@"abs:": @"abs",
|
||||
@"floor:": @"floor",
|
||||
@"uppercase:": @"upcase",
|
||||
@"lowercase:": @"downcase",
|
||||
@"length:": @"length",
|
||||
@"mgl_round:": @"round",
|
||||
// Vararg aftermarket expressions need to be declared with an explicit and implicit first argument.
|
||||
@"MGL_LET": @"let",
|
||||
@"MGL_LET:": @"let",
|
||||
@@ -826,18 +843,9 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
|
||||
return [@[@"max"] arrayByAddingObjectsFromArray:arguments];
|
||||
} else if ([function isEqualToString:@"exp:"]) {
|
||||
return [NSExpression expressionForFunction:@"raise:toPower:" arguments:@[@(M_E), self.arguments.firstObject]].mgl_jsonExpressionObject;
|
||||
} else if ([function isEqualToString:@"ceiling:"]) {
|
||||
return [NSExpression expressionWithFormat:@"trunc:(%@) + TERNARY(modulus:by:(%@, 1) > 0, 1, 0)",
|
||||
self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
|
||||
} else if ([function isEqualToString:@"trunc:"]) {
|
||||
return [NSExpression expressionWithFormat:@"%@ - modulus:by:(%@, 1)",
|
||||
self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
|
||||
} else if ([function isEqualToString:@"abs:"]) {
|
||||
return [NSExpression expressionWithFormat:@"%@ * TERNARY(%@ > 0, 1, -1)",
|
||||
self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
|
||||
} else if ([function isEqualToString:@"floor:"]) {
|
||||
return [NSExpression expressionWithFormat:@"trunc:(%@) - TERNARY(modulus:by:(%@, 1) < 0, 1, 0)",
|
||||
self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
|
||||
} else if ([function isEqualToString:@"mgl_join:"]) {
|
||||
NSArray *arguments = [self.arguments.firstObject.collection valueForKeyPath:@"mgl_jsonExpressionObject"];
|
||||
return [@[@"concat"] arrayByAddingObjectsFromArray:arguments];
|
||||
|
||||
@@ -393,29 +393,25 @@ using namespace std::string_literals;
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@1.5)]];
|
||||
NSArray *jsonTruncation = @[@"-", @1.5, @[@"%", @1.5, @1]];
|
||||
NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @1.5, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"ceil", @1.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@-1.5)]];
|
||||
NSArray *jsonTruncation = @[@"-", @-1.5, @[@"%", @-1.5, @1]];
|
||||
NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @-1.5, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"ceil", @-1.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-1);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@2)]];
|
||||
NSArray *jsonTruncation = @[@"-", @2, @[@"%", @2, @1]];
|
||||
NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @2, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"ceil", @2];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@-2)]];
|
||||
NSArray *jsonTruncation = @[@"-", @-2, @[@"%", @-2, @1]];
|
||||
NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @-2, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"ceil", @-2];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
|
||||
}
|
||||
@@ -433,44 +429,64 @@ using namespace std::string_literals;
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"abs:" arguments:@[MGLConstantExpression(@2)]];
|
||||
NSArray *jsonExpression = @[@"*", @2, @[@"case", @[@">", @2, @0], @1, @-1]];
|
||||
NSArray *jsonExpression = @[@"abs", @2];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"abs:" arguments:@[MGLConstantExpression(@-2)]];
|
||||
NSArray *jsonExpression = @[@"*", @-2, @[@"case", @[@">", @-2, @0], @1, @-1]];
|
||||
NSArray *jsonExpression = @[@"abs", @-2];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@1.5)]];
|
||||
NSArray *jsonTruncation = @[@"-", @1.5, @[@"%", @1.5, @1]];
|
||||
NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @1.5, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"floor", @1.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@-1.5)]];
|
||||
NSArray *jsonTruncation = @[@"-", @-1.5, @[@"%", @-1.5, @1]];
|
||||
NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @-1.5, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"floor", @-1.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@2)]];
|
||||
NSArray *jsonTruncation = @[@"-", @2, @[@"%", @2, @1]];
|
||||
NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @2, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"floor", @2];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@-2)]];
|
||||
NSArray *jsonTruncation = @[@"-", @-2, @[@"%", @-2, @1]];
|
||||
NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @-2, @1], @0], @1, @0]];
|
||||
NSArray *jsonExpression = @[@"floor", @-2];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@1.5)]];
|
||||
NSArray *jsonExpression = @[@"round", @1.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@-1.5)]];
|
||||
NSArray *jsonExpression = @[@"round", @-1.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@2.5)]];
|
||||
NSArray *jsonExpression = @[@"round", @2.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @3);
|
||||
}
|
||||
{
|
||||
NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@-2.5)]];
|
||||
NSArray *jsonExpression = @[@"round", @-2.5];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-3);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)testTrigonometricExpressionObject {
|
||||
|
||||
@@ -364,11 +364,14 @@ In style specification | Method, function, or predicate type | Format string syn
|
||||
`%` | `modulus:by:` |
|
||||
`^` | `raise:toPower:` | `2 ** 2`
|
||||
`+` | `add:to:` | `1 + 2`
|
||||
`abs` | `abs:` | `abs(-1)`
|
||||
`acos` | |
|
||||
`asin` | |
|
||||
`atan` | |
|
||||
`ceil` | `ceiling:` | `ceiling(0.99999)`
|
||||
`cos` | |
|
||||
`e` | | `%@` representing `NSNumber` containing `M_E`
|
||||
`floor` | `floor:` | `floor(-0.99999)`
|
||||
`ln` | `ln:` | `ln(2)`
|
||||
`ln2` | | `%@` representing `NSNumber` containing `M_LN2`
|
||||
`log10` | `log:` | `log(1)`
|
||||
@@ -376,6 +379,7 @@ In style specification | Method, function, or predicate type | Format string syn
|
||||
`max` | `max:` | `max({1, 2, 2, 3, 4, 7, 9})`
|
||||
`min` | `min:` | `min({1, 2, 2, 3, 4, 7, 9})`
|
||||
`pi` | | `%@` representing `NSNumber` containing `M_PI`
|
||||
`round` | `mgl_round:` | `mgl_round(1.5)`
|
||||
`sin` | |
|
||||
`sqrt` | `sqrt:` | `sqrt(2)`
|
||||
`tan` | |
|
||||
|
||||
@@ -357,11 +357,14 @@ In style specification | Method, function, or predicate type | Format string syn
|
||||
`%` | `modulus:by:` |
|
||||
`^` | `raise:toPower:` | `2 ** 2`
|
||||
`+` | `add:to:` | `1 + 2`
|
||||
`abs` | `abs:` | `abs(-1)`
|
||||
`acos` | |
|
||||
`asin` | |
|
||||
`atan` | |
|
||||
`ceil` | `ceiling:` | `ceiling(0.99999)`
|
||||
`cos` | |
|
||||
`e` | | `%@` representing `NSNumber` containing `M_E`
|
||||
`floor` | `floor:` | `floor(-0.99999)`
|
||||
`ln` | `ln:` | `ln(2)`
|
||||
`ln2` | | `%@` representing `NSNumber` containing `M_LN2`
|
||||
`log10` | `log:` | `log(1)`
|
||||
@@ -369,6 +372,7 @@ In style specification | Method, function, or predicate type | Format string syn
|
||||
`max` | `max:` | `max({1, 2, 2, 3, 4, 7, 9})`
|
||||
`min` | `min:` | `min({1, 2, 2, 3, 4, 7, 9})`
|
||||
`pi` | | `%@` representing `NSNumber` containing `M_PI`
|
||||
`round` | `mgl_round:` | `mgl_round(1.5)`
|
||||
`sin` | |
|
||||
`sqrt` | `sqrt:` | `sqrt(2)`
|
||||
`tan` | |
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <mbgl/util/ignore.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/platform.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
@@ -362,6 +363,11 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
|
||||
return result;
|
||||
});
|
||||
|
||||
define("round", [](double x) -> Result<double> { return std::round(x); });
|
||||
define("floor", [](double x) -> Result<double> { return std::floor(x); });
|
||||
define("ceil", [](double x) -> Result<double> { return std::ceil(x); });
|
||||
define("abs", [](double x) -> Result<double> { return std::abs(x); });
|
||||
|
||||
define(">", [](double lhs, double rhs) -> Result<bool> { return lhs > rhs; });
|
||||
define(">", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs > rhs; });
|
||||
define(">=", [](double lhs, double rhs) -> Result<bool> { return lhs >= rhs; });
|
||||
|
||||
Reference in New Issue
Block a user