semantic-scene 0.1.1

Rust parser for semantic scene descriptors, currently focused on Habitat-Sim Matterport3D .house files.
Documentation
//! Semantic level model.

use std::fmt;

use crate::{Aabb, Vec3};

use super::{SemanticObject, SemanticRegion};

/// Represents a level of a semantic scene.
///
/// A level owns its semantic regions and exposes its original descriptor index,
/// label, position, and axis-aligned bounding box.
#[derive(Debug, Clone, PartialEq)]
pub struct SemanticLevel<ObjectCategory, RegionCategory> {
    index: i32,
    label: String,
    position: Vec3,
    aabb: Aabb,
    regions: Vec<SemanticRegion<ObjectCategory, RegionCategory>>,
}

impl<ObjectCategory, RegionCategory> SemanticLevel<ObjectCategory, RegionCategory> {
    /// Creates a semantic level.
    ///
    /// `index` is the original descriptor index for this level.
    #[must_use]
    pub const fn new(
        index: i32,
        label: String,
        position: Vec3,
        aabb: Aabb,
        regions: Vec<SemanticRegion<ObjectCategory, RegionCategory>>,
    ) -> Self {
        Self {
            index,
            label,
            position,
            aabb,
            regions,
        }
    }

    /// Returns this level's id.
    ///
    /// This is the original descriptor index converted to a string.
    #[must_use]
    pub fn id(&self) -> String {
        self.index.to_string()
    }

    /// Returns the source descriptor index.
    #[must_use]
    pub const fn index(&self) -> i32 {
        self.index
    }

    /// Returns the source descriptor label code.
    #[must_use]
    pub fn label(&self) -> &str {
        &self.label
    }

    /// Returns the level position from the source descriptor.
    #[must_use]
    pub const fn position(&self) -> Vec3 {
        self.position
    }

    /// Returns the level axis-aligned bounding box.
    #[must_use]
    pub const fn aabb(&self) -> &Aabb {
        &self.aabb
    }

    /// Returns regions contained by this level.
    #[must_use]
    pub fn regions(&self) -> &[SemanticRegion<ObjectCategory, RegionCategory>] {
        &self.regions
    }

    /// Returns objects contained by this level.
    pub fn objects(&self) -> impl Iterator<Item = &SemanticObject<ObjectCategory>> {
        self.regions.iter().flat_map(SemanticRegion::objects)
    }
}

impl<OC, RC> fmt::Display for SemanticLevel<OC, RC> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            formatter,
            "level {}: regions={}, objects={}, bounds=[{}]",
            self.index,
            self.regions.len(),
            self.objects().count(),
            self.aabb
        )
    }
}