Skip to content

osmnx.consolidate_intersections incorrectly merges cloverleaf interchange loop ramps #1342

@wlc185

Description

@wlc185

Contributing guidelines

  • I understand the contributing guidelines

Documentation

  • My problem is not addressed by the documentation or examples

Existing issues

  • My problem does not appear in an existing issue

What operating system and Python version are you using?

Windows11, python3.12

What OSMnx version are you using?

v2.0.1

Environment packages and versions

Package                   Version        Editable project location
------------------------- -------------- ----------------------------------------------
absl-py                   2.1.0
annotated-types           0.7.0
anyio                     4.9.0
argon2-cffi               25.1.0
argon2-cffi-bindings      25.1.0
arrow                     1.3.0
asttokens                 3.0.0
astunparse                1.6.3
async-lru                 2.0.5
attrs                     25.3.0
babel                     2.17.0
beautifulsoup4            4.13.4
black                     24.10.0
bleach                    6.2.0
branca                    0.8.1
certifi                   2024.12.14
cffi                      1.17.1
charset-normalizer        3.4.1
click                     8.1.8
coacd                     1.0.5
colorama                  0.4.6
comm                      0.2.3
contourpy                 1.3.1
cycler                    0.12.1
dataclasses-json          0.6.7
debugpy                   1.8.15
decorator                 5.1.1
defusedxml                0.7.1
Deprecated                1.2.15
dill                      0.3.9
et_xmlfile                2.0.0
etils                     1.11.0
executing                 2.2.0
fastjsonschema            2.21.1
filelock                  3.16.1
flatbuffers               25.2.10
folium                    0.20.0
fonttools                 4.55.3
fqdn                      1.5.1
freetype-py               2.5.1
fsspec                    2024.12.0
gast                      0.6.0
genesis-world             0.2.1          C:\Users\Luche\OneDrive\python project\Genesis   
geographiclib             2.0
geopandas                 1.1.1
geopy                     2.4.1
glfw                      2.8.0
google-pasta              0.2.0
grpcio                    1.70.0
h11                       0.16.0
h5py                      3.14.0
httpcore                  1.0.9
httpx                     0.28.1
idna                      3.10
imageio                   2.37.0
imageio-ffmpeg            0.6.0
importlib_resources       6.5.2
ipykernel                 6.30.0
ipython                   9.4.0
ipython_pygments_lexers   1.1.1
isoduration               20.11.0
jedi                      0.19.2
Jinja2                    3.1.5
joblib                    1.4.2
json5                     0.12.0
jsonpointer               3.0.0
jsonschema                4.25.0
jsonschema-specifications 2025.4.1
jupyter_client            8.6.3
jupyter_core              5.8.1
jupyter-events            0.12.0
jupyter-lsp               2.2.6
jupyter_server            2.16.0
jupyter_server_terminals  0.5.3
jupyterlab                4.4.5
jupyterlab_pygments       0.3.0
jupyterlab_server         2.27.3
keras                     3.10.0
kiwisolver                1.4.8
lark                      1.2.2
lazy_loader               0.4
libclang                  18.1.1
libigl                    2.5.1
llvmlite                  0.44.0
lxml                      5.3.0
Markdown                  3.7
markdown-it-py            3.0.0
MarkupSafe                3.0.2
marshmallow               3.25.1
matplotlib                3.10.0
matplotlib-inline         0.1.7
matplotlib-scalebar       0.9.0
mdurl                     0.1.2
mistune                   3.1.3
ml_dtypes                 0.5.1
moviepy                   2.1.2
mpmath                    1.3.0
mujoco                    3.2.5
mypy-extensions           1.0.0
namex                     0.1.0
nbclient                  0.10.2
nbconvert                 7.16.6
nbformat                  5.10.4
nest-asyncio              1.6.0
networkx                  3.4.2
notebook                  7.4.4
notebook_shim             0.2.4
numba                     0.61.0
numpy                     1.26.4
opencv-python             4.11.0.86
OpenEXR                   3.3.2
openpyxl                  3.1.5
opt_einsum                3.4.0
optree                    0.16.0
osmnx                     2.0.1
overrides                 7.7.0
packaging                 24.2
pandarallel               1.6.5
pandas                    2.2.3
pandas-stubs              2.3.0.250703
pandocfilters             1.5.1
parso                     0.8.4
pathspec                  0.12.1
pillow                    10.4.0
pip                       25.2
platformdirs              4.3.6
plotly                    5.24.1
pooch                     1.8.2
proglog                   0.1.10
prometheus_client         0.22.1
prompt_toolkit            3.0.51
protobuf                  5.29.3
psutil                    6.1.1
pure_eval                 0.2.3
pycollada                 0.8
pycparser                 2.22
pydantic                  2.7.1
pydantic_core             2.18.2
PyGEL3D                   0.5.2
pyglet                    2.1.1
pygltflib                 1.16.0
Pygments                  2.19.1
pymeshlab                 2023.12.post2
pyogrio                   0.10.0
PyOpenGL                  3.1.9
pyparsing                 3.2.1
pyproj                    3.7.0
python-dateutil           2.9.0.post0
python-dotenv             1.0.1
python-json-logger        3.3.0
pytz                      2024.2
pyvista                   0.44.2
pywin32                   311
pywinpty                  2.0.15
PyYAML                    6.0.2
pyzmq                     27.0.0
referencing               0.36.2
requests                  2.32.3
rfc3339-validator         0.1.4
rfc3986-validator         0.1.1
rfc3987-syntax            1.1.0
rich                      13.9.4
rpds-py                   0.26.0
scikit-image              0.25.0
scikit-learn              1.6.1
scipy                     1.15.1
scipy-stubs               1.16.2.0
scooby                    0.10.0
screeninfo                0.8.1
Send2Trash                1.8.3
setuptools                75.8.0
shapely                   2.1.1
six                       1.17.0
sniffio                   1.3.1
soupsieve                 2.7
stack-data                0.6.3
sympy                     1.13.1
taichi                    1.7.3
tenacity                  9.0.0
tensorboard               2.19.0
tensorboard-data-server   0.7.2
tensorflow                2.19.0
termcolor                 3.1.0
terminado                 0.18.1
tetgen                    0.6.4
threadpoolctl             3.5.0
tifffile                  2025.1.10
tinycss2                  1.4.0
torch                     2.5.1
torchaudio                2.5.1
torchvision               0.20.1
tornado                   6.5.1
tqdm                      4.67.1
traitlets                 5.14.3
types-python-dateutil     2.9.0.20250708
typing_extensions         4.12.2
typing-inspect            0.9.0
tzdata                    2024.2
uri-template              1.3.0
urllib3                   2.3.0
utm                       0.8.1
vtk                       9.3.1
wcwidth                   0.2.13
webcolors                 24.11.1
webencodings              0.5.1
websocket-client          1.8.0
Werkzeug                  3.1.3
wheel                     0.45.1
wrapt                     1.17.2
xyzservices               2025.4.0
zipp                      3.21.0

