gboeing / osmnx

OSMnx is a Python package to easily download, model, analyze, and visualize street networks and other geospatial features from OpenStreetMap.
https://osmnx.readthedocs.io
MIT License
4.85k stars 823 forks source link

Strange results from ox.consolidate_intersectons #910

Closed davidmurray closed 1 year ago

davidmurray commented 1 year ago

Problem description

Environment information

Package Version Editable project location ------------------------ ------------ ------------------------------------------- adjustText 0.7.3 affine 2.3.1 aiohttp 3.8.1 aiohttp-cors 0.7.0 aiosignal 1.2.0 anyio 3.6.2 appnope 0.1.3 argon2-cffi 21.3.0 argon2-cffi-bindings 21.2.0 asttokens 2.0.5 async-timeout 4.0.2 attrs 21.4.0 backcall 0.2.0 beautifulsoup4 4.11.1 bleach 5.0.1 blessed 1.19.1 boto3 1.24.77 botocore 1.27.77 branca 0.5.0 cachetools 5.2.0 certifi 2022.6.15 cffi 1.15.1 charset-normalizer 2.1.0 click 8.1.3 click-plugins 1.1.1 cligj 0.7.2 cloudpickle 2.2.0 colorful 0.5.4 contextily 1.2.0 cycler 0.11.0 Cython 0.29.32 cytoolz 0.12.0 dask 2022.1.1 deap 1.3.3 debugpy 1.6.2 decorator 5.1.1 defusedxml 0.7.1 distlib 0.3.6 distributed 2022.1.1 entrypoints 0.4 et-xmlfile 1.1.0 executing 0.8.3 fastjsonschema 2.16.1 filelock 3.8.0 Fiona 1.8.21 folium 0.12.1.post1 fonttools 4.34.4 frozenlist 1.3.0 fsspec 2022.8.2 GDAL 3.5.1 geographiclib 1.52 geopandas 0.12.2 geopy 2.2.0 geotiler 0.14.6 google-api-core 2.10.1 google-auth 2.11.1 googleapis-common-protos 1.56.4 gpustat 1.0.0 grpcio 1.43.0 HeapDict 1.0.1 idna 3.3 ipykernel 6.15.1 ipyleaflet 0.17.1 ipympl 0.9.2 ipython 8.4.0 ipython-genutils 0.2.0 ipywidgets 7.7.1 jedi 0.18.1 Jinja2 3.1.2 jmespath 1.0.1 joblib 1.1.0 jsonschema 4.7.2 jupyter 1.0.0 jupyter-client 7.3.4 jupyter-console 6.4.4 jupyter-core 4.11.1 jupyter-server 1.23.3 jupyterlab-execute-time 2.3.0 jupyterlab-pygments 0.2.2 jupyterlab-widgets 1.1.1 kiwisolver 1.4.4 line-profiler 4.0.1 locket 1.0.0 lxml 4.9.1 MarkupSafe 2.1.1 matplotlib 3.5.2 matplotlib-inline 0.1.3 mercantile 1.2.1 mistune 0.8.4 modin-spreadsheet 0.1.2 msgpack 1.0.4 multidict 6.0.2 munch 2.5.0 nbclient 0.6.6 nbconvert 6.5.0 nbformat 5.4.0 nest-asyncio 1.5.5 networkx 2.8.5 notebook 6.4.12 numpy 1.23.1 nvidia-ml-py 11.495.46 opencensus 0.11.0 opencensus-context 0.1.3 openpyxl 3.0.10 osmnx 1.3.0 packaging 21.3 pandas 1.5.2 pandocfilters 1.5.0 parso 0.8.3 partd 1.3.0 pexpect 4.8.0 pickleshare 0.7.5 Pillow 9.2.0 pip 22.1.1 pip-autoremove 0.10.0 platformdirs 2.5.2 plotly 5.9.0 plumbum 1.7.2 polyline 1.4.0 prometheus-client 0.13.1 prompt-toolkit 3.0.30 protobuf 3.20.2 psutil 5.9.1 ptyprocess 0.7.0 pure-eval 0.2.2 py-spy 0.3.14 pyarrow 9.0.0 pyasn1 0.4.8 pyasn1-modules 0.2.8 pycparser 2.21 pygad 2.17.0 Pygments 2.12.0 pyinstrument 4.3.0 pyparsing 3.0.9 pyproj 3.4.1 pyrsistent 0.18.1 pyshp 2.3.1 python-dateutil 2.8.2 pytz 2022.1 PyYAML 6.0 pyzmq 23.2.0 qtconsole 5.3.2 QtPy 2.2.0 rasterio 1.3.2 ray 1.12.1 redis 3.5.3 requests 2.28.1 rpyc 4.1.5 rsa 4.9 Rtree 1.0.0 s3transfer 0.6.0 scipy 1.9.1 Send2Trash 1.8.0 setuptools 62.3.2 shapely 2.0.0 six 1.16.0 smart-open 6.2.0 sniffio 1.3.0 snuggs 1.4.7 sortedcontainers 2.4.0 soupsieve 2.3.2.post1 stack-data 0.3.0 swifter 1.3.4 tblib 1.7.0 tenacity 8.0.1 terminado 0.15.0 tinycss2 1.1.1 toolz 0.12.0 tornado 6.2 tqdm 4.64.0 traitlets 5.3.0 traittypes 0.2.1 ujson 5.6.0 urllib3 1.26.10 utilities 1.0 virtualenv 20.16.5 wcwidth 0.2.5 webencodings 0.5.1 websocket-client 1.4.2 widgetsnbextension 3.6.1 xyzservices 2022.6.0 yappi 1.4.0 yarl 1.7.2 zict 2.2.0

Provide a complete minimal reproducible example

## Complete minimal example
import osmnx as ox

if "all_private" not in ox.settings.bidirectional_network_types:
    ox.settings.bidirectional_network_types.append('all_private')

G = ox.graph_from_xml(os.path.join(PROJECT_ROOT, "osm", "algo", "osm_network_agglomeration_montreal.xml"),
                               simplify=False,
                               retain_all=True,
                               bidirectional=True) # We want bidirectional edges, even for one-way streets.

# Project the graph to meters
G = ox.project_graph(G, to_crs='epsg:2950')

# Filter edges based on highway type
allowed_highway_types = ["primary", 
                         "secondary", 
                         "tertiary", 
                        ]
edges_subset = []
for u, v, data in G.edges(data=True):
    if data['highway'] in allowed_highway_types:
        edges_subset.append((u, v, 0))

G_subset = G.edge_subgraph(edges_subset)
gdf_links_raw = ox.graph_to_gdfs(G_subset, nodes=False)

G_consolidated = ox.consolidate_intersections(G_subset, rebuild_graph=True, tolerance=15, dead_ends=False)
gdf_links_consolidated = ox.graph_to_gdfs(G_consolidated, nodes=False)

# Then plot those graphs using folium for example

Unconsolidated intersections: image

Consolidated intersections: image

Question: why isn't it merged like this? image

Note: I tried changing the tolerance to 10m and 20m but I never seem to get the intended result. Perhaps I am misunderstanding the results that consolidate_intersections should offer. Note: The OSM XML file is attached, but it's basically just an export of highway=* from Overpass.

Here is the intersection in OpenStreetMap: https://www.openstreetmap.org/#map=18/45.55885/-73.59832

Thanks! osm_network_agglomeration_montreal.xml.zip

gboeing commented 1 year ago

Please provide the OSM IDs of the nodes that were merged together into this single consolidated node, and which of them you believe should not have been merged.

davidmurray commented 1 year ago

Hi, I think I had misunderstood the "tolerance" parameter and accidentally set it larger than it had to be, thus merging nodes that shouldn't be merged. Closing this issue :)