brepjs-bim 0.25.1 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,22 +25,30 @@ the low-level path (and covers elements the declarative route doesn't yet). See
25
25
 
26
26
  Parametric authoring of the common IFC4 building elements plus the data layers that make a model
27
27
  useful downstream (psets, classification, materials, quantities), with import, export, and
28
- validation. Geometry is produced by brepjs (OCCT). Walls and railings carry a `ProductBody`, either
29
- a parametric solid or a non-empty collection of authoritative exact solids. Use `bodySolids()` to
30
- borrow their Product-local model handles and narrow `geometry.kind` when a caller specifically
31
- needs the parametric branch. Other solid-bearing categories continue to expose their existing
32
- geometry types.
33
-
34
- `takeExactProductBody(localId, { kind: 'EXACT', solids })` installs an authoritative wall or
35
- railing Body atomically. Success transfers every supplied handle to the model and disposes the
36
- superseded parametric Body; failure transfers nothing. Add wall openings before takeover, because
37
- an exact wall rejects later `addDoor()` and `addWindow()` mutations.
28
+ validation. Geometry is produced by brepjs (OCCT). Walls and railings carry a `ProductBody`:
29
+ `PARAMETRIC` or `AUTHORITATIVE`, both with a nonempty, ordered `solids` collection. Authority and
30
+ item count are independent. `bodySolids()` borrows Product-local model handles; do not dispose
31
+ those handles. Other solid-bearing categories retain their current geometry types.
32
+
33
+ `model.replaceProductBody({ localId, body: { kind: 'AUTHORITATIVE', solids } })` validates and
34
+ installs the complete collection atomically. `Err` leaves the model and caller ownership
35
+ unchanged. `Ok` returns a `COMMITTED` receipt and transfers every supplied handle, even when
36
+ `receipt.cleanup.kind === 'FAILED'` reports a failed release of the superseded Body. Do not
37
+ retry an uncertain release or dispose transferred handles. Parametric Bodies may be replaced by
38
+ either authority; authoritative Bodies may only be replaced by authoritative Bodies. Add wall
39
+ openings before installing an authoritative Body: later `addDoor()` and `addWindow()` return
40
+ `AUTHORITATIVE_WALL_BODY_IMMUTABLE`.
41
+
42
+ Civil-semantic Families Wall/Railing routes require an evaluator and retain the authored Body as
43
+ `AUTHORITATIVE`, including when it coincides with the nominal recipe. The adapter copies borrowed
44
+ evaluator items, localizes every item, and respects the replacement receipt's ownership outcome.
45
+ Conventional archetype routes retain their existing recipe authoring behavior.
38
46
 
39
47
  Element geometry is **unplaced template geometry** in local coordinates. Placement (`origin` /
40
48
  `axisX` / `axisZ`) is applied by the IFC layer via `IfcLocalPlacement`, not baked into the brepjs
41
49
  solid. Use `placedSolids(element)` to read fresh, caller-owned solids transformed by the element's
42
50
  own placement. Stairs and ramps return one solid per flight, curtain walls return their panels and
43
- mullions, and an exact Product Body returns one placed copy per Body item. When an element is
51
+ mullions, and either Product Body authority returns one placed copy per Body item. When an element is
44
52
  beneath a placed spatial structure, pass its cumulative frame as
45
53
  `placedSolids(element, { parentFrame })` to obtain world coordinates. This is especially important
46
54
  for parent-local Proxy and Earthworks Fill bodies.
@@ -57,8 +65,29 @@ through either property. Complete Bodies also expose aggregate `bounds` and `vol
57
65
  - Stable identity: deterministic IFC GUIDs (`deriveIfcGuid`) and local id counters.
58
66
  - Shaped geometry: roofs build real shed/gable/hip/dome solids when `pitch` is set (flat slab
59
67
  otherwise); railings build posts + top/bottom rails with `infill: 'POSTED'` (a single swept panel
60
- otherwise). Shaped roofs and posted railings serialize to IFC as tessellated bodies; flat roofs
61
- and panel railings keep their parametric `IfcExtrudedAreaSolid`.
68
+ otherwise). Every retained Wall/Railing Body item serializes independently as a tessellated
69
+ representation, with one conversion from mm to metres. Shaped roofs also use tessellation;
70
+ flat roofs keep their parametric `IfcExtrudedAreaSolid`.
71
+
72
+ Wall net volume measures occupied material across all retained items, so overlaps count once.
73
+ Nominal recipe quantities require current model recipe eligibility; public Body replacement
74
+ clears that eligibility even if the new tag is `PARAMETRIC`. Failed measurements omit the affected
75
+ quantity and appear in `toIfcValidated()` as `WALL_QUANTITY_OMITTED` issues.
76
+
77
+ Wall openings export as IFC `Reference` geometry because the retained Wall Body already
78
+ contains its cuts. Void/fill relationships and opening placements remain intact. IFC4 defines
79
+ Reference openings as non-subtractive; gross recipe exports such as Slab openings still use
80
+ subtractive `Body` geometry. The importer keeps Reference opening records and relationships
81
+ without treating their reference shape as a display Body or cutting tool.
82
+
83
+ IfcOpenShell 0.8.5 still subtracts Reference openings in its default geometry engine, even with
84
+ a separate Reference context. If a replacement Body adds material inside a retained opening's
85
+ region, that engine can remove the added material. Schema validation and shape generation alone
86
+ do not detect this difference; check the representation semantics and retained item geometry.
87
+
88
+ Step 1 retains class-specific geometry storage outside Wall/Railing and the transitional
89
+ `model/modelGeometry.ts` ownership enumerator. Converging those records and renaming
90
+ `ProductBody` to `Body` belong to [step 2](docs/architecture-migration.md#migration-order).
62
91
 
63
92
  ## Status
64
93
 
@@ -95,16 +124,16 @@ otherwise supplied. Existing non-semantic Families archetypes continue to use th
95
124
  registry beneath Bridge Parts. Bridge, Bridge Part, and Earthworks Fill require IFC4X3; `fromIfc`
96
125
  reconstructs their civil spatial hierarchy, direct containment, and typed Earthworks inventory.
97
126
 
98
- Civil-semantic wall and railing routes require `bodyEvaluator` (or the
99
- `proxyEvaluator` fallback) so the adapter can verify the authored Product Body. Missing the
100
- evaluator is `FAMILIES_PRODUCT_BODY_EVALUATOR_REQUIRED` (element path and mapped category); the
101
- adapter does not silently keep a parametric envelope. Conventional archetype walls and railings
102
- stay specification-authoritative and do not need an evaluator. When the evaluator is present, the
103
- adapter applies registered wall openings to the parametric candidate, then compares that candidate
104
- with the evaluated source in Product-local coordinates. Coincident bodies retain editable
105
- parametric IFC; compound, voided, or otherwise different bodies retain their typed Wall or Railing
106
- classification and export every authoritative item as tessellation. The evaluator's source handles
107
- remain borrowed. Other typed civil routes continue to use their semantic envelope dimensions.
127
+ Civil-semantic wall and railing routes require `bodyEvaluator` or the `proxyEvaluator` fallback
128
+ to retain the authored Product Body. Missing the evaluator is
129
+ `FAMILIES_PRODUCT_BODY_EVALUATOR_REQUIRED`, with the element path and mapped category.
130
+ Conventional archetype walls and railings retain their existing recipe authoring behavior and do
131
+ not need an evaluator. The adapter registers wall openings before installing the authored Body,
132
+ copies every borrowed evaluator item into Product-local coordinates, and retains `AUTHORITATIVE`
133
+ authority even when the geometry coincides with the nominal recipe. These products keep their
134
+ typed Wall or Railing classification and export every Body item as tessellation. The evaluator's
135
+ source handles remain borrowed. Other typed civil routes continue to use their semantic envelope
136
+ dimensions.
108
137
 
109
138
  This is deliberately not a claim of complete IFC infrastructure coverage or unchanged parity with
110
139
  the full scratch prototype. Member and Sign remain outside the profile: without `proxyEvaluator`
@@ -179,8 +208,8 @@ warnings travel inside the payload rather than throwing.
179
208
  Each `add*` call parses and validates its spec and stores a typed `BimElement` keyed by a `LocalId`.
180
209
  Parametric physical elements build an analytical brepjs solid; civil spatial elements are body-less,
181
210
  and arbitrary-body products such as Earthworks Fill take ownership of a validated authored solid.
182
- Families-projected civil walls and railings retain evaluated authored solids when their Bodies do
183
- not coincide with the post-opening parametric candidate.
211
+ Families-projected civil walls and railings always retain copies of the evaluated authored items
212
+ as an `AUTHORITATIVE` Product Body, even when the geometry coincides with the nominal recipe.
184
213
  The IFC writer walks the model, applies placement, and emits schema-correct IFC entities; the
185
214
  importer is the inverse. No kernel/WASM changes are required.
186
215
 
@@ -192,36 +221,3 @@ npm run lint --workspace=brepjs-bim
192
221
  npm run build --workspace=brepjs-bim
193
222
  npm run test --workspace=brepjs-bim
194
223
  ```
195
-
196
- ### Body material measurement
197
-
198
- Exact Wall quantities measure occupied material across all retained items. Overlapping solids count once. Bounds include every item. Measurement and temporary cleanup failures make these optional measurements unavailable and preserve the borrowed inputs. Cleanup never retries an uncertain native release.
199
-
200
- The BIM package requires `brepjs >=19.0.5` for native cleanup-error reporting.
201
-
202
- ### Wall quantity failures
203
-
204
- Wall `NetVolume` measures retained occupied material for both `PARAMETRIC` and `EXACT` geometry. Recipe Walls retain supported area and weight quantities. Exact takeover has no recipe quantity eligibility.
205
-
206
- If measurement or temporary cleanup fails, serialization omits optional Wall quantities. `toIfcValidated` reports an element-specific `WALL_QUANTITY_OMITTED` warning from that same serialization. `toIfc` still returns a bytes `Result`.
207
-
208
- ### Imported Body survivors
209
-
210
- Opening reconstruction retains every surviving solid in source-item order, including split results. Complete removal produces no imported solids and null aggregate bounds and volume. The singleton `.solid` field remains a borrowed alias only for a complete one-solid result.
211
-
212
- Complete imported aggregates use shared occupied-material measurement and all-item bounds. Overlaps count once. Failed measurement leaves both aggregates unavailable with an import diagnostic. Later opening failures clean the current host list, including every earlier survivor, and never retry an uncertain release.
213
-
214
- ### Retained Body IFC geometry
215
-
216
- Wall and Railing exports preflight and tessellate every retained item in order, preserving placement, styles, and metadata.
217
-
218
- Wall openings export as IFC `Reference` geometry because the retained Wall Body already
219
- contains its cuts. Void/fill relationships and opening placements remain intact. IFC4 defines
220
- Reference openings as non-subtractive; gross recipe exports such as Slab openings still use
221
- subtractive `Body` geometry. The importer keeps Reference opening records and relationships
222
- without treating their reference shape as a display Body or cutting tool.
223
-
224
- IfcOpenShell 0.8.5 still subtracts Reference openings in its default geometry engine, even with
225
- a separate Reference context. If a replacement Body adds material inside a retained opening's
226
- region, that engine can remove the added material. Schema validation and shape generation alone
227
- do not detect this difference; check the representation semantics and retained item geometry.