|
1 | 1 | use std::collections::HashMap; |
2 | 2 |
|
| 3 | +use geo::{Haversine, Length, LineString}; |
3 | 4 | use routee_compass_core::model::network::{Edge, EdgeId, EdgeListId, Vertex, VertexId}; |
4 | | -use uom::si::f64::Length; |
5 | 5 |
|
6 | 6 | use crate::{ |
7 | 7 | collection::{OvertureMapsCollectionError, TransportationSegmentRecord}, |
@@ -102,11 +102,65 @@ impl SegmentSplit { |
102 | 102 | edge_id, |
103 | 103 | src_vertex_id: VertexId(*src_id), |
104 | 104 | dst_vertex_id: VertexId(*dst_id), |
105 | | - distance: Length::new::<uom::si::length::meter>(distance as f64), |
| 105 | + distance: uom::si::f64::Length::new::<uom::si::length::meter>(distance as f64), |
106 | 106 | }; |
107 | 107 |
|
108 | 108 | Ok(edge) |
109 | 109 | } |
110 | 110 | } |
111 | 111 | } |
| 112 | + |
| 113 | + pub fn create_geometry_from_split( |
| 114 | + &self, |
| 115 | + segments: &[&TransportationSegmentRecord], |
| 116 | + segment_lookup: &HashMap<String, usize>, |
| 117 | + ) -> Result<LineString<f32>, OvertureMapsCollectionError> { |
| 118 | + use OvertureMapsCollectionError as E; |
| 119 | + |
| 120 | + match self { |
| 121 | + SegmentSplit::SimpleConnectorSplit { src, dst } => { |
| 122 | + let segment_id = &src.segment_id; |
| 123 | + let segment_idx = segment_lookup.get(segment_id).ok_or_else(|| { |
| 124 | + let msg = format!("missing lookup entry for segment {segment_id}"); |
| 125 | + E::InvalidSegmentConnectors(msg) |
| 126 | + })?; |
| 127 | + let segment = segments.get(*segment_idx).ok_or_else(|| { |
| 128 | + let msg = format!( |
| 129 | + "missing lookup entry for segment {segment_id} with index {segment_idx}" |
| 130 | + ); |
| 131 | + E::InvalidSegmentConnectors(msg) |
| 132 | + })?; |
| 133 | + |
| 134 | + let distance_to_src = segment.get_distance_at(src.linear_reference.0)?; |
| 135 | + let distance_to_dst = segment.get_distance_at(dst.linear_reference.0)?; |
| 136 | + let segment_geometry = segment.get_linestring()?; |
| 137 | + |
| 138 | + let mut out_coords = vec![]; |
| 139 | + |
| 140 | + // Add the initial point |
| 141 | + out_coords.push(segment.get_coord_at(src.linear_reference.0)?); |
| 142 | + |
| 143 | + // Check all points to see if we need to add them |
| 144 | + let mut total_distance = 0.; |
| 145 | + for line in segment_geometry.lines() { |
| 146 | + let line_distance = Haversine.length(&line); |
| 147 | + total_distance += line_distance; |
| 148 | + |
| 149 | + if total_distance <= distance_to_src { |
| 150 | + continue; |
| 151 | + } |
| 152 | + if total_distance >= distance_to_dst { |
| 153 | + break; |
| 154 | + } |
| 155 | + |
| 156 | + out_coords.push(line.end); |
| 157 | + } |
| 158 | + |
| 159 | + // Add final point |
| 160 | + out_coords.push(segment.get_coord_at(dst.linear_reference.0)?); |
| 161 | + |
| 162 | + Ok(LineString::new(out_coords)) |
| 163 | + } |
| 164 | + } |
| 165 | + } |
112 | 166 | } |
0 commit comments