Pourcentage de polygone dans un fichier de formes dans un polygone d'un autre

13

Je suis un débutant, excuses si cela est évident / a déjà été demandé et répondu mais je n'ai rien trouvé.

J'ai deux fichiers de formes: 1. une couche limite administrative pour un comté au Royaume-Uni connu comme une limite LSOA qui contient 500 petites zones 2. une zone inondable.

Idéalement, je veux savoir lesquelles des petites zones LSOA sont ≥50% dans la zone d'inondation et finir avec un oui / non ou un 1/0 pour chacune des 500 zones LSOA.

Mais je ne sais pas comment faire ça. J'ai pensé que je pouvais rejoindre les deux fichiers de formes, mais il n'y a pas d'attribut commun entre eux. Ensuite, j'ai pensé que je pouvais utiliser la fonction Join Attribute by Location, qui fonctionnait et me montrait quels LSOA se trouvaient dans la zone inondable, mais c'est presque tous (voir l'image 2).

Je pense que c'est un problème SQL mais je ne sais pas. Je suis nouveau sur QGIS et je n'ai jamais utilisé PostgreSQL.

Toute aide serait grandement appréciée. Je peux vous fournir toutes les informations dont vous avez besoin pour vous aider.

entrez la description de l'image ici

entrez la description de l'image ici

KJGarbutt
la source

Réponses:

11

Il s'agit d'une tâche relativement simple utilisant les outils de géotraitement inclus dans QGIS.

  1. Calculez l'aire de vos zones LSOA.

    • Ouvrez la table attributaire de couche LSOA.
    • Activez le mode d'édition.
    • Ouvrez la calculatrice de terrain.
    • Créez un nouveau champ de type "Nombre décimal (réel)" avec l'expression "$ area".
    • Désactivez le mode d'édition (sauvegarde des modifications).
  2. Fusionnez la couche de zone inondable en une seule entité en plusieurs parties.

    • Vector > Geometry Tools > Singleparts to Multipart.
    • Sélectionnez "--- Fusionner tout ---" pour le champ ID unique.
  3. Intersection de la couche de zone LSOA avec la couche de zone d'inondation en plusieurs parties.

    • Vector > Geoprocessing Tools > Intersect.
    • La couche d'entrée est les zones LSOA, la couche d'intersection est les zones inondables.
  4. La couche résultante sera constituée des parties des zones LSOA (avec les attributs de la couche des zones LSOA) qui se chevauchent avec la couche des zones inondables. Pour calculer la proportion de chaque zone LSOA dans une zone inondable:

    • Calculez l'aire des entités intersectées (comme à l'étape 1), puis
    • Ajoutez un autre champ en divisant la zone d'origine (totale) par la zone intersectée. Le résultat est une décimale entre 0 et 1. Multipliez par 100 pour donner un pourcentage.
  5. Joignez la couche LSOA d'origine à la couche intersectée, en utilisant l'ID unique partagé par les deux couches.

  6. Exportez le calque joint en tant que nouveau fichier de formes.

  7. Supprimez les attributs dupliqués.

Et voilà!

Sans l'étape 2, une entité individuelle serait créée pour chaque entité de zone d'inondation différente pour chaque entité LSOA. Ce n'est probablement pas ce que vous voulez si vous êtes uniquement intéressé par la couverture totale de chaque zone LSOA. Si vous souhaitez faire la différence entre les inondations fluviales / marémotrices / pluviales (et les données de la zone inondable le prennent en charge), vous pouvez convertir des pièces uniques en plusieurs parties en spécifiant le champ "TYPE" comme champ ID unique.

