brepjs-bim 0.16.0 → 0.16.1

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.
@@ -7781,9 +7781,42 @@ function writeHeader(w, meta) {
7781
7781
  ownerHistoryId,
7782
7782
  geomContextId,
7783
7783
  geomSubContextId,
7784
- unitAssignmentId
7784
+ unitAssignmentId,
7785
+ lengthUnitId
7785
7786
  };
7786
7787
  }
7788
+ /**
7789
+ * Writes IfcProjectedCRS + IfcMapConversion georeferencing the model context
7790
+ * (GRF003). Coordinates are metres; rotation defaults to identity.
7791
+ */
7792
+ function writeMapConversion(w, crs, geomContextId, lengthUnitId) {
7793
+ const crsId = w.nextId();
7794
+ w.writeLine({
7795
+ expressID: crsId,
7796
+ type: WebIFC.IFCPROJECTEDCRS,
7797
+ Name: w.mkType(WebIFC.IFCLABEL, crs.name),
7798
+ Description: crs.description !== void 0 ? w.mkType(WebIFC.IFCTEXT, crs.description) : null,
7799
+ GeodeticDatum: crs.geodeticDatum !== void 0 ? w.mkType(WebIFC.IFCIDENTIFIER, crs.geodeticDatum) : null,
7800
+ VerticalDatum: crs.verticalDatum !== void 0 ? w.mkType(WebIFC.IFCIDENTIFIER, crs.verticalDatum) : null,
7801
+ MapProjection: crs.mapProjection !== void 0 ? w.mkType(WebIFC.IFCIDENTIFIER, crs.mapProjection) : null,
7802
+ MapZone: crs.mapZone !== void 0 ? w.mkType(WebIFC.IFCIDENTIFIER, crs.mapZone) : null,
7803
+ MapUnit: w.ref(lengthUnitId)
7804
+ });
7805
+ const conversionId = w.nextId();
7806
+ w.writeLine({
7807
+ expressID: conversionId,
7808
+ type: WebIFC.IFCMAPCONVERSION,
7809
+ SourceCRS: w.ref(geomContextId),
7810
+ TargetCRS: w.ref(crsId),
7811
+ Eastings: w.mkType(WebIFC.IFCLENGTHMEASURE, crs.eastings ?? 0),
7812
+ Northings: w.mkType(WebIFC.IFCLENGTHMEASURE, crs.northings ?? 0),
7813
+ OrthogonalHeight: w.mkType(WebIFC.IFCLENGTHMEASURE, crs.orthogonalHeight ?? 0),
7814
+ XAxisAbscissa: crs.xAxisAbscissa !== void 0 ? w.mkType(WebIFC.IFCREAL, crs.xAxisAbscissa) : null,
7815
+ XAxisOrdinate: crs.xAxisOrdinate !== void 0 ? w.mkType(WebIFC.IFCREAL, crs.xAxisOrdinate) : null,
7816
+ Scale: crs.scale !== void 0 ? w.mkType(WebIFC.IFCREAL, crs.scale) : null
7817
+ });
7818
+ return crsId;
7819
+ }
7787
7820
  function writeAxis2Placement3D(w, origin = [
7788
7821
  0,
7789
7822
  0,
@@ -9549,12 +9582,56 @@ function writeStairFlightEntity(w, guid, name, flight, ownerHistoryId, localPlac
9549
9582
  ObjectPlacement: w.ref(localPlacementId),
9550
9583
  Representation: w.ref(productDefinitionShapeId),
9551
9584
  Tag: null,
9552
- NumberOfRisers: w.mkType(WebIFC.IFCINTEGER, flight.numberOfRisers),
9553
- NumberOfTreads: w.mkType(WebIFC.IFCINTEGER, flight.numberOfRisers - 1),
9554
- RiserHeight: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, toIfcLengthM(flight.riserHeight)),
9555
- TreadLength: w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, toIfcLengthM(flight.treadLength)),
9585
+ NumberOfRisers: null,
9586
+ NumberOfTreads: null,
9587
+ RiserHeight: null,
9588
+ TreadLength: null,
9556
9589
  PredefinedType: null
9557
9590
  });
9591
+ writeStairFlightCommonPset(w, ownerHistoryId, id, flight);
9592
+ return id;
9593
+ }
9594
+ /** Pset_StairFlightCommon: the standard home for the flight geometry data the
9595
+ * deprecated IfcStairFlight attributes used to carry. Note the standard's
9596
+ * singular `NumberOfRiser`. */
9597
+ function writeStairFlightCommonPset(w, ownerHistoryId, flightExpressId, flight) {
9598
+ const props = [
9599
+ writeSingleValue(w, "NumberOfRiser", w.mkType(WebIFC.IFCCOUNTMEASURE, flight.numberOfRisers)),
9600
+ writeSingleValue(w, "NumberOfTreads", w.mkType(WebIFC.IFCCOUNTMEASURE, flight.numberOfRisers - 1)),
9601
+ writeSingleValue(w, "RiserHeight", w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, toIfcLengthM(flight.riserHeight))),
9602
+ writeSingleValue(w, "TreadLength", w.mkType(WebIFC.IFCPOSITIVELENGTHMEASURE, toIfcLengthM(flight.treadLength)))
9603
+ ];
9604
+ const psetId = w.nextId();
9605
+ w.writeLine({
9606
+ expressID: psetId,
9607
+ type: WebIFC.IFCPROPERTYSET,
9608
+ GlobalId: w.mkType(WebIFC.IFCGLOBALLYUNIQUEID, w.guidFor(psetId)),
9609
+ OwnerHistory: w.ref(ownerHistoryId),
9610
+ Name: w.mkType(WebIFC.IFCLABEL, "Pset_StairFlightCommon"),
9611
+ Description: null,
9612
+ HasProperties: props.map((id) => w.ref(id))
9613
+ });
9614
+ w.writeLine({
9615
+ expressID: w.nextId(),
9616
+ type: WebIFC.IFCRELDEFINESBYPROPERTIES,
9617
+ GlobalId: w.mkType(WebIFC.IFCGLOBALLYUNIQUEID, w.guidFor(psetId + 1e5)),
9618
+ OwnerHistory: w.ref(ownerHistoryId),
9619
+ Name: null,
9620
+ Description: null,
9621
+ RelatedObjects: [w.ref(flightExpressId)],
9622
+ RelatingPropertyDefinition: w.ref(psetId)
9623
+ });
9624
+ }
9625
+ function writeSingleValue(w, name, value) {
9626
+ const id = w.nextId();
9627
+ w.writeLine({
9628
+ expressID: id,
9629
+ type: WebIFC.IFCPROPERTYSINGLEVALUE,
9630
+ Name: w.mkType(WebIFC.IFCIDENTIFIER, name),
9631
+ Description: null,
9632
+ NominalValue: value,
9633
+ Unit: null
9634
+ });
9558
9635
  return id;
9559
9636
  }
