egml_io/geometry/
point.rs1use crate::error::Error;
2use crate::error::Error::{MissingElements, Only3DSupported};
3use egml_core::model::geometry::DirectPosition;
4use quick_xml::de;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
8#[serde(rename = "gml:Point")]
9struct GmlPoint {
10 #[serde(rename = "@id", default)]
11 id: String,
12 pos: GmlPos,
13}
14
15#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
16#[serde(rename = "gml:pos")]
17struct GmlPos {
18 #[serde(rename = "@srsDimension")]
19 srs_dimension: Option<u32>,
20 #[serde(rename = "$value")]
21 value: String,
22}
23
24impl TryFrom<GmlPos> for DirectPosition {
25 type Error = Error;
26
27 fn try_from(value: GmlPos) -> Result<Self, Self::Error> {
28 if value.srs_dimension.unwrap_or(3) != 3 {
29 return Err(Only3DSupported());
30 }
31
32 let parsed_values: Vec<f64> = value
33 .value
34 .split_whitespace()
35 .map(|s| s.parse().unwrap())
36 .collect();
37 if parsed_values.len() % 3 != 0 {
38 return Err(MissingElements());
39 }
40
41 let position = DirectPosition::new(parsed_values[0], parsed_values[1], parsed_values[2])?;
42 Ok(position)
43 }
44}
45
46pub fn parse_point(source_text: &str) -> Result<DirectPosition, Error> {
47 let parsed_point: GmlPoint = de::from_str(source_text)?;
48 parsed_point.pos.try_into()
49}
50
51#[cfg(test)]
52mod tests {
53 use crate::parse_point;
54
55 #[test]
56 fn parsing_point() {
57 let source_text = "<gml:Point>
58 <gml:pos srsDimension=\"3\" gml:id=\"UUID_6b33ecfa-6e08-4e8e-a4b5-e1d06540faf0\">678000.9484065345 5403659.060043676 417.3802376791456</gml:pos>
59 </gml:Point>";
60
61 let _result = parse_point(source_text).unwrap();
62 }
63
64 #[test]
65 fn parsing_point_without_id() {
66 let source_text = "<gml:Point>
67 <gml:pos srsDimension=\"3\">678000.9484065345 5403659.060043676 417.3802376791456</gml:pos>
68 </gml:Point>";
69
70 let _result = parse_point(source_text).unwrap();
71 }
72}