Snorfalorpagus
la source
Merci de votre aide! Très appréciée. Cependant, j'ai des problèmes. J'ai suivi les étapes. L'étape 3, l'intersection, a duré 10 heures et une fois terminée, je n'ai obtenu qu'un fichier de forme vide: i.imgur.com/QIM6Gtg.png Y a-t-il quelque chose que j'ai manqué? J'ai essayé de terminer le processus et de faire l'étape 4 mais il n'y a pas de données pour calculer la zone d'intersection.
KJGarbutt
J'ai eu des problèmes avant de faire des intersections avec des couches d'inondation. Les fonctionnalités sont grandes et compliquées. La façon dont j'ai travaillé dans le passé est de les diviser en entités plus petites, afin que l'index spatial puisse faire plus de travail. Pour ce faire, créez une grille vectorielle de même étendue que la couche d'inondation ( Vector > Research Tools > Vector Grid... Output grid as polygons), puis coupez la grille avec la couche d'inondation. Utilisez ensuite la sortie au lieu de la couche Flood à l'étape 3. Je suppose que la raison pour laquelle la couche était vide est parce qu'elle s'est écrasée.
Snorfalorpagus du
Merci encore. Le seul problème maintenant est que QGIS se bloque chaque fois que j'essaie de créer la grille vectorielle. J'ai suivi les conseils d' ici mais ça plante à chaque fois. J'ai changé les paramètres plusieurs fois et j'ai essayé d'utiliser uniquement le fichier de formes de la zone inondable, au lieu d'avoir tout mon fichier de projet ouvert et il échoue à chaque fois. Des idées? ! Capture d'écran ici .
KJGarbutt
Les paramètres X et Y que vous avez spécifiés sont beaucoup trop petits. Essayez quelque chose comme 1000 x 1000. Vous pouvez même le faire plusieurs fois, c'est-à-dire faire d'abord 5000 x 5000, utilisez la sortie pour créer 500 x 500. Voir la réponse connexe ici: gis.stackexchange.com/a/66319/12420
Snorfalorpagus
Je l'ai presque craqué avec votre aide! Cependant, lorsque je vais rejoindre la couche LSOA d'origine avec la couche intersectée, je perds beaucoup de données. Je pense que c'est parce que certains des carrés de la grille vectorielle créés entrent dans la même zone LSOA et ont donc le même code LSOA que chacun. Ainsi, je me retrouve avec 2+ pourcentages pour chaque zone LSOA lorsque je fais la jointure et je ne semble en obtenir qu'un. Existe-t-il un moyen de additionner chaque pourcentage pour chaque carré de la grille vectorielle avec le même LSOA?
KJGarbutt
6

Vous pouvez utiliser spatialite et certaines fonctions SQL spatiales.

Select t1.geometry, t1.ID, area(t1.geometry), area(t2.geometry) ...... (anything you need to have in the table results)

(area(intersection(t1.geometry,t2.geometry))) as "Commun_AREA"

, ("Commun_AREA"*100/(area(t1.geometry))) as "Percent_AREA"

From lsoa as t1, flood_zone as t2

Where Intersects( t1.geometry,t2.geometry ) = 1
Cyrille
la source
3

Cela semble être quelque chose qui pourrait être fait beaucoup plus facilement que les réponses soumises. J'utiliserais personnellement un simple script python:

floodName = "the layer name here"
boundryName = "the layer name here"
fieldName = "the name of the field to contain the output 1/0"
minCoverage = 0.5 # the minimum amount of area covered to write 1
updateMap = [] # this will store values to be written    

# get layers
floodLayer = QgsMapLayerRegistry.instance().mapLayersByName(floodName)[0]
boundryLayer = QgsMapLayerRegistry.instance().mapLayersByName(boundryName)[0]
fieldIndex = boundryLayer.dataProvider().fieldNameIndex(fieldName)    

# iterate through boundries
for b in boundryLayer.getFeatures():
    # get only flood features that intersect with this feature's bounding box
    # this will make the script go way faster than it would otherwise
    request = QgsFeatureRequest().setFilterRect(b.geometry().boundingBox())
    floodGeom = geometry()
    floodFeat = QgsFeature()
    iter = floodLayer.getFeatures(request)
    iter.nextFeature(feat)
    while iter.nextFeature(feat):
        floodGeom = floodGeom.combine(feat.geometry())
    intersectGeom = b.geometry().intersection(feat.geometry())
    if intersectGeom.area() > minCoverage * b.geometry().area():
        updateMap[b.id()] = {fieldIndex : 1}
    else:
        updateMap[b.id()] = {fieldIndex : 0}

boundryLayer.dataProvider().changeAttributeValues(updateMap)

cela n'évalue que les polygones d'inondation qui se croisent avec le cadre de délimitation de chaque couche de délimitation de sorte qu'il devrait être assez rapide à exécuter, puis il ne met à jour qu'un champ dans la couche existante (au lieu d'une opération complexe consistant à créer une toute nouvelle couche et à copier les anciennes valeurs puis suppression)

Jesse McMillan
la source
2

J'ai eu le même problème que KJ en suivant les instructions de Snorfalorpagus en utilisant la méthode "Intersect" à l'étape 3. Il a fallu un certain temps pour calculer et ce qui me restait était vide.

J'ai essayé de suivre les mêmes étapes, sauf en utilisant la méthode "Clip" dans QGIS au lieu d'Intersect - donc, dans votre exemple, ce qui resterait serait les parties des zones qui ne sont PAS couvertes par la zone inondable. Cela semblait fonctionner pour une raison quelconque et j'ai pu utiliser le calcul du champ "Surface" de l'étape précédente, plus un nouveau calcul "Surface" sur les parties restantes de chaque polygone, pour déterminer le% de chaque surface qui n'était PAS recouvert par l'autre couche Polygon.

C'est techniquement l'inverse de ce que vous avez demandé. Mais à partir de là, il suffit de soustraire chaque valeur de 1 pour obtenir ce qui est couvert par la zone inondable.

déterreur de scandales
la source