Suite

Shapely / Python en boucle à travers un certain nombre de polygones


J'essaie de parcourir un ensemble de polygones en forme en utilisant python) pour déterminer s'ils se chevauchent ou non. Je ne veux pas le faire manuellement car plus tard, je veux généraliser la procédure et le faire pour un certain nombre de polygones importés à partir d'un fichier de formes (via Fiona). Ce sont les polygones que je teste maintenantpolA = Polygone([(0,0), (3,0), (3,3), (0,3)]) polB = Polygone([(2,-1), (5,-1), ( 5,2), (2,2)]) polC = Polygone([(5,2), (8,2), (8,5), (5,5)])J'ai créé une collection à partir de cescollection = [polA, polB, polC]et maintenant je veux qu'une boucle for parcoure la liste et vérifie chaque polygone s'il chevauche le suivant. Mais rien de ce que j'essaie ne fonctionne, car je ne sais pas comment boucler et tester avec succès toutes les combinaisons possibles. Je ne sais pas si je suis compris. Est-ce que quelqu'un a une idée de comment faire cela en utilisant Shapely de Fiona?


Quelques solutions selon la position d'un élément dans une liste :

polA = Polygone([(0,0), (3,0), (3,3), (0,3)]) polB = Polygone([(2,-1), (5,-1), ( 5,2), (2,2)]) polC = Polygone([(5,2), (8,2), (8,5), (5,5)]) collection = [polA, polB, polC ]

Itération par index :

for i in range(len(collection)-1): print collection[i], collection[i+1], collection[i].touches(collection[i+1]) POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) Faux POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) Vrai

Itération avec itertools (module standard), toutes les combinaisons sans éléments répétés

importer itertools pour pol dans itertools.combinations(collection, 2) : imprimer pol[0],pol[1], pol[0].touches(pol[1]) POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) Faux POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ( (5 2, 8 2, 8 5, 5 5, 5 2)) Faux POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) Vrai

ou avec la suggestion de Mike T

pour pol1, pol2 dans itertools.combinations(collection, 2) : imprimez pol1, pol2, pol1.touches(pol2) POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ((2 -1 , 5 -1, 5 2, 2 2, 2 -1)) Faux POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ((5 2, 8 2, 8 5, 5 5 , 5 2)) Faux POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) Vrai

Comparer avec

pour pol dans itertools.permutations(collection, 2) : print pol[0],pol[1], pol[0].touches(pol[1]) POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) Faux POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) Faux POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) Faux POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) Vrai POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) Faux POLYGONE ((5 2, 8 2, 8 5 , 5 5, 5 2)) POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) Vrai

Regardez aussi Python - Valeurs précédentes et suivantes à l'intérieur d'une boucle

à partir d'itertools import tee, islice, chain, izip def previous_and_next(some_iterable): prevs, items, nexts = tee(some_iterable, 3) prevs = chain([None], prevs) nexts = chain(islice(nexts, 1, None) , [Aucun]) renvoie izip(précédents, éléments, suivants) pour précédent, élément, nxt dans previous_and_next(collection): print "L'élément est maintenant", élément, "le suivant est", nxt, "le précédent est", l'élément précédent est maintenant POLYGONE ((0 0, 3 0, 3 3, 0 3, 0 0)) suivant est POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) précédent est Aucun L'article est maintenant POLYGONE ((2 -1, 5 -1, 5 2, 2 2, 2 -1)) suivant est POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) précédent est POLYGONE ((0 0 , 3 0, 3 3, 0 3, 0 0)) L'article est maintenant POLYGONE ((5 2, 8 2, 8 5, 5 5, 5 2)) le suivant est Aucun précédent est POLYGONE ((2 -1, 5 - 1, 5 2, 2 2, 2 -1))

GDAL et Python | Chapitre 3. Lecture et écriture de données vectorielles

Chapitre 3. Lecture et écriture de données vectorielles

Ce chapitre couvre

  • Comprendre les données vectorielles
  • Présentation de l'OGR
  • Lecture de données vectorielles
  • Création de nouveaux jeux de données vectorielles
  • Mise à jour des jeux de données existants

Ils semblent être rares de nos jours, mais vous avez probablement déjà vu une feuille de route papier conçue pour être pliée et conservée dans votre voiture. Contrairement aux cartes Web les plus récentes que nous avons l'habitude d'utiliser, ces cartes n'utilisent pas d'imagerie aérienne. Au lieu de cela, les entités sur les cartes sont toutes dessinées en tant qu'objets géométriques, à savoir des points, des lignes et des polygones. Ces types de données, où les entités géographiques sont tous des objets distincts, sont appelés ensembles de données vectorielles .

