Unveiling Walkability Metrics: Isochrone Analysis

The first step involves constructing an isochrone graph centered around a point of interest (POI) with latitude and longitude coordinates over our pedestrian network. The isochrone is created based on a specified walking distance (500 meters in this example) from the POI:

    
from geopy.distance import geodesic

# Provide a point of interest with lat/lon coordinates
poi = (-6.153536, 106.726189)

# Compute the walking isochrone based on distance (500 meters in this example)
def compute_isochrone_for_poi(graph, poi, distance):
    isochrone = nx.MultiDiGraph()
    reachable_nodes = set()

    for node in graph.nodes(data=True):
        node_coords = (node[1]['y'], node[1]['x'])
        if geodesic(poi, node_coords).meters <= distance:
            reachable_nodes.add(node[0])
            # Add nodes to the isochrone
            isochrone.add_node(node[0], **node[1])

    for u, v, key, data in graph.edges(keys=True, data=True):
        if u in reachable_nodes and v in reachable_nodes:
            # Add edges to the isochrone
            isochrone.add_edge(u, v, key=key, **data)

    # Set the CRS for the isochrone (same as G2)
    isochrone.graph["crs"] = graph.graph["crs"]

    return isochrone

isochrone = compute_isochrone_for_poi(G2, poi, distance=500)
    

This function reads the pedestrian network data and constructs an isochrone graph, laying the foundation for subsequent walkability analyses.

Generating Convex Hull for Isochrone

We take a step further by defining the spatial extent of the isochrone through a convex hull analysis. This analysis creates a convex polygon encompassing the walkable area, offering a clearer visual representation.

The following code snippet defines a function, generate_convex_hull_for_isochrone(isochrone), which computes the convex hull for the coordinates of nodes within the isochrone:

    
from scipy.spatial import ConvexHull
from shapely.geometry import Polygon

def generate_convex_hull_for_iscochrone(isochrone):
    # Create a list to store the coordinates of nodes in the isochrone
    node_coords = []

    for node, data in isochrone.nodes(data=True):
        node_coords.append((data['x'], data['y']))

    # Compute the convex hull of the node coordinates
    hull = ConvexHull(node_coords)

    # Extract the convex hull vertices
    hull_vertices = [node_coords[i] for i in hull.vertices]

    # Create a Polygon from the convex hull vertices
    convex_hull_polygon = Polygon(hull_vertices)

    # Create a GeoDataFrame with the convex hull polygon
    hull_gdf = gpd.GeoDataFrame({'geometry': [convex_hull_polygon]}, crs=isochrone.graph["crs"])

    return hull_gdf

# Now you have a GeoDataFrame 'hull_gdf' containing the solid convex hull polygon
hull_gdf =  generate_convex_hull_for_iscochrone(isochrone)
    
    
def plot_hull_for_iscochrone(hull_gdf):
#### Plot
# Create a basic plot
hull_gdf.plot()
# Add title and labels
plt.title("Your isochrone")
plt.xlabel("Longitude")
plt.ylabel("Latitude")
# Show the plot
plt.show()
hull_gdf.columns

plot_hull_for_iscochrone(hull_gdf)
    

This function utilizes the scipy.spatial.ConvexHull algorithm to compute the convex hull of node coordinates within the isochrone. The resulting convex hull polygon is then encapsulated in a GeoDataFrame, hull_gdf, for further analysis.