egml_io/geometry/
point.rs

1use 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}