How did you install OSMnx?

pip or uv (via PyPI)

Problem description

I used osmnx.consolidate_intersections to simplify a network with the default parameters, and it causes a merging error on cloverleaf interchanges.

Image Image

By inspecting the source code, I found that “topologically close” nodes are defined as nodes that are in the same weakly connected component. However, the loop ramp of a cloverleaf interchange indeed satisfies this condition (the two endpoints of the loop ramp can be very close in position), which leads to the loop being merged incorrectly. This is very likely to happen when tolerance is set to a single scalar.

A simple solution I’m proposing is to add a new parameter to osmnx.consolidate_intersections, e.g., distance_tolerance, which accepts the same data types as tolerance. Its meaning is: if two endpoints are to be merged, they must also be very close along the path (network distance), not just satisfy Euclidean proximity and weak connectivity. I provide a simple modification of the source code to show how this new parameter could work (I hard-coded the new parameter as 50 here—this is only to illustrate the idea; the actual code may be more complex, since it might accept the same data types as tolerance):

Image

The idea is to delete longer edges in the copied subgraph according to the new parameter to form finer subclusters (without needing to change tolerance). This can effectively avoid the cloverleaf interchange merging error when using the default parameters of osmnx.consolidate_intersections.

Minimal standalone reproducible example

import osmnx as ox
g = ox.graph_from_bbox((117.98,24.48,118.00,24.50))
g = ox.project_graph(g)
g = ox.consolidate_intersections(g)
ox.plot.plot_graph(g)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions