ecitygml-core 0.0.2-alpha.3

Core primitives and operations for processing CityGML data.
Documentation
use crate::model::common::{FeatureRef, FeatureRefMut};
use crate::model::core::{
    AbstractFeatureWithLifespan, AsAbstractFeatureWithLifespan, AsAbstractFeatureWithLifespanMut,
    ExternalReference, RelativeToTerrain, RelativeToWater,
};
use crate::model::generics::GenericAttributeKind;
use egml::model::geometry::Envelope;
use nalgebra::Isometry3;

#[derive(Debug, Clone, PartialEq)]
pub struct AbstractCityObject {
    pub(crate) abstract_feature_with_lifespan: AbstractFeatureWithLifespan,
    pub external_references: Vec<ExternalReference>,
    pub relative_to_terrain: Option<RelativeToTerrain>,
    pub relative_to_water: Option<RelativeToWater>,
    pub generic_attributes: Vec<GenericAttributeKind>,
}

impl AbstractCityObject {
    pub fn new(abstract_feature_with_lifespan: AbstractFeatureWithLifespan) -> Self {
        Self {
            abstract_feature_with_lifespan,
            external_references: vec![],
            relative_to_terrain: None,
            relative_to_water: None,
            generic_attributes: vec![],
        }
    }

    pub fn iter_features<'a>(&'a self) -> impl Iterator<Item = FeatureRef<'a>> + 'a {
        std::iter::empty()
    }

    pub fn for_each_feature_mut<F: FnMut(FeatureRefMut<'_>)>(&mut self, _f: &mut F) {}

    pub fn compute_envelope(&self) -> Option<Envelope> {
        None
    }

    pub fn apply_transform(&mut self, m: &Isometry3<f64>) {
        self.abstract_feature_with_lifespan.apply_transform(m);
    }
}

pub trait AsAbstractCityObject: AsAbstractFeatureWithLifespan {
    fn abstract_city_object(&self) -> &AbstractCityObject;

    fn relative_to_terrain(&self) -> Option<&RelativeToTerrain> {
        self.abstract_city_object().relative_to_terrain.as_ref()
    }

    fn relative_to_water(&self) -> Option<&RelativeToWater> {
        self.abstract_city_object().relative_to_water.as_ref()
    }

    fn generic_attributes(&self) -> &[GenericAttributeKind] {
        &self.abstract_city_object().generic_attributes
    }

    fn external_references(&self) -> &[ExternalReference] {
        &self.abstract_city_object().external_references
    }
}

pub trait AsAbstractCityObjectMut: AsAbstractFeatureWithLifespanMut + AsAbstractCityObject {
    fn abstract_city_object_mut(&mut self) -> &mut AbstractCityObject;

    fn set_relative_to_terrain(&mut self, value: Option<RelativeToTerrain>) {
        self.abstract_city_object_mut().relative_to_terrain = value;
    }

    fn set_relative_to_water(&mut self, value: Option<RelativeToWater>) {
        self.abstract_city_object_mut().relative_to_water = value;
    }

    fn set_generic_attributes(&mut self, generic_attributes: Vec<GenericAttributeKind>) {
        self.abstract_city_object_mut().generic_attributes = generic_attributes;
    }

    fn set_external_references(&mut self, external_references: Vec<ExternalReference>) {
        self.abstract_city_object_mut().external_references = external_references;
    }
}

impl AsAbstractCityObject for AbstractCityObject {
    fn abstract_city_object(&self) -> &AbstractCityObject {
        self
    }
}

impl AsAbstractCityObjectMut for AbstractCityObject {
    fn abstract_city_object_mut(&mut self) -> &mut AbstractCityObject {
        self
    }
}

#[macro_export]
macro_rules! impl_abstract_city_object_traits {
    ($type:ty) => {
        $crate::impl_abstract_feature_with_lifespan_traits!($type);

        impl $crate::model::core::AsAbstractFeatureWithLifespan for $type {
            fn abstract_feature_with_lifespan(
                &self,
            ) -> &$crate::model::core::AbstractFeatureWithLifespan {
                use $crate::model::core::AsAbstractCityObject;
                &self.abstract_city_object().abstract_feature_with_lifespan
            }
        }

        impl $crate::model::core::AsAbstractFeatureWithLifespanMut for $type {
            fn abstract_feature_with_lifespan_mut(
                &mut self,
            ) -> &mut $crate::model::core::AbstractFeatureWithLifespan {
                use $crate::model::core::AsAbstractCityObjectMut;
                &mut self
                    .abstract_city_object_mut()
                    .abstract_feature_with_lifespan
            }
        }
    };
}

impl_abstract_city_object_traits!(AbstractCityObject);

#[cfg(test)]
mod tests {
    use super::*;
    use crate::model::core::{AbstractFeature, AsAbstractFeature};
    use egml::model::base::Id;

    #[test]
    fn trait_implementation_macro_test() {
        let abstract_feature = AbstractFeature::new(egml::model::base::Id::generate_uuid_v4());
        let abstract_feature_with_lifespan = AbstractFeatureWithLifespan::new(abstract_feature);
        let abstract_city_object = AbstractCityObject::new(abstract_feature_with_lifespan);
        abstract_city_object.id();
    }
}