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
for
orwhile
loops, 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$smartshape
variable [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:
true
if the current contextNode
has its name set to "groundfloor";false
otherwise.
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:
true
if the current contextNode
name ends with "42" and has astatus
attribute set to "controlled";false
otherwise.
Types¶
Boolean¶
Boolean literal values are true
and false
.
SmartShapeQL supports implicit coercion of other types to "truthy" and "falsy" boolean values:
- an empty
String
is evaluated asfalse
- the 0
Number
is evaluated asfalse
, every otherNumber
is 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:
false
is not aString
literal (it's aBoolean
literal), but"false"
is42f
is aString
literal-
42
is not aString
literal (it's aNumber
literal), 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: