1use std::default;
2
3use geojson::{Feature, Geometry, Value};
4use serde::{Deserialize, Serialize};
5use serde_json::Map;
6
7use crate::loaders::euroscope::{
8 position::{Position, Valid},
9 symbology::SymbologyItemType,
10};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct AtcMapSymbol {
14 pub name: String,
15 pub symbol_type: String,
16 pub feature: Feature,
17}
18
19impl AtcMapSymbol {
20 pub fn try_from_es_position(sector_file_id: String, item_type: String, ident: String, position: Position<Valid>) -> anyhow::Result<Self> {
21 let id = format!("{}_{}_{}", sector_file_id.to_string(), item_type.to_string(), ident.to_string());
22 let mut props_map = Map::new();
24 props_map.insert("text".to_string(), serde_json::to_value(ident.to_string())?);
25
26 Ok(AtcMapSymbol {
27 name: id.to_string(),
28 symbol_type: item_type.to_string(),
29 feature: Feature {
30 id: None,
31 bbox: None,
32 foreign_members: None,
33 geometry: Some(Geometry::new(Value::Point(vec![position.lon, position.lat]))),
34 properties: Some(props_map),
35 },
36 })
37 }
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub enum SymbolDrawItem {
42 Line {
43 start: (i8, i8),
44 end: (i8, i8),
45 },
46 Polygon(Vec<(i8, i8)>),
47 Arc {
48 center: (i8, i8),
49 radius: i8,
50 inner_radius: i8,
51 start_angle: i16,
52 end_angle: i16,
53 fill: bool,
54 },
55 SetPixel((i8, i8)),
56 Ellipse {
57 center: (i8, i8),
58 radius: (i8, i8),
59 inner_radius: (i8, i8),
60 rotation: i16,
61 start_angle: i16,
62 end_angle: i16,
63 fill: bool
64 }
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize, Default)]
68pub struct SymbolIcon {
69 pub symbol_type: String,
70 pub draw_items: Vec<SymbolDrawItem>,
71}
72
73impl SymbolIcon {
74 pub fn try_from_es_symbol_icon(icon_index: u8, icon: Vec<String>) -> anyhow::Result<Self> {
75 let name = match icon_index {
76 0 => SymbologyItemType::Airports.to_key_string(),
77 1 => SymbologyItemType::Ndbs.to_key_string(),
78 2 => SymbologyItemType::Vors.to_key_string(),
79 3 => SymbologyItemType::Fixes.to_key_string(),
80 4 => "aircraft_stby".to_string(),
81 5 => "aircraft_prim".to_string(),
82 6 => "aircraft_corr_sec_a+c".to_string(),
83 7 => "aircraft_corr_sec_s".to_string(),
84 8 => "aircraft_corr_prim_a+c".to_string(),
85 9 => "aircraft_corr_prim_s".to_string(),
86 10 => "aircraft_corr_a+c_ident".to_string(),
87 11 => "aircraft_corr_s_ident".to_string(),
88 12 => "aircraft_flt_plan".to_string(),
89 13 => "aircraft_coast".to_string(),
90 14 => "history_dot".to_string(),
91 15 => "aircraft_ground".to_string(),
92 16 => "aircraft_uncorr_sec_a+c".to_string(),
93 17 => "aircraft_uncorr_sec_s".to_string(),
94 18 => "aircraft_uncorr_prim_a+c".to_string(),
95 19 => "aircraft_uncorr_prim_s".to_string(),
96 20 => "aircraft_uncorr_a+c_ident".to_string(),
97 21 => "aircraft_uncorr_s_ident".to_string(),
98 22 => "ground_vehicle".to_string(),
99 23 => "ground_rotorcraft".to_string(),
100 _ => "unknown".to_string(),
101 };
102
103 let mut draw_items = Vec::new();
104 let mut cursor_pos = (0_i8, 0_i8);
105 for line in icon {
106 let split = line.split(" ").collect::<Vec<&str>>();
107 if split.len() > 0 {
108 match split[0] {
109 "MOVETO" => cursor_pos = (split[1].parse()?, -split[2].parse()?),
110 "LINETO" => {
111 let end_point = (split[1].parse()?, -split[2].parse::<i8>()?);
112 draw_items.push(SymbolDrawItem::Line {
113 start: cursor_pos,
114 end: end_point,
115 });
116 cursor_pos = end_point;
117 }
118 "SETPIXEL" => {
119 let point = (split[1].parse()?, -split[2].parse::<i8>()?);
120 draw_items.push(SymbolDrawItem::SetPixel(point));
121 cursor_pos = point;
122 }
123 "POLYGON" => {
124 let mut i = 1;
125 let mut points = Vec::new();
126 while i < split.len() - 1 {
127 let point = (split[i].parse::<i8>()?, -split[i + 1].parse::<i8>()?);
128 cursor_pos = point;
129 points.push(point);
130 i += 2;
131 }
132 draw_items.push(SymbolDrawItem::Polygon(points));
133 }
134 "ARC" => {
135 draw_items.push(SymbolDrawItem::Arc {
136 center: (split[1].parse()?, -split[2].parse()?),
137 radius: split[3].parse()?,
138 inner_radius: 0,
139 start_angle: split[4].parse()?,
140 end_angle: split[5].parse()?,
141 fill: false,
142 });
143 }
144 "FILLARC" => {
145 draw_items.push(SymbolDrawItem::Arc {
146 center: (split[1].parse()?, -split[2].parse()?),
147 radius: split[3].parse()?,
148 inner_radius: 0,
149 start_angle: split[4].parse()?,
150 end_angle: split[5].parse()?,
151 fill: true,
152 });
153 }
154 &_ => {}
155 }
156 }
157 }
158
159 Ok(SymbolIcon {
160 symbol_type: name.to_string(),
161 draw_items: draw_items,
162 })
163 }
164}