ifc_lite_landxml/alignment/
inspection.rs1use super::{
8 LandXmlAlignment, LandXmlCantStation, LandXmlNumericDiagnostic, LandXmlStationMapping,
9 LandXmlSuperelevation,
10};
11
12#[derive(Clone, Debug, PartialEq, serde::Serialize)]
17pub struct LandXmlCantProbe {
18 pub internal_station: f64,
19 pub station: LandXmlStationMapping,
20 pub previous: Option<LandXmlCantStation>,
21 pub next: Option<LandXmlCantStation>,
22}
23
24impl LandXmlAlignment {
25 pub fn cant_at_distance(
29 &self,
30 distance: f64,
31 ) -> Result<Option<LandXmlCantProbe>, LandXmlNumericDiagnostic> {
32 let station = self.station_at_distance(distance)?;
33 let Some(cant) = &self.cant else {
34 return Ok(None);
35 };
36 let internal_station = self.sta_start + distance;
37 if cant
38 .stations
39 .iter()
40 .any(|candidate| !candidate.station.is_finite())
41 || cant
42 .stations
43 .windows(2)
44 .any(|pair| pair[1].station <= pair[0].station)
45 {
46 return Err(super::numeric::diagnostic(
47 &cant.source_id,
48 "LXMLA207",
49 "CantStation values must be finite and strictly increasing",
50 ));
51 }
52 let split = cant
53 .stations
54 .partition_point(|candidate| candidate.station <= internal_station);
55 Ok(Some(LandXmlCantProbe {
56 internal_station,
57 station,
58 previous: split
59 .checked_sub(1)
60 .and_then(|index| cant.stations.get(index))
61 .cloned(),
62 next: cant.stations.get(split).cloned(),
63 }))
64 }
65
66 pub fn superelevations_at_distance(
70 &self,
71 distance: f64,
72 ) -> Result<Vec<&LandXmlSuperelevation>, LandXmlNumericDiagnostic> {
73 self.station_at_distance(distance)?;
74 let internal_station = self.sta_start + distance;
75 Ok(self
76 .superelevations
77 .iter()
78 .filter(|value| {
79 value
80 .sta_start
81 .is_none_or(|start| internal_station >= start)
82 && value.sta_end.is_none_or(|end| internal_station <= end)
83 })
84 .collect())
85 }
86}