ifc_lite_processing/scan_proposals/
report.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//! Element proposals. Coordinates are the IFC model frame (Z up, metres).
6use serde::{Deserialize, Serialize};
7
8/// The IFC class a proposal would create (EXPRESS names).
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
10pub enum ProposalClass {
11    IfcWall,
12    IfcSlab,
13    IfcColumn,
14    IfcPipeSegment,
15    IfcFlowSegment,
16}
17
18/// How the proposal was derived from its sources.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub enum ProposalBasis {
22    /// Two opposite parallel wall faces: thickness measured.
23    PairedFaces,
24    /// One wall face: `defaultWallThicknessMetres`, behind the scanned side.
25    SingleFace,
26    /// A ceiling and the floor above it: thickness measured.
27    FloorCeilingPair,
28    /// A floor seen from above: `defaultSlabThicknessMetres` below it.
29    Floor,
30    /// A ceiling seen from below: `defaultSlabThicknessMetres` above it.
31    Ceiling,
32    /// One fitted cylinder.
33    Cylinder,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
37#[serde(rename_all = "camelCase")]
38pub enum DetectionKind {
39    Plane,
40    Cylinder,
41}
42
43/// A detection the proposal came from: an index into the segmentation
44/// report's `planes` or `cylinders`.
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[serde(rename_all = "camelCase")]
47pub struct DetectionRef {
48    pub kind: DetectionKind,
49    pub index: u32,
50}
51
52/// Fit statistics over all sources, in the model frame.
53#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
54#[serde(rename_all = "camelCase")]
55pub struct ProposalFit {
56    /// Inlier-weighted RMS of the sources' residuals.
57    pub rms_metres: f64,
58    pub inlier_points: u64,
59    pub inlier_voxels: u64,
60    /// Measured surface area of the sources (planes) or lateral area covered
61    /// (cylinders: arc times radius times length).
62    pub area_square_metres: f64,
63}
64
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66#[serde(tag = "kind", rename_all = "camelCase")]
67pub enum ProposalGeometry {
68    /// Axis line on the wall's centre plane at its base elevation.
69    #[serde(rename_all = "camelCase")]
70    Wall { start: [f64; 3], end: [f64; 3], thickness_metres: f64, height_metres: f64 },
71    /// Top face outline, counter-clockwise seen from above, at the top
72    /// elevation; the slab extends `thicknessMetres` below it.
73    #[serde(rename_all = "camelCase")]
74    Slab { outline: Vec<[f64; 3]>, thickness_metres: f64 },
75    /// Circular column: axis base point, height up, radius.
76    #[serde(rename_all = "camelCase")]
77    Column { base: [f64; 3], height_metres: f64, radius_metres: f64 },
78    /// Circular pipe between two axis points.
79    #[serde(rename_all = "camelCase")]
80    Pipe { start: [f64; 3], end: [f64; 3], radius_metres: f64 },
81}
82
83#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct ScanElementProposal {
86    /// Stable within one report: `wall-0`, `slab-2`, `column-1`, `pipe-0`.
87    pub id: String,
88    pub ifc_class: ProposalClass,
89    /// 0..1; see the module docs for the formula.
90    pub confidence: f64,
91    pub basis: ProposalBasis,
92    pub sources: Vec<DetectionRef>,
93    pub fit: ProposalFit,
94    pub geometry: ProposalGeometry,
95}
96
97#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
98#[serde(rename_all = "camelCase")]
99pub struct ScanProposalStats {
100    pub vertical_planes: u32,
101    pub horizontal_planes: u32,
102    /// Neither vertical nor horizontal in the model frame: no proposal.
103    pub sloped_planes: u32,
104    pub paired_walls: u32,
105    pub single_face_walls: u32,
106    /// Vertical planes below `minWallLengthMetres` or `minWallHeightMetres`.
107    pub faces_too_small: u32,
108    pub paired_slabs: u32,
109    pub single_slabs: u32,
110    /// Horizontal planes below `minSlabAreaSquareMetres`.
111    pub slabs_too_small: u32,
112    pub columns: u32,
113    pub pipes: u32,
114}
115
116#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
117#[serde(rename_all = "camelCase")]
118pub struct ScanProposalReport {
119    pub algorithm: String,
120    /// Walls, then slabs, columns and pipes; each class by descending support.
121    pub proposals: Vec<ScanElementProposal>,
122    /// Uniform scale of `scanToModel` (1 for a rigid alignment).
123    pub transform_scale: f64,
124    pub stats: ScanProposalStats,
125}