@@ -2,11 +2,11 @@ use std::collections::{BTreeMap, BTreeSet, HashMap};
2
2
3
3
use anyhow:: Result ;
4
4
use geo:: { Coord , LineInterpolatePoint , LineString , Polygon } ;
5
- use osm_reader:: { Element , NodeID } ;
5
+ use osm_reader:: { NodeID , OsmID , RelationID , WayID } ;
6
6
use petgraph:: graphmap:: UnGraphMap ;
7
7
use rstar:: { primitives:: GeomWithData , RTree } ;
8
8
use utils:: {
9
- osm2graph:: { EdgeID , Graph } ,
9
+ osm2graph:: { EdgeID , Graph , OsmReader } ,
10
10
Tags ,
11
11
} ;
12
12
@@ -15,94 +15,75 @@ use crate::{
15
15
Router ,
16
16
} ;
17
17
18
- pub fn create_from_osm (
19
- input_bytes : & [ u8 ] ,
20
- boundary_wgs84 : Polygon ,
21
- study_area_name : Option < String > ,
22
- ) -> Result < MapModel > {
23
- info ! ( "Parsing {} bytes of OSM data" , input_bytes. len( ) ) ;
24
- // This doesn't use osm2graph's helper, because it needs to scrape more things from OSM
25
- let mut node_mapping = HashMap :: new ( ) ;
26
- let mut highways = Vec :: new ( ) ;
27
- let mut bus_routes_on_roads = HashMap :: new ( ) ;
28
- let mut railways = Vec :: new ( ) ;
29
- let mut waterways = Vec :: new ( ) ;
30
- let mut barrier_nodes: BTreeSet < NodeID > = BTreeSet :: new ( ) ;
31
- osm_reader:: parse ( input_bytes, |elem| match elem {
32
- Element :: Node {
33
- id, lon, lat, tags, ..
34
- } => {
35
- let pt = Coord { x : lon, y : lat } ;
36
- node_mapping. insert ( id, pt) ;
37
-
38
- // Tuning these by hand for a few known areas.
39
- // https://wiki.openstreetmap.org/wiki/Key:barrier is proper reference.
40
- if let Some ( kind) = tags. get ( "barrier" ) {
41
- // Bristol has many gates that don't seem as relevant
42
- if kind != "gate" {
43
- barrier_nodes. insert ( id) ;
44
- }
18
+ #[ derive( Default ) ]
19
+ struct Osm {
20
+ bus_routes_on_roads : HashMap < WayID , Vec < String > > ,
21
+ railways : Vec < LineString > ,
22
+ waterways : Vec < LineString > ,
23
+ barrier_nodes : BTreeSet < NodeID > ,
24
+ }
25
+
26
+ impl OsmReader for Osm {
27
+ fn node ( & mut self , id : NodeID , _: Coord , tags : Tags ) {
28
+ // Tuning these by hand for a few known areas.
29
+ // https://wiki.openstreetmap.org/wiki/Key:barrier is proper reference.
30
+ if let Some ( kind) = tags. get ( "barrier" ) {
31
+ // Bristol has many gates that don't seem as relevant
32
+ if kind != "gate" {
33
+ self . barrier_nodes . insert ( id) ;
45
34
}
46
35
}
47
- Element :: Way {
48
- id,
49
- mut node_ids,
50
- tags,
51
- ..
52
- } => {
53
- let tags = tags. into ( ) ;
54
- if is_road ( & tags) {
55
- // TODO This sometimes happens from Overpass?
56
- let num = node_ids. len ( ) ;
57
- node_ids. retain ( |n| node_mapping. contains_key ( n) ) ;
58
- if node_ids. len ( ) != num {
59
- warn ! ( "{id} refers to nodes outside the imported area" ) ;
60
- }
61
- if node_ids. len ( ) >= 2 {
62
- highways. push ( utils:: osm2graph:: Way { id, node_ids, tags } ) ;
63
- }
64
- } else if tags. has ( "railway" ) && ( !tags. has ( "layer" ) || tags. is ( "layer" , "0" ) ) {
65
- node_ids. retain ( |n| node_mapping. contains_key ( n) ) ;
66
- if node_ids. len ( ) >= 2 {
67
- railways. push ( LineString (
68
- node_ids. into_iter ( ) . map ( |n| node_mapping[ & n] ) . collect ( ) ,
69
- ) ) ;
70
- }
71
- } else if tags. is_any ( "natural" , vec ! [ "water" , "coastline" ] )
72
- || tags. is ( "waterway" , "dock" )
73
- {
74
- // If the entire area is inside the study area, the LineString will be closed. If
75
- // it intersects the study area, then it might not be.
76
- node_ids. retain ( |n| node_mapping. contains_key ( n) ) ;
77
- if node_ids. len ( ) >= 2 {
78
- waterways. push ( LineString (
79
- node_ids. into_iter ( ) . map ( |n| node_mapping[ & n] ) . collect ( ) ,
80
- ) ) ;
81
- }
82
- }
36
+ }
37
+
38
+ fn way (
39
+ & mut self ,
40
+ _: WayID ,
41
+ node_ids : & Vec < NodeID > ,
42
+ node_mapping : & HashMap < NodeID , Coord > ,
43
+ tags : & Tags ,
44
+ ) {
45
+ if node_ids. len ( ) < 2 {
46
+ return ;
47
+ }
48
+ if tags. has ( "railway" ) && ( !tags. has ( "layer" ) || tags. is ( "layer" , "0" ) ) {
49
+ self . railways . push ( LineString (
50
+ node_ids. into_iter ( ) . map ( |n| node_mapping[ & n] ) . collect ( ) ,
51
+ ) ) ;
52
+ } else if tags. is_any ( "natural" , vec ! [ "water" , "coastline" ] ) || tags. is ( "waterway" , "dock" )
53
+ {
54
+ // If the entire area is inside the study area, the LineString will be closed. If
55
+ // it intersects the study area, then it might not be.
56
+ self . waterways . push ( LineString (
57
+ node_ids. into_iter ( ) . map ( |n| node_mapping[ & n] ) . collect ( ) ,
58
+ ) ) ;
83
59
}
84
- Element :: Relation { tags , members , .. } => {
85
- let tags : Tags = tags . into ( ) ;
86
- if tags . is ( "type" , "route" ) && tags. is ( "route" , "bus" ) {
87
- if let Some ( name ) = tags. get ( "name ") {
88
- for ( role , member ) in members {
89
- if let osm_reader :: OsmID :: Way ( w ) = member {
90
- if role . is_empty ( ) {
91
- bus_routes_on_roads
92
- . entry ( w )
93
- . or_insert_with ( Vec :: new )
94
- . push ( name . to_string ( ) ) ;
95
- }
60
+ }
61
+
62
+ fn relation ( & mut self , _ : RelationID , members : & Vec < ( String , OsmID ) > , tags : & Tags ) {
63
+ if tags . is ( "type" , "route" ) && tags. is ( "route" , "bus ") {
64
+ if let Some ( name ) = tags . get ( "name" ) {
65
+ for ( role , member ) in members {
66
+ if let OsmID :: Way ( w ) = member {
67
+ if role . is_empty ( ) {
68
+ self . bus_routes_on_roads
69
+ . entry ( * w )
70
+ . or_insert_with ( Vec :: new )
71
+ . push ( name . to_string ( ) ) ;
96
72
}
97
73
}
98
74
}
99
75
}
100
76
}
101
- Element :: Bounds { .. } => { }
102
- } ) ? ;
77
+ }
78
+ }
103
79
104
- info ! ( "Splitting {} ways into edges" , highways. len( ) ) ;
105
- let mut graph = Graph :: from_scraped_osm ( node_mapping, highways) ;
80
+ pub fn create_from_osm (
81
+ input_bytes : & [ u8 ] ,
82
+ boundary_wgs84 : Polygon ,
83
+ study_area_name : Option < String > ,
84
+ ) -> Result < MapModel > {
85
+ let mut osm = Osm :: default ( ) ;
86
+ let mut graph = Graph :: new ( input_bytes, is_road, & mut osm) ?;
106
87
remove_disconnected_components ( & mut graph) ;
107
88
graph. compact_ids ( ) ;
108
89
@@ -135,10 +116,10 @@ pub fn create_from_osm(
135
116
} )
136
117
. collect ( ) ;
137
118
138
- for ls in & mut railways {
119
+ for ls in & mut osm . railways {
139
120
graph. mercator . to_mercator_in_place ( ls) ;
140
121
}
141
- for ls in & mut waterways {
122
+ for ls in & mut osm . waterways {
142
123
graph. mercator . to_mercator_in_place ( ls) ;
143
124
}
144
125
@@ -166,15 +147,15 @@ pub fn create_from_osm(
166
147
let mut map = MapModel {
167
148
roads,
168
149
intersections,
169
- bus_routes_on_roads,
150
+ bus_routes_on_roads : osm . bus_routes_on_roads ,
170
151
mercator : graph. mercator ,
171
152
boundary_wgs84,
172
153
study_area_name,
173
154
closest_road,
174
155
closest_intersection,
175
156
176
- railways,
177
- waterways,
157
+ railways : osm . railways ,
158
+ waterways : osm . waterways ,
178
159
179
160
router_before : None ,
180
161
router_after : None ,
@@ -196,7 +177,7 @@ pub fn create_from_osm(
196
177
// TODO Batch some or all of these initial edits?
197
178
198
179
// Apply barriers on any surviving edges. RoadID and osm2graph::EdgeID are the same.
199
- for node in barrier_nodes {
180
+ for node in osm . barrier_nodes {
200
181
// If there's no surviving edge, then it was a barrier on something we don't consider a
201
182
// road or on a road that was removed
202
183
let Some ( edge) = graph. node_to_edge . get ( & node) else {
0 commit comments