À moins que vous ne prévoyiez de regarder uniquement des cartes créées par quelqu'un d'autre, vous devrez savoir lire et écrire ce type de données. Si vous souhaitez utiliser des données existantes de quelque manière que ce soit, que vous résumiez, éditiez, obteniez de nouvelles données ou effectuiez des analyses spatiales sophistiquées, vous devez d'abord les lire à partir d'un fichier. Vous devez également réécrire toutes les données nouvelles ou modifiées sur un disque. Par exemple, si vous disposiez d'un ensemble de données de ville à l'échelle nationale mais que vous deviez analyser uniquement les données de villes de 100 000 habitants ou plus, vous pouvez extraire ces villes de votre ensemble de données d'origine et exécuter votre analyse sur elles en ignorant les petites villes. En option, vous pouvez également enregistrer le plus petit ensemble de données dans un nouveau fichier pour une utilisation ultérieure.

Dans ce chapitre, vous apprendrez les idées de base derrière les données vectorielles et comment utiliser la bibliothèque OGR pour lire, écrire et éditer ces types de jeux de données.

3.1. Introduction aux données vectorielles

Dans sa forme la plus basique, données vectorielles sont des données dans lesquelles les entités géographiques sont représentées sous forme de géométries discrètes, en particulier des points, des lignes et des polygones. Les entités géographiques qui ont des limites distinctes, telles que les villes, fonctionnent bien comme données vectorielles, mais pas les données continues, telles que l'altitude. Il serait difficile de dessiner un seul polygone autour de toutes les zones avec la même altitude, du moins si vous étiez dans une zone montagneuse. Vous pouvez cependant utiliser des polygones pour différencier les différentes plages d'altitude. Par exemple, des polygones montrant des zones subalpines pour une région seraient un bon indicateur pour une plage d'altitude, mais vous perdriez une grande partie des données d'altitude détaillées dans ces polygones. Cependant, de nombreux types de données sont d'excellents candidats pour une représentation vectorielle, comme les caractéristiques de la feuille de route mentionnée précédemment. Les routes sont représentées sous forme de lignes, les comtés et les États sont des polygones, et selon l'échelle de la carte, les villes sont dessinées sous forme de points ou de polygones. En fait, toutes les entités sur la carte sont probablement représentées sous forme de points, de lignes ou de polygones.

Cependant, le type de géométrie utilisé pour dessiner une entité peut dépendre de l'échelle. La figure 3.1 en montre un exemple. Sur la carte de l'État de New York, les villes sont représentées sous forme de points, les routes principales sous forme de lignes et les comtés sous forme de polygones. Une carte d'une zone plus petite, telle que New York, symbolisera les caractéristiques différemment. Dans ce cas, les routes sont toujours des lignes, mais la ville et ses arrondissements sont des polygones au lieu de points. Désormais, les points seraient utilisés pour représenter des éléments tels que des bibliothèques ou des postes de police.

Graphique 3.1. Un exemple de la façon dont l'échelle modifie les géométries utilisées pour dessiner certaines entités. La ville de New York est un point sur la carte de l'État, mais est constituée de plusieurs polygones sur la carte de la ville.

Vous pouvez imaginer de nombreux autres exemples de données géographiques qui se prêtent à être représentées de cette façon. Tout ce qui peut être décrit avec un seul ensemble de coordonnées, comme la latitude et la longitude, peut être représenté comme un point. Cela inclut les villes, les restaurants, les sommets des montagnes, les stations météorologiques et les emplacements de géocache. En plus de leurs coordonnées x et y (telles que la latitude et la longitude), les points peuvent avoir une troisième coordonnée z qui représente l'altitude.

Les zones géographiques aux limites fermées peuvent être représentées sous forme de polygones. Les exemples sont les États, les lacs, les districts du Congrès, les codes postaux et la propriété foncière, ainsi que bon nombre des mêmes caractéristiques qui peuvent être symbolisées par des points tels que des villes et des parcs. D'autres entités qui pourraient être représentées sous forme de polygones, mais probablement pas sous forme de points, incluent les pays, les continents et les océans.

Les éléments linéaires, tels que les routes, les rivières, les lignes électriques et les itinéraires de bus, se prêtent tous à être caractérisés comme des lignes. Encore une fois, cependant, l'échelle peut faire une différence. Par exemple, une carte de la Nouvelle-Orléans pourrait montrer le fleuve Mississippi sous la forme d'un polygone plutôt que d'une ligne, car il est très large. Cela permettrait également à la carte de montrer les berges irrégulières de la rivière, plutôt qu'une simple ligne lisse, comme le montre la figure 3.2 .

Graphique 3.2. La différence entre l'utilisation de polygones et ligne /> géométries pour représenter le fleuve Mississippi. Le polygone montre les détails le long des berges, contrairement à la ligne.

