Suite

Matrice du plus court chemin avec QGIS/GRASS

Matrice du plus court chemin avec QGIS/GRASS


J'analyse le réseau électrique à haute tension de l'Allemagne. J'ai extrait les données d'OSM, les ai importées dans QGIS et simplifié sa structure à la main, en créant spécifiquement des nœuds uniques où les lignes électriques sont connectées contrairement à beaucoup de sous-stations haute tension avec des géométries compliquées. En fin de compte, je souhaite exporter ce réseau et l'utiliser dans GAMS pour y exécuter un modèle d'optimisation. Mais longue histoire courte. J'ai deux fichiers .shp, WGS 84 CRS standard.

  1. un fichier contenant le réseau sous forme de lignes (environ 250)
  2. un fichier contenant tous les nœuds (environ 350) du réseau (où les lignes électriques se croisent)

Maintenant, je veux extraire une matrice de distance la plus courte contenant les distances entre tous les nœuds du fichier 2, après avoir utilisé le fichier 1 comme réseau "routier".

J'ai lu quelques réponses suggérant python, GRASS ou PostGIS avec pgrouting, mais aucune d'entre elles n'a fonctionné pour moi. Je suis nouveau sur Python, GRASS et PostGIS, ce qui n'aide pas vraiment.

(presque oublié. Mac OS 10.7.5, GRASS 7.0, QGIS 2.8.1, PostgreSQL 9.0.13, PostGIS 2.1.7, pgrouting 2.0.0)


Ok, mettez à jour après encore quelques heures d'essai. Je pense avoir résolu le problème, plus ou moins par accident.

Depuis que j'ai numérisé/simplifié la structure de la grille à la main, l'un des problèmes était censé être que quelques lignes auraient des intersections entre leurs points de début et de fin. Cela semble être une bonne idée de laisser QGIS gérer cela et d'utiliser "Split lines with lines" de la boîte à outils Processing.

Cela fait, j'ai importé la grille et les nœuds en tant que fichiers shp dans GRASS. Les nœuds sont assez faciles à obtenir via l'outil d'analyse vectorielle de QGIS 'Line Intersections'. Ayant les deux couches importées dans GRASS, j'ai utilisé v.net avec operation:connect et option -c pour attacher la couche de nœud à la couche de ligne (nœuds en tant que couche 2). Alternativement, operation:nodes fait presque la même chose, car les nœuds calculés sont les mêmes que ceux que j'ai importés dans mon fichier shp depuis QGIS. Seule différence : les nœuds obtiennent des identifiants différents, vous ne pouvez donc pas vraiment conserver un schéma d'identifiant personnel pour identifier certains points dans QGIS.
Néanmoins, le réseau étant désormais "préparé", la fonction v.net.allpairs peut être utilisée. Toutes mes lignes sont dans la couche 1, tous les nœuds sont dans la couche 2. Les sélectionner, activer le calcul géodésique (mes fichiers shp étaient au standard WGS 84) et attendre quelques minutes a fait le travail. N'ayant défini aucun coût, la colonne 'from_cat' et la colonne 'to_cat' dans la table des attributs de la couche vectorielle en sortie sont maintenant mes anciens identifiants QGIS, et la colonne coût est la distance entre les nœuds en km.

J'espère que cette description pourra être utile à d'autres comme moi, pas trop familiarisés avec SQL/Python, etc. et à la recherche d'une solution assez cliquable. J'avais besoin de la table de distance la plus courte pour un modèle GAMS et j'ai pensé que ce serait un jeu d'enfant.


NetworkX (http://cheeseshop.python.org/pypi/networkx/) est un package Python avec de nombreuses fonctions pour l'analyse de graphes et de réseaux. Avec ce package installé, vous pouvez résoudre le problème de génération d'une matrice de distance la plus courte à l'aide de la console Python dans QGIS.

Tout ce dont vous avez besoin est une couche réseau (les bords) avec une topologie valide. Les arêtes ont besoin d'au moins 3 attributs : les identifiants du nœud de départ et du nœud de fin de chaque arête, et la longueur de chaque arête. Dans le code suivant, je m'attends à ce que ces champs soient d'index 1 à 3. Vous pouvez créer ce schéma de données à l'aide d'une requête SQL appropriée ou d'une jointure spatiale, suivi d'un calcul (de champ) de la longueur de ligne.

Faites de la couche réseau la couche active, puis dans la console Python :

importer networkx en tant que nx aLayer = qgis.utils.iface.activeLayer() DM = nx.Graph() DM.add_weighted_edges_from([(feat[1], feat[2], feat[3]) pour feat dans aLayer.getFeatures( )]) imprimer nx.all_pairs_dijkstra_path_length(DM)

La commande print de la dernière ligne affiche le résultat sous la forme d'un dictionnaire de dictionnaires. Au lieu d'imprimer la sortie sur la console, cette structure peut être utilisée pour un traitement ultérieur ou écrite dans un fichier.

De cette façon, de nombreux algorithmes de NetworkX peuvent être utilisés pour le géotraitement dans QGIS.


Voir la vidéo: QGIS Basics #48: Why does my Geoprocessing Buffer Distance show in Degrees?