Exemple de script permettant de répondre à la question en créant un champ “NEIGHBORS” et un champ “SUM” pour chaque entité de la couche puis en récupérant :
la valeur du champ “SUM” pour la Hongrie
le nombre de pays sans voisin
Exercice3.py
from qgis.utils import iface
from PyQt5.QtCore import QVariant
# Nom des champs à utiliser :
_NAME_FIELD = 'NAME'
_SUM_FIELD = 'POP_EST'
# Nom des champs à créer
_NEW_NEIGHBORS_FIELD = 'NEIGHBORS'
_NEW_SUM_FIELD = 'SUM'
layer = iface.activeLayer()
# Création des deux nouveaux champs après avoir activé le mode édition
layer.startEditing()
layer.dataProvider().addAttributes(
[QgsField(_NEW_NEIGHBORS_FIELD, QVariant.String),
QgsField(_NEW_SUM_FIELD, QVariant.LongLong)])
layer.updateFields()
# Construction d'un index spatial :
index = QgsSpatialIndex()
for f in layer.getFeatures():
index.insertFeature(f)
# Parcours de l'ensemble de nos entités :
for f in layer.getFeatures():
# print('Calcul en cours pour {}'.format(f[_NAME_FIELD]))
geom = f.geometry()
# Recherche des entités qui intersectent la bbox de l'entité courrante
# L'utilisation d'un index spatial permet à ce moment de n'itérer que
# sur les entités qui intersectent sa bbox et non pas sur l'ensemble
# des entités.
intersecting_ids = index.intersects(geom.boundingBox())
# Pour stocker la liste des voisins :
neighbors = []
neighbors_sum = 0
request = QgsFeatureRequest().setFilterFids(intersecting_ids)
for intersecting_f in layer.getFeatures(request):
# Ici on considère qu'une entité est voisine si elle touche
# l'entité en cours. Nous utilisons donc le prédicat spatial
# 'touches' pour vérifier cela:
if intersecting_f.geometry().touches(geom):
neighbors.append(intersecting_f[_NAME_FIELD])
neighbors_sum += intersecting_f[_SUM_FIELD]
f[_NEW_NEIGHBORS_FIELD] = ','.join(neighbors)
f[_NEW_SUM_FIELD] = neighbors_sum
# Mise à jour de l'entité modifiée :
layer.updateFeature(f)
layer.commitChanges()
# Récupération de l'entité correspondant à la Hongrie
feature_hungary = list(layer.getFeatures("\"ISO_A2\" is 'HU'"))[0]
# On lit la valeur de son champ 'SUM'
print("Les pays voisins de la Hongrie totalisent environ {} habitants"
.format(feature_hungary['SUM']))
# Pour savoir la nombre de pays sans voisins
# on va lister ceux qui ont une valeur NULL
# dans le champ 'NEIGHBORS'
features_without_neighbors = list(layer.getFeatures("\"NEIGHBORS\" is NULL"))
# On regarde la longeur de la liste obtenue en résultat
print("{} pays n'ont pas de voisin"
.format(len(features_without_neighbors)))
➜ Les pays voisins de la Hongrie totalisent environ 91 173 260 habitants.
➜ 83 pays n’ont pas de voisin