Les données vectorielles sont cependant plus que des géométries. Chacune de ces caractéristiques a également des attributs associés. Ces attributs peuvent se rapporter directement à la géométrie elle-même, comme la surface ou le périmètre d'un polygone, ou la longueur d'une ligne, mais d'autres attributs peuvent également être présents. La figure 3.3 montre un exemple simple d'un ensemble de données d'états qui stocke le nom de l'état, l'abréviation, la population et d'autres données avec chaque caractéristique. Comme vous pouvez le voir sur la figure, ces attributs peuvent être de différents types. Ils peuvent être numériques, tels que la population de la ville ou la limite de vitesse de la route, des chaînes telles que les noms de ville ou de route, ou des dates telles que la date à laquelle la parcelle de terrain a été achetée ou la dernière évaluation. Certains types de données vectorielles prennent également en charge les BLOB (binary large objects), qui peuvent être utilisés pour stocker des données binaires telles que des photographies.

Graphique 3.3. Une table attributaire pour un ensemble de données contenant des limites d'État aux États-Unis. Chaque polygone d'état a une ligne associée dans la table de données avec plusieurs attributs, y compris le nom de l'état et la population en 2010.

Il devrait être clair maintenant que ce type de données est bien adapté pour faire des cartes, mais certaines raisons peuvent ne pas être si évidentes. Un exemple est la qualité de l'échelle lors du dessin. Si vous êtes familier avec les graphiques Web, vous savez probablement que les graphiques vectoriels tels que SVG (graphiques vectoriels évolutifs) fonctionnent bien mieux que les graphiques raster tels que PNG lorsqu'ils sont affichés à différentes échelles. Même si vous ne connaissez rien au SVG, vous avez sûrement vu une image sur un site Web pixelisée et moche. Il s'agit d'un graphique raster affiché à une résolution supérieure à celle pour laquelle il a été conçu. Cela ne se produit pas avec les graphiques vectoriels, et le même principe s'applique aux données SIG vectorielles. Il a toujours l'air lisse, quelle que soit l'échelle.

Cela ne signifie pas pour autant que l'échelle n'est pas pertinente. Comme vous l'avez vu précédemment, l'échelle affecte le type de géométrie utilisé pour représenter une entité géographique, mais elle affecte également la résolution que vous devez utiliser pour une entité. Une façon simple de penser à la résolution est de l'assimiler au détail. Plus la résolution est élevée, plus les détails peuvent être affichés. Par exemple, une carte des États-Unis ne montrerait pas toutes les îles San Juan individuelles au large des côtes de l'État de Washington et, en fait, l'ensemble de données n'aurait même pas besoin de les inclure. Une carte de l'État de Washington uniquement, cependant, aurait certainement besoin d'un ensemble de données à plus haute résolution qui inclut les îles, comme le montre la figure 3.4 . Gardez à l'esprit que la résolution n'est pas seulement importante pour l'affichage, mais aussi pour l'analyse. Par exemple, les deux cartes de Washington fourniraient des mesures extrêmement différentes de la longueur du littoral.

Graphique 3.4. Un exemple montrant la différence que fait la résolution. Le jeu de données affiché avec le contour épais a une résolution inférieure à celui affiché avec l'ombrage. Notez la différence dans la quantité de détails disponibles dans les deux ensembles de données.

LE PARADOXE DU LITTORAL

Avez-vous déjà pensé à la façon de mesurer le littoral d'une masse continentale ? Comme l'a souligné pour la première fois le mathématicien anglais Lewis Fry Richardson, ce n'est pas aussi facile qu'on pourrait le penser, car la mesure finale dépend totalement de l'échelle. Par exemple, pensez à une partie sauvage de la côte avec plusieurs promontoires, avec une route qui la longe. Imaginez que vous conduisiez le long de cette route et que vous utilisiez le compteur kilométrique de votre voiture pour mesurer la distance, puis que vous descendiez de la voiture et repreniez le chemin d'où vous veniez. Mais à pied, vous longez les bords des promontoires et suivez d'autres courbes de la côte que la route ne fait pas. Il devrait être facile d'imaginer que vous marcheriez plus loin que vous n'auriez conduit parce que vous avez fait plus de détours. Le même principe s'applique lors de la mesure de l'ensemble du littoral, car vous pouvez mesurer plus de variation si vous mesurez par incréments plus petits. En fait, mesurer la côte de la Grande-Bretagne par incréments de 50 km au lieu de 100 km augmente la mesure finale d'environ 600 km. Vous pouvez en voir un autre exemple, utilisant une partie de l'État de Washington, dans la figure 3.3 . Si vous deviez mesurer tous les méandres du jeu de données à plus haute résolution, vous obtiendriez une mesure de côte plus longue que si vous mesuriez la côte à plus faible résolution indiquée par la ligne sombre, qui n'inclut même pas la plupart des îles.

