sct_reader/package/
symbol.rs

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        // Properties
23        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}