QGIS Vector Layer – Creating Dynamic Vector Layer or Virtual Layer in QGIS

atlasqgisqgis-3vectorvirtual-layer

The problem

I want to create a vector layer in QGIS 3.26 with a varying number of features. The number of features should be the same as the number of raster layers open in the project. So if I have 12 raster layers, I want a point layer with 12 features; if 30 rasters are open in the project, I want to get a layer with 30 points and so on.

Hint (see at the bottom): I need this as coverage layer for an atlas that outputs each raster layer separately.

What I tried

  1. I created a point layer called count_layer with one feature and a virtual field named no_of_rasters with an expression based on the variable @layers that returns the number of raster layers opened in the project.

  2. The idea now is to create a virtual layer with the query select make_point (47,15).

The question

Up to this point, everything works. I am now stuck as to how to create not one point at coordinates (47,15), but several points – the number of points should correspond to the number created above in step 1: the value in the field no_of_rasters.

How to do that?


Context (not necessary to understand the question)

Just to make clear why I want to do that: I want to use the virtual layer as coverage layer for an atlas. I want to output each raster separately, so in the virtual layer, I want to create a virtual field containing for each feature one of the names of the raster layers (using @layers and selecting from the resulting array one element corresponding to @row_number).

This field (name of raster layer) can than be used in the atlas in the Lock layers setting to just output one raster layer per feature of the coverage layer so that in the end, I have an output with each raster layer separately printed.

Best Answer

Assuming you want each of the points to have an identical geometry, you could use a recursive CTE and generate a row (with unique id) for each layer as such:

WITH seq AS (SELECT 1 AS n UNION ALL SELECT n + 1 FROM seq 
WHERE n + 1 <= (SELECT no_of_rasters FROM count_layer))

SELECT n, make_point(47,15) AS geometry FROM seq

As for assigning a raster name to each generated point, to my knowledge you can't do that in Virtual Layers, but you could set up a virtual field on the virtual layer with the following expression (where n is the sequence generated in the virtual layer):

array_get(
         array_foreach(
                       array_filter(@layers,
                                    layer_property(@element,'type') =  'Raster'),
                       layer_property(@element,'name')
         ),"n"-1)

This just extracts the raster name from the position in the @layers array corresponding to n - 1 (because zero-index).

Example:

enter image description here

Related Question