Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions rust/bambam-gbfs/src/app/gbfs_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ impl GbfsOperation {

fn parse_duration(s: &str) -> Result<chrono::TimeDelta, String> {
let std_duration =
humantime::parse_duration(s).map_err(|e| format!("Invalid duration: {}", e))?;
chrono::TimeDelta::from_std(std_duration).map_err(|e| format!("TimeDelta out of range: {}", e))
humantime::parse_duration(s).map_err(|e| format!("Invalid duration: {e}"))?;
chrono::TimeDelta::from_std(std_duration).map_err(|e| format!("TimeDelta out of range: {e}"))
}
3 changes: 2 additions & 1 deletion rust/bambam-omf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ serde_arrow = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true }
uom = { workspace = true }
wkb = { workspace = true }
wkt = { workspace = true }
wkb = { workspace = true }
2 changes: 1 addition & 1 deletion rust/bambam-omf/src/app/cli_bbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub struct CliBoundingBox {
pub fn parse_bbox(s: &str) -> Result<CliBoundingBox, String> {
let parts: Vec<&str> = s.split(',').collect();
if parts.len() != 4 {
return Err(format!("expected format: xmin,xmax,ymin,ymax, got: {}", s));
return Err(format!("expected format: xmin,xmax,ymin,ymax, got: {s}"));
}

let xmin = parse_lon(parts[0])?;
Expand Down
2 changes: 1 addition & 1 deletion rust/bambam-omf/src/graph/connector_in_segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl ConnectorInSegment {
/// identifiers to sub-segments by their segment id along with linear reference ranges.
/// see <https://docs.overturemaps.org/guides/transportation/#transportation-splitter>
pub fn new_without_connector_id(segment_id: String, linear_reference: f64) -> Self {
let connector_id = format!("{}@{}", segment_id, linear_reference);
let connector_id = format!("{segment_id}@{linear_reference}");
Self {
segment_id,
connector_id,
Expand Down
41 changes: 40 additions & 1 deletion rust/bambam-omf/src/graph/omf_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ use crate::{
};
use csv::QuoteStyle;
use flate2::{write::GzEncoder, Compression};
use geo::LineString;
use kdam::tqdm;
use rayon::prelude::*;
use routee_compass_core::model::network::{EdgeConfig, EdgeList, EdgeListId, Vertex};
use wkt::ToWkt;

pub struct OmfGraphVectorized {
pub vertices: Vec<Vertex>,
Expand All @@ -24,7 +26,7 @@ pub struct OmfGraphVectorized {

pub struct OmfEdgeList {
pub edges: EdgeList,
// pub geometries: Vec<LineString<f32>>
pub geometries: Vec<LineString<f32>>,
}

impl OmfGraphVectorized {
Expand Down Expand Up @@ -75,8 +77,10 @@ impl OmfGraphVectorized {
&vertex_lookup,
edge_list_id,
)?;
let geometries = ops::create_geometries(&segments, &segment_lookup, &splits)?;
let edge_list = OmfEdgeList {
edges: EdgeList(edges.into_boxed_slice()),
geometries,
};
edge_lists.push(edge_list);
}
Expand Down Expand Up @@ -154,6 +158,13 @@ impl OmfGraphVectorized {
QuoteStyle::Necessary,
overwrite,
);
let mut geometries_writer = create_writer(
&mode_dir,
"edges-geometries-enumerated.txt.gz",
false,
QuoteStyle::Never,
overwrite,
);

// Write Edges
let e_iter = tqdm!(
Expand Down Expand Up @@ -186,6 +197,34 @@ impl OmfGraphVectorized {
))
})?;
}

// Write geometries
let g_iter = tqdm!(
edge_list.geometries.iter(),
total = edge_list.geometries.len(),
desc = "geometries",
position = 1
);
for row in g_iter {
if let Some(ref mut writer) = geometries_writer {
writer
.serialize(row.to_wkt().to_string())
.map_err(|e| {
OvertureMapsCollectionError::CsvWriteError(format!(
"Failed to write to geometry file edges-geometries-enumerated.txt.gz: {e}"
))
})?;
}
}
eprintln!();

if let Some(ref mut writer) = geometries_writer {
writer.flush().map_err(|e| {
OvertureMapsCollectionError::CsvWriteError(format!(
"Failed to flush edges-geometries-enumerated.txt.gz: {e}"
))
})?;
}
}
eprintln!();

Expand Down
58 changes: 56 additions & 2 deletions rust/bambam-omf/src/graph/segment_split.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashMap;

use geo::{Haversine, Length, LineString};
use routee_compass_core::model::network::{Edge, EdgeId, EdgeListId, Vertex, VertexId};
use uom::si::f64::Length;

use crate::{
collection::{OvertureMapsCollectionError, TransportationSegmentRecord},
Expand Down Expand Up @@ -102,11 +102,65 @@ impl SegmentSplit {
edge_id,
src_vertex_id: VertexId(*src_id),
dst_vertex_id: VertexId(*dst_id),
distance: Length::new::<uom::si::length::meter>(distance as f64),
distance: uom::si::f64::Length::new::<uom::si::length::meter>(distance as f64),
};

Ok(edge)
}
}
}

pub fn create_geometry_from_split(
&self,
segments: &[&TransportationSegmentRecord],
segment_lookup: &HashMap<String, usize>,
) -> Result<LineString<f32>, OvertureMapsCollectionError> {
use OvertureMapsCollectionError as E;

match self {
SegmentSplit::SimpleConnectorSplit { src, dst } => {
let segment_id = &src.segment_id;
let segment_idx = segment_lookup.get(segment_id).ok_or_else(|| {
let msg = format!("missing lookup entry for segment {segment_id}");
E::InvalidSegmentConnectors(msg)
})?;
let segment = segments.get(*segment_idx).ok_or_else(|| {
let msg = format!(
"missing lookup entry for segment {segment_id} with index {segment_idx}"
);
E::InvalidSegmentConnectors(msg)
})?;

let distance_to_src = segment.get_distance_at(src.linear_reference.0)?;
let distance_to_dst = segment.get_distance_at(dst.linear_reference.0)?;
let segment_geometry = segment.get_linestring()?;

let mut out_coords = vec![];

// Add the initial point
out_coords.push(segment.get_coord_at(src.linear_reference.0)?);

// Check all points to see if we need to add them
let mut total_distance = 0.;
for line in segment_geometry.lines() {
let line_distance = Haversine.length(&line);
total_distance += line_distance;

if total_distance <= distance_to_src {
continue;
}
if total_distance >= distance_to_dst {
break;
}

out_coords.push(line.end);
}

// Add final point
out_coords.push(segment.get_coord_at(dst.linear_reference.0)?);

Ok(LineString::new(out_coords))
}
}
}
}
13 changes: 12 additions & 1 deletion rust/bambam-omf/src/graph/serialize_ops.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use geo::Coord;
use geo::{Coord, LineString};
use itertools::Itertools;
use kdam::{tqdm, Bar, BarExt};
use rayon::prelude::*;
Expand Down Expand Up @@ -178,3 +178,14 @@ pub fn create_edges(
})
.collect::<Result<Vec<Edge>, OvertureMapsCollectionError>>()
}

pub fn create_geometries(
segments: &[&TransportationSegmentRecord],
segment_lookup: &HashMap<String, usize>,
splits: &[SegmentSplit],
) -> Result<Vec<LineString<f32>>, OvertureMapsCollectionError> {
splits
.par_iter()
.map(|split| split.create_geometry_from_split(segments, segment_lookup))
.collect::<Result<Vec<LineString<f32>>, OvertureMapsCollectionError>>()
}
Loading