Les extraits de code sur cette page nécessitent les importations suivantes si vous êtes en dehors de la console pyqgis :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from qgis.core import (
  QgsGeometry,
  QgsPoint,
  QgsPointXY,
  QgsWkbTypes,
  QgsProject,
  QgsFeatureRequest,
  QgsVectorLayer,
  QgsDistanceArea,
  QgsUnitTypes,
)

7. Manipulation de la géométrie

Points, linestrings and polygons that represent a spatial feature are commonly referred to as geometries. In QGIS they are represented with the QgsGeometry class.

Parfois, une entité correspond à une collection d’éléments géométriques simples (d’un seul tenant). Une telle géométrie est appelée multi-parties. Si elle ne contient qu’un seul type de géométrie, il s’agit de multi-points, de multi-lignes ou de multi-polygones. Par exemple, un pays constitué de plusieurs îles peut être représenté par un multi-polygone.

Les coordonnées des géométries peuvent être dans n’importe quel système de coordonnées de référence (SCR). Lorsqu’on accède aux entités d’une couche, les géométries correspondantes auront leurs coordonnées dans le SCR de la couche.

Description and specifications of all possible geometries construction and relationships are available in the OGC Simple Feature Access Standards for advanced details.

7.1. Construction de géométrie

PyQGIS fournit plusieurs options pour créer une géométrie:

  • à partir des coordonnées

    1
    2
    3
    4
    5
    6
    7
    gPnt = QgsGeometry.fromPointXY(QgsPointXY(1,1))
    print(gPnt)
    gLine = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)])
    print(gLine)
    gPolygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 1),
        QgsPointXY(2, 2), QgsPointXY(2, 1)]])
    print(gPolygon)
    

    Coordinates are given using QgsPoint class or QgsPointXY class. The difference between these classes is that QgsPoint supports M and Z dimensions.

    Une polyligne (Linestring) est représentée par une liste de points.

    A Polygon is represented by a list of linear rings (i.e. closed linestrings). The first ring is the outer ring (boundary), optional subsequent rings are holes in the polygon. Note that unlike some programs, QGIS will close the ring for you so there is no need to duplicate the first point as the last.

    Les géométries multi-parties sont d’un niveau plus complexe: les multipoints sont une succession de points, les multilignes une succession de lignes et les multipolygones une succession de polygones.

  • depuis un Well-Known-Text (WKT)

    geom = QgsGeometry.fromWkt("POINT(3 4)")
    print(geom)
    
  • depuis un Well-Known-Binary (WKB)

    1
    2
    3
    4
    5
    6
    g = QgsGeometry()
    wkb = bytes.fromhex("010100000000000000000045400000000000001440")
    g.fromWkb(wkb)
    
    # print WKT representation of the geometry
    print(g.asWkt())
    

7.2. Accéder à la Géométrie

First, you should find out the geometry type. The wkbType() method is the one to use. It returns a value from the QgsWkbTypes.Type enumeration.

1
2
3
4
5
6
7
8
9
if gPnt.wkbType() == QgsWkbTypes.Point:
  print(gPnt.wkbType())
  # output: 1 for Point
if gLine.wkbType() == QgsWkbTypes.LineString:
  print(gLine.wkbType())
  # output: 2 for LineString
if gPolygon.wkbType() == QgsWkbTypes.Polygon:
  print(gPolygon.wkbType())
  # output: 3 for Polygon

As an alternative, one can use the type() method which returns a value from the QgsWkbTypes.GeometryType enumeration.

You can use the displayString() function to get a human readable geometry type.

1
2
3
4
5
6
print(QgsWkbTypes.displayString(gPnt.wkbType()))
# output: 'Point'
print(QgsWkbTypes.displayString(gLine.wkbType()))
# output: 'LineString'
print(QgsWkbTypes.displayString(gPolygon.wkbType()))
# output: 'Polygon'
Point
LineString
Polygon

There is also a helper function isMultipart() to find out whether a geometry is multipart or not.

To extract information from a geometry there are accessor functions for every vector type. Here’s an example on how to use these accessors:

