Nuevos algoritmos como OSMnx nos presentan una serie de indicadores que ayudan a definir la l贸gica espacial y el orden urbano, revelando el orden y el desorden de las calles, as铆 como las mejores estrategias de la din谩mica del transporte de una ciudad. En esta oportunidad exploraremos el Municipio Libertador utilizando datos de OpenStreetMap y OSMnx en una primra oportunidad para conocer la red vial y ejecutar un modelado de rutas basado en las distancias y la impendancia y finalmente aplicar el indicador de orientaci贸n de las ciudades a manera de cuantificar c贸mo la red vial en Caracas sigue una l贸gica de ordenamiento geom茅trico de una cuadr铆cula 煤nica 贸 su patr贸n es heterog茅neo.
1.- Datos del API de OpenStreetMap para descargar los datos de la red.
2.- Datos del API de Google Maps para descargar los datos de altitud y asociarlos a la red vial, para desarrollar nuestro modelo de impendancias, definido este por la diferencia altitudinal de las rutas.
3.- Aplicar el algoristmo de OSMnx para desarrollar los modelos y definir las orientaciones cardinales de los ejes viales.
from api import APIKey
import networkx as nx
import numpy as np
import osmnx as ox
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline
ox.config(log_console=True, use_cache=True)
ox.__version__
# Extraemos los datos asociados al municipio Libertador: Caracas
place = 'Municipio Libertador'
G = ox.graph_from_place('Municipio Libertador, Venezuela', network_type='drive', which_result=5)
# Consultamos los datos para cada nodo vial extraido utilizando los datos de Google Elevation API
G = ox.add_node_elevations(G, api_key=APIKey)
G = ox.add_edge_grades(G)
Usamos los nodos para definir la red y solo tomamos los valores 煤nicos para evitar duplicar los datos y finalmente calculamos los valores porcentuales de pendiente.
edge_grades = [data['grade_abs'] for u, v, k, data in ox.get_undirected(G).edges(keys=True, data=True)]
avg_grade = np.mean(edge_grades)
print('Pendiente Promedio de la red vial en Caracas {} is {:.1f}%'.format(place, avg_grade*100))
med_grade = np.median(edge_grades)
print('Mediana de la pendiente de la red vial en Caracas {} is {:.1f}%'.format(place, med_grade*100))
Comparemos estos datos con el Guia de Diseno de Infraestructura y Equipamiento Ciclista elaborado por la Facultad de Arquitectura de la UNAM - M茅xico
Vemos que en promedio el Municipio Libertador cuenta con una condici贸n Normal para el desarrollo de una infraestructura de Ciclovia si bien lo ideal ser铆a contar con valores cercanos a 1% en pendiente, la actual estructura vial ofrece condiciones igualmente favorables para su planificaci贸n, para ello a continuaci贸n visualizaremos la red elaborando un modelo de impendancia por la condici贸n altitudinal.
Siendo los valores de menor altitud violeta y los de mayor altitud amarillo.
G_proj = ox.project_graph(G)
nc = ox.get_node_colors_by_attr(G_proj, 'elevation', cmap='plasma', num_bins=20)
fig, ax = ox.plot_graph(G_proj, fig_height=6, node_color=nc, node_size=12, node_zorder=2, edge_color='#dddddd')
# get a color for each edge, by grade, then plot the network
ec = ox.get_edge_colors_by_attr(G_proj, 'grade_abs', cmap='plasma', num_bins=100)
fig, ax = ox.plot_graph(G_proj, fig_height=6, edge_color=ec, edge_linewidth=0.8, node_size=0)
# Seleccionamos una ruta en la ciudad de Caracas
origin = ox.get_nearest_node(G, (10.501716,-66.946971))
destination = ox.get_nearest_node(G, (10.506104,-66.914742))
bbox = ox.bbox_from_point((10.510113,-66.931951), distance=3000, project_utm=True)
# Definimos nuestro modelo basado en la distancia y las variaciones de pendiente
def impedance(length, grade):
penalty = grade ** 2
return length * penalty
for u, v, k, data in G_proj.edges(keys=True, data=True):
data['impedance'] = impedance(data['length'], data['grade_abs'])
data['rise'] = data['length'] * data['grade']
route_by_length = nx.shortest_path(G_proj, source=origin, target=destination, weight='length')
fig, ax = ox.plot_graph_route(G_proj, route_by_length, bbox=bbox, node_size=0)
route_by_impedance = nx.shortest_path(G_proj, source=origin, target=destination, weight='impedance')
fig, ax = ox.plot_graph_route(G_proj, route_by_impedance, bbox=bbox, node_size=0)
def print_route_stats(route):
route_grades = ox.get_route_edge_attributes(G_proj, route, 'grade_abs')
msg = 'The average grade is {:.1f}% and the max is {:.1f}%'
print(msg.format(np.mean(route_grades)*100, np.max(route_grades)*100))
route_rises = ox.get_route_edge_attributes(G_proj, route, 'rise')
ascent = np.sum([rise for rise in route_rises if rise >= 0])
descent = np.sum([rise for rise in route_rises if rise < 0])
msg = 'Total elevation change is {:.0f} meters: a {:.0f} meter ascent and a {:.0f} meter descent'
print(msg.format(np.sum(route_rises), ascent, abs(descent)))
route_lengths = ox.get_route_edge_attributes(G_proj, route, 'length')
print('Total trip distance: {:,.0f} meters'.format(np.sum(route_lengths)))
# Estad铆sticas de la ruta m谩s corta
print_route_stats(route_by_length)
# Estad铆sticas para la ruta con la menor pendiente
print_route_stats(route_by_impedance)
En nuestro modelo de menor pendiente disminuimos la pendiente promedio a lo largo de la ruta de una pendiente del 20% a una pendiente del 11% disminuyendo el ascenso total de 98 m茅tros a 13 m茅tros (pero la distancia de viaje aumenta de 4,5 Km a 5.3 km).
G = ox.add_edge_bearings(G)
bearings = pd.Series([data['bearing'] for u, v, k, data in G.edges(keys=True, data=True)])
ax = bearings.hist(bins=30, zorder=2, alpha=0.8)
xlim = ax.set_xlim(0, 360)
ax.set_title('Municipio Libertador Orientaciones Cardinales de la Red Vial y su frecuencia')
plt.show()
Creamos un histograma polar d贸nde cada barra representar谩 la direcci贸n de las calles con relaci贸n a los puntos cardinales (Norte, Sur, Este y Oeste) y su longitud representar谩 la cantidad de calles en una direcci贸n concreta.
import numpy as np
n = 30
count, division = np.histogram(bearings, bins=[ang*360/n for ang in range(0,n+1)])
division = division[0:-1]
width = 2 * np.pi/n
ax = plt.subplot(111, projection='polar')
ax.set_theta_zero_location('N')
ax.set_theta_direction('clockwise')
bars = ax.bar(division * np.pi/180 - width * 0.5 , count, width=width, bottom=0.0)
ax.set_title('Histograma Polar de la red vial del Municipio Libertador de Caracas', y=1.1)
plt.show()
Este histograma nos permite dimensionar la heterogeneidad de la red vial, sin embargo en su mayoria es posible observar que la red obedece a un patr贸n Este-Oeste definido principalemente por la Avenida Bol铆var y sus calles paralelas, veamos un escenario m谩s homog茅neo como lo es el Municipio Chacao.
G = ox.graph_from_place('Chacao, Caracas, Venezuela', network_type='drive')
fig, ax = ox.plot_graph(ox.project_graph(G), node_size=0)
G = ox.add_edge_bearings(G)
bearings = pd.Series([data['bearing'] for u, v, k, data in G.edges(keys=True, data=True)])
ax = bearings.hist(bins=30, zorder=2, alpha=0.8)
ax.set_xlim(0, 360)
ax.set_title('Municipio Chacao Orientaciones Cardinales de la Red Vial y su frecuencia')
plt.show()
n = 30
count, division = np.histogram(bearings, bins=[ang*360/n for ang in range(0,n+1)])
division = division[0:-1]
width = 2 * np.pi/n
ax = plt.subplot(111, projection='polar')
ax.set_theta_zero_location('N')
ax.set_theta_direction('clockwise')
bars = ax.bar(division * np.pi/180 - width * 0.5 , count, width=width, bottom=20.0)
ax.set_title('Histograma Polar de la red vial del Municipio Chacao', y=1.1)
plt.show()
Vemos para el Municipio Chacao una mayor homogeneidad que sigue la l贸gica de un ordenamiento geom茅trico de cuadr铆cula 煤nica con Avenidas (Norte-Sur) y Calles paralelas (Este-Oeste)
Las red vial organiza y limita la din谩mica de transporte en la ciudad de acuerdo con una cierta l贸gica espacial, ya sea planificada o no planificada, ordenada o desordenada.
Este estudio present贸 un modelo basado en los algoritmos de OSMnx para la optimizaci贸n de potenciales rutas para bicicletas basadas en la logitud y la altitud de la red vial utilizando datos de OpenStreetMap y el API de GoogleMaps.
Finalmente se visualiz贸 un histograma polar de orientaciones para descrubir por primera vez la l贸gica espacial de la estructura v铆al del Municipio Libertador de Caracas y lo comparamos con el Municipio Chacao siendo este 煤ltimo m谩s ajustado a una grilla 煤nica y homog茅nea a diferencia d ela complejidad de la red vial del Municipio Libertador, demuestrando ambos casos que los modelos son una t茅cnica escalable viable para medir y visualizar emp铆ricamente la complejidad del orden espacial, ilustrando patrones en la urbanizaci贸n y el transporte en Caracas.
Para una visualizaci贸n din谩mica del algoritmo de OSMnx es posible encontrar aqu铆.