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