Comme mentionné précédemment, les données vectorielles ne servent pas uniquement à créer des cartes. En fait, je ne pourrais pas faire une jolie carte si ma vie en dépendait, mais j'en sais un peu plus sur l'analyse des données. Un type courant d'analyse de données vectorielles consiste à mesurer les relations entre les entités géographiques, généralement en les superposant les unes aux autres pour déterminer leur relation spatiale. Par exemple, vous pouvez déterminer si deux entités se chevauchent spatialement et quelle est cette zone de chevauchement. La figure 3.5 montre les limites de la ville de la Nouvelle-Orléans superposées sur un ensemble de données sur les zones humides. Vous pouvez utiliser ces informations pour déterminer où se trouvent les zones humides dans la ville de la Nouvelle-Orléans et quelle superficie de la ville est ou n'est pas une zone humide.

Graphique 3.5. Un exemple d'opération de superposition vectorielle. Le contour sombre est la limite de la ville de la Nouvelle-Orléans et les zones terrestres les plus sombres sont les zones humides. Ces deux ensembles de données pourraient être utilisés pour déterminer le pourcentage de terres humides à l'intérieur des limites de la Nouvelle-Orléans.

Un autre aspect des relations spatiales est la distance entre deux entités. Vous pouvez trouver la distance entre deux stations météorologiques ou toutes les sandwicheries situées à moins d'un mile de votre bureau. J'ai participé à une étude il y a quelques années dans laquelle les chercheurs avaient besoin à la fois de distances et de relations spatiales. Ils avaient besoin de connaître la distance parcourue par les cerfs munis d'un collier GPS entre les lectures, mais aussi la direction de leur déplacement et comment ils interagissaient avec les caractéristiques artificielles telles que les routes. Une question en particulier était de savoir s'ils traversaient les routes, et si oui, à quelle fréquence.

En parlant de routes, les jeux de données vectorielles font également un bon travail de représentation des réseaux, tels que les réseaux routiers. Un réseau routier correctement configuré peut être utilisé pour rechercher des itinéraires et des temps de trajet entre deux emplacements, de la même manière que les résultats que vous voyez sur divers sites de cartographie Web. Les entreprises peuvent également utiliser de telles informations pour fournir des services. Par exemple, une pizzeria peut utiliser l'analyse de réseau pour déterminer les quartiers de la ville qu'elle peut atteindre en 15 minutes de route pour définir sa zone de livraison.

Comme pour les autres types de données, vous disposez de plusieurs façons de stocker des données vectorielles. De la même manière que vous pouvez stocker une photo au format JPEG, PNG, TIFF, bitmap ou l'un des nombreux autres types de fichiers, de nombreux formats de fichiers différents peuvent être utilisés pour stocker des données vectorielles. Je parlerai davantage des possibilités dans le prochain chapitre, mais pour l'instant, je mentionnerai brièvement quelques formats courants, dont plusieurs que nous utiliserons dans ce chapitre.

Les fichiers de formes sont un format populaire pour stocker des données vectorielles. Cependant, un fichier de formes n'est pas composé d'un seul fichier. En fait, ce format nécessite un minimum de trois fichiers binaires, chacun ayant un objectif différent. Les informations de géométrie sont stockées dans des fichiers .shp et .shx, et les valeurs d'attribut sont stockées dans un fichier .dbf. De plus, d'autres données, telles que des index ou des informations de référence spatiale, peuvent être stockées dans encore plus de fichiers. En général, vous n'avez pas besoin de savoir quoi que ce soit sur ces fichiers, mais vous devez vous assurer qu'ils sont tous conservés ensemble dans le même dossier.

Un autre format largement utilisé, en particulier pour les applications de cartographie Web, est GeoJSON. Ce sont des fichiers en texte brut que vous pouvez ouvrir et consulter dans n'importe quel éditeur de texte. Contrairement à un fichier de formes, un jeu de données GeoJSON se compose d'un fichier qui stocke toutes les informations requises.

Les données vectorielles peuvent également être stockées dans des bases de données relationnelles, ce qui permet un accès multi-utilisateur ainsi que divers types d'indexation. Deux des options les plus courantes pour cela sont les extensions spatiales conçues pour les systèmes de bases de données largement utilisés. L'extension PostGIS s'exécute sur PostgreSQL et SpatiaLite fonctionne avec les bases de données SQLite. Un autre format de base de données populaire est la géodatabase fichier Esri, qui est complètement différente en ce sens qu'elle ne fait pas partie d'un système de base de données existant.

3.2. Introduction à OGR

La bibliothèque de fonctionnalités simples OGR fait partie de la bibliothèque d'abstraction de données géospatiales (GDAL), une bibliothèque open source extrêmement populaire pour la lecture et l'écriture de données spatiales. La partie OGR de GDAL est la partie qui permet de lire et d'écrire de nombreux formats de données vectorielles différents. OGR vous permet également de créer et de manipuler des géométries, d'éditer des valeurs d'attributs de filtrer des données vectorielles en fonction des valeurs d'attributs ou de l'emplacement spatial et il offre également des capacités d'analyse de données. En bref, si vous souhaitez utiliser GDAL pour travailler avec des données vectorielles, OGR est ce que vous devez apprendre, et vous le ferez, dans les quatre prochains chapitres.

