ifc_lite_processing/analytic_export/
extrusion_definitions.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Reusable exact extrusion sources and placed product occurrences.
6
7use std::collections::BTreeMap;
8use ifc_lite_geometry::analytic::AnalyticExtrusion;
9use serde::Serialize;
10
11use super::definitions::{model_sha256, source_key,
12    AnalyticSourceContext, AnalyticSourceKey, SweptDiskInstance};
13use super::{extrusion_nominal_quantities, ExtrusionNominalQuantities};
14
15/// One authored extrusion before product or representation-map placement.
16/// `source` retains raw IFC file units and separate profile/solid positions.
17#[derive(Debug, Clone, Serialize)]
18pub struct ExtrusionDefinition {
19    pub key: AnalyticSourceKey,
20    pub source: AnalyticExtrusion,
21    /// Derived from the unplaced source, in squared/cubed IFC file units.
22    /// Absent when source parameters or profile geometry are unsupported.
23    pub nominal_quantities: Option<ExtrusionNominalQuantities>,
24}
25
26impl ExtrusionDefinition {
27    pub(super) fn from_source(key: AnalyticSourceKey, source: &AnalyticExtrusion) -> Self {
28        Self { key, source: source.clone(),
29            nominal_quantities: extrusion_nominal_quantities(source) }
30    }
31}
32
33/// A use of an extrusion source. `world_from_source` maps its solid-local raw
34/// coordinates to absolute IFC Z-up metres. Apply the source's profile and
35/// solid Position matrices before this matrix for a profile boundary point.
36pub type ExtrusionInstance = SweptDiskInstance;
37
38/// Bounded exact source/occurrence view; never substitutes tessellated loops.
39#[derive(Debug, Clone, Serialize)]
40pub struct ExtrusionDefinitions {
41    pub up_axis: &'static str,
42    pub source_units: &'static str,
43    pub world_units: &'static str,
44    pub coordinate_space: &'static str,
45    pub model_sha256: String,
46    pub schema: Option<String>,
47    pub length_unit_scale: f64,
48    pub sources: Vec<ExtrusionDefinition>,
49    pub instances: BTreeMap<u32, Vec<ExtrusionInstance>>,
50    pub diagnostics: Vec<String>,
51}
52
53impl ExtrusionDefinitions {
54    pub(super) fn new(content: &[u8], length_unit_scale: f64) -> Self {
55        Self { up_axis: "Z", source_units: "ifc_file_length_units", world_units: "m",
56            coordinate_space: "absolute_ifc_world", model_sha256: model_sha256(content),
57            schema: ifc_lite_core::declared_schema_bounded(content), length_unit_scale,
58            sources: Vec::new(), instances: BTreeMap::new(), diagnostics: Vec::new() }
59    }
60
61    pub(super) fn key(&self, context: AnalyticSourceContext, solid_id: u32) -> AnalyticSourceKey {
62        source_key(&self.model_sha256, self.schema.as_deref(), self.length_unit_scale,
63            context, solid_id)
64    }
65}
66
67pub(super) fn profile_segment_count(source: &AnalyticExtrusion) -> usize {
68    source.profile.as_ref().map_or(0, |profile| {
69        profile.loops.iter().map(|boundary| boundary.segments.len()).sum()
70    })
71}