
Les exigences des clients pour les symboles sur les cartes vous semblent-elles irréalistes? Plus loin, vous apprendrez à utiliser le générateur de géométrie, QGIS et Python pour optimiser vos conditionneurs.
introduction
! , , , , , QGIS Python PyQt. , , () . QGIS , geometry generator — . . , .
«» ?
QGIS MVC . , .. , Model-Based PyQt . , . , .
QGIS:

?
99% . ! , (, ), (, ), , .
, :

«» :

. , , , ( ). QGIS Python.
, , -, , , , (!) , , ! , .
- QGIS 3.10.6 Ubuntu 18.04.
- «» UTM 37N, .
- GitHub .
- «» , .
- , , , .
geometry generator
— .
, : /, /, /. , , , , . : , , .
«»?
, , (expression), . Expressions, Python Expressions, Filtering and Calculating Values.
, , . — , . Python, . QGIS. , a .
: . - , .
, , QGIS, , , , . . .
...
, .
, ( , ), , , , , , :

: , , ; , , — , . points.
geometry_n()
, :
geometry_n($geometry, 1)
$geometry
— , .
, :
if(
@geometry_part_num > 1,
geometry_n($geometry, @geometry_part_num ),
NULL
)
, if()
— . 2 @geometry_part_num
, , ( @
). NULL
. , , , .
— , :
if(
@geometry_part_num > 1,
with_variable(
'inputs',
array(
10000,
length(
make_line(
start_point($geometry),
geometry_n($geometry, @geometry_part_num)
)
),
azimuth(
geometry_n($geometry, @geometry_part_num),
start_point($geometry)
)
),
if(
@inputs[0] < @inputs[1],
make_line(
geometry_n($geometry, @geometry_part_num),
project(
geometry_n($geometry, @geometry_part_num),
@inputs[1] - @inputs[0],
@inputs[2]
)
),
NULL
)
),
NULL
)
. , , , NULL
.
— . , . , . , .
with_variable()
, : , , . , - , with_variable
, . .
— inputs
array()
— 0. — , . — , :
...
length(
make_line(
start_point($geometry),
geometry_n($geometry, @geometry_part_num)
)
),
azimuth(
geometry_n($geometry, @geometry_part_num),
start_point($geometry)
)
...
length()
, , make_line()
— start_point($geometry)
, ( ). azimuth()
, !
, . if()
, , . @inputs
, , «» NULL
.
:
...
make_line(
geometry_n($geometry, @geometry_part_num),
project(
geometry_n($geometry, @geometry_part_num),
@inputs[1] - @inputs[0],
@inputs[2]
)
)
...
project()
, , . , .
, Klas Karlsson, QGIS. , , , , :

, . , WKT , , «||», . , , . :
( lines1). , :
:
collect_geometries(
array_foreach(
generate_series(1, num_points($geometry)),
point_n($geometry, @element)
)
)
«» . . generate_series()
, () 1 num_points($geometry)
, . . . array_foreach()
. array_foreach
, point_n($geometry, @element)
, . . (point_n()
— ), @element
— . , . — , collect_geometries()
. ( ).
. «/». :
with_variable(
'minimal_length',
7000.0,
collect_geometries(
array_foreach(
generate_series(1, num_points($geometry) - 1),
with_variable(
'inputs',
array(
azimuth(
point_n($geometry, @element),
point_n($geometry, @element + 1)
),
length(
make_line(
point_n($geometry, @element),
point_n($geometry, @element + 1)
)
)
),
if(
@inputs[1] - @minimal_length * 2 > 0,
line_substring(
make_line(
point_n($geometry, @element),
point_n($geometry, @element+1)
),
@minimal_length, @inputs[1] - @minimal_length
),
geom_from_wkt('LINESTRING EMPTY')
)
)
)
)
)
, . @minimal_length
. collect_geometries
, array_foreach
, . , , @inputs
: .
. , @minimal_length
( ). , , :
geom_from_wkt('LINESTRING EMPTY')
, , NULL
, . , . WKT «LINESTRING EMPTY», WKT QGIS geom_from_wkt()
.
. line_subtring()
, . , .
? , , . (. lines2).
, buffer()
, : , 1. .. :