La bibliothèque GDAL a été écrite à l'origine en C et C & 43 & 43, mais elle a des liaisons pour plusieurs autres langages, y compris Python, donc il y a une interface vers la bibliothèque GDAL/OGR de Python, pas que le code a été réécrit en Python. Par conséquent, pour utiliser GDAL avec Python, vous devez installer à la fois la bibliothèque GDAL et les liaisons Python correspondantes. Si vous ne l'avez pas encore fait, veuillez consulter l'annexe A pour des instructions d'installation détaillées.

Que signifie l'acronyme OGR, de toute façon? Auparavant, il signifiait OpenGIS Simple Features Reference Implementation, mais comme OGR n'est pas entièrement conforme à la spécification OpenGIS Simple Features, le nom a été modifié et maintenant la partie OGR ne représente rien et n'est que de nature historique.

Plusieurs fonctions utilisées dans ce chapitre proviennent du module Python ospybook disponible en téléchargement sur www.manning.com/books/geoprocessing-with-python . Vous voudrez également installer ce module. Les exemples d'ensembles de données sont disponibles sur le même site.

Avant de commencer à travailler avec OGR, il est utile d'examiner comment les divers objets de l'univers OGR sont liés les uns aux autres, comme le montre la figure 3.6 . Si vous ne comprenez pas cette hiérarchie, les étapes nécessaires pour lire et écrire des données n'auront pas beaucoup de sens. Lorsque vous utilisez OGR pour ouvrir une source de données, telle qu'un fichier de formes, un fichier GeoJSON, une base de données SpatiaLite ou PostGIS, vous aurez un objet DataSource. Cette source de données peut avoir un ou plusieurs objets Layer enfants, un pour chaque jeu de données contenu dans la source de données. De nombreux formats de données vectorielles, tels que les exemples de fichiers de formes utilisés dans ce chapitre, ne peuvent contenir qu'un seul ensemble de données. Mais d'autres, comme SpatiaLite, peuvent contenir plusieurs ensembles de données, et vous en verrez des exemples dans le chapitre suivant. Quel que soit le nombre de jeux de données dans une source de données, chacun est considéré comme une couche par OGR. Même plusieurs de mes étudiants, qui utilisent régulièrement le SIG pour leurs cours et leurs recherches, sont confus s'ils utilisent principalement des fichiers de formes, car il leur est contre-intuitif que quelque chose appelé une couche se trouve entre la source de données et les données réelles.

Graphique 3.6. La structure de classe OGR. Chaque source de données peut avoir plusieurs couches, chaque couche peut avoir plusieurs entités et chaque entité contient une géométrie et un ou plusieurs attributs.

Et en parlant des données réelles, chaque couche contient une collection d'objets Feature qui contiennent les géométries et leurs attributs. Si vous chargez des données vectorielles dans un SIG, tel que QGIS, puis regardez la table attributaire, vous verrez quelque chose de similaire à la figure 3.7 . Chaque ligne du tableau correspond à une entité, telle que l'entité représentant l'Afghanistan. Chaque colonne correspond à un champ d'attribut, et dans ce cas, deux des attributs sont SOVEREIGNT et TYPE . Bien que vous puissiez ouvrir des tables de données qui n'ont pas d'informations spatiales ou de géométries associées aux entités, nous travaillerons avec des jeux de données qui ont des géométries. Comme vous pouvez le voir sur la figure 3.7, les géométries n'apparaissent pas dans la table attributaire de QGIS, bien que d'autres progiciels SIG, tels qu'ArcGIS, affichent une colonne de forme dans la table attributaire.

Graphique 3.7. Un exemple de table attributaire montré dans QGIS. Chaque ligne correspond à une caractéristique et chaque colonne est un champ attributaire.

La première étape pour accéder aux données vectorielles consiste à ouvrir la source de données. Pour cela, vous devez disposer d'un pilote approprié qui indique à OGR comment travailler avec votre format de données. Le site Web GDAL/OGR répertorie plus de 70 formats vectoriels que l'OGR est capable de lire, bien qu'il ne puisse pas les écrire tous. Chacun d'eux a son propre pilote. Il est probable que votre version d'OGR ne prenne pas en charge toutes celles répertoriées, mais vous pouvez toujours la compiler vous-même si vous avez besoin de quelque chose qui manque (notez que c'est plus facile à dire qu'à faire dans de nombreux cas). Voir www.gdal.org/ogr_formats.html pour la liste de tous les formats disponibles et les détails spécifiques relatifs à chacun.

Un pilote est un traducteur pour un format de données spécifique, tel que Geo-JSON ou shapefile. Il indique à OGR comment lire et écrire ce format particulier. Si aucun pilote pour un format n'est compilé dans OGR, alors OGR ne peut pas fonctionner avec.

