Skip to main content

ifc_style/
extent.rs

1//! `IfcPlanarExtent` and its `IfcPlanarBox` subtype.
2//!
3//! These are `IfcGeometricRepresentationItem` subtypes that carry no shape:
4//! they describe the 2D area a presentation element occupies. `ifc-geometry`
5//! classifies both `non-shape` with `ifc-style` as owner, so the typed reads
6//! live here rather than in a lowering path.
7
8use ifc_model::EntityId;
9
10use crate::error::StyleResult;
11use crate::view::Record;
12
13/// Borrowed projection of `IfcPlanarExtent`: a rectangular presentation area.
14///
15/// `SizeInX`/`SizeInY` are `IfcLengthMeasure`, which unlike the positive
16/// measures elsewhere in this crate permits zero and negative values, so they
17/// are read as plain numbers without a range guard.
18#[derive(Debug, Clone, Copy)]
19pub struct PlanarExtent<'m, 's> {
20    record: Record<'m, 's>,
21}
22
23impl<'m, 's> PlanarExtent<'m, 's> {
24    pub(crate) fn from_record(record: Record<'m, 's>) -> Self {
25        Self { record }
26    }
27
28    /// The `SizeInX` attribute. Mandatory.
29    pub fn size_in_x(&self) -> StyleResult<f64> {
30        self.record.required_number("SizeInX")
31    }
32
33    /// The `SizeInY` attribute. Mandatory.
34    pub fn size_in_y(&self) -> StyleResult<f64> {
35        self.record.required_number("SizeInY")
36    }
37}
38
39/// Borrowed projection of `IfcPlanarBox`: a planar extent plus the placement
40/// that positions it.
41#[derive(Debug, Clone, Copy)]
42pub struct PlanarBox<'m, 's> {
43    record: Record<'m, 's>,
44}
45
46impl<'m, 's> PlanarBox<'m, 's> {
47    pub(crate) fn from_record(record: Record<'m, 's>) -> Self {
48        Self { record }
49    }
50
51    /// The inherited `IfcPlanarExtent` attributes.
52    #[must_use]
53    pub fn planar_extent(&self) -> PlanarExtent<'m, 's> {
54        PlanarExtent::from_record(self.record)
55    }
56
57    /// The `Placement` attribute. Mandatory.
58    ///
59    /// `IfcAxis2Placement` is a select over the 2D and 3D placements, so both
60    /// are admitted; the id is returned for a geometry-side reader to resolve
61    /// rather than interpreted here.
62    pub fn placement(&self) -> StyleResult<EntityId> {
63        self.record.required_ref_select(
64            "Placement",
65            "IfcAxis2Placement",
66            &["IfcAxis2Placement2D", "IfcAxis2Placement3D"],
67        )
68    }
69}