1
2
3
4
5
6
print(gPnt.asPoint())
# output: <QgsPointXY: POINT(1 1)>
print(gLine.asPolyline())
# output: [<QgsPointXY: POINT(1 1)>, <QgsPointXY: POINT(2 2)>]
print(gPolygon.asPolygon())
# output: [[<QgsPointXY: POINT(1 1)>, <QgsPointXY: POINT(2 2)>, <QgsPointXY: POINT(2 1)>, <QgsPointXY: POINT(1 1)>]]

Note

The tuples (x,y) are not real tuples, they are QgsPoint objects, the values are accessible with x() and y() methods.

For multipart geometries there are similar accessor functions: asMultiPoint(), asMultiPolyline() and asMultiPolygon().

7.3. Prédicats et opérations géométriques

QGIS uses GEOS library for advanced geometry operations such as geometry predicates (contains(), intersects(), …) and set operations (combine(), difference(), …). It can also compute geometric properties of geometries, such as area (in the case of polygons) or lengths (for polygons and lines).

Let’s see an example that combines iterating over the features in a given layer and performing some geometric computations based on their geometries. The below code will compute and print the area and perimeter of each country in the countries layer within our tutorial QGIS project.

The following code assumes layer is a QgsVectorLayer object that has Polygon feature type.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# let's access the 'countries' layer
layer = QgsProject.instance().mapLayersByName('countries')[0]

# let's filter for countries that begin with Z, then get their features
query = '"name" LIKE \'Zu%\''
features = layer.getFeatures(QgsFeatureRequest().setFilterExpression(query))

# now loop through the features, perform geometry computation and print the results
for f in features:
  geom = f.geometry()
  name = f.attribute('NAME')
  print(name)
  print('Area: ', geom.area())
  print('Perimeter: ', geom.length())
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Zubin Potok
Area:  0.040717371293465573
Perimeter:  0.9406133328077781
Zulia
Area:  3.708060762610232
Perimeter:  17.172123598311487
Zuid-Holland
Area:  0.4204687950359031
Perimeter:  4.098878517120812
Zug
Area:  0.027573510374275363
Perimeter:  0.7756605461489624

Now you have calculated and printed the areas and perimeters of the geometries. You may however quickly notice that the values are strange. That is because areas and perimeters don’t take CRS into account when computed using the area() and length() methods from the QgsGeometry class. For a more powerful area and distance calculation, the QgsDistanceArea class can be used, which can perform ellipsoid based calculations:

The following code assumes layer is a QgsVectorLayer object that has Polygon feature type.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
d = QgsDistanceArea()
d.setEllipsoid('WGS84')

layer = QgsProject.instance().mapLayersByName('countries')[0]

# let's filter for countries that begin with Z, then get their features
query = '"name" LIKE \'Zu%\''
features = layer.getFeatures(QgsFeatureRequest().setFilterExpression(query))

for f in features:
  geom = f.geometry()
  name = f.attribute('NAME')
  print(name)
  print("Perimeter (m):", d.measurePerimeter(geom))
  print("Area (m2):", d.measureArea(geom))

  # let's calculate and print the area again, but this time in square kilometers
  print("Area (km2):", d.convertAreaMeasurement(d.measureArea(geom), QgsUnitTypes.AreaSquareKilometers))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
Zubin Potok
Perimeter (m): 87581.40256396442
Area (m2): 369302069.18814206
Area (km2): 369.30206918814207
Zulia
Perimeter (m): 1891227.0945423362
Area (m2): 44973645460.19726
Area (km2): 44973.64546019726
Zuid-Holland
Perimeter (m): 331941.8000214341
Area (m2): 3217213408.4100943
Area (km2): 3217.213408410094
Zug
Perimeter (m): 67440.22483063207
Area (m2): 232457391.52097562
Area (km2): 232.45739152097562

Alternatively, you may want to know the distance and bearing between two points.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
d = QgsDistanceArea()
d.setEllipsoid('WGS84')

# Let's create two points.
# Santa claus is a workaholic and needs a summer break,
# lets see how far is Tenerife from his home
santa = QgsPointXY(25.847899, 66.543456)
tenerife = QgsPointXY(-16.5735, 28.0443)

print("Distance in meters: ", d.measureLine(santa, tenerife))

Vous trouverez de nombreux exemples d’algorithmes inclus dans QGIS et utiliser ces méthodes pour analyser et modifier les données vectorielles. Voici des liens vers le code de quelques-uns.