Je cherche un moyen de définir automatiquement les quartiers des villes comme des polygones sur un graphique.
Ma définition d'un quartier comporte deux parties:
- Un bloc : zone comprise entre plusieurs rues, où le nombre de rues (bords) et d'intersections (nœuds) est au minimum de trois (un triangle).
- Un quartier : pour un bloc donné, tous les blocs directement adjacents à ce bloc et le bloc lui-même.
Voir cette illustration pour un exemple:
Par exemple B4 est un bloc défini par 7 nœuds et 6 arêtes les reliant. Comme la plupart des exemples ici, les autres blocs sont définis par 4 nœuds et 4 arêtes les reliant. De plus, le quartier de B1 comprend B2 (et vice versa) tandis que B2 comprend également B3 .
J'utilise osmnx pour obtenir des données de rue d'OSM.
- En utilisant osmnx et networkx, comment puis-je parcourir un graphique pour trouver les nœuds et les arêtes qui définissent chaque bloc?
- Pour chaque bloc, comment trouver les blocs adjacents?
Je travaille moi-même vers un morceau de code qui prend un graphique et une paire de coordonnées (latitude, longitude) en entrée, identifie le bloc pertinent et renvoie le polygone pour ce bloc et le quartier tel que défini ci-dessus.
Voici le code utilisé pour faire la carte:
import osmnx as ox
import networkx as nx
import matplotlib.pyplot as plt
G = ox.graph_from_address('Nørrebrogade 20, Copenhagen Municipality',
network_type='all',
distance=500)
et ma tentative de trouver des cliques avec un nombre différent de nœuds et de degrés.
def plot_cliques(graph, number_of_nodes, degree):
ug = ox.save_load.get_undirected(graph)
cliques = nx.find_cliques(ug)
cliques_nodes = [clq for clq in cliques if len(clq) >= number_of_nodes]
print("{} cliques with more than {} nodes.".format(len(cliques_nodes), number_of_nodes))
nodes = set(n for clq in cliques_nodes for n in clq)
h = ug.subgraph(nodes)
deg = nx.degree(h)
nodes_degree = [n for n in nodes if deg[n] >= degree]
k = h.subgraph(nodes_degree)
nx.draw(k, node_size=5)
Théorie qui pourrait être pertinente:
Énumération de tous les cycles dans un graphique non orienté
Réponses:
Trouver des blocs de villes à l'aide du graphique est étonnamment non trivial. Fondamentalement, cela revient à trouver le plus petit ensemble de plus petits anneaux (SSSR), qui est un problème NP-complet. Un examen de ce problème (et des problèmes connexes) peut être trouvé ici . Sur SO, il existe une description d'un algorithme pour le résoudre ici . Pour autant que je sache, il n'y a pas d'implémentation correspondante dans
networkx
(ou en python d'ailleurs). J'ai essayé brièvement cette approche, puis je l'ai abandonnée - mon cerveau n'est pas à la hauteur pour ce genre de travail aujourd'hui. Cela étant dit, je remettrai une prime à quiconque pourrait visiter cette page à une date ultérieure et publier une implémentation testée d'un algorithme qui trouve le SSSR en python.Au lieu de cela, j'ai poursuivi une approche différente, en tirant parti du fait que le graphique est garanti d'être plan. En bref, au lieu de traiter cela comme un problème de graphe, nous le traitons comme un problème de segmentation d'image. Tout d'abord, nous trouvons toutes les régions connectées dans l'image. Nous déterminons ensuite le contour autour de chaque région, transformons les contours en coordonnées image en longitudes et latitudes.
Étant donné les importations et les définitions de fonction suivantes:
Chargez les données. Mettez en cache les importations, si vous testez cela à plusieurs reprises - sinon votre compte peut être banni. Parlant d'expérience ici.
Taillez les nœuds et les arêtes qui ne peuvent pas faire partie d'un cycle. Cette étape n'est pas strictement nécessaire mais donne de plus beaux contours.
Convertissez le tracé en image et trouvez les régions connectées:
Pour chaque région étiquetée, recherchez le contour et reconvertissez les coordonnées des pixels du contour en coordonnées de données.
Déterminez tous les points du graphique d'origine qui se trouvent à l'intérieur (ou sur) le contour.
Il est assez facile de déterminer si deux blocs sont voisins. Vérifiez simplement s'ils partagent un nœud:
la source
Je ne suis pas complètement sûr que
cycle_basis
cela vous donnera les quartiers que vous recherchez, mais si c'est le cas, c'est une chose simple pour en obtenir le graphique de quartier:la source
nx.Graph(G)
je perds beaucoup d'informations (directivité et type multigraph), j'ai donc du mal à vérifier votre réponse, car je ne peux pas sembler relier le nouveau graphiqueI
à mon graphique d'origineG
.Je n'ai pas de code, mais je suppose qu'une fois que je serai sur le trottoir, si je continue à tourner à droite à chaque coin, je vais parcourir les bords de mon bloc. Je ne connais pas les bibliothèques donc je vais juste parler algo ici.
C'est en fait un algorithme à utiliser pour sortir d'un labyrinthe: gardez votre main droite sur le mur et marchez. Cela ne fonctionne pas en cas de boucles dans le labyrinthe, il suffit de boucler. Mais cela donne une solution à votre problème.
la source
Ceci est une mise en œuvre de l'idée de Hashemi Emad . Cela fonctionne bien tant que la position de départ est choisie de telle sorte qu'il existe un moyen de faire un pas dans le sens antihoraire dans un cercle serré. Pour certains bords, en particulier autour de l'extérieur de la carte, cela n'est pas possible. Je ne sais pas comment sélectionner les bonnes positions de départ, ni comment filtrer les solutions - mais peut-être que quelqu'un d'autre en a une.
Exemple de travail (en commençant par le bord (1204573687, 4555480822)):
Exemple, où cette approche ne fonctionne pas (en commençant par le bord (1286684278, 5818325197)):
Code
la source