tp_lib_core/models/path_metadata.rs
1//! Path calculation metadata
2
3use serde::{Deserialize, Serialize};
4
5use crate::models::AssociatedNetElement;
6
7/// Algorithm configuration and diagnostic metadata
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct PathMetadata {
10 /// Distance scale parameter used for probability calculation
11 pub distance_scale: f64,
12
13 /// Heading scale parameter used for probability calculation
14 pub heading_scale: f64,
15
16 /// Cutoff distance for candidate selection (meters)
17 pub cutoff_distance: f64,
18
19 /// Heading difference cutoff (degrees)
20 pub heading_cutoff: f64,
21
22 /// Probability threshold for path segment inclusion
23 pub probability_threshold: f64,
24
25 /// Resampling distance applied (meters), None if disabled
26 pub resampling_distance: Option<f64>,
27
28 /// Whether fallback mode was used
29 pub fallback_mode: bool,
30
31 /// Number of candidate paths evaluated
32 pub candidate_paths_evaluated: usize,
33
34 /// Whether path existed in both directions (bidirectional validation)
35 pub bidirectional_path: bool,
36
37 /// Snapshot of segment-level diagnostics (order, intrinsics, probabilities)
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub diagnostic_info: Option<PathDiagnosticInfo>,
40}
41
42/// Collection of segment-level diagnostics for a calculated path
43#[derive(Debug, Clone, Serialize, Deserialize)]
44pub struct PathDiagnosticInfo {
45 /// Ordered diagnostics per segment in the path
46 pub segments: Vec<SegmentDiagnostic>,
47}
48
49impl PathDiagnosticInfo {
50 /// Build diagnostics from associated netelements, preserving traversal order
51 pub fn from_segments(segments: &[AssociatedNetElement]) -> Self {
52 let segments = segments
53 .iter()
54 .map(|segment| SegmentDiagnostic {
55 netelement_id: segment.netelement_id.clone(),
56 probability: segment.probability,
57 start_intrinsic: segment.start_intrinsic,
58 end_intrinsic: segment.end_intrinsic,
59 gnss_start_index: segment.gnss_start_index,
60 gnss_end_index: segment.gnss_end_index,
61 })
62 .collect();
63
64 Self { segments }
65 }
66}
67
68/// Diagnostic details for a single segment in a train path
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct SegmentDiagnostic {
71 /// ID of the netelement
72 pub netelement_id: String,
73
74 /// Probability assigned to this segment
75 pub probability: f64,
76
77 /// Intrinsic coordinate where the path enters this segment
78 pub start_intrinsic: f64,
79
80 /// Intrinsic coordinate where the path exits this segment
81 pub end_intrinsic: f64,
82
83 /// Index of the first GNSS position associated with this segment
84 pub gnss_start_index: usize,
85
86 /// Index of the last GNSS position associated with this segment
87 pub gnss_end_index: usize,
88}
89
90#[cfg(test)]
91mod tests;