Si vous n'êtes pas sûr que votre installation de GDAL/OGR prend en charge un format de données particulier, vous pouvez utiliser l'utilitaire de ligne de commande ogrinfo pour savoir quels pilotes sont disponibles. L'emplacement de cet utilitaire sur votre ordinateur dépend de votre système d'exploitation et de la façon dont vous avez installé GDAL, vous devrez donc peut-être vous reporter à l'annexe A . Si vous n'êtes pas habitué à utiliser une ligne de commande, vous pouvez être tenté de double-cliquer sur le fichier exécutable ogrinfo, mais cela ne vous sera utile nulle part. Au lieu de cela, vous devez exécuter ogrinfo à partir d'une fenêtre de terminal ou d'une invite de commande Windows. Quoi qu'il en soit, une fois que vous aurez trouvé l'exécutable, vous voudrez l'exécuter avec l'option --formats. La figure 3.8 montre un exemple de son exécution sur ma machine Windows 7, bien que j'aie coupé la plupart de la sortie.

Graphique 3.8. Un exemple d'exécution de l'utilitaire ogrinfo à partir d'une invite de commande GDAL sur un ordinateur Windows

Comme vous pouvez le voir, ogrinfo vous indique non seulement quels pilotes sont inclus avec votre version d'OGR, mais aussi s'il peut écrire sur chacun d'eux ainsi que lire à partir de celui-ci.

Des informations sur les formats vectoriels pris en charge par OGR sont disponibles sur www.gdal.org/ogr_formats.html .

Vous pouvez également déterminer quels pilotes sont disponibles à l'aide de Python. En fait, essayons. Commencez par ouvrir votre environnement interactif Python préféré. J'utiliserai IDLE ( figure 3.9) parce que c'est celui qui est fourni avec Python, mais vous pouvez utiliser celui avec lequel vous êtes à l'aise. La première chose à faire est d'importer le module ogr pour pouvoir l'utiliser. Ce module réside dans le package osgeo, qui a été installé lorsque vous avez installé les liaisons Python pour GDAL. Tous les modules de ce package sont nommés avec des lettres minuscules, c'est ainsi que vous devez vous y référer en Python. Une fois que vous avez importé ogr , vous pouvez utiliser ogr.GetDriverByName pour trouver un pilote spécifique :

de osgeo importer ogr

pilote = ogr.GetDriverByName( 'GeoJSON' )

Graphique 3.9. Exemple de session interactive Python montrant comment obtenir des pilotes

Utilisez le nom de la colonne Code sur la page Web OGR Vector Formats. Si vous obtenez un pilote valide et que vous l'imprimez, vous verrez des informations sur l'emplacement de stockage de l'objet en mémoire. L'important est qu'il y ait quelque chose à imprimer car cela signifie que vous avez réussi à trouver un pilote. Si vous passez un nom invalide, ou le nom d'un pilote manquant, la fonction renverra None . Voir la figure 3.9 pour des exemples.

Une fonction appelée print_drivers dans le module ospybook imprimera également une liste des pilotes disponibles. Ceci est montré dans la figure 3.9.

3.3. Lecture de données vectorielles

Maintenant que vous connaissez les formats disponibles, il est temps de lire les données. Vous commencerez avec un fichier de formes de villes, le jeu de données ne_50m_populated_places.shp dans le sous-dossier global de votre dossier osgeopy-data. N'hésitez pas à l'ouvrir dans QGIS et regardez. Non seulement vous verrez les villes montrées dans la figure 3.10 , mais vous verrez également que la table attributaire contient une collection de champs, dont la plupart ne sont pas visibles dans la capture d'écran.

Graphique 3.10. Les géométries et les attributs de ne_50m_populated_places.shp comme vu dans QGIS

Le listing 3.1 montre un petit script qui imprime les noms, les populations et les coordonnées des 10 premières entités de cet ensemble de données. Ne vous inquiétez pas si cela n'a pas beaucoup de sens à première vue, car nous y reviendrons dans des détails atroces dans un instant. Le fichier est inclus avec le code source de ce chapitre, donc si vous voulez l'essayer, vous pouvez l'ouvrir dans IDLE, changer le nom du fichier dans la troisième ligne de code pour qu'il corresponde à votre configuration, puis choisir Exécuter le module sous Exécuter menu.

Liste 3.1. Impression des données des dix premières entités d'un fichier de formes

Le schéma de base est simple. La première chose à faire est d'ouvrir le fichier de formes et de vous assurer que le résultat de cette opération n'est pas égal à None , car cela signifierait que la source de données ne pourrait pas être ouverte. J'ai tendance à appeler cette variable ds , abréviation de source de données. Après vous être assuré que le fichier est ouvert, vous récupérez la première couche de la source de données. Ensuite, vous parcourez les 10 premières entités de la couche et pour chacune, obtenez l'objet géométrique, ses coordonnées et les valeurs des attributs NAME et POP_MAX. Ensuite, vous imprimez les informations sur la fonctionnalité avant de passer à la suivante. Une fois terminé, vous supprimez la variable ds pour forcer la fermeture du fichier.

