ecitygml-io 0.0.2-alpha.5

IO operations for processing CityGML data.
Documentation
use crate::Error;
use crate::gml::codec::relief::abstract_relief_component::{
    deserialize_abstract_relief_component, serialize_abstract_relief_component,
};
use crate::gml::codec::relief::tin_property::{deserialize_tin_property, serialize_tin_property};
use crate::gml::util::CityGmlElement;
use ecitygml_core::model::relief::{AsAbstractReliefComponent, TinRelief};
use egml::io::util::{
    Formatting, XmlNode, XmlNodeContent, collect_child, extract_xml_element_spans, serialize_inner,
};
use serde::{Deserialize, Serialize};

pub fn deserialize_tin_relief(xml_document: &[u8]) -> Result<TinRelief, Error> {
    let spans = extract_xml_element_spans(xml_document)?;
    let (abstract_relief_component_result, tin_result) = rayon::join(
        || deserialize_abstract_relief_component(xml_document, &spans),
        || {
            collect_child(
                xml_document,
                &spans,
                CityGmlElement::TinProperty.into(),
                deserialize_tin_property,
            )
        },
    );
    let abstract_relief_component = abstract_relief_component_result?;
    let tin = tin_result?;

    let mut tin_relief = TinRelief::from_abstract_relief_component(abstract_relief_component);
    tin_relief.set_tin_opt(tin);

    Ok(tin_relief)
}

pub fn serialize_tin_relief(
    tin_relief: &TinRelief,
    formatting: Formatting,
) -> Result<XmlNode, Error> {
    let mut xml_node_parts =
        serialize_abstract_relief_component(tin_relief.abstract_relief_component(), formatting)?;

    if let Some(raw) = serialize_inner(GmlTinRelief::from(tin_relief), formatting)? {
        xml_node_parts.content.push(XmlNodeContent::Raw(raw));
    }

    if let Some(prop) = tin_relief.tin() {
        xml_node_parts
            .content
            .push(serialize_tin_property(prop, formatting)?.into());
    }

    Ok(XmlNode::new(
        CityGmlElement::TINRelief.into(),
        xml_node_parts,
    ))
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct GmlTinRelief {}

impl From<&TinRelief> for GmlTinRelief {
    fn from(_item: &TinRelief) -> Self {
        Self {}
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ecitygml_core::model::common::LevelOfDetail;
    use ecitygml_core::model::core::AsAbstractFeature;
    use ecitygml_core::model::relief::AsAbstractReliefComponent;
    use egml::model::base::Id;
    use egml::model::geometry::primitives::AsSurface;

    #[test]
    fn test_deserialize_tin_relief() {
        let xml_document = "
            <dem:TINRelief gml:id=\"abc\">
                <dem:lod>3</dem:lod>
                <dem:tin>
                    <gml:TriangulatedSurface gml:id=\"ground\">
                      <gml:patches>
                        <gml:Triangle>
                          <gml:exterior>
                            <gml:LinearRing gml:id=\"Geo28109128\">
                              <gml:posList>513037.352708 5403284.890495 247.27 513034.424098 5403297.424959 247.19 513034.423981 5403287.429362 247.3 513037.352708 5403284.890495 247.27</gml:posList>
                            </gml:LinearRing>
                          </gml:exterior>
                        </gml:Triangle>
                      </gml:patches>
                    </gml:TriangulatedSurface>
                </dem:tin>
            </dem:TINRelief>";

        let tin_relief = deserialize_tin_relief(xml_document.as_bytes()).expect("should work");

        assert_eq!(tin_relief.feature_id(), &Id::try_from("abc").unwrap());
        assert_eq!(tin_relief.lod(), LevelOfDetail::Three);
        assert_eq!(tin_relief.tin().unwrap().object().unwrap().patches_len(), 1);
    }

    #[test]
    pub fn test_deserialize_tin_relief_basic() {
        let xml_document = "<dem:TINRelief>
          <dem:lod>2</dem:lod>
          <dem:tin>
            <gml:TriangulatedSurface gml:id=\"ground\">
              <gml:patches>
                <gml:Triangle>
                  <gml:exterior>
                    <gml:LinearRing gml:id=\"Geo28109128\">
                      <gml:posList>513037.352708 5403284.890495 247.27 513034.424098 5403297.424959 247.19 513034.423981 5403287.429362 247.3 513037.352708 5403284.890495 247.27</gml:posList>
                    </gml:LinearRing>
                  </gml:exterior>
                </gml:Triangle>
                <gml:Triangle>
                  <gml:exterior>
                    <gml:LinearRing gml:id=\"Geo28109129\">
                      <gml:posList>513077.98546 5403284.940675 245.28 513073.615171 5403277.62549 244.056421 513080.474403 5403283.461339 245.28 513077.98546 5403284.940675 245.28</gml:posList>
                    </gml:LinearRing>
                  </gml:exterior>
                </gml:Triangle>
              </gml:patches>
            </gml:TriangulatedSurface>
          </dem:tin>
        </dem:TINRelief>";

        let tin_relief = deserialize_tin_relief(xml_document.as_bytes()).expect("should work");

        assert_eq!(tin_relief.lod(), LevelOfDetail::Two);
        assert_eq!(tin_relief.tin().unwrap().object().unwrap().patches_len(), 2);
    }
}