sct_reader/loaders/euroscope/
waypoint.rs1use std::fmt::Display;
2
3use super::{
4 position::{Heading, Position, Valid},
5 AirspaceClass,
6};
7
8pub trait Waypoint {
9 fn identifier(&self) -> &String;
10 fn position(&self) -> Position<Valid>;
11}
12
13#[derive(Debug, Clone)]
14pub struct Fix {
15 pub identifier: String,
16 pub position: Position<Valid>,
17}
18impl Waypoint for Fix {
19 fn identifier(&self) -> &String {
20 &self.identifier
21 }
22 fn position(&self) -> Position<Valid> {
23 self.position
24 }
25}
26
27#[derive(Debug, Clone)]
28pub struct Vor {
29 pub identifier: String,
30 pub position: Position<Valid>,
31 pub frequency: String,
32}
33impl Waypoint for Vor {
34 fn identifier(&self) -> &String {
35 &self.identifier
36 }
37 fn position(&self) -> Position<Valid> {
38 self.position
39 }
40}
41impl Vor {
42 pub fn frequency(&self) -> &String {
43 &self.frequency
44 }
45}
46
47#[derive(Debug, Clone)]
48pub struct Ndb {
49 pub identifier: String,
50 pub position: Position<Valid>,
51 pub frequency: String,
52}
53impl Waypoint for Ndb {
54 fn identifier(&self) -> &String {
55 &self.identifier
56 }
57 fn position(&self) -> Position<Valid> {
58 self.position
59 }
60}
61impl Ndb {
62 pub fn frequency(&self) -> &String {
63 &self.frequency
64 }
65}
66
67#[derive(Debug, Clone)]
68pub struct Airport {
69 pub identifier: String,
70 pub position: Position<Valid>,
71 pub tower_frequency: String,
72 pub airspace_class: AirspaceClass,
73 pub runways: Vec<RunwayStrip>,
74}
75impl Waypoint for Airport {
76 fn identifier(&self) -> &String {
77 &self.identifier
78 }
79 fn position(&self) -> Position<Valid> {
80 self.position
81 }
82}
83impl Airport {
84 pub fn tower_frequency(&self) -> &String {
85 &self.tower_frequency
86 }
87 pub fn airspace_class(&self) -> AirspaceClass {
88 self.airspace_class
89 }
90}
91
92#[derive(Debug, Clone)]
93pub struct RunwayStrip {
94 pub end_a: RunwayEnd,
95 pub end_b: RunwayEnd,
96}
97
98#[derive(Debug, Clone, PartialEq)]
99pub struct RunwayEnd {
100 pub number: u8,
101 pub td_threshold_pos: Position<Valid>,
102 pub se_threshold_pos: Position<Valid>,
103 pub modifier: RunwayModifier,
104 pub magnetic_hdg: Heading,
105}
106impl RunwayEnd {
107 pub fn identifier(&self) -> String {
108 format!("{:02}{}", self.number, self.modifier)
109 }
110 pub fn reciprocal(&self) -> RunwayEnd {
111 let number = self.reciprocal_number();
112 let td_threshold_pos = self.se_threshold_pos;
113 let se_threshold_pos = self.td_threshold_pos;
114 let modifier = self.modifier.reciprocal();
115 let magnetic_hdg = self.magnetic_hdg.reciprocal();
116 RunwayEnd {
117 number,
118 td_threshold_pos,
119 se_threshold_pos,
120 modifier,
121 magnetic_hdg,
122 }
123 }
124 fn reciprocal_number(&self) -> u8 {
125 if self.number > 18 {
126 self.number - 18
127 } else {
128 self.number + 18
129 }
130 }
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
134pub enum RunwayModifier {
135 Left,
136 Right,
137 Centre,
138 Grass,
139 None,
140}
141impl RunwayModifier {
142 pub fn reciprocal(&self) -> RunwayModifier {
143 match self {
144 Self::Left => Self::Right,
145 Self::Right => Self::Left,
146 Self::Centre => Self::Centre,
147 Self::Grass => Self::Grass,
148 Self::None => Self::None,
149 }
150 }
151}
152
153impl Display for RunwayModifier {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 write!(
156 f,
157 "{}",
158 match self {
159 Self::Left => "L",
160 Self::Right => "R",
161 Self::Centre => "C",
162 Self::Grass => "G",
163 Self::None => "",
164 }
165 )
166 }
167}