Si vous avez exécuté le code avec succès, vous devriez avoir 10 lignes de sortie qui ressemblent à ceci, bien que vous n'ayez pas les parenthèses si vous utilisez Python 3:

( 'Bombo' , 75000, 32.533299524864844, 0.5832991056146284)

( 'Portail Fort' , 42670, 30.27500161597942, 0.671004121125236)

( 'Clermont-Ferrand' , 233050, 3.080008095928406, 45.779982115759424)

Voyons cela un peu plus en détail. Vous ouvrez une source de données en passant le nom de fichier et un indicateur de mise à jour facultatif à la fonction Ouvrir. Il s'agit d'une fonction autonome dans le module OGR, vous devez donc préfixer le nom de la fonction avec le nom du module afin que Python puisse le trouver. Si le deuxième paramètre n'est pas fourni, sa valeur par défaut est 0, ce qui ouvrira le fichier en mode lecture seule. Vous auriez pu passer 1 ou True pour l'ouvrir en mode mise à jour ou édition à la place.

Si le fichier ne peut pas être ouvert, la fonction Ouvrir renvoie None , donc la prochaine chose que vous faites est de vérifier cela et d'imprimer un message d'erreur et de quitter si nécessaire. J'aime vérifier cela afin de pouvoir résoudre le problème immédiatement et de la manière de mon choix (en quittant, dans ce cas) au lieu d'attendre que le script se bloque lorsqu'il essaie d'utiliser la source de données inexistante. Remplacez le nom de fichier dans la liste 3.1 par un faux et exécutez le script si vous voulez voir ce comportement en action :

si ds est Rien :

