1- use geo:: { Geometry , Haversine , Length } ;
1+ use geo:: { Coord , Geometry , Haversine , InterpolatableLine , Length , LineString } ;
22use serde:: { Deserialize , Serialize } ;
33
44use crate :: collection:: { OvertureMapsCollectionError , OvertureRecord } ;
@@ -12,9 +12,10 @@ use super::{OvertureMapsBbox, OvertureMapsNames, OvertureMapsSource};
1212/// and other attributes relevant to routing and mapping.
1313#[ derive( Debug , Serialize , Deserialize ) ]
1414pub struct TransportationSegmentRecord {
15+ /// GERS identifier for this segment record
1516 pub id : String ,
1617 #[ serde( deserialize_with = "deserialize_geometry" ) ]
17- pub geometry : Option < Geometry > ,
18+ pub geometry : Option < Geometry < f32 > > ,
1819 bbox : OvertureMapsBbox ,
1920 version : i32 ,
2021 sources : Option < Vec < Option < OvertureMapsSource > > > ,
@@ -50,21 +51,43 @@ impl TryFrom<OvertureRecord> for TransportationSegmentRecord {
5051}
5152
5253impl TransportationSegmentRecord {
53- pub fn get_distance_at ( & self , at : f64 ) -> Result < f64 , OvertureMapsCollectionError > {
54- let geometry =
55- self . geometry
56- . as_ref ( )
57- . ok_or ( OvertureMapsCollectionError :: InvalidGeometry (
58- "empty geometry" . to_string ( ) ,
59- ) ) ?;
60-
54+ pub fn get_linestring ( & self ) -> Result < & LineString < f32 > , OvertureMapsCollectionError > {
55+ let geometry = self . geometry . as_ref ( ) . ok_or_else ( || {
56+ OvertureMapsCollectionError :: InvalidGeometry ( "empty geometry" . to_string ( ) )
57+ } ) ?;
6158 match geometry {
62- Geometry :: LineString ( line_string) => Ok ( Haversine . length ( line_string) * at ) ,
59+ Geometry :: LineString ( line_string) => Ok ( line_string) ,
6360 _ => Err ( OvertureMapsCollectionError :: InvalidGeometry ( format ! (
6461 "geometry was not a linestring {geometry:?}"
6562 ) ) ) ,
6663 }
6764 }
65+
66+ pub fn get_distance_at ( & self , at : f64 ) -> Result < f32 , OvertureMapsCollectionError > {
67+ if !( 0.0 ..=1.0 ) . contains ( & at) {
68+ return Err ( OvertureMapsCollectionError :: InvalidLinearReference ( at) ) ;
69+ }
70+ let linestring = self . get_linestring ( ) ?;
71+ Ok ( Haversine . length ( linestring) * at as f32 )
72+ }
73+
74+ /// gets a coordinate from this linestring at some linear reference.
75+ pub fn get_coord_at ( & self , at : f64 ) -> Result < Coord < f32 > , OvertureMapsCollectionError > {
76+ if !( 0.0 ..=1.0 ) . contains ( & at) {
77+ return Err ( OvertureMapsCollectionError :: InvalidLinearReference ( at) ) ;
78+ }
79+ let linestring = self . get_linestring ( ) ?;
80+ match linestring. point_at_ratio_from_start ( & Haversine , at as f32 ) {
81+ Some ( pt) => Ok ( pt. 0 ) ,
82+ None => {
83+ let msg = format ! (
84+ "unexpected error getting point for segment {} at {at}" ,
85+ self . id
86+ ) ;
87+ Err ( OvertureMapsCollectionError :: InternalError ( msg) )
88+ }
89+ }
90+ }
6891}
6992
7093#[ derive( Debug , Serialize , Deserialize ) ]
0 commit comments