Correction - Exercice 3 : Géométries et calcul de champ ======================================================= **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`` .. code-block:: python 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