sys.exit( 'Impossible d'ouvrir <0>.' .format(fn))

N'oubliez pas que les sources de données sont constituées d'une ou plusieurs couches qui contiennent les données, donc après avoir ouvert la source de données, vous devez en extraire la couche. Les sources de données ont une fonction appelée GetLayer qui prend soit un index de couche, soit un nom de couche et renvoie l'objet Layer correspondant à l'intérieur de cette source de données particulière. Les index de couche commencent à 0, donc la première couche a l'index 0, la seconde a l'index 1, et ainsi de suite. Si vous ne fournissez aucun paramètre à GetLayer, il renvoie la première couche de la source de données. Le shapefile n'a qu'une seule couche, donc l'index n'est pas techniquement nécessaire dans ce cas.

Vous voulez maintenant extraire les données de votre couche. Rappelez-vous que chaque couche est constituée d'une ou plusieurs entités, chaque entité représentant un objet géographique. Les géométries et les valeurs attributaires sont attachées à ces entités, vous devez donc les examiner pour obtenir vos données. La seconde moitié du code de la liste 3.1 parcourt les 10 premières entités de la couche et imprime des informations sur chacune d'entre elles. Voici à nouveau la partie intéressante :

pour exploit en lyr :

pop = feat.GetField( 'POP_MAX' )

imprimer(Nom, pop, X, oui)

La couche est un ensemble de fonctionnalités que vous pouvez parcourir avec une boucle for. À chaque passage dans la boucle, la variable feat sera l'entité suivante de la couche et la boucle parcourra toutes les entités de la couche avant de s'arrêter. Cependant, vous ne voulez pas imprimer toutes les 1 249 fonctionnalités, vous forcez donc l'arrêt après les 10 premières.

La première chose que vous faites à l'intérieur de la boucle est d'obtenir la géométrie de l'entité et de la coller dans une variable appelée pt . Une fois que vous avez la géométrie, vous récupérez ses coordonnées x et y et les stockez dans des variables à utiliser plus tard.

Ensuite, vous récupérez les valeurs des champs NAME et POP_MAX et les stockez également dans des variables. La fonction GetField prend un nom d'attribut ou un index et renvoie la valeur de ce champ. Une fois que vous avez les attributs, vous imprimez toutes les informations que vous avez recueillies sur l'entité actuelle.

Une chose que vous devez savoir est que la fonction GetField renvoie des données qui sont du même type de données que celles de l'ensemble de données sous-jacent. Dans cet exemple, la valeur de la variable name est une chaîne, mais la valeur stockée dans pop est un nombre. Si vous souhaitez que les données soient dans un autre format, consultez l'annexe B pour voir une liste de fonctions qui renvoient des valeurs d'un type spécifique. Par exemple, si vous souhaitez que pop soit une chaîne afin de pouvoir la concaténer en une autre chaîne, vous pouvez utiliser GetFieldAsString .

pop = feat.GetFieldAsString( 'POP_MAX' )

Notez que tous les formats de données ne prennent pas en charge tous les types de champs et que toutes les données ne peuvent pas être converties avec succès entre les types, vous devez donc tester soigneusement les choses avant de vous fier à ces conversions automatiques. Non seulement ces fonctions sont utiles pour convertir des données entre types, mais vous pouvez également les utiliser pour rendre les types de données plus évidents dans votre code. Par exemple, si vous utilisez GetFieldAsInteger , il est évident pour quiconque lit votre code que la valeur est un entier.

3.3.1. Accéder à des fonctionnalités spécifiques

Parfois, vous n'avez pas besoin de toutes les fonctionnalités, vous n'avez donc aucune raison de les parcourir toutes comme vous l'avez fait jusqu'à présent. Une méthode puissante pour limiter les entités à un sous-ensemble consiste à les sélectionner par valeur attributaire ou étendue spatiale, et vous le ferez au chapitre 5 . Une autre façon consiste à examiner les entités avec des décalages spécifiques, également appelés ID de fonctionnalité (FID). Le décalage est la position à laquelle se trouve l'entité dans le jeu de données, en commençant par zéro. Cela dépend entièrement de la position de l'entité dans le fichier et n'a rien à voir avec l'ordre de tri en mémoire. Par exemple, si vous ouvrez le fichier de formes ne_50m_populated_places dans QGIS et regardez la table attributaire, il affichera Bombo comme premier enregistrement de la table, comme dans la figure 3.11 A. Voir les nombres dans la colonne la plus à gauche ? Ce sont les valeurs de décalage. Now try sorting the table by name by clicking on the NAME column header, as shown in figure 3.11 B. Now the first record shown in the table is the one for Abakan, but it has an offset of 346. As you can see, that left-most column isn’t a row number like you see in spreadsheets, where the row numbers are always in the right order no matter how you sort the data. These numbers represent the order in the file instead.

Figure 3.11. The attribute table for the ne_50m_populated_places shapefile. Table A shows the native sort order, with the FIDs in order. Table B has been sorted by city name, and the FIDs are no longer ordered sequentially.

If you know the offset of the feature you want, you can ask for that feature by FID. To get the feature for Vatican City, you use GetFeature(7) .

You can also get the total number of features with GetFeatureCount , so you could grab the last feature in the layer like this:

>> > last_feature = lyr.GetFeature(num_features - 1 )

You have to subtract one from the total number of features because the first index is zero. If you had tried to get the feature at index num_features, you’d have gotten an error message saying that the feature ID was out of the available range. This snippet also shows an alternate way of retrieving an attribute value from a feature, instead of using GetField , but it only works if you know the names beforehand so that you can hardcode them into your script.

The current feature

Another important point is that the functions that return features keep track of which feature was last accessed this is the current feature . When you first get the layer object, it has no current feature. But if you start iterating through features, the first time through the loop, the current feature is the one with an FID of zero. The second time through the loop, the current feature is the one with offset 1, and so on. If you use GetFeature to get the one with an FID of 5, that’s now the current feature, and if you then call GetNextFeature or start a loop, the next feature returned will be the one with offset 6. Yes, you read that right. If you iterate through the features in the layer, it doesn’t start at the first one if you’ve already set the current feature.

Based on what you’ve learned so far, what do you think would happen if you iterated through all of the features and printed out their names and populations, but then later tried to iterate through a second time to print out their names and coordinates? If you guessed that no coordinates would print out, you were right. The first loop stops when it runs out of features, so the current feature is pointing past the last one and isn’t reset to the beginning (see figure 3.12 ). No next feature is there when the second loop starts, so nothing happens. How do you get the current feature to point to the beginning again? You wouldn’t want to use a FID of zero, because if you tried to iterate through them all, the first feature would be skipped. To solve this problem, use the layer.ResetReading() function, which sets the current feature pointer to a location before the first feature, similar to when you first opened the layer.

Figure 3.12. The location of the current feature pointer at various times

3.3.2. Viewing your data

Before we continue, you might find it useful to know about functions in the ospybook module that will help you visualize your data without opening it in another software program. These don’t allow the level of interaction with the data that a GIS does, so opening it in QGIS is still a much better option for exploring the data in any depth.

Viewing attributes

You can print out attribute values to your screen using the print_attributes function, which looks like this:

print_attributes (lyr_or_fn, [n] , [fields] , [geom] , [reset] )

  • lyr_or_fn is either a layer object or the path to a data source. If it’s a data source, the first layer will be used.
  • n is an optional number of records to print. The default is to print them all.
  • fields is an optional list of attribute fields to include in the printout. The default is to include them all.
  • geom is an optional Boolean flag indicating whether the geometry type is printed. The default is True.
  • reset is an optional Boolean flag indicating whether the layer should be reset to the first record before printing. The default is True.

For example, to print out the name and population for the first three cities in the populated places shapefile, you could do something like this from a Python interactive window:


Voir la vidéo: How to Install Python GeoPandas - Easy and Straightforward Tutorial (Octobre 2021).