, .

, , , . , . , . :
with_variable(
'distance',
4000,
with_variable(
'offset_lines',
array(
extend(
offset_curve($geometry, @distance, join:=2),
@distance, @distance
),
extend(
offset_curve($geometry, -@distance, join:=2),
@distance, @distance
)
),
collect_geometries(
@offset_lines[0],
@offset_lines[1],
make_line(
start_point(@offset_lines[0]),
start_point(@offset_lines[1])
),
make_line(
end_point(@offset_lines[0]),
end_point(@offset_lines[1])
)
)
)
)
, with_variable
, , , . . @offset_lines
, , ( offset_curve()
), extend()
. , — start_point()
— end_point()
.
— , —
, , . (. lines3). , :
with_variable(
'lines',
segments_to_lines($geometry),
collect_geometries(
array_foreach(
generate_series(2, num_geometries(@lines), 2),
geometry_n(@lines, @element)
)
)
)
segments_to_lines()
, — , . , generate_series
. :

. , ( poly2).

«/» :
with_variable(
'points_num',
num_points($geometry) - 1,
collect_geometries(
array_foreach(
generate_series(1, round(@points_num / 2.0)),
make_line(
point_n(
$geometry,
@element
),
point_n(
$geometry,
@element + floor(@points_num / 2.0)
)
)
)
)
)
«» , generate_series()
. .
, ( poly3):

:
collect_geometries(
array_foreach(
generate_series(1, num_points($geometry) - 1),
make_line(
centroid($geometry),
point_n($geometry, @element)
)
)
)
, centroid()
, , , .
— poly4. , , «», . «» — , , , . :

, , . . . , :
with_variable(
'lines',
segments_to_lines($geometry),
collect_geometries(
array_foreach(
segments_between_sides_nums(
array_foreach(
generate_series(1, num_geometries(@lines)),
array(
@element,
length(
geometry_n(@lines, @element)
)
)
)
),
geometry_n(@lines, @element)
)
)
)
, . , , .
segments_between_sides_num()
. QGIS Python ( custom.py ~/.local/share/QGIS/QGIS3/profiles/default/python/expressions):
@qgsfunction(args="auto", group="")
def segments_between_sides_nums(sides, feature, parent):
"""
.
sides - ( , )
"""
sorted_sides = sorted(sides, key=lambda x: x[1])
return list(range(int(sorted_sides[0][0]) + 1, int(sorted_sides[1][0])))
Python , .. ( ), .
. , Python?
, : QGIS Python? . , .
create_poly_lyr.py, ( ).
Python, QGIS, Python. expression_benchmarking.py:
EXPRESSION = """
collect_geometries(
array_foreach(
generate_series(1, num_points($geometry)),
make_line(
centroid($geometry),
point_n($geometry, @element)
)
)
)
"""
…
for counter, poly in enumerate(lyr_polys.getFeatures()):
exp = QgsExpression(EXPRESSION)
context = QgsExpressionContext()
context.setFeature(poly)
star = exp.evaluate(context)
python_benchmarking.py:
for counter, poly in enumerate(lyr_polys.getFeatures()):
centroid = QgsPoint(poly.geometry().centroid().asPoint())
star = QgsMultiLineString()
for vertex in poly.geometry().vertices():
line = QgsLineString(centroid, vertex)
star.addGeometry(line)

Python 5,3 , 23,16 . Python 4,5 . , , , .
:
- . «» , , «- 1» , Python, .
- QGIS, . . , .
:
Python:
Python:
- () *.py .
- Python , .
- Python, , ( Windows).
, QGIS . , , , , . , «» Python.
? .
: WGS84 (/), — . , , . , . , :

: , , . , . poly3 «» :

, .
, , /? , :

«» , ? , , .
«», ?
, , . , , .
Les générateurs offrent des possibilités presque illimitées, plus précisément, les possibilités ne sont limitées que par les performances et sont un outil indispensable pour créer des panneaux conventionnels vraiment complexes.
J'espère que l'article vous sera utile, et nous pourrons considérer des cas complexes dans le prochain article. Merci pour l'attention.
Références