ifc_style/light/goniometric.rs
1//! `IfcLightSourceGoniometric`: the photometric light source.
2
3use ifc_model::EntityId;
4
5use crate::error::StyleResult;
6use crate::light::source::LightSource;
7use crate::view::Record;
8
9/// Members of the `IfcLightDistributionDataSourceSelect` type.
10///
11/// Kept beside the accessor that validates against it so the select's
12/// membership is stated once, in the same place it is enforced.
13const DISTRIBUTION_DATA_SOURCE: &[&str] =
14 &["IfcExternalReference", "IfcLightIntensityDistribution"];
15
16/// Borrowed projection of `IfcLightSourceGoniometric`: a real luminaire
17/// described by photometric data rather than a renderer's approximation.
18///
19/// This is the only light source carrying absolute photometric quantities
20/// (luminous flux, colour temperature, lamp technology). Every other subtype
21/// is a normalized shading construct. The values are reported exactly as
22/// authored; this crate performs no photometric or colour-space conversion.
23#[derive(Debug, Clone, Copy)]
24pub struct LightSourceGoniometric<'m, 's> {
25 record: Record<'m, 's>,
26}
27
28impl<'m, 's> LightSourceGoniometric<'m, 's> {
29 pub(crate) fn from_record(record: Record<'m, 's>) -> Self {
30 Self { record }
31 }
32
33 /// The inherited `IfcLightSource` colour and intensity attributes.
34 pub fn light_source(&self) -> LightSource<'m, 's> {
35 LightSource::from_record(self.record)
36 }
37
38 /// The `Position` attribute: a mandatory `IfcAxis2Placement3D` reference.
39 ///
40 /// A full placement, not a bare point: a luminaire's intensity
41 /// distribution is defined in its own local axes, so the orientation is
42 /// what makes `IfcLightIntensityDistribution` angles meaningful.
43 pub fn position(&self) -> StyleResult<EntityId> {
44 self.record.required_ref("Position", "IfcAxis2Placement3D")
45 }
46
47 /// The `ColourAppearance` attribute, when authored: an `IfcColourRgb`
48 /// reference giving the perceived colour.
49 ///
50 /// Distinct from the inherited `LightColour`, which is the shading colour.
51 /// A lamp can have one chromaticity and be rendered with another.
52 pub fn colour_appearance(&self) -> StyleResult<Option<EntityId>> {
53 self.record.optional_ref("ColourAppearance", "IfcColourRgb")
54 }
55
56 /// The `ColourTemperature` attribute, an
57 /// `IfcThermodynamicTemperatureMeasure`.
58 ///
59 /// Mandatory. Reported in the file's own temperature unit; IFC's SI
60 /// default is kelvin, but the value is not converted here.
61 pub fn colour_temperature(&self) -> StyleResult<f64> {
62 self.record.required_number("ColourTemperature")
63 }
64
65 /// The `LuminousFlux` attribute, an `IfcLuminousFluxMeasure` (lumen under
66 /// the SI default). Mandatory.
67 pub fn luminous_flux(&self) -> StyleResult<f64> {
68 self.record.required_number("LuminousFlux")
69 }
70
71 /// The `LightEmissionSource` attribute: the lamp technology token from
72 /// `IfcLightEmissionSourceEnum`.
73 ///
74 /// Returned as the raw schema token rather than a Rust enum. The
75 /// enumeration is schema-versioned, and this crate's census marks such
76 /// tokens `SchemaValue` -- promoting one to a closed Rust type would make
77 /// a future schema's new member unrepresentable.
78 pub fn light_emission_source(&self) -> StyleResult<&'m str> {
79 self.record.required_enum("LightEmissionSource")
80 }
81
82 /// The `LightDistributionDataSource` attribute: a mandatory reference to
83 /// either an `IfcLightIntensityDistribution` (inline photometric data) or
84 /// an `IfcExternalReference` (e.g. an EULUMDAT or IES file).
85 ///
86 /// The select is validated, so a reference to an unrelated entity is a
87 /// typed [`crate::StyleError::ReferenceType`] rather than a surprise at
88 /// the point of use.
89 pub fn light_distribution_data_source(&self) -> StyleResult<EntityId> {
90 self.record.required_ref_select(
91 "LightDistributionDataSource",
92 "IfcLightDistributionDataSourceSelect",
93 DISTRIBUTION_DATA_SOURCE,
94 )
95 }
96}