SmartShape QL Language Reference
Basic concepts¶
Functional programing¶
The goal of the SmartShape Query Language (aka "SmartShapeQL") is to perform computations on large tree-like data sets, such as the scene tree of the 3D scene. As such, it aims at efficiency and seeks performance through massive lock-free parallelisation. This is why SmartShapeQL is a (pure) functional programing language.
As a functional programing languages, SmartShapeQL is different from other languages such as C or Javascript. Those differences include (but are not limited to):
- there are no variables, only immutable constants
- there are no
fororwhileloops, only iterators
You can read more on functional programing on Wikipedia.
Use cases¶
SmartShapeQL evaluation is used to implement many features of the SmartShape platform. In many place, the API will accept and store SmartShapeQL programs instead of values in order to implement business logic in key areas of the platforms.
SmartshapeQL (Smartshape Query Language) is used throughout Smartshape and covers: - Nodes search - Annotations search - Behaviors - Layers - Rendering styles - Search forms - Attribute metadata - Attribute transformation
SmartshapeQL queries: - Can only access data the current user is allowed to access to. - Are case-insensitive.
Similarities and differences with other languages¶
Similarities¶
Function calls¶
Functions are called like in most programming languages, by writing their name followed by their parameters in parentheses. Functions can return only one value.
Types¶
SmartShapeQL is a dynamically typed language. Its memory model is loosely based on the one of Javascript.
Differences¶
Variables¶
Variables are more similar to macros in other languages. They are defined only once by the runtime and the query cannot declare nor modify any variable.
Expressions¶
A SmartShapeQL query is composed of only one expression, so complex behavior is achieved by composing function calls.
Notion of context¶
Depending on the API the query is called in, it may behave differently.
Nodes search¶
The query is applied to each node of the scene and is casted to a boolean value to know whether the node is kept in the search results or not. By default, when no operator nor qualifier is used, the query matches the node name.
Variables¶
$smartshape: See the reference on the$smartshapevariable [TBD].
Axis operators¶
children, /¶
Executes a subquery on the direct children of the current node and returns every child that matches the subquery.
Note: This operator won’t match the currently evaluated node if used in conjunction with “parent”.
parent, ..¶
Executes a subquery on the parents of the current node and returns every parent that matches the subquery.
## Match the nodes whose siblings have the attribute "TypeRemarque" equal to "Reprise".
## Note that the / operator won't match the currently evaluated node.
..children:(@"TypeRemarque"="Reprise")
ancestors, ...¶
Executes a subquery on all the ancestors of the current node and returns every ancestor that matches the subquery.
.¶
The . operator references the current element that the query is being evaluated on. Useful for calling functions on it.
Axis List¶
| Axis Operator | Axis Operator Shorthand |
|---|---|
| children | / |
| parent | .. |
| ancestors | ... |
| current element | . |
Qualifiers¶
Node qualifiers allow to access some properties of the currently evaluated node.
Syntax¶
All qualifiers have a long notation.
For some qualifiers, a short notation is available.
Long notation¶
Short notation¶
Implicit “and”¶
All operators can be combined with an implicit “and”. For instance, you could find all the walls with a wood material with a query like:
which is equivalent to:Qualifiers list¶
| Qualifier | Qualifier Shorthand |
|---|---|
| name | N/A |
| attribute | @ |
| layer | % |
| inherited-layer | %% |
| modifier | N/A |
| inherited-modifier | N/A |
| id | N/A |
| uuid | N/A |
name¶
Matches a node with a given name.
## Get the node named "Pillar 1"
name:"Pillar 1"
## Get all the nodes whose name begins with "Pillar"
name:"Pillar*"
attribute, @¶
Matches a node which contains a given attribute. This operator returns the value of the matched attribute, so it can be used to also match the value of the attribute.
## Get the nodes with a "Thickness" attribute.
attribute:"Thickness"
## Format the "Thickness" attribute value of the node to display it in a legend for instance.
concat(round(multiply(@"Thickness", 1000), 0), " mm")
layer, %¶
Matches a node belonging to a given layer.
Please note that this operator accepts only layer IDs.
## Match the nodes that belong to a given layer.
layer:5bf7ce66ec8d606d53c2fb91
%5bf7ce66ec8d606d53c2fb91
inherited-layer, %%¶
Matches a node that has an ancestor (or itself) belonging to a given layer. Please note that this operator accepts only layer IDs.
## Match the nodes that belong to a given layer or that have a parent belonging to a given layer.
inherited-layer:5bf7ce66ec8d606d53c2fb91
%%5bf7ce66ec8d606d53c2fb91
modifier¶
Matches a node that has a given modifier applied to it.
Accepted modifier types:
- hidden
- color
- transparent
- lock
inherited-modifier¶
Matches a node that has a given modifier applied to itself or its ancestors. See “modifier” for the list of accepted modifier types.
## Match the nodes that have a "hidden" modifier applied to them or their ancestors.
modifier:hidden
id¶
Matches a node with a specific id.
uuid¶
Matches a node with a specific uuid.
Legacy¶
Because SmartShapeQL was originally just a fancy list of operators for SmartShape's scene search engine, some legacy behaviors still apply.
Node name matching¶
By default, String literals are evaluated as the regular expression match against the name of the
context Node if any, or false otherwise.
For example, the program "groundfloor" will actually be evaluated to:
trueif the current contextNodehas its name set to "groundfloor";falseotherwise.
In certain cases, it is also possible to omit the quotes. For example groundfloor is evaluated to true if and only if the name of the current Node contains "groundfloor". It is equivalent to "*groundfloor*" (see text matching).
Implicit logical and¶
Unless explicitly specified otherwise, literal values are casted to Boolean and combined with the and operators.
For example, the "*42" @status=controlled program is strictly equivalent to "*42" and @status=controlled.
As such, it will return:
trueif the current contextNodename ends with "42" and has astatusattribute set to "controlled";falseotherwise.
Types¶
Boolean¶
Boolean literal values are true and false.
SmartShapeQL supports implicit coercion of other types to "truthy" and "falsy" boolean values:
- an empty
Stringis evaluated asfalse - the 0
Numberis evaluated asfalse, every otherNumberis evaluated astrue
String¶
String literal values are made of any string of characters that do not match any reserved keyword. Ambiguity can be resolved by using quotes:
For example:
falseis not aStringliteral (it's aBooleanliteral), but"false"is42fis aStringliteral-
42is not aStringliteral (it's aNumberliteral), but"42"is - String functions
Number¶
SmartShapeQL Number values are 64bit floating precision numerical values.
Integers are also represented using the Number type.
Array¶
SmartShapeQL support compound arrays: each Array can store values of mixed types.
Array values have no literal notation. Instead,Array values are created using the array() function.
Variables¶
Operators¶
Logical operators¶
Boolean operators¶
The &&, and ||, or, ! and not operators are available and work as expected.
Comparison operators¶
The =, !=, >, <, >= and <= operators are available and work as expected.
Note that there are no arithmetic operators.
This query is not valid
Use add insteadMath operators¶
Math operators are not available. Use math functions instead.
Array operators¶
[<¶
Works down the array and matches the first element found with a given text.
>]¶
Works down the array backwards and matches the first element found with a given text.
## Match the nodes whose "progress" array attribute contains "done" as its last value.
@progress>]"done"
[*]¶
Matches any element of an array with a given text.
## Match the nodes whose "progress" array attribute contains the value "done" at any index.
@progress[*]"done"
Text matching¶
Simple text search¶
The simplest form of a search query is a node name. Entering any text will match the nodes that have this character sequence in their name.
Find nodes whose name contain "groundfloor_entrance":
The characters authorized for simple text search are:
* Alphanumeric characters and letters with accents.
* ., -, _, @
If you need to search nodes by name with other characters, you can use quoting.
Globbing and quoting¶
You can use globbing (*) and quoting (" ") to fine-tune your query.
* characters match any character sequence:
## Match nodes whose name contains "basement_" then anything then "_ext"
## like "basement_room_a_ext_building_1" for instance.
basement_*_ext
" " characters match exactly the character sequence:
## Match all nodes whose name is exactly "groundfloor_entrance"
## unlike "groundfloor_entrance_door" for instance.
"groundfloor_entrance"
Functions¶
add(a: Number, b: Number) : Number¶
Returns a + b.
all(values: Array) : Boolean¶
Returns true if all elements of values are truthy, false otherwise.
apply(element: Any, query: Query) : Any¶
Runs query on element. Returns the return value of query.
array(value1: Any, value2: Any, …) : Array¶
Creates an array containing each value passed in argument in the same order they are passed in.
concat(leftString: String, rightString: String) : String¶
Concatenates two strings together.
Concatenate the “Status” attribute of the node with another String
count(values: Array) : Number¶
Counts the number of elements of an array.
Counts the number of children of the current node
divide(dividend: Number, divisor: Number) : Number¶
Returns dividend / divisor.
dot(vec1: Array, vec2: Array) : Number¶
Returns the dot product between vec1 and vec2.
vec1 and vec2 must be arrays of numbers of length 3.
flatten(values: Array) : Array¶
Flattens values a single level deep.
indexOf(values: Array, value: Any) : Number¶
Returns the index at which the first occurrence of value is stored in the values array.
fill(values: Array, item: Any, count: Number) : Array¶
Add the value item to the values array, count times.
filter(values: Array, query: Query) : Array¶
Creates a new array with all elements that pass the test implemented by the query.
Example:
floor(num: Number) : Number¶
Computes number rounded down to 0.
get(object: Object, field: String) : Any¶
Returns the field field of the object object.
getRangeIndex(value: Number, min: Number, max: Number, numRanges: Number) : Number¶
Returns the index of the range in which value is found.
Example:
map(values: Array, query: Query) : Array¶
Creates an array of values by running query over each element of values and returns the resulting array.
max(values: Array) : Number¶
Returns the maximum value of an array.
min(values: Array) : Number¶
Returns the minimum value of an array.
multiply(a: Number, b: Number) : Number¶
Returns a * b.
nth(values: Array, index: Number) : Any¶
Returns the element of values at index index.
range(min: Number, max: Number, step: Number) : Array¶
Returns the range [min, max]. If only one argument is given this method will assume it is for the range max.
Examples:
range(5) = array(0, 1, 2, 3, 4, 5)
range(3, 5) = array(3, 4, 5)
range(0, 10, 2) = array(0, 2, 4, 6, 8, 10)
replace(string: String, pattern: String, replacement: String) : String¶
Replaces matches for pattern in string with replacement.
round(num: Number, precision: Number) : Number¶
Computes num rounded to precision.
select(query: Query): Array<Node>¶
Executes a query on every node of the scene. Returns the nodes matched by the query.
Returns every node of the scene
sort(values: Array) : Array¶
Returns the values array sorted in ascending order. This method performs a stable sort, that is, it preserves the original sort order of equal elements.
string(value: Any) : String¶
Convert value to a String.
timestampToIsoDate(timestamp: Number, offset: Number) : String¶
Converts a UNIX timestamp (in milliseconds, like the dates stored in annotations) to an ISO 8601 date. The timezone can be chosen with the offset parameter which corresponds to the offset from UTC.
converts a timestamp to Eastern Standard Time
unique(values: Array) : Array¶
Returns a duplicate-free version of the values array. Only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the array.
Example:
zip(leftArray: Array, rightArray: Array) : Array¶
Creates an array of grouped elements, the first of which contains the first elements of the given arrays, the second of which contains the second elements of the given arrays, and so on.
Example: