e57/
transform.rs

1use crate::xml;
2use crate::Result;
3use roxmltree::Node;
4
5/// Describes the rotation of a point cloud.
6#[derive(Clone, Debug)]
7pub struct Quaternion {
8    /// The scalar part of the quaternion. Shall be nonnegative.
9    pub w: f64,
10    /// The i coefficient of the quaternion.
11    pub x: f64,
12    /// The j coefficient of the quaternion.
13    pub y: f64,
14    /// The k coefficient of the quaternion.
15    pub z: f64,
16}
17
18impl Quaternion {
19    pub(crate) fn from_node(node: &Node) -> Result<Self> {
20        let w = xml::req_f64(node, "w")?;
21        let x = xml::req_f64(node, "x")?;
22        let y = xml::req_f64(node, "y")?;
23        let z = xml::req_f64(node, "z")?;
24        Ok(Self { w, x, y, z })
25    }
26}
27
28impl Default for Quaternion {
29    fn default() -> Self {
30        Self {
31            w: 1.0,
32            x: 0.0,
33            y: 0.0,
34            z: 0.0,
35        }
36    }
37}
38
39/// Describes the translation of a point cloud.
40#[derive(Clone, Debug)]
41pub struct Translation {
42    /// The X coordinate of the translation in meters.
43    pub x: f64,
44    /// The Y coordinate of the translation in meters.
45    pub y: f64,
46    /// The Z coordinate of the translation in meters.
47    pub z: f64,
48}
49
50impl Translation {
51    pub(crate) fn from_node(node: &Node) -> Result<Self> {
52        let x = xml::req_f64(node, "x")?;
53        let y = xml::req_f64(node, "y")?;
54        let z = xml::req_f64(node, "z")?;
55        Ok(Self { x, y, z })
56    }
57}
58
59impl Default for Translation {
60    fn default() -> Self {
61        Self {
62            x: 0.0,
63            y: 0.0,
64            z: 0.0,
65        }
66    }
67}
68
69/// Describes a transformation of a point cloud with a rotation and translation component.
70#[derive(Clone, Debug, Default)]
71pub struct Transform {
72    /// A unit quaternion representing the rotation of the transform.
73    pub rotation: Quaternion,
74    /// The translation of the transform.
75    pub translation: Translation,
76}
77
78impl Transform {
79    pub(crate) fn from_node(node: &Node) -> Result<Self> {
80        let translation = match node.children().find(|n| n.has_tag_name("translation")) {
81            Some(node) => Translation::from_node(&node)?,
82            None => Translation::default(),
83        };
84        let rotation = match node.children().find(|n| n.has_tag_name("rotation")) {
85            Some(node) => Quaternion::from_node(&node)?,
86            None => Quaternion::default(),
87        };
88        Ok(Self {
89            rotation,
90            translation,
91        })
92    }
93
94    pub(crate) fn xml_string(&self, tag_name: &str) -> String {
95        let w = xml::gen_float("w", self.rotation.w);
96        let x = xml::gen_float("x", self.rotation.x);
97        let y = xml::gen_float("y", self.rotation.y);
98        let z = xml::gen_float("z", self.rotation.z);
99        let quat = format!("<rotation type=\"Structure\">\n{w}{x}{y}{z}</rotation>\n");
100
101        let x = xml::gen_float("x", self.translation.x);
102        let y = xml::gen_float("y", self.translation.y);
103        let z = xml::gen_float("z", self.translation.z);
104        let trans = format!("<translation type=\"Structure\">\n{x}{y}{z}</translation>\n");
105
106        format!("<{tag_name} type=\"Structure\">\n{quat}{trans}</{tag_name}>\n")
107    }
108}