library(qgisprocess) library(sf)
Many QGIS processing algorithms provide the possibility to use QGIS expressions.
If an algorithm argument expects a QGIS expression, this is typically marked by a button in the QGIS processing dialog that opens the QGIS expression builder (e.g. in native:extractbyexpression
), or by a directly integrated QGIS expression builder (e.g. in native:fieldcalculator
).
Such arguments are of type expression
, as seen in the output of qgis_get_argument_specs()
.
qgis_get_argument_specs("native:fieldcalculator") |> subset(name == "FORMULA")
Secondly, one can use expressions for data-defined overriding.
This means that an algorithm argument that is usually a fixed value (number, distance, boolean, string or color) can also take on the value of another field or the result of an expression.
In the QGIS processing dialog, such arguments have a 'data-defined override' button.
An example is provided by the DISTANCE
argument of native:buffer
, for which we query the acceptable values below.
qgis_get_argument_specs("native:buffer") |> subset(name == "DISTANCE", acceptable_values) |> tidyr::unnest_longer(acceptable_values) |> knitr::kable()
As example data, we use a lake polygon and a set of points that have lake depth as attribute.
longlake_path <- system.file("longlake/longlake.gpkg", package = "qgisprocess") longlake_depth_path <- system.file("longlake/longlake_depth.gpkg", package = "qgisprocess")
nrow(read_sf(longlake_depth_path))
In a first example, we use a QGIS expression to filter points by depth. We can simply pass the expression as a string:
qgis_run_algorithm( "native:extractbyexpression", INPUT = longlake_depth_path, EXPRESSION = '"DEPTH_M" > 1' ) |> st_as_sf()
More often, you will want to use QGIS functions in expressions, and look at the relationship between geometries or create new geometries.
Let's calculate the distance between the points and the lake border, and add it as an attribute to the points.
For that we will use the native:fieldcalculator
algorithm.
We first create the lake border:
lake_border_path <- qgis_run_algorithm( "native:polygonstolines", INPUT = longlake_path ) |> qgis_extract_output("OUTPUT")
Next, build the QGIS expression.
Referring to the INPUT
geometry in native:fieldcalculator
is done with the @geometry
variable.
expr <- glue::glue("distance( @geometry, geometry( get_feature_by_id( load_layer('{lake_border_path}', 'ogr'), 1 ) ) )")
Referring to the lake border geometry in an expression is a bit trickier, since it requires several QGIS functions.
The layer can be loaded from a filepath with the load_layer()
function, then the first (and only) feature is selected with get_feature_by_id()
, and the geometry of that feature is selected using the geometry()
function.
These steps are needed because the distance()
function needs geometries to work on, not features, layers or filepaths.
Use the QGIS expression builder to look up function documentation, or consult the online QGIS function documentation.
Note: the load_layer()
function is only available since QGIS 3.30.0!
In earlier versions, you needed to refer to the layer's name in an existing QGIS project, and refer to the project path in qgis_run_algorithm()
with the special PROJECT_PATH
argument.
The load_layer()
approach since QGIS 3.30.0 avoids the need for a QGIS project.
Now we can run the algorithm:
qgis_run_algorithm( "native:fieldcalculator", INPUT = longlake_depth_path, FIELD_NAME = "distance", FORMULA = expr ) |> st_as_sf()
Suppose that we want to create a buffer around the points with a dynamic radius expressed as a function of DEPTH_M
, e.g. 10 times the depth at each point.
We will use native:buffer
for that purpose.
Note: applying a data-defined override with qgisprocess is only possible since QGIS 3.30.0!
Because DISTANCE
by default expects a numeric value, you have to use the prefix expression:
if you want to pass an expression string.
Double quotes are used in QGIS expressions to denote fields (attributes), but you can also omit them.
Let's try:
buffer <- qgis_run_algorithm( "native:buffer", INPUT = longlake_depth_path, DISTANCE = 'expression: "DEPTH_M" * 10' ) |> st_as_sf()
So from the r nrow(buffer)
points we have created r nrow(buffer)
polygons:
st_geometry_type(buffer) |> as.character() |> table()
Plot the result:
oldpar <- par(mar = rep(0.1, 4)) plot(read_sf(lake_border_path) |> st_geometry()) plot(buffer[, "DEPTH_M"], add = TRUE) par(oldpar)
If you just want to refer to the value of another attribute, then you can also use the field:
prefix instead, without double quotes around the attribute name and without spaces:
qgis_run_algorithm( "native:buffer", INPUT = longlake_depth_path, DISTANCE = "field:DEPTH_M" ) |> st_as_sf()
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.