9560
9637
  function writeStairEntity(w, guid, name, _predefinedType, ownerHistoryId, localPlacementId) {
@@ -11065,12 +11142,11 @@ function writeRoofBaseQuantities(w, ownerHistoryId, roofExpressId, spec) {
11065
11142
  const widthM = toIfcLengthM(spec.width);
11066
11143
  const thicknessM = toIfcLengthM(spec.thickness);
11067
11144
  const grossAreaM2 = lengthM * widthM;
11068
- const grossVolumeM3 = grossAreaM2 * thicknessM;
11145
+ grossAreaM2 * thicknessM;
11069
11146
  writeRelDefinesByProperties(w, ownerHistoryId, roofExpressId, writeElementQuantity(w, ownerHistoryId, "Qto_RoofBaseQuantities", [
11070
11147
  writeQtyArea(w, "GrossArea", grossAreaM2),
11071
11148
  writeQtyArea(w, "NetArea", grossAreaM2),
11072
- writeQtyVolume(w, "GrossVolume", grossVolumeM3),
11073
- writeQtyVolume(w, "NetVolume", grossVolumeM3)
11149
+ writeQtyArea(w, "ProjectedArea", grossAreaM2)
11074
11150
  ]));
11075
11151
  }
11076
11152
  function writeCurtainWallCommonPset(w, ownerHistoryId, curtainWallExpressId, spec) {
@@ -11097,7 +11173,7 @@ function writeFootingBaseQuantities(w, ownerHistoryId, footingExpressId, spec) {
11097
11173
  writeRelDefinesByProperties(w, ownerHistoryId, footingExpressId, writeElementQuantity(w, ownerHistoryId, "Qto_FootingBaseQuantities", [
11098
11174
  writeQtyLength(w, "Length", lengthM),
11099
11175
  writeQtyLength(w, "Width", widthM),
11100
- writeQtyLength(w, "Depth", depthM),
11176
+ writeQtyLength(w, "Height", depthM),
11101
11177
  writeQtyVolume(w, "GrossVolume", grossVolumeM3),
11102
11178
  writeQtyVolume(w, "NetVolume", grossVolumeM3)
11103
11179
  ]));
@@ -12045,6 +12121,918 @@ async function checkRoundTrip(bytes) {
12045
12121
  };
12046
12122
  }
12047
12123
  //#endregion
12124
+ //#region src/import/spfReader.ts
12125
+ var SUPPORTED_SCHEMAS = [
12126
+ "IFC2X3",
12127
+ "IFC4",
12128
+ "IFC4X3"
12129
+ ];
12130
+ /**
12131
+ * Foundation layer of the IFC reader: owns the web-ifc WASM model handle and
12132
+ * exposes typed line access, GUID↔expressId lookup, world-transform composition,
12133
+ * geometry-engine access and STEP string decoding.
12134
+ *
12135
+ * Lifecycle: created via the static async {@link SpfReader.create}; the caller
12136
+ * MUST call {@link SpfReader.close} (it always issues `CloseModel`, preventing
12137
+ * WASM handle leaks). The handle is `using`-friendly via `Symbol.dispose`.
12138
+ */
12139
+ function deleteVector(vec) {
12140
+ vec.delete?.();
12141
+ }
12142
+ var SpfReader = class SpfReader {
12143
+ schema;
12144
+ modelId;
12145
+ #api;
12146
+ #closed = false;
12147
+ #linesByType = /* @__PURE__ */ new Map();
12148
+ constructor(api, modelId, schema) {
12149
+ this.#api = api;
12150
+ this.modelId = modelId;
12151
+ this.schema = schema;
12152
+ }
12153
+ static async create(bytes, settings = {}) {
12154
+ let api;
12155
+ try {
12156
+ api = new IfcAPI();
12157
+ await initIfcApi(api);
12158
+ } catch (e) {
12159
+ return err(importError("OPEN_MODEL_FAILED", "Failed to initialize web-ifc", e));
12160
+ }
12161
+ let modelId;
12162
+ try {
12163
+ modelId = api.OpenModel(bytes, { COORDINATE_TO_ORIGIN: settings.coordinateToOrigin ?? false });
12164
+ } catch (e) {
12165
+ return err(importError("OPEN_MODEL_FAILED", "web-ifc OpenModel threw", e));
12166
+ }
12167
+ if (modelId < 0 || !api.IsModelOpen(modelId)) {
12168
+ if (modelId >= 0) api.CloseModel(modelId);
12169
+ return err(importError("OPEN_MODEL_FAILED", "web-ifc OpenModel returned an invalid model id"));
12170
+ }
12171
+ const schemaRaw = api.GetModelSchema(modelId);
12172
+ if (!SUPPORTED_SCHEMAS.includes(schemaRaw)) {
12173
+ api.CloseModel(modelId);
12174
+ return err(importError("SCHEMA_UNSUPPORTED", `Unsupported IFC schema "${schemaRaw}"`));
12175
+ }
12176
+ return ok(new SpfReader(api, modelId, schemaRaw));
12177
+ }
12178
+ /** Always issues CloseModel; safe to call more than once. */
12179
+ close() {
12180
+ if (this.#closed) return;
12181
+ this.#closed = true;
12182
+ this.#api.CloseModel(this.modelId);
12183
+ }
12184
+ [Symbol.dispose]() {
12185
+ this.close();
12186
+ }
12187
+ /**
12188
+ * Raw line object for an express id. With `flatten=false` (default) references
12189
+ * appear as `{ type, value }` wrappers and nested entities are not resolved;
12190
+ * pass `flatten=true` to recursively inline referenced lines.
12191
+ */
12192
+ getLine(expressId, flatten = false) {
12193
+ return this.#api.GetLine(this.modelId, expressId, flatten) ?? null;
12194
+ }
12195
+ /** Express ids of every line whose type equals `type` (no inherited types). */
12196
+ getLinesOfType(type) {
12197
+ const cached = this.#linesByType.get(type);
12198
+ if (cached !== void 0) return cached;
12199
+ const vec = this.#api.GetLineIDsWithType(this.modelId, type);
12200
+ const out = [];
12201
+ for (let i = 0; i < vec.size(); i++) out.push(vec.get(i));
12202
+ deleteVector(vec);
12203
+ this.#linesByType.set(type, out);
12204
+ return out;
12205
+ }
12206
+ /** Express ids of every line in the model. */
12207
+ getAllLines() {
12208
+ const vec = this.#api.GetAllLines(this.modelId);
12209
+ const out = [];
12210
+ for (let i = 0; i < vec.size(); i++) out.push(vec.get(i));
12211
+ deleteVector(vec);
12212
+ return out;
12213
+ }
12214
+ /** IFC type code for an express id. */
12215
+ /** Uppercased IFC entity name of the instance (e.g. `IFCWALL`). */
12216
+ typeNameOf(expressId) {
12217
+ return this.#api.GetNameFromTypeCode(this.getLineType(expressId)).toUpperCase();
12218
+ }
12219
+ getLineType(expressId) {
12220
+ const t = this.#api.GetLineType(this.modelId, expressId);
12221
+ return typeof t === "number" ? t : Number(t?.value ?? t);
12222
+ }
12223
+ /** Builds web-ifc's internal GUID→expressId index; call before guid lookups. */
12224
+ buildGuidMap() {
12225
+ this.#api.CreateIfcGuidToExpressIdMapping(this.modelId);
12226
+ }
12227
+ /** expressId for a GlobalId, or undefined. Requires {@link buildGuidMap} first. */
12228
+ expressIdFromGuid(guid) {
12229
+ const id = this.#api.GetExpressIdFromGuid(this.modelId, guid);
12230
+ return typeof id === "number" ? id : void 0;
12231
+ }
12232
+ /** GlobalId for an express id, or undefined. Requires {@link buildGuidMap} first. */
12233
+ guidFromExpressId(expressId) {
12234
+ const guid = this.#api.GetGuidFromExpressId(this.modelId, expressId);
12235
+ return typeof guid === "string" ? guid : void 0;
12236
+ }
12237
+ /**
12238
+ * Composed world transform (column-major 16-float matrix) for a placement
12239
+ * express id, resolving the full IfcLocalPlacement chain.
12240
+ */
12241
+ getWorldTransform(placementExpressId) {
12242
+ return this.#api.GetWorldTransformMatrix(this.modelId, placementExpressId);
12243
+ }
12244
+ /** Streams placed meshes for the given product express ids. */
12245
+ streamMeshes(expressIds, cb) {
12246
+ this.#api.StreamMeshes(this.modelId, expressIds, cb);
12247
+ }
12248
+ /** Geometry buffers for a geometry express id; caller MUST call `.delete()`. */
12249
+ getGeometry(geometryExpressId) {
12250
+ return this.#api.GetGeometry(this.modelId, geometryExpressId);
12251
+ }
12252
+ /** Reads a Float32Array view of vertex data from a WASM pointer. */
12253
+ getVertexArray(ptr, size) {
12254
+ return this.#api.GetVertexArray(ptr, size);
12255
+ }
12256
+ /** Reads a Uint32Array view of index data from a WASM pointer. */
12257
+ getIndexArray(ptr, size) {
12258
+ return this.#api.GetIndexArray(ptr, size);
12259
+ }
12260
+ /** Decodes IFC STEP string escapes (`\X2\`, `\S\`, `\X\`) in a raw value. */
12261
+ decodeText(s) {
12262
+ const decoded = this.#api.DecodeText(s);
12263
+ return typeof decoded === "string" ? decoded : s;
12264
+ }
12265
+ };
12266
+ //#endregion
12267
+ //#region src/validation/qtoDefinitions.generated.ts
12268
+ var QTO_DEFINITIONS = {
12269
+ "Qto_ActuatorBaseQuantities": {
12270
+ "entities": ["IFCACTUATOR"],
12271
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12272
+ },
12273
+ "Qto_AirTerminalBaseQuantities": {
12274
+ "entities": ["IFCAIRTERMINAL"],
12275
+ "quantities": {
12276
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12277
+ "Perimeter": "IFCQUANTITYLENGTH",
12278
+ "TotalSurfaceArea": "IFCQUANTITYAREA"
12279
+ }
12280
+ },
12281
+ "Qto_AirTerminalBoxTypeBaseQuantities": {
12282
+ "entities": ["IFCAIRTERMINALBOX"],
12283
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12284
+ },
12285
+ "Qto_AirToAirHeatRecoveryBaseQuantities": {
12286
+ "entities": ["IFCAIRTOAIRHEATRECOVERY"],
12287
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12288
+ },
12289
+ "Qto_AlarmBaseQuantities": {
12290
+ "entities": ["IFCALARM"],
12291
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12292
+ },
12293
+ "Qto_AudioVisualApplianceBaseQuantities": {
12294
+ "entities": ["IFCAUDIOVISUALAPPLIANCE"],
12295
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12296
+ },
12297
+ "Qto_BeamBaseQuantities": {
12298
+ "entities": ["IFCBEAM"],
12299
+ "quantities": {
12300
+ "CrossSectionArea": "IFCQUANTITYAREA",
12301
+ "GrossSurfaceArea": "IFCQUANTITYAREA",
12302
+ "GrossVolume": "IFCQUANTITYVOLUME",
12303
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12304
+ "Length": "IFCQUANTITYLENGTH",
12305
+ "NetSurfaceArea": "IFCQUANTITYAREA",
12306
+ "NetVolume": "IFCQUANTITYVOLUME",
12307
+ "NetWeight": "IFCQUANTITYWEIGHT",
12308
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12309
+ }
12310
+ },
12311
+ "Qto_BoilerBaseQuantities": {
12312
+ "entities": ["IFCBOILER"],
12313
+ "quantities": {
12314
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12315
+ "NetWeight": "IFCQUANTITYWEIGHT",
12316
+ "TotalSurfaceArea": "IFCQUANTITYAREA"
12317
+ }
12318
+ },
12319
+ "Qto_BuildingBaseQuantities": {
12320
+ "entities": ["IFCBUILDING"],
12321
+ "quantities": {
12322
+ "EavesHeight": "IFCQUANTITYLENGTH",
12323
+ "FootprintArea": "IFCQUANTITYAREA",
12324
+ "GrossFloorArea": "IFCQUANTITYAREA",
12325
+ "GrossVolume": "IFCQUANTITYVOLUME",
12326
+ "Height": "IFCQUANTITYLENGTH",
12327
+ "NetFloorArea": "IFCQUANTITYAREA",
12328
+ "NetVolume": "IFCQUANTITYVOLUME"
12329
+ }
12330
+ },
12331
+ "Qto_BuildingElementProxyQuantities": {
12332
+ "entities": ["IFCBUILDINGELEMENTPROXY"],
12333
+ "quantities": {
12334
+ "NetSurfaceArea": "IFCQUANTITYCOUNT",
12335
+ "NetVolume": "IFCQUANTITYCOUNT"
12336
+ }
12337
+ },
12338
+ "Qto_BuildingStoreyBaseQuantities": {
12339
+ "entities": ["IFCBUILDINGSTOREY"],
12340
+ "quantities": {
12341
+ "GrossFloorArea": "IFCQUANTITYAREA",
12342
+ "GrossHeight": "IFCQUANTITYLENGTH",
12343
+ "GrossPerimeter": "IFCQUANTITYLENGTH",
12344
+ "GrossVolume": "IFCQUANTITYVOLUME",
12345
+ "NetFloorArea": "IFCQUANTITYAREA",
12346
+ "NetHeigtht": "IFCQUANTITYLENGTH",
12347
+ "NetVolume": "IFCQUANTITYVOLUME"
12348
+ }
12349
+ },
12350
+ "Qto_BurnerBaseQuantities": {
12351
+ "entities": ["IFCBURNER"],
12352
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12353
+ },
12354
+ "Qto_CableCarrierFittingBaseQuantities": {
12355
+ "entities": ["IFCCABLECARRIERFITTING"],
12356
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12357
+ },
12358
+ "Qto_CableCarrierSegmentBaseQuantities": {
12359
+ "entities": ["IFCCABLECARRIERSEGMENT"],
12360
+ "quantities": {
12361
+ "CrossSectionArea": "IFCQUANTITYAREA",
12362
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12363
+ "Length": "IFCQUANTITYLENGTH",
12364
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12365
+ }
12366
+ },
12367
+ "Qto_CableFittingBaseQuantities": {
12368
+ "entities": ["IFCCABLEFITTING"],
12369
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12370
+ },
12371
+ "Qto_CableSegmentBaseQuantities": {
12372
+ "entities": ["IFCCABLESEGMENT"],
12373
+ "quantities": {
12374
+ "CrossSectionArea": "IFCQUANTITYAREA",
12375
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12376
+ "Length": "IFCQUANTITYLENGTH",
12377
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12378
+ }
12379
+ },
12380
+ "Qto_ChillerBaseQuantities": {
12381
+ "entities": ["IFCCHILLER"],
12382
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12383
+ },
12384
+ "Qto_ChimneyBaseQuantities": {
12385
+ "entities": ["IFCCHIMNEY"],
12386
+ "quantities": { "Length": "IFCQUANTITYLENGTH" }
12387
+ },
12388
+ "Qto_CoilBaseQuantities": {
12389
+ "entities": ["IFCCOIL"],
12390
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12391
+ },
12392
+ "Qto_ColumnBaseQuantities": {
12393
+ "entities": ["IFCCOLUMN"],
12394
+ "quantities": {
12395
+ "CrossSectionArea": "IFCQUANTITYAREA",
12396
+ "GrossSurfaceArea": "IFCQUANTITYAREA",
12397
+ "GrossVolume": "IFCQUANTITYVOLUME",
12398
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12399
+ "Length": "IFCQUANTITYLENGTH",
12400
+ "NetSurfaceArea": "IFCQUANTITYAREA",
12401
+ "NetVolume": "IFCQUANTITYVOLUME",
12402
+ "NetWeight": "IFCQUANTITYWEIGHT",
12403
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12404
+ }
12405
+ },
12406
+ "Qto_CommunicationsApplianceBaseQuantities": {
12407
+ "entities": ["IFCCOMMUNICATIONSAPPLIANCE"],
12408
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12409
+ },
12410
+ "Qto_CompressorBaseQuantities": {
12411
+ "entities": ["IFCCOMPRESSOR"],
12412
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12413
+ },
12414
+ "Qto_CondenserBaseQuantities": {
12415
+ "entities": ["IFCCONDENSER"],
12416
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12417
+ },
12418
+ "Qto_ConstructionEquipmentResourceBaseQuantities": {
12419
+ "entities": ["IFCCONSTRUCTIONEQUIPMENTRESOURCE"],
12420
+ "quantities": {
12421
+ "OperatingTime": "IFCQUANTITYTIME",
12422
+ "UsageTime": "IFCQUANTITYTIME"
12423
+ }
12424
+ },
12425
+ "Qto_ConstructionMaterialResourceBaseQuantities": {
12426
+ "entities": ["IFCCONSTRUCTIONMATERIALRESOURCE"],
12427
+ "quantities": {
12428
+ "GrossVolume": "IFCQUANTITYVOLUME",
12429
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12430
+ "NetVolume": "IFCQUANTITYVOLUME",
12431
+ "NetWeight": "IFCQUANTITYWEIGHT"
12432
+ }
12433
+ },
12434
+ "Qto_ControllerBaseQuantities": {
12435
+ "entities": ["IFCCONTROLLER"],
12436
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12437
+ },
12438
+ "Qto_CooledBeamBaseQuantities": {
12439
+ "entities": ["IFCCOOLEDBEAM"],
12440
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12441
+ },
12442
+ "Qto_CoolingTowerBaseQuantities": {
12443
+ "entities": ["IFCCOOLINGTOWER"],
12444
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12445
+ },
12446
+ "Qto_CoveringBaseQuantities": {
12447
+ "entities": ["IFCCOVERING"],
12448
+ "quantities": {
12449
+ "GrossArea": "IFCQUANTITYAREA",
12450
+ "NetArea": "IFCQUANTITYAREA",
12451
+ "Width": "IFCQUANTITYLENGTH"
12452
+ }
12453
+ },
12454
+ "Qto_CurtainWallQuantities": {
12455
+ "entities": ["IFCCURTAINWALL"],
12456
+ "quantities": {
12457
+ "GrossSideArea": "IFCQUANTITYAREA",
12458
+ "Height": "IFCQUANTITYLENGTH",
12459
+ "Length": "IFCQUANTITYLENGTH",
12460
+ "NetSideArea": "IFCQUANTITYAREA",
12461
+ "Width": "IFCQUANTITYLENGTH"
12462
+ }
12463
+ },
12464
+ "Qto_DamperBaseQuantities": {
12465
+ "entities": ["IFCDAMPER"],
12466
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12467
+ },
12468
+ "Qto_DistributionChamberElementBaseQuantities": {
12469
+ "entities": ["IFCDISTRIBUTIONCHAMBERELEMENT"],
12470
+ "quantities": {
12471
+ "GrossSurfaceArea": "IFCQUANTITYAREA",
12472
+ "GrossVolume": "IFCQUANTITYVOLUME",
12473
+ "NetSurfaceArea": "IFCQUANTITYAREA",
12474
+ "NetVolume": "IFCQUANTITYVOLUME"
12475
+ }
12476
+ },
12477
+ "Qto_DoorBaseQuantities": {
12478
+ "entities": ["IFCDOOR"],
12479
+ "quantities": {
12480
+ "Area": "IFCQUANTITYAREA",
12481
+ "Height": "IFCQUANTITYLENGTH",
12482
+ "Perimeter": "IFCQUANTITYLENGTH",
12483
+ "Width": "IFCQUANTITYLENGTH"
12484
+ }
12485
+ },
12486
+ "Qto_DuctFittingBaseQuantities": {
12487
+ "entities": ["IFCDUCTFITTING"],
12488
+ "quantities": {
12489
+ "GrossCrossSectionArea": "IFCQUANTITYAREA",
12490
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12491
+ "Length": "IFCQUANTITYLENGTH",
12492
+ "NetCrossSectionArea": "IFCQUANTITYAREA",
12493
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12494
+ }
12495
+ },
12496
+ "Qto_DuctSegmentBaseQuantities": {
12497
+ "entities": ["IFCDUCTSEGMENT"],
12498
+ "quantities": {
12499
+ "GrossCrossSectionArea": "IFCQUANTITYAREA",
12500
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12501
+ "Length": "IFCQUANTITYLENGTH",
12502
+ "NetCrossSectionArea": "IFCQUANTITYAREA",
12503
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12504
+ }
12505
+ },
12506
+ "Qto_DuctSilencerBaseQuantities": {
12507
+ "entities": ["IFCDUCTSILENCER"],
12508
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12509
+ },
12510
+ "Qto_ElectricApplianceBaseQuantities": {
12511
+ "entities": ["IFCELECTRICAPPLIANCE"],
12512
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12513
+ },
12514
+ "Qto_ElectricDistributionBoardBaseQuantities": {
12515
+ "entities": ["IFCELECTRICDISTRIBUTIONBOARD"],
12516
+ "quantities": {
12517
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12518
+ "NumberOfCircuits": "IFCQUANTITYCOUNT"
12519
+ }
12520
+ },
12521
+ "Qto_ElectricFlowStorageDeviceBaseQuantities": {
12522
+ "entities": ["IFCELECTRICFLOWSTORAGEDEVICE"],
12523
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12524
+ },
12525
+ "Qto_ElectricGeneratorBaseQuantities": {
12526
+ "entities": ["IFCELECTRICGENERATOR"],
12527
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12528
+ },
12529
+ "Qto_ElectricMotorBaseQuantities": {
12530
+ "entities": ["IFCELECTRICMOTOR"],
12531
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12532
+ },
12533
+ "Qto_ElectricTimeControlBaseQuantities": {
12534
+ "entities": ["IFCELECTRICTIMECONTROL"],
12535
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12536
+ },
12537
+ "Qto_EvaporativeCoolerBaseQuantities": {
12538
+ "entities": ["IFCEVAPORATIVECOOLER"],
12539
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12540
+ },
12541
+ "Qto_EvaporatorBaseQuantities": {
12542
+ "entities": ["IFCEVAPORATOR"],
12543
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12544
+ },
12545
+ "Qto_FanBaseQuantities": {
12546
+ "entities": ["IFCFAN"],
12547
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12548
+ },
12549
+ "Qto_FilterBaseQuantities": {
12550
+ "entities": ["IFCFILTER"],
12551
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12552
+ },
12553
+ "Qto_FireSuppressionTerminalBaseQuantities": {
12554
+ "entities": ["IFCFIRESUPPRESSIONTERMINAL"],
12555
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12556
+ },
12557
+ "Qto_FlowInstrumentBaseQuantities": {
12558
+ "entities": ["IFCFLOWINSTRUMENT"],
12559
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12560
+ },
12561
+ "Qto_FlowMeterBaseQuantities": {
12562
+ "entities": ["IFCFLOWMETER"],
12563
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12564
+ },
12565
+ "Qto_FootingBaseQuantities": {
12566
+ "entities": ["IFCFOOTING"],
12567
+ "quantities": {
12568
+ "CrossSectionArea": "IFCQUANTITYAREA",
12569
+ "GrossSurfaceArea": "IFCQUANTITYAREA",
12570
+ "GrossVolume": "IFCQUANTITYVOLUME",
12571
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12572
+ "Height": "IFCQUANTITYLENGTH",
12573
+ "Length": "IFCQUANTITYLENGTH",
12574
+ "NetVolume": "IFCQUANTITYVOLUME",
12575
+ "NetWeight": "IFCQUANTITYWEIGHT",
12576
+ "OuterSurfaceArea": "IFCQUANTITYAREA",
12577
+ "Width": "IFCQUANTITYLENGTH"
12578
+ }
12579
+ },
12580
+ "Qto_HeatExchangerBaseQuantities": {
12581
+ "entities": ["IFCHEATEXCHANGER"],
12582
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12583
+ },
12584
+ "Qto_HumidifierBaseQuantities": {
12585
+ "entities": ["IFCHUMIDIFIER"],
12586
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12587
+ },
12588
+ "Qto_InterceptorBaseQuantities": {
12589
+ "entities": ["IFCINTERCEPTOR"],
12590
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12591
+ },
12592
+ "Qto_JunctionBoxBaseQuantities": {
12593
+ "entities": ["IFCJUNCTIONBOX"],
12594
+ "quantities": {
12595
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12596
+ "NumberOfGangs": "IFCQUANTITYCOUNT"
12597
+ }
12598
+ },
12599
+ "Qto_LaborResourceBaseQuantities": {
12600
+ "entities": ["IFCLABORRESOURCE"],
12601
+ "quantities": {
12602
+ "OvertimeWork": "IFCQUANTITYTIME",
12603
+ "StandardWork": "IFCQUANTITYTIME"
12604
+ }
12605
+ },
12606
+ "Qto_LampBaseQuantities": {
12607
+ "entities": ["IFCLAMP"],
12608
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12609
+ },
12610
+ "Qto_LightFixtureBaseQuantities": {
12611
+ "entities": ["IFCLIGHTFIXTURE"],
12612
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12613
+ },
12614
+ "Qto_MemberBaseQuantities": {
12615
+ "entities": ["IFCMEMBER"],
12616
+ "quantities": {
12617
+ "CrossSectionArea": "IFCQUANTITYAREA",
12618
+ "GrossSurfaceArea": "IFCQUANTITYAREA",
12619
+ "GrossVolume": "IFCQUANTITYVOLUME",
12620
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12621
+ "Length": "IFCQUANTITYLENGTH",
12622
+ "NetSurfaceArea": "IFCQUANTITYAREA",
12623
+ "NetVolume": "IFCQUANTITYVOLUME",
12624
+ "NetWeight": "IFCQUANTITYWEIGHT",
12625
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12626
+ }
12627
+ },
12628
+ "Qto_MotorConnectionBaseQuantities": {
12629
+ "entities": ["IFCMOTORCONNECTION"],
12630
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12631
+ },
12632
+ "Qto_OpeningElementBaseQuantities": {
12633
+ "entities": ["IFCOPENINGELEMENT"],
12634
+ "quantities": {
12635
+ "Area": "IFCQUANTITYAREA",
12636
+ "Depth": "IFCQUANTITYLENGTH",
12637
+ "Height": "IFCQUANTITYLENGTH",
12638
+ "Volume": "IFCQUANTITYVOLUME",
12639
+ "Width": "IFCQUANTITYLENGTH"
12640
+ }
12641
+ },
12642
+ "Qto_OutletBaseQuantities": {
12643
+ "entities": ["IFCOUTLET"],
12644
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12645
+ },
12646
+ "Qto_PileBaseQuantities": {
12647
+ "entities": ["IFCPILE"],
12648
+ "quantities": {
12649
+ "CrossSectionArea": "IFCQUANTITYAREA",
12650
+ "GrossSurfaceArea": "IFCQUANTITYAREA",
12651
+ "GrossVolume": "IFCQUANTITYVOLUME",
12652
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12653
+ "Length": "IFCQUANTITYLENGTH",
12654
+ "NetVolume": "IFCQUANTITYVOLUME",
12655
+ "NetWeight": "IFCQUANTITYWEIGHT",
12656
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12657
+ }
12658
+ },
12659
+ "Qto_PipeFittingBaseQuantities": {
12660
+ "entities": ["IFCPIPEFITTING"],
12661
+ "quantities": {
12662
+ "GrossCrossSectionArea": "IFCQUANTITYAREA",
12663
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12664
+ "Length": "IFCQUANTITYLENGTH",
12665
+ "NetCrossSectionArea": "IFCQUANTITYAREA",
12666
+ "NetWeight": "IFCQUANTITYWEIGHT",
12667
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12668
+ }
12669
+ },
12670
+ "Qto_PipeSegmentBaseQuantities": {
12671
+ "entities": ["IFCPIPESEGMENT"],
12672
+ "quantities": {
12673
+ "GrossCrossSectionArea": "IFCQUANTITYAREA",
12674
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12675
+ "Length": "IFCQUANTITYLENGTH",
12676
+ "NetCrossSectionArea": "IFCQUANTITYAREA",
12677
+ "NetWeight": "IFCQUANTITYWEIGHT",
12678
+ "OuterSurfaceArea": "IFCQUANTITYAREA"
12679
+ }
12680
+ },
12681
+ "Qto_PlateBaseQuantities": {
12682
+ "entities": ["IFCPLATE"],
12683
+ "quantities": {
12684
+ "GrossArea": "IFCQUANTITYAREA",
12685
+ "GrossVolume": "IFCQUANTITYVOLUME",
12686
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12687
+ "NetArea": "IFCQUANTITYAREA",
12688
+ "NetVolume": "IFCQUANTITYVOLUME",
12689
+ "NetWeight": "IFCQUANTITYWEIGHT",
12690
+ "Perimeter": "IFCQUANTITYLENGTH",
12691
+ "Width": "IFCQUANTITYLENGTH"
12692
+ }
12693
+ },
12694
+ "Qto_ProjectionElementBaseQuantities": {
12695
+ "entities": ["IFCPROJECTIONELEMENT"],
12696
+ "quantities": {
12697
+ "Area": "IFCQUANTITYAREA",
12698
+ "Volume": "IFCQUANTITYVOLUME"
12699
+ }
12700
+ },
12701
+ "Qto_ProtectiveDeviceBaseQuantities": {
12702
+ "entities": ["IFCPROTECTIVEDEVICE"],
12703
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12704
+ },
12705
+ "Qto_ProtectiveDeviceTrippingUnitBaseQuantities": {
12706
+ "entities": ["IFCPROTECTIVEDEVICETRIPPINGUNIT"],
12707
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12708
+ },
12709
+ "Qto_PumpBaseQuantities": {
12710
+ "entities": ["IFCPUMP"],
12711
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12712
+ },
12713
+ "Qto_RailingBaseQuantities": {
12714
+ "entities": ["IFCRAILING"],
12715
+ "quantities": { "Length": "IFCQUANTITYLENGTH" }
12716
+ },
12717
+ "Qto_RampFlightBaseQuantities": {
12718
+ "entities": ["IFCRAMPFLIGHT"],
12719
+ "quantities": {
12720
+ "GrossArea": "IFCQUANTITYAREA",
12721
+ "GrossVolume": "IFCQUANTITYVOLUME",
12722
+ "Length": "IFCQUANTITYLENGTH",
12723
+ "NetArea": "IFCQUANTITYAREA",
12724
+ "NetVolume": "IFCQUANTITYVOLUME",
12725
+ "Width": "IFCQUANTITYLENGTH"
12726
+ }
12727
+ },
12728
+ "Qto_ReinforcingElementBaseQuantities": {
12729
+ "entities": ["IFCREINFORCINGELEMENT"],
12730
+ "quantities": {
12731
+ "Count": "IFCQUANTITYCOUNT",
12732
+ "Length": "IFCQUANTITYLENGTH",
12733
+ "Weight": "IFCQUANTITYWEIGHT"
12734
+ }
12735
+ },
12736
+ "Qto_RoofBaseQuantities": {
12737
+ "entities": ["IFCROOF"],
12738
+ "quantities": {
12739
+ "GrossArea": "IFCQUANTITYAREA",
12740
+ "NetArea": "IFCQUANTITYAREA",
12741
+ "ProjectedArea": "IFCQUANTITYAREA"
12742
+ }
12743
+ },
12744
+ "Qto_SanitaryTerminalBaseQuantities": {
12745
+ "entities": ["IFCSANITARYTERMINAL"],
12746
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12747
+ },
12748
+ "Qto_SensorBaseQuantities": {
12749
+ "entities": ["IFCSENSOR"],
12750
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12751
+ },
12752
+ "Qto_SiteBaseQuantities": {
12753
+ "entities": ["IFCSITE"],
12754
+ "quantities": {
12755
+ "GrossArea": "IFCQUANTITYAREA",
12756
+ "GrossPerimeter": "IFCQUANTITYLENGTH"
12757
+ }
12758
+ },
12759
+ "Qto_SlabBaseQuantities": {
12760
+ "entities": ["IFCSLAB"],
12761
+ "quantities": {
12762
+ "Depth": "IFCQUANTITYLENGTH",
12763
+ "GrossArea": "IFCQUANTITYAREA",
12764
+ "GrossVolume": "IFCQUANTITYVOLUME",
12765
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12766
+ "Length": "IFCQUANTITYLENGTH",
12767
+ "NetArea": "IFCQUANTITYAREA",
12768
+ "NetVolume": "IFCQUANTITYVOLUME",
12769
+ "NetWeight": "IFCQUANTITYWEIGHT",
12770
+ "Perimeter": "IFCQUANTITYLENGTH",
12771
+ "Width": "IFCQUANTITYLENGTH"
12772
+ }
12773
+ },
12774
+ "Qto_SolarDeviceBaseQuantities": {
12775
+ "entities": ["IFCSOLARDEVICE"],
12776
+ "quantities": {
12777
+ "GrossArea": "IFCQUANTITYAREA",
12778
+ "GrossWeight": "IFCQUANTITYWEIGHT"
12779
+ }
12780
+ },
12781
+ "Qto_SpaceBaseQuantities": {
12782
+ "entities": ["IFCSPACE"],
12783
+ "quantities": {
12784
+ "FinishCeilingHeight": "IFCQUANTITYLENGTH",
12785
+ "FinishFloorHeight": "IFCQUANTITYLENGTH",
12786
+ "GrossCeilingArea": "IFCQUANTITYAREA",
12787
+ "GrossFloorArea": "IFCQUANTITYAREA",
12788
+ "GrossPerimeter": "IFCQUANTITYLENGTH",
12789
+ "GrossVolume": "IFCQUANTITYVOLUME",
12790
+ "GrossWallArea": "IFCQUANTITYAREA",
12791
+ "Height": "IFCQUANTITYLENGTH",
12792
+ "NetCeilingArea": "IFCQUANTITYAREA",
12793
+ "NetFloorArea": "IFCQUANTITYAREA",
12794
+ "NetPerimeter": "IFCQUANTITYLENGTH",
12795
+ "NetVolume": "IFCQUANTITYVOLUME",
12796
+ "NetWallArea": "IFCQUANTITYAREA"
12797
+ }
12798
+ },
12799
+ "Qto_SpaceHeaterBaseQuantities": {
12800
+ "entities": ["IFCSPACEHEATER"],
12801
+ "quantities": {
12802
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12803
+ "Length": "IFCQUANTITYLENGTH",
12804
+ "NetWeight": "IFCQUANTITYWEIGHT"
12805
+ }
12806
+ },
12807
+ "Qto_StackTerminalBaseQuantities": {
12808
+ "entities": ["IFCSTACKTERMINAL"],
12809
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12810
+ },
12811
+ "Qto_StairFlightBaseQuantities": {
12812
+ "entities": ["IFCSTAIRFLIGHT"],
12813
+ "quantities": {
12814
+ "GrossVolume": "IFCQUANTITYVOLUME",
12815
+ "Length": "IFCQUANTITYLENGTH",
12816
+ "NetVolume": "IFCQUANTITYVOLUME"
12817
+ }
12818
+ },
12819
+ "Qto_SwitchingDeviceBaseQuantities": {
12820
+ "entities": ["IFCSWITCHINGDEVICE"],
12821
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12822
+ },
12823
+ "Qto_TankBaseQuantities": {
12824
+ "entities": ["IFCTANK"],
12825
+ "quantities": {
12826
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12827
+ "NetWeight": "IFCQUANTITYWEIGHT",
12828
+ "TotalSurfaceArea": "IFCQUANTITYAREA"
12829
+ }
12830
+ },
12831
+ "Qto_TransformerBaseQuantities": {
12832
+ "entities": ["IFCTRANSFORMER"],
12833
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12834
+ },
12835
+ "Qto_TubeBundleBaseQuantities": {
12836
+ "entities": ["IFCTUBEBUNDLE"],
12837
+ "quantities": {
12838
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12839
+ "NetWeight": "IFCQUANTITYWEIGHT"
12840
+ }
12841
+ },
12842
+ "Qto_UnitaryControlElementBaseQuantities": {
12843
+ "entities": ["IFCUNITARYCONTROLELEMENT"],
12844
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12845
+ },
12846
+ "Qto_UnitaryEquipmentBaseQuantities": {
12847
+ "entities": ["IFCUNITARYEQUIPMENT"],
12848
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12849
+ },
12850
+ "Qto_ValveBaseQuantities": {
12851
+ "entities": ["IFCVALVE"],
12852
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12853
+ },
12854
+ "Qto_VibrationIsolatorBaseQuantities": {
12855
+ "entities": ["IFCVIBRATIONISOLATOR"],
12856
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12857
+ },
12858
+ "Qto_WallBaseQuantities": {
12859
+ "entities": ["IFCWALL"],
12860
+ "quantities": {
12861
+ "GrossFootprintArea": "IFCQUANTITYAREA",
12862
+ "GrossSideArea": "IFCQUANTITYAREA",
12863
+ "GrossVolume": "IFCQUANTITYVOLUME",
12864
+ "GrossWeight": "IFCQUANTITYWEIGHT",
12865
+ "Height": "IFCQUANTITYLENGTH",
12866
+ "Length": "IFCQUANTITYLENGTH",
12867
+ "NetFootprintArea": "IFCQUANTITYAREA",
12868
+ "NetSideArea": "IFCQUANTITYAREA",
12869
+ "NetVolume": "IFCQUANTITYVOLUME",
12870
+ "NetWeight": "IFCQUANTITYWEIGHT",
12871
+ "Width": "IFCQUANTITYLENGTH"
12872
+ }
12873
+ },
12874
+ "Qto_WasteTerminalBaseQuantities": {
12875
+ "entities": ["IFCWASTETERMINAL"],
12876
+ "quantities": { "GrossWeight": "IFCQUANTITYWEIGHT" }
12877
+ },
12878
+ "Qto_WindowBaseQuantities": {
12879
+ "entities": ["IFCWINDOW"],
12880
+ "quantities": {
12881
+ "Area": "IFCQUANTITYAREA",
12882
+ "Height": "IFCQUANTITYLENGTH",
12883
+ "Perimeter": "IFCQUANTITYLENGTH",
12884
+ "Width": "IFCQUANTITYLENGTH"
12885
+ }
12886
+ }
12887
+ };
12888
+ //#endregion
12889
+ //#region src/validation/gherkinChecks.ts
12890
+ /**
12891
+ * Local implementations of the buildingSMART Validation Service's gherkin
12892
+ * normative rules that apply to the entity vocabulary this writer emits:
12893
+ *
12894
+ * - IFC102 — absence of deprecated entities and attributes (IFC4 lists from
12895
+ * the official rule definition).
12896
+ * - QTY001 — every `Qto_*` element quantity uses the standard set name,
12897
+ * quantity names, quantity entity types, applicable element, and
12898
+ * `MethodOfMeasurement='BaseQuantities'` (table generated from the official
12899
+ * qto_definitions.csv).
12900
+ * - GRF003 — a model containing facilities (IfcBuilding) declares a
12901
+ * coordinate reference system (warning severity, like the service).
12902
+ *
12903
+ * These run inside `toIfcValidated`, so the local gate covers the gherkin
12904
+ * layer before anything is uploaded.
12905
+ */
12906
+ async function checkGherkinRules(bytes) {
12907
+ const readerResult = await SpfReader.create(bytes);
12908
+ if (!readerResult.ok) return [issue("error", "PARSE_FAILED", `Could not open the model: ${readerResult.error.message}`)];
12909
+ const reader = readerResult.value;
12910
+ try {
12911
+ return [
12912
+ ...checkDeprecated(reader),
12913
+ ...checkQuantitySets(reader),
12914
+ ...checkGeoreferencing(reader)
12915
+ ];
12916
+ } finally {
12917
+ reader.close();
12918
+ }
12919
+ }
12920
+ /** IFC4 deprecated entities (IFC102, official rule table). */
12921
+ var DEPRECATED_IFC4_ENTITIES = [
12922
+ "IFC2DCOMPOSITECURVE",
12923
+ "IFCBEAMSTANDARDCASE",
12924
+ "IFCCONNECTIONPORTGEOMETRY",
12925
+ "IFCCOLUMNSTANDARDCASE",
12926
+ "IFCDOORSTANDARDCASE",
12927
+ "IFCDOORSTYLE",
12928
+ "IFCELECTRICALELEMENT",
12929
+ "IFCEQUIPMENTELEMENT",
12930
+ "IFCFACEBASEDSURFACEMODEL",
12931
+ "IFCMATERIALCLASSIFICATIONRELATIONSHIP",
12932
+ "IFCMATERIALLIST",
12933
+ "IFCMEMBERSTANDARDCASE",
12934
+ "IFCOPENINGSTANDARDCASE",
12935
+ "IFCPLATESTANDARDCASE",
12936
+ "IFCPRESENTATIONSTYLEASSIGNMENT",
12937
+ "IFCPROXY",
12938
+ "IFCRELCOVERSBLDGELEMENTS",
12939
+ "IFCRELCOVERSSPACES",
12940
+ "IFCSLABELEMENTEDCASE",
12941
+ "IFCSLABSTANDARDCASE",
12942
+ "IFCTEXTLITERAL",
12943
+ "IFCWALLELEMENTEDCASE",
12944
+ "IFCWALLSTANDARDCASE",
12945
+ "IFCWINDOWSTANDARDCASE",
12946
+ "IFCWINDOWSTYLE"
12947
+ ];
12948
+ /** IFC4 deprecated attributes (IFC102): entity -> attributes that must be empty. */
12949
+ var DEPRECATED_IFC4_ATTRIBUTES = {
12950
+ IFCDOORLININGPROPERTIES: ["ShapeAspectStyle"],
12951
+ IFCDOORPANELPROPERTIES: ["ShapeAspectStyle"],
12952
+ IFCFILLAREASTYLEHATCHING: ["PointOfReferenceHatchLine"],
12953
+ IFCREINFORCINGELEMENT: ["SteelGrade"],
12954
+ IFCRELASSIGNSTOACTOR: ["RelatedObjectsType"],
12955
+ IFCRELASSIGNSTOCONTROL: ["RelatedObjectsType"],
12956
+ IFCRELASSIGNSTOGROUP: ["RelatedObjectsType"],
12957
+ IFCRELASSIGNSTOGROUPBYFACTOR: ["RelatedObjectsType"],
12958
+ IFCRELASSIGNSTOPROCESS: ["RelatedObjectsType"],
12959
+ IFCRELASSIGNSTOPRODUCT: ["RelatedObjectsType"],
12960
+ IFCRELASSIGNSTORESOURCE: ["RelatedObjectsType"],
12961
+ IFCSTAIRFLIGHT: [
12962
+ "NumberOfRisers",
12963
+ "NumberOfTreads",
12964
+ "RiserHeight",
12965
+ "TreadLength"
12966
+ ],
12967
+ IFCWINDOWPANELPROPERTIES: ["ShapeAspectStyle"],
12968
+ IFCWINDOWLININGPROPERTIES: ["ShapeAspectStyle"]
12969
+ };
12970
+ function checkDeprecated(reader) {
12971
+ const issues = [];
12972
+ if (reader.schema !== "IFC4") return issues;
12973
+ for (const id of reader.getAllLines()) {
12974
+ const typeName = reader.typeNameOf(id);
12975
+ if (DEPRECATED_IFC4_ENTITIES.includes(typeName)) {
12976
+ issues.push(issue("error", "DEPRECATED_ENTITY", `#${id} ${typeName} is deprecated in IFC4 (IFC102)`, id));
12977
+ continue;
12978
+ }
12979
+ const attrs = DEPRECATED_IFC4_ATTRIBUTES[typeName];
12980
+ if (attrs === void 0) continue;
12981
+ const line = reader.getLine(id);
12982
+ if (line === null) continue;
12983
+ for (const attr of attrs) if (line[attr] !== null && line[attr] !== void 0) issues.push(issue("error", "DEPRECATED_ATTRIBUTE", `#${id} ${typeName}.${attr} is deprecated in IFC4 and must be empty (IFC102)`, id));
12984
+ }
12985
+ return issues;
12986
+ }
12987
+ function textOf(v) {
12988
+ const value = v?.value;
12989
+ return typeof value === "string" ? value : void 0;
12990
+ }
12991
+ function checkQuantitySets(reader) {
12992
+ const issues = [];
12993
+ const related = /* @__PURE__ */ new Map();
12994
+ for (const relId of reader.getLinesOfType(WebIFC.IFCRELDEFINESBYPROPERTIES)) {
12995
+ const rel = reader.getLine(relId);
12996
+ if (rel === null) continue;
12997
+ const target = rel["RelatingPropertyDefinition"]?.value;
12998
+ if (typeof target !== "number") continue;
12999
+ const objects = rel["RelatedObjects"];
13000
+ if (!Array.isArray(objects)) continue;
13001
+ const names = objects.map((o) => o.value).filter((v) => typeof v === "number").map((id) => reader.typeNameOf(id));
13002
+ related.set(target, [...related.get(target) ?? [], ...names]);
13003
+ }
13004
+ for (const id of reader.getLinesOfType(WebIFC.IFCELEMENTQUANTITY)) {
13005
+ const line = reader.getLine(id);
13006
+ if (line === null) continue;
13007
+ const name = textOf(line["Name"]);
13008
+ if (name === void 0 || !name.startsWith("Qto_")) continue;
13009
+ const definition = QTO_DEFINITIONS[name];
13010
+ if (definition === void 0) {
13011
+ issues.push(issue("error", "QTO_UNKNOWN_SET", `#${id} '${name}' is not a standard quantity set (QTY001)`, id));
13012
+ continue;
13013
+ }
13014
+ if (textOf(line["MethodOfMeasurement"]) !== "BaseQuantities") issues.push(issue("error", "QTO_METHOD", `#${id} '${name}' must declare MethodOfMeasurement='BaseQuantities' (QTY001)`, id));
13015
+ for (const entity of related.get(id) ?? []) if (!definition.entities.includes(entity)) issues.push(issue("error", "QTO_WRONG_ENTITY", `#${id} '${name}' is not applicable to ${entity} (QTY001)`, id));
13016
+ const quantities = line["Quantities"];
13017
+ if (!Array.isArray(quantities)) continue;
13018
+ for (const q of quantities) {
13019
+ const qid = q.value;
13020
+ if (typeof qid !== "number") continue;
13021
+ const qName = textOf(reader.getLine(qid)?.["Name"]);
13022
+ if (qName === void 0) continue;
13023
+ const expectedType = definition.quantities[qName];
13024
+ if (expectedType === void 0) issues.push(issue("error", "QTO_UNKNOWN_QUANTITY", `#${qid} '${qName}' is not defined in ${name} (QTY001)`, qid));
13025
+ else if (reader.typeNameOf(qid) !== expectedType) issues.push(issue("error", "QTO_WRONG_TYPE", `#${qid} '${qName}' must be a ${expectedType} (QTY001)`, qid));
13026
+ }
13027
+ }
13028
+ return issues;
13029
+ }
13030
+ function checkGeoreferencing(reader) {
13031
+ if (!(reader.getLinesOfType(WebIFC.IFCBUILDING).length > 0)) return [];
13032
+ if (reader.getLinesOfType(WebIFC.IFCPROJECTEDCRS).length > 0 || reader.getLinesOfType(WebIFC.IFCGEOGRAPHICCRS).length > 0) return [];
13033
+ return [issue("warning", "NO_GEOREFERENCING", "Model contains a facility but no IfcProjectedCRS/IfcGeographicCRS (GRF003) — set ProjectSpec.crs")];
13034
+ }
13035
+ //#endregion
12048
13036
  //#region src/serialize/toIfc.ts
12049
13037
  async function toIfc(model, meta) {
12050
13038
  const project = model.getProject();
@@ -12078,7 +13066,8 @@ async function toIfc(model, meta) {
12078
13066
  const assemblies = model.getElementAssemblies();
12079
13067
  const zones = model.getZones();
12080
13068
  const systems = model.getSystems();
12081
- const { ownerHistoryId, geomContextId, geomSubContextId, unitAssignmentId } = writeHeader(w, meta);
13069
+ const { ownerHistoryId, geomContextId, geomSubContextId, unitAssignmentId, lengthUnitId } = writeHeader(w, meta);
13070
+ if (project.spec.crs !== void 0) writeMapConversion(w, project.spec.crs, geomContextId, lengthUnitId);
12082
13071
  const densityByElement = buildDensityMap(relationships);
12083
13072
  const idMap = /* @__PURE__ */ new Map();
12084
13073
  const placementMap = /* @__PURE__ */ new Map();
@@ -12579,11 +13568,13 @@ async function toIfcValidated(model, meta) {
12579
13568
  const geometry = collectGeometryIssues(model);
12580
13569
  const schema = await checkSchema(bytes);
12581
13570
  const roundTrip = await checkRoundTrip(bytes);
13571
+ const gherkin = await checkGherkinRules(bytes);
12582
13572
  const report = { issues: [
12583
13573
  ...integrity.issues,
12584
13574
  ...geometry.issues,
12585
13575
  ...schema.issues,
12586
- ...roundTrip.issues
13576
+ ...roundTrip.issues,
13577
+ ...gherkin
12587
13578
  ] };
12588
13579
  return ok({
12589
13580
  bytes,
@@ -12668,149 +13659,6 @@ function findContainerOf(elementId, relationships) {
12668
13659
  return null;
12669
13660
  }
12670
13661
  //#endregion
12671
- //#region src/import/spfReader.ts
12672
- var SUPPORTED_SCHEMAS = [
12673
- "IFC2X3",
12674
- "IFC4",
12675
- "IFC4X3"
12676
- ];
12677
- /**
12678
- * Foundation layer of the IFC reader: owns the web-ifc WASM model handle and
12679
- * exposes typed line access, GUID↔expressId lookup, world-transform composition,
12680
- * geometry-engine access and STEP string decoding.
12681
- *
12682
- * Lifecycle: created via the static async {@link SpfReader.create}; the caller
12683
- * MUST call {@link SpfReader.close} (it always issues `CloseModel`, preventing
12684
- * WASM handle leaks). The handle is `using`-friendly via `Symbol.dispose`.
12685
- */
12686
- function deleteVector(vec) {
12687
- vec.delete?.();
12688
- }
12689
- var SpfReader = class SpfReader {
12690
- schema;
12691
- modelId;
12692
- #api;
12693
- #closed = false;
12694
- #linesByType = /* @__PURE__ */ new Map();
12695
- constructor(api, modelId, schema) {
12696
- this.#api = api;
12697
- this.modelId = modelId;
12698
- this.schema = schema;
12699
- }
12700
- static async create(bytes, settings = {}) {
12701
- let api;
12702
- try {
12703
- api = new IfcAPI();
12704
- await initIfcApi(api);
12705
- } catch (e) {
12706
- return err(importError("OPEN_MODEL_FAILED", "Failed to initialize web-ifc", e));
12707
- }
12708
- let modelId;
12709
- try {
12710
- modelId = api.OpenModel(bytes, { COORDINATE_TO_ORIGIN: settings.coordinateToOrigin ?? false });
12711
- } catch (e) {
12712
- return err(importError("OPEN_MODEL_FAILED", "web-ifc OpenModel threw", e));
12713
- }
12714
- if (modelId < 0 || !api.IsModelOpen(modelId)) {
12715
- if (modelId >= 0) api.CloseModel(modelId);
12716
- return err(importError("OPEN_MODEL_FAILED", "web-ifc OpenModel returned an invalid model id"));
12717
- }
12718
- const schemaRaw = api.GetModelSchema(modelId);
12719
- if (!SUPPORTED_SCHEMAS.includes(schemaRaw)) {
12720
- api.CloseModel(modelId);
12721
- return err(importError("SCHEMA_UNSUPPORTED", `Unsupported IFC schema "${schemaRaw}"`));
12722
- }
12723
- return ok(new SpfReader(api, modelId, schemaRaw));
12724
- }
12725
- /** Always issues CloseModel; safe to call more than once. */
12726
- close() {
12727
- if (this.#closed) return;
12728
- this.#closed = true;
12729
- this.#api.CloseModel(this.modelId);
12730
- }
12731
- [Symbol.dispose]() {
12732
- this.close();
12733
- }
12734
- /**
12735
- * Raw line object for an express id. With `flatten=false` (default) references
12736
- * appear as `{ type, value }` wrappers and nested entities are not resolved;
12737
- * pass `flatten=true` to recursively inline referenced lines.
12738
- */
12739
- getLine(expressId, flatten = false) {
12740
- return this.#api.GetLine(this.modelId, expressId, flatten) ?? null;
12741
- }
12742
- /** Express ids of every line whose type equals `type` (no inherited types). */
12743
- getLinesOfType(type) {
12744
- const cached = this.#linesByType.get(type);
12745
- if (cached !== void 0) return cached;
12746
- const vec = this.#api.GetLineIDsWithType(this.modelId, type);
12747
- const out = [];
12748
- for (let i = 0; i < vec.size(); i++) out.push(vec.get(i));
12749
- deleteVector(vec);
12750
- this.#linesByType.set(type, out);
12751
- return out;
12752
- }
12753
- /** Express ids of every line in the model. */
12754
- getAllLines() {
12755
- const vec = this.#api.GetAllLines(this.modelId);
12756
- const out = [];
12757
- for (let i = 0; i < vec.size(); i++) out.push(vec.get(i));
12758
- deleteVector(vec);
12759
- return out;
12760
- }
12761
- /** IFC type code for an express id. */
12762
- /** Uppercased IFC entity name of the instance (e.g. `IFCWALL`). */
12763
- typeNameOf(expressId) {
12764
- return this.#api.GetNameFromTypeCode(this.getLineType(expressId)).toUpperCase();
12765
- }
12766
- getLineType(expressId) {
12767
- const t = this.#api.GetLineType(this.modelId, expressId);
12768
- return typeof t === "number" ? t : Number(t?.value ?? t);
12769
- }
12770
- /** Builds web-ifc's internal GUID→expressId index; call before guid lookups. */
12771
- buildGuidMap() {
12772
- this.#api.CreateIfcGuidToExpressIdMapping(this.modelId);
12773
- }
12774
- /** expressId for a GlobalId, or undefined. Requires {@link buildGuidMap} first. */
12775
- expressIdFromGuid(guid) {
12776
- const id = this.#api.GetExpressIdFromGuid(this.modelId, guid);
12777
- return typeof id === "number" ? id : void 0;
12778
- }
12779
- /** GlobalId for an express id, or undefined. Requires {@link buildGuidMap} first. */
12780
- guidFromExpressId(expressId) {
12781
- const guid = this.#api.GetGuidFromExpressId(this.modelId, expressId);
12782
- return typeof guid === "string" ? guid : void 0;
12783
- }
12784
- /**
12785
- * Composed world transform (column-major 16-float matrix) for a placement
12786
- * express id, resolving the full IfcLocalPlacement chain.
12787
- */
12788
- getWorldTransform(placementExpressId) {
12789
- return this.#api.GetWorldTransformMatrix(this.modelId, placementExpressId);
12790
- }
12791
- /** Streams placed meshes for the given product express ids. */
12792
- streamMeshes(expressIds, cb) {
12793
- this.#api.StreamMeshes(this.modelId, expressIds, cb);
12794
- }
12795
- /** Geometry buffers for a geometry express id; caller MUST call `.delete()`. */
12796
- getGeometry(geometryExpressId) {
12797
- return this.#api.GetGeometry(this.modelId, geometryExpressId);
12798
- }
12799
- /** Reads a Float32Array view of vertex data from a WASM pointer. */
12800
- getVertexArray(ptr, size) {
12801
- return this.#api.GetVertexArray(ptr, size);
12802
- }
12803
- /** Reads a Uint32Array view of index data from a WASM pointer. */
12804
- getIndexArray(ptr, size) {
12805
- return this.#api.GetIndexArray(ptr, size);
12806
- }
12807
- /** Decodes IFC STEP string escapes (`\X2\`, `\S\`, `\X\`) in a raw value. */
12808
- decodeText(s) {
12809
- const decoded = this.#api.DecodeText(s);
12810
- return typeof decoded === "string" ? decoded : s;
12811
- }
12812
- };
12813
- //#endregion
12814
13662
  //#region src/import/spatialTree.ts
12815
13663
  var CATEGORY_BY_TYPE = /* @__PURE__ */ new Map([
12816
13664
  [WebIFC.IFCPROJECT, "PROJECT"],
@@ -26994,4 +27842,4 @@ function familiesToBim(root, options) {
26994
27842
  });
26995
27843
  }
26996
27844
  //#endregion
26997
- export { BimModel, DEFAULT_IFC_SCHEMA, DEFAULT_UNITS, IFC_SCHEMAS, PSET_PROPERTY_TYPE_TABLE, PSET_TEMPLATES, SpfReader, bcfError, checkGeometryValidity, checkIdsData as checkIds, checkIdsData, checkReferentialIntegrity, checkRoundTrip, checkSchema, countBySeverity, deriveCobieModel, deriveCobieModel as exportCobie, deriveIfcGuid, deriveIfcGuidSync, disposeImportedModel, emptyReport, extendedProfileArea, extendedProfileToFace, familiesToBim, fileSchemaString, fromBrepError, fromIfc, geometryError, hasErrors, idsError, ifcError, importError, isExtendedProfile, isIfcSchema, isSlabOpening, isValidIfcGuid, isWallOpening, issue, makeLocalIdCounter, measureTypeFor, newIfcGuid, parseBcfFiles, parseBeamSpec, parseColumnSpec, parseCoveringSpec, parseCurtainWallSpec, parseDoorSpec, parseElementAssemblySpec, parseFootingSpec, parseIdsXml, parsePileSpec, parseProfile, parseRailingSpec, parseRampFlightSpec, parseRampSpec, parseRoofSpec, parseSlabOpeningInput, parseSlabSpec, parseSpaceSpec, parseStairFlightSpec, parseStairSpec, parseSurfaceStyleSpec, parseSystemSpec, parseWallSpec, parseWindowSpec, parseZoneSpec, placedSolids, schemaSupports, serializeBcfFiles, serializeCobieToCsv, serializeCobieToJson, setIfcWasmLocateFile, specError, templateFor, toIfc, toIfcLengthM, toIfcValidated, toLengthMm, writeClassificationRefs, writeElementAssemblyEntity, writeIfcType, writeMaterialLayerSet, writeMaterialProfileSet, writeMaterialSimple, writePresentationLayer, writeRelAggregatesElements, writeRelAssignsToGroup, writeRelConnectsElements, writeRelConnectsPathElements, writeRelNests, writeStyledItem, writeSurfaceStyle, writeSystemEntity, writeZoneEntity };
27845
+ export { BimModel, DEFAULT_IFC_SCHEMA, DEFAULT_UNITS, IFC_SCHEMAS, PSET_PROPERTY_TYPE_TABLE, PSET_TEMPLATES, SpfReader, bcfError, checkGeometryValidity, checkGherkinRules, checkIdsData as checkIds, checkIdsData, checkReferentialIntegrity, checkRoundTrip, checkSchema, countBySeverity, deriveCobieModel, deriveCobieModel as exportCobie, deriveIfcGuid, deriveIfcGuidSync, disposeImportedModel, emptyReport, extendedProfileArea, extendedProfileToFace, familiesToBim, fileSchemaString, fromBrepError, fromIfc, geometryError, hasErrors, idsError, ifcError, importError, isExtendedProfile, isIfcSchema, isSlabOpening, isValidIfcGuid, isWallOpening, issue, makeLocalIdCounter, measureTypeFor, newIfcGuid, parseBcfFiles, parseBeamSpec, parseColumnSpec, parseCoveringSpec, parseCurtainWallSpec, parseDoorSpec, parseElementAssemblySpec, parseFootingSpec, parseIdsXml, parsePileSpec, parseProfile, parseRailingSpec, parseRampFlightSpec, parseRampSpec, parseRoofSpec, parseSlabOpeningInput, parseSlabSpec, parseSpaceSpec, parseStairFlightSpec, parseStairSpec, parseSurfaceStyleSpec, parseSystemSpec, parseWallSpec, parseWindowSpec, parseZoneSpec, placedSolids, schemaSupports, serializeBcfFiles, serializeCobieToCsv, serializeCobieToJson, setIfcWasmLocateFile, specError, templateFor, toIfc, toIfcLengthM, toIfcValidated, toLengthMm, writeClassificationRefs, writeElementAssemblyEntity, writeIfcType, writeMaterialLayerSet, writeMaterialProfileSet, writeMaterialSimple, writePresentationLayer, writeRelAggregatesElements, writeRelAssignsToGroup, writeRelConnectsElements, writeRelConnectsPathElements, writeRelNests, writeStyledItem, writeSurfaceStyle, writeSystemEntity, writeZoneEntity };