GithubHelp home page GithubHelp logo

Comments (8)

gboeing avatar gboeing commented on August 21, 2024 2

I think this solution is fast, powerful, and useful enough that I'll bake it into OSMnx directly. It'll be pushed shortly and released in the upcoming minor version.

from osmnx.

gboeing avatar gboeing commented on August 21, 2024 2

@kuanb @kelanstoy see OSMnx's new clean_intersections function and this example notebook demonstrating it.

from osmnx.

gboeing avatar gboeing commented on August 21, 2024 1

This is primarily an issue with the data model that OSM (and TIGER/Line shapefiles, etc) use to represent street networks. Generally, divided roads get represented as separate centerline edges. I've floated some ideas for dealing with this from a geometric perspective (see #12) but dealing with it topologically is a different story and probably outside the scope of OSMnx for now.

from osmnx.

gboeing avatar gboeing commented on August 21, 2024 1

@kelanstoy @kuanb here's a simple solution using the geometric dissolve method I suggested in #12:

import osmnx as ox, matplotlib.pyplot as plt, numpy as np, geopandas as gpd

# get a street network and plot it with all edge intersections
address = '2700 Shattuck Ave, Berkeley, CA'
G = ox.graph_from_address(address, network_type='drive', distance=750)
G_proj = ox.project_graph(G)
fig, ax = ox.plot_graph(G_proj, fig_height=10, node_color='orange', node_size=30, 
                        node_zorder=2, node_edgecolor='k')

# clean up intersections by buffering 15 meters, dissolving, and using centroid
gdf_nodes = ox.graph_to_gdfs(G_proj, edges=False)
buff = gdf_nodes.buffer(15)
unified = gpd.GeoDataFrame(geometry=list(buff.unary_union))
intersections = unified.centroid

# plot the cleaned-up intersections
fig, ax = ox.plot_graph(G_proj, fig_height=10, show=False, close=False, node_alpha=0)
points = np.array([point.xy for point in intersections])
ax.scatter(x=points[:,0], y=points[:,1], zorder=2, color='#66ccff', edgecolors='k')
plt.show()

...and you get something like this: before (left) and after (right):

It doesn't fix the topology (i.e., reconnect all the streets to the new intersection point), but it improves the intersection density counts.

from osmnx.

kuanb avatar kuanb commented on August 21, 2024

Just to add my solution here for anyone else interested in dealing with this, I set up a simple for loop that (hopefully) should not get "out of control" with larger datasets.

Here's what the results look like with a small subset of data:
image

The gist is here with the most critical bit of code in lines 40 - up.

Basically, I create a boolean column and for loop through the geodataframe, marking "off" any intersections whose buffer intersects the one being currently reviewed. As I move through the whole geodataframe, I skip any rows that have already been marked as "off," thereby avoiding repeating the intersection test on any of an already reviewed intersection's "siblings."

# set a bool column to track which intersections to use
gdf_nodes['use'] = True

list_of_nodes = gdf_nodes.index.values

for node_id in list_of_nodes:
    current = gdf_nodes.loc[node_id]

    # only proceed if has not already been marked as False (don't use)
    if current['use']:
        ints_with = gdf_nodes.intersects(current.geometry)

        # review intersecting buffered nodes
        sub_gdf = gdf_nodes[ints_with]
        sub_gdf_sans_current = sub_gdf[sub_gdf.index != node_id]

        # get the indexes of other rows and 'turn them off'
        turn_these_off = sub_gdf_sans_current.index.values
        for sub_node_id in turn_these_off:
            gdf_nodes.loc[sub_node_id, 'use'] = False

# here is a dataframe of unique geometries
cleaned_ints = gdf_nodes[gdf_nodes['use'] == True]

from osmnx.

kuanb avatar kuanb commented on August 21, 2024

Fantastic!

So a plain language interpretation of your methodology:

  1. Convert network to GeoDataFrame
  2. Create a GeoSeries of buffered nodes (in your case, 15 meters)
  3. Perform a unary union on the GeoSeries (I presume a MultiPolygon is returned)
  4. Extract all centroids from aforementioned MultPolygon

from osmnx.

kuanb avatar kuanb commented on August 21, 2024

Update - Geoff's method took under 2 minutes whereas for the for loop method took over 30 minutes!

from osmnx.

kuanb avatar kuanb commented on August 21, 2024

Nice, thanks!!

from osmnx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.