Skip to content

Commit 511d09c

Browse files
committed
editoast: osm-to-railjson: read operational points (stations)
1 parent 04c350e commit 511d09c

File tree

4 files changed

+81
-3
lines changed

4 files changed

+81
-3
lines changed

editoast/src/converters/osm_to_railjson.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,14 @@ pub fn parse_osm(osm_pbf_in: PathBuf) -> Result<RailJson, Box<dyn Error + Send +
6868
}
6969

7070
let nodes_tracks = NodeToTrack::from_edges(&edges);
71-
let signals = signals(osm_pbf_in, &nodes_tracks, &adjacencies);
71+
let signals = signals(&osm_pbf_in, &nodes_tracks, &adjacencies);
7272
let mut railjson = RailJson {
7373
switch_types: default_switch_types(),
7474
detectors: signals.iter().map(detector).collect(),
7575
signals,
7676
speed_sections: rail_edges.clone().flat_map(speed_sections).collect(),
7777
catenaries: rail_edges.clone().flat_map(catenaries).collect(),
78+
operational_points: operational_points(&osm_pbf_in, &nodes_tracks),
7879
..Default::default()
7980
};
8081

@@ -261,4 +262,15 @@ mod tests {
261262
assert_eq!(1, rj.catenaries.len());
262263
assert_eq!("15000", rj.catenaries[0].voltage);
263264
}
265+
266+
#[test]
267+
fn parse_stations() {
268+
let rj = parse_osm("src/tests/station.osm.pbf".into()).unwrap();
269+
assert_eq!(1, rj.operational_points.len());
270+
let op = &rj.operational_points[0];
271+
assert_eq!(2, op.parts.len());
272+
let ext = op.extensions.identifier.as_ref().unwrap();
273+
assert_eq!("atlantis", ext.name);
274+
assert_eq!(1234, ext.uic);
275+
}
264276
}

editoast/src/converters/utils.rs

+64-1
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ impl<'a> NodeToTrack<'a> {
277277
}
278278

279279
pub fn signals(
280-
osm_pbf_in: std::path::PathBuf,
280+
osm_pbf_in: &std::path::PathBuf,
281281
nodes_to_tracks: &NodeToTrack,
282282
adjacencies: &HashMap<osm4routing::NodeId, NodeAdjacencies>,
283283
) -> Vec<Signal> {
@@ -456,6 +456,69 @@ pub fn catenaries(edge: &Edge) -> Option<Catenary> {
456456
})
457457
}
458458

459+
pub fn operational_points(
460+
osm_pbf_in: &std::path::PathBuf,
461+
nodes_to_tracks: &NodeToTrack,
462+
) -> Vec<OperationalPoint> {
463+
let file = std::fs::File::open(osm_pbf_in).unwrap();
464+
let mut pbf = osmpbfreader::OsmPbfReader::new(file);
465+
pbf.iter()
466+
.flatten()
467+
.filter(|obj| obj.tags().contains("public_transport", "stop_area")) // https://wiki.openstreetmap.org/wiki/Tag:public_transport%3Dstop_area
468+
.flat_map(|obj| match obj {
469+
osmpbfreader::OsmObj::Relation(rel) => Some(rel), // Only consider OSM relations
470+
_ => None, // Discard Nodes and Ways
471+
})
472+
.map(|rel| {
473+
let parts = rel
474+
.refs
475+
.iter()
476+
.filter(|r| r.role == "stop") // We ignore other members of the relation
477+
.flat_map(|r| match r.member {
478+
osmpbfreader::OsmId::Node(id) => Some(id),
479+
_ => {
480+
warn!("OpenStreetMap relation ({}) has a member ({:?}) with role `stop` that isn’t a node", rel.id.0, r.member);
481+
None
482+
},
483+
})
484+
.flat_map(|node| {
485+
nodes_to_tracks
486+
.track_and_position(node)
487+
.map(|(track, position)| OperationalPointPart { track, position })
488+
})
489+
.collect();
490+
491+
OperationalPoint {
492+
id: rel.id.0.to_string().into(),
493+
parts,
494+
extensions: OperationalPointExtensions {
495+
identifier: identifier(&rel.tags),
496+
sncf: None,
497+
},
498+
}
499+
})
500+
.collect()
501+
}
502+
503+
fn identifier(tags: &osmpbfreader::Tags) -> Option<OperationalPointIdentifierExtension> {
504+
let uic = tags
505+
.get("uic_ref")
506+
.and_then(|uic| match i64::from_str(uic.as_str()) {
507+
Ok(uic) => Some(uic),
508+
Err(_) => {
509+
warn!("Could not parse {uic} uic code as integer");
510+
None
511+
}
512+
})
513+
.unwrap_or_default();
514+
515+
tags.get("name")
516+
.map(|name| OperationalPointIdentifierExtension {
517+
name: name.as_str().into(),
518+
uic,
519+
})
520+
}
521+
459522
#[cfg(test)]
460523
mod tests {
461524
use osm4routing::Coord;

editoast/src/schema/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ pub use detector::{Detector, DetectorCache};
2626
use enum_map::Enum;
2727
pub use errors::{InfraError, InfraErrorType};
2828
pub use geo_json::GeoJson;
29-
pub use operational_point::{OperationalPoint, OperationalPointCache, OperationalPointPart};
29+
pub use operational_point::{
30+
OperationalPoint, OperationalPointCache, OperationalPointExtensions,
31+
OperationalPointIdentifierExtension, OperationalPointPart,
32+
};
3033
pub use railjson::{find_objects, RailJson, RailjsonError};
3134
pub use route::Route;
3235
use serde::{Deserialize, Serialize};

editoast/src/tests/station.osm.pbf

364 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)