Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ConRE-OSM

Continuity-based Road Extraction from OSM

OSM Road Surface Reconstruction — Case Study: Delft

Reconstruct lane-level road and intersection polygons from OpenStreetMap (OSM) centerline data for Delft, Netherlands.

This repository contains the source code of the ConRE-OSM tool, developed as part of a thesis study using road centerline data from OpenStreetMap for the city of Delft, Netherlands. ConRE-OSM reconstructs topologically continuous, lane-level road surface polygons and intersection areas directly from OSM way geometry, without requiring additional surveyed or manually prepared inputs. The pipeline derives lane offsets, corrects geometric connectivity at forks and bi-directional junctions, and generates semantically labelled road and intersection polygons that preserve the continuity and topology of the underlying street network.


Citation

This repository accompanies the MSc thesis:

Rao, C. (2024). Reconstructing a high-detailed 2D areal representation of road network based on OSM data [Master's thesis, Delft University of Technology]. TU Delft Repository. https://resolver.tudelft.nl/uuid:0bae72e4-ff16-4921-8f6e-d92fa4a377d7

If you use this work ConRE-OSM, please cite the following:

Thesis

@mastersthesis{rao2024roadreconstructing,
  author  = {Rao, Chengzhi},
  title   = {Reconstructing a high-detailed 2D areal representation of road network based on OSM data},
  school  = {Delft University of Technology},
  year    = {2024},
  type    = {Master's thesis},
  note    = {Faculty of Architecture and the Built Environment, Programme: Geomatics},
  url     = {https://resolver.tudelft.nl/uuid:0bae72e4-ff16-4921-8f6e-d92fa4a377d7}
}

Tool

@software{conre_osm_2026,
  author  = {[Chengzhi Rao]},
  title   = {{ConRE-OSM}: Continuity-based Road Extraction from OSM},
  year    = {2026},
  url     = {[repository URL]},
  license = {GPL-3.0-or-later}
}

References

The following works informed the design of ConRE-OSM:

Methods and tools used

Related projects


Final outputs

File Description Rows
data/output/road_intersections.geojson Intersection polygons 108
data/output/road_segments.geojson Road polygons with intersections removed 329

All files use EPSG:28992 (RD New, metres).


Setup

pip install -r requirements.txt

Python 3.10+. Place your OSM export at:

data/input/delft_osm_ways.geojson

This is the only external input required. It should be an OSM ways export in WGS84 (EPSG:4326) covering the study area. Filtering to the required highway types and reprojection to EPSG:28992 happen automatically inside the pipeline.


Run

python run.py               # run all 5 stages
python run.py --stages 1 2  # run only stages 1 and 2
python run.py --from 3      # run stages 3 through 5
python run.py --no-mid      # skip saving mid-results (faster)

All output paths are defined at the top of run.py. Change them there to relocate data.


Pipeline overview

data/input/delft_osm_ways.geojson          ──► Stage 1, Stage 4, Stage 5

Stage 1 ──► data/output/stage/s1_road_attributes.geojson  ──► Stage 2, 3, 4
Stage 2 ──► data/output/stage/s2_lane_centerlines.geojson ──► Stage 3
         ──► data/output/stage/s2_lane_polygons.geojson   ──► Stage 3
         ──► data/output/stage/s2_lane_boundaries.geojson ──► Stage 3
         ──► data/output/stage/s2_road_dict.json          ──► Stage 3
Stage 3 ──► data/output/stage/s3_lane_segments.geojson    ──► Stage 4, Stage 5
Stage 4 ──► data/output/stage/s4_road_polygons.geojson    ──► Stage 5
         ──► data/output/stage/s4_network_nodes.geojson   ──► Stage 5
Stage 5 ──► data/output/road_intersections.geojson        (FINAL)
         ──► data/output/road_segments.geojson            (FINAL)

Data flow — detailed

Stage 1 — Extract, Classify and Label Road Centerlines

Input: data/input/delft_osm_ways.geojson

Stage result → stages 2, 3, 4:

File Rows Role
data/output/stage/s1_road_attributes.geojson 554 Road attribute table: lane counts, turn:lanes, bearings, group_index, oneway, fork_type per road segment

Mid results (data/output/mid/):

File After which step
s1_cycle_extract.geojson Cycleway extraction from parent-road attributes
s1_backward_split.geojson Bi-directional roads split into _forward/_backward
s1_turn_normalized.geojson turn:lanes normalised to pipe-separated strings
s1_grouped.geojson Initial grouping (superseded by stage result)

Stage 2 — Offset Lane Centerlines

Input: data/output/stage/s1_road_attributes.geojson

Stage results → stage 3:

File Description
data/output/stage/s2_lane_centerlines.geojson Offset lane centerlines (id_raw, lane_type, lane_order, geometry)
data/output/stage/s2_lane_polygons.geojson Buffered lane polygons, same structure
data/output/stage/s2_lane_boundaries.geojson Two outermost boundary lines per road
data/output/stage/s2_road_dict.json Per-road lane data (393 entries): ids, types, turns, offsets, widths, groups

Mid results: none.


Stage 3 — Modify Lane Geometry for Topology

Inputs: s1_road_attributes.geojson + all s2_* files (stage 2)

Stage result → stages 4, 5:

File Rows Role
data/output/stage/s3_lane_segments.geojson 659 Per-lane metadata with corrected geometry: id_raw, id_lane, type, highway, order, turn_lanes, offset, width, fork_type, geometry

Mid results (data/output/mid/):

File Contents
s3_fork_aligned.geojson Fork lane centerlines after start-node alignment
s3_fork_buffered.geojson Buffered fork polygons
s3_cycle_lines.geojson Cycleway centerlines after endpoint alignment
s3_cycle_polys.geojson Cycleway polygons after alignment
s3_pre_bifork_lines.geojson Lane centerlines after fork+cycle+accessor fixes, pre-bi-fork pass
s3_pre_bifork_polys.geojson Same state, polygons
s3_final_lane_lines.geojson Final lane centerlines — all passes complete
s3_final_lane_polys.geojson Final lane polygons
s3_final_boundaries.geojson Final road boundary lines

Stage 4 — Post-Process Road Polygons

Inputs: data/input/delft_osm_ways.geojson + s1_road_attributes.geojson + s3_lane_segments.geojson

degree_true (corrected intersection degree for interior nodes) is computed directly from the road graph geometry — no additional external file required.

Stage results → stage 5:

File Rows Role
data/output/stage/s4_network_nodes.geojson 408 Network nodes with degree (momepy count) and degree_true (corrected for interior nodes). Stage 5 overrides degree with degree_true where set.
data/output/stage/s4_road_polygons.geojson 395 Per-road polygons after all trim passes. Stage 5 clips these by intersection polygons.

Mid results (data/output/mid/):

File After which trim pass
s4_trim_degree2.geojson Degree-2 pseudo-intersection node trim
s4_trim_bikelanes.geojson Mixed vehicle+cycleway boundary trim
s4_fixed_polys.geojson Merged state after pseudo + mixed trims
s4_endpoint_trim.geojson Degree-3 dead-end stub trim
s4_fixed_polys2.geojson State after endpoint trim
s4_multitype_trim.geojson Final multi-type trim (cycle + vehicle at same node)

Stage 5 — Generate Intersection Polygons

Inputs: data/input/delft_osm_ways.geojson + s4_road_polygons.geojson + s4_network_nodes.geojson + s3_lane_segments.geojson

Final outputs:

File Rows Contents
data/output/road_intersections.geojson 108 Intersection polygons (vehicle and cycleway, including roundabouts), each buffered 0.005 m
data/output/road_segments.geojson 329 Road polygons with intersections removed; type, width, lanes, fork_type, bridge, tunnel, junction, name, oneway

Mid results: none.


Output types

Type Location Description Can delete?
Stage result data/output/stage/ Required input for the next stage No, until downstream stage completes
Mid result data/output/mid/ Inspection snapshots for debugging Yes, after verification
Final output data/output/ End product of the pipeline Keep

Project structure

ConRE-OSM/
├── run.py                  ← CLI entry point; all paths defined here
├── README.md
├── LICENSE                 ← GPL-3.0-or-later (code)
├── LICENSE-DATA            ← CC BY-NC 4.0 (output data)
├── requirements.txt
├── pipeline/
│   ├── stage1_centerlines.py
│   ├── stage2_lane_offset.py
│   ├── stage3_lane_geometry.py
│   ├── stage4_road_polygon.py
│   └── stage5_intersections.py
└── data/
    ├── input/
    │   └── delft_osm_ways.geojson   ← place your OSM export here
    └── output/
        ├── stage/                   ← stage results (auto-created)
        ├── mid/                     ← mid results (auto-created)
        ├── road_intersections.geojson
        └── road_segments.geojson

Licenses

Code — GNU General Public License v3.0 or later (GPL-3.0-or-later) See LICENSE · Full text

Output data — Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) See LICENSE-DATA · Full text

Input data — © OpenStreetMap contributors, Open Database License (ODbL 1.0) Any use of the output data must retain OSM attribution.

About

Continuity-based Road Extraction from OSM

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages