@bldrs-ai/conway 1.344.1099 → 1.347.1107

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.
Files changed (25) hide show
  1. package/compiled/examples/browser-bundled.cjs +1 -1
  2. package/compiled/examples/cli-bundled.cjs +1 -1
  3. package/compiled/examples/cli-step-bundled.cjs +1 -1
  4. package/compiled/examples/validator-bundled.cjs +1 -1
  5. package/compiled/src/AP214E3_2010/ap214_product_structure_extraction.d.ts +144 -0
  6. package/compiled/src/AP214E3_2010/ap214_product_structure_extraction.d.ts.map +1 -0
  7. package/compiled/src/AP214E3_2010/ap214_product_structure_extraction.js +236 -0
  8. package/compiled/src/AP214E3_2010/ap214_product_structure_extraction.test.d.ts +2 -0
  9. package/compiled/src/AP214E3_2010/ap214_product_structure_extraction.test.d.ts.map +1 -0
  10. package/compiled/src/AP214E3_2010/ap214_product_structure_extraction.test.js +107 -0
  11. package/compiled/src/AP214E3_2010/ap214_property_extraction.d.ts +90 -0
  12. package/compiled/src/AP214E3_2010/ap214_property_extraction.d.ts.map +1 -0
  13. package/compiled/src/AP214E3_2010/ap214_property_extraction.js +143 -0
  14. package/compiled/src/AP214E3_2010/ap214_property_extraction.test.d.ts +2 -0
  15. package/compiled/src/AP214E3_2010/ap214_property_extraction.test.d.ts.map +1 -0
  16. package/compiled/src/AP214E3_2010/ap214_property_extraction.test.js +56 -0
  17. package/compiled/src/compat/web-ifc/ap214_properties.d.ts +140 -13
  18. package/compiled/src/compat/web-ifc/ap214_properties.d.ts.map +1 -1
  19. package/compiled/src/compat/web-ifc/ap214_properties.js +267 -26
  20. package/compiled/src/compat/web-ifc/ap214_properties.test.d.ts +2 -0
  21. package/compiled/src/compat/web-ifc/ap214_properties.test.d.ts.map +1 -0
  22. package/compiled/src/compat/web-ifc/ap214_properties.test.js +85 -0
  23. package/compiled/src/version/version.js +1 -1
  24. package/compiled/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +1 -1
@@ -69608,7 +69608,7 @@ var IfcStepParser = class extends StepParser {
69608
69608
  IfcStepParser.Instance = new IfcStepParser();
69609
69609
 
69610
69610
  // compiled/src/version/version.js
69611
- var versionString = "Conway Web-Ifc Shim v1.344.1099";
69611
+ var versionString = "Conway Web-Ifc Shim v1.347.1107";
69612
69612
 
69613
69613
  // compiled/src/statistics/statistics.js
69614
69614
  var Statistics = class {
@@ -85869,7 +85869,7 @@ var IfcSceneBuilder = class {
85869
85869
  };
85870
85870
 
85871
85871
  // compiled/src/version/version.js
85872
- var versionString = "Conway Web-Ifc Shim v1.344.1099";
85872
+ var versionString = "Conway Web-Ifc Shim v1.347.1107";
85873
85873
 
85874
85874
  // compiled/src/statistics/statistics.js
85875
85875
  var Statistics = class {
@@ -79320,7 +79320,7 @@ var ExtractResult;
79320
79320
  })(ExtractResult || (ExtractResult = {}));
79321
79321
 
79322
79322
  // compiled/src/version/version.js
79323
- var versionString = "Conway Web-Ifc Shim v1.344.1099";
79323
+ var versionString = "Conway Web-Ifc Shim v1.347.1107";
79324
79324
 
79325
79325
  // compiled/src/statistics/statistics.js
79326
79326
  var Statistics = class {
@@ -69606,7 +69606,7 @@ var IfcStepParser = class extends StepParser {
69606
69606
  IfcStepParser.Instance = new IfcStepParser();
69607
69607
 
69608
69608
  // compiled/src/version/version.js
69609
- var versionString = "Conway Web-Ifc Shim v1.344.1099";
69609
+ var versionString = "Conway Web-Ifc Shim v1.347.1107";
69610
69610
 
69611
69611
  // compiled/src/statistics/statistics.js
69612
69612
  var Statistics = class {
@@ -0,0 +1,144 @@
1
+ import AP214StepModel from "./ap214_step_model.js";
2
+ import { AP214ProductShapeMap } from "./ap214_product_shape_map.js";
3
+ /**
4
+ * A node in the extracted STEP product / assembly structure.
5
+ *
6
+ * The structure is *occurrence*-keyed, not product-keyed: STEP instancing lets
7
+ * one `product_definition` (a part *type*) appear many times in an assembly via
8
+ * distinct `next_assembly_usage_occurrence` (NAUO) edges. A scalar express id of
9
+ * the product cannot tell two visual instances apart, so each occurrence node
10
+ * carries both its NAUO express id (`expressID`) and the ordered
11
+ * `occurrencePath` (root→node, NAUO ids) that is the stable
12
+ * selection / permalink token. See
13
+ * `design/new/step-metadata-nist.md` §"Occurrence identity".
14
+ *
15
+ * This is the forcing function for Share's goal of generalizing its scalar
16
+ * `expressID` selection key into a format-agnostic *occurrence path* — flag it
17
+ * wherever this tree is consumed Share-side.
18
+ */
19
+ export interface ProductStructureNode {
20
+ /**
21
+ * Node selection key. For an occurrence node this is the NAUO express id; for
22
+ * a root (single-part files have no NAUO) it falls back to the
23
+ * `product_definition` express id.
24
+ */
25
+ expressID: number;
26
+ /** Readable node kind: `'product'` for roots, `'product_occurrence'` for NAUO nodes. */
27
+ type: string;
28
+ /** Display label: `product.name`, falling back to the NAUO name / reference designator. */
29
+ name: string;
30
+ /** Express id of the underlying `product_definition` (the part *type*). */
31
+ productDefinitionExpressID: number;
32
+ /** NAUO express id for occurrence nodes; `undefined` for roots. */
33
+ occurrenceExpressID?: number;
34
+ /**
35
+ * Ordered occurrence path (NAUO express ids) from the top-level occurrence to
36
+ * this node. Empty for roots. Disambiguates instances of the same part — e.g.
37
+ * `[3810, 1921, 1910]` vs `[6217, 1921, 1910]` for the two bolts in `as1`.
38
+ */
39
+ occurrencePath: number[];
40
+ /**
41
+ * Shape representation express ids linked to this part (via
42
+ * `product_definition_shape` → `shape_definition_representation`). The seam to
43
+ * scene geometry for NavTree-click ⇄ viewport-pick round-tripping.
44
+ */
45
+ shapeRepresentationIds: number[];
46
+ /** Child occurrence nodes. */
47
+ children: ProductStructureNode[];
48
+ }
49
+ /**
50
+ * Extracts the STEP product / assembly structure from a populated
51
+ * {@link AP214StepModel} into a nested, named, occurrence-keyed tree.
52
+ *
53
+ * Mirrors the IFC precedent (`src/ifc/ifc_property_extraction.ts`) but for
54
+ * AP214/AP242: walks `product` / `product_definition` /
55
+ * `next_assembly_usage_occurrence` into a tree, resolves labels from
56
+ * `product.name`, and links each part to its shape representations so a NavTree
57
+ * node can highlight the right geometry instance.
58
+ */
59
+ export declare class AP214ProductStructureExtraction {
60
+ private readonly model;
61
+ private readonly productShapeMap?;
62
+ private readonly nauosByParent_;
63
+ private readonly childProductDefIds_;
64
+ private readonly productDefById_;
65
+ private readonly shapeRepsByProductDef_;
66
+ /**
67
+ * @param model The populated AP214/AP242 step model to walk.
68
+ * @param productShapeMap Optional product↔shape map populated during geometry
69
+ * extraction. When provided its links are merged with the ones derived here so
70
+ * the tree's `shapeRepresentationIds` agree with the scene; the map is empty
71
+ * unless geometry extraction has run, so the entity-graph walk below is the
72
+ * primary source.
73
+ */
74
+ constructor(model: AP214StepModel, productShapeMap?: AP214ProductShapeMap | undefined);
75
+ /**
76
+ * Build the product-structure tree.
77
+ *
78
+ * @return {ProductStructureNode[]} The roots of the assembly forest. A
79
+ * single-part file yields one root; a multi-level assembly (e.g. `as1`) yields
80
+ * one root whose descendants are the NAUO occurrences.
81
+ */
82
+ extractProductStructure(): ProductStructureNode[];
83
+ /**
84
+ * Index every `product_definition` by express id for O(1) lookup during the
85
+ * recursive walk.
86
+ */
87
+ private indexProductDefinitions;
88
+ /**
89
+ * Index every NAUO by its parent (`relating_product_definition`) express id
90
+ * and record which product definitions appear as a child
91
+ * (`related_product_definition`) so roots can be identified.
92
+ */
93
+ private indexAssemblyUsages;
94
+ /**
95
+ * Link product definitions to their shape representations by walking
96
+ * `shape_definition_representation` → `product_definition_shape` →
97
+ * `product_definition`, and merge any links already present in the
98
+ * geometry-extraction product↔shape map.
99
+ */
100
+ private indexShapeRepresentations;
101
+ /**
102
+ * Record a shape-representation id for a product definition, de-duplicating.
103
+ *
104
+ * @param productDefId The product definition express id.
105
+ * @param shapeId The shape representation express id to associate.
106
+ */
107
+ private addShapeRepresentation;
108
+ /**
109
+ * Recursively build a tree node for one product-definition occurrence.
110
+ *
111
+ * @param productDef The product definition this node represents.
112
+ * @param occurrence The NAUO edge that introduced this occurrence, or
113
+ * `undefined` for a root.
114
+ * @param parentPath The occurrence path of the parent node (NAUO ids).
115
+ * @param onPath Product-definition ids currently on the recursion stack;
116
+ * guards against a malformed cyclic assembly causing infinite recursion (a
117
+ * legitimately re-used part in sibling branches is unaffected).
118
+ * @return {ProductStructureNode} The built node, with children.
119
+ */
120
+ private buildNode;
121
+ /**
122
+ * Resolve a node label, preferring the product name, then the occurrence's
123
+ * own name / reference designator.
124
+ *
125
+ * @param productDef The product definition for the node.
126
+ * @param occurrence The NAUO edge, when this is an occurrence node.
127
+ * @return {string} The best available human-readable label.
128
+ */
129
+ private resolveLabel;
130
+ /**
131
+ * Resolve the owning `product_definition` express id from a
132
+ * `property_definition`-style `definition` select. Handles the direct
133
+ * `product_definition` case and the `product_definition_shape` indirection
134
+ * (its own `definition` points at the product definition).
135
+ *
136
+ * @param definition The resolved `definition` reference, or `undefined`.
137
+ * @return {number | undefined} The product definition express id, or
138
+ * `undefined` if it does not resolve to one.
139
+ */
140
+ static resolveProductDefinitionId(definition: {
141
+ expressID?: number;
142
+ } | undefined): number | undefined;
143
+ }
144
+ //# sourceMappingURL=ap214_product_structure_extraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ap214_product_structure_extraction.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_product_structure_extraction.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAOhE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,oBAAoB;IAEnC;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;IAEjB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAA;IAEZ,2FAA2F;IAC3F,IAAI,EAAE,MAAM,CAAA;IAEZ,2EAA2E;IAC3E,0BAA0B,EAAE,MAAM,CAAA;IAElC,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAE5B;;;;OAIG;IACH,cAAc,EAAE,MAAM,EAAE,CAAA;IAExB;;;;OAIG;IACH,sBAAsB,EAAE,MAAM,EAAE,CAAA;IAEhC,8BAA8B;IAC9B,QAAQ,EAAE,oBAAoB,EAAE,CAAA;CACjC;AAMD;;;;;;;;;GASG;AACH,qBAAa,+BAA+B;IAgBtC,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC;IAfrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsD;IACrF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAoB;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwC;IACxE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA8B;IAErE;;;;;;;OAOG;gBAEkB,KAAK,EAAE,cAAc,EACrB,eAAe,CAAC,kCAAsB;IAG3D;;;;;;OAMG;IACI,uBAAuB,IAAI,oBAAoB,EAAE;IA6BxD;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAa/B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IAiCjC;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAc9B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,SAAS;IAsDjB;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IA0BpB;;;;;;;;;OASG;IACH,MAAM,CAAC,0BAA0B,CAC7B,UAAU,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,GAAI,MAAM,GAAG,SAAS;CAgBzE"}
@@ -0,0 +1,236 @@
1
+ import { next_assembly_usage_occurrence } from "./AP214E3_2010_gen/next_assembly_usage_occurrence.gen.js";
2
+ import { product_definition } from "./AP214E3_2010_gen/product_definition.gen.js";
3
+ import { product_definition_shape } from "./AP214E3_2010_gen/product_definition_shape.gen.js";
4
+ import { shape_definition_representation } from "./AP214E3_2010_gen/shape_definition_representation.gen.js";
5
+ /** Readable node-kind strings for {@link ProductStructureNode.type}. */
6
+ const ROOT_NODE_TYPE = "product";
7
+ const OCCURRENCE_NODE_TYPE = "product_occurrence";
8
+ /**
9
+ * Extracts the STEP product / assembly structure from a populated
10
+ * {@link AP214StepModel} into a nested, named, occurrence-keyed tree.
11
+ *
12
+ * Mirrors the IFC precedent (`src/ifc/ifc_property_extraction.ts`) but for
13
+ * AP214/AP242: walks `product` / `product_definition` /
14
+ * `next_assembly_usage_occurrence` into a tree, resolves labels from
15
+ * `product.name`, and links each part to its shape representations so a NavTree
16
+ * node can highlight the right geometry instance.
17
+ */
18
+ export class AP214ProductStructureExtraction {
19
+ /**
20
+ * @param model The populated AP214/AP242 step model to walk.
21
+ * @param productShapeMap Optional product↔shape map populated during geometry
22
+ * extraction. When provided its links are merged with the ones derived here so
23
+ * the tree's `shapeRepresentationIds` agree with the scene; the map is empty
24
+ * unless geometry extraction has run, so the entity-graph walk below is the
25
+ * primary source.
26
+ */
27
+ constructor(model, productShapeMap) {
28
+ this.model = model;
29
+ this.productShapeMap = productShapeMap;
30
+ this.nauosByParent_ = new Map();
31
+ this.childProductDefIds_ = new Set();
32
+ this.productDefById_ = new Map();
33
+ this.shapeRepsByProductDef_ = new Map();
34
+ }
35
+ /**
36
+ * Build the product-structure tree.
37
+ *
38
+ * @return {ProductStructureNode[]} The roots of the assembly forest. A
39
+ * single-part file yields one root; a multi-level assembly (e.g. `as1`) yields
40
+ * one root whose descendants are the NAUO occurrences.
41
+ */
42
+ extractProductStructure() {
43
+ this.indexProductDefinitions();
44
+ this.indexAssemblyUsages();
45
+ this.indexShapeRepresentations();
46
+ const roots = [];
47
+ for (const [productDefId, productDef] of this.productDefById_) {
48
+ if (this.childProductDefIds_.has(productDefId)) {
49
+ continue;
50
+ }
51
+ // A genuine root is a part: it has geometry and/or sub-assembly children.
52
+ // This excludes stray product_definitions referenced only by metadata.
53
+ const hasChildren = this.nauosByParent_.has(productDefId);
54
+ const hasShape = this.shapeRepsByProductDef_.has(productDefId);
55
+ if (!hasChildren && !hasShape) {
56
+ continue;
57
+ }
58
+ roots.push(this.buildNode(productDef, undefined, [], new Set()));
59
+ }
60
+ return roots;
61
+ }
62
+ /**
63
+ * Index every `product_definition` by express id for O(1) lookup during the
64
+ * recursive walk.
65
+ */
66
+ indexProductDefinitions() {
67
+ for (const element of this.model.types(product_definition)) {
68
+ const productDef = element;
69
+ const expressID = productDef.expressID;
70
+ if (expressID !== void 0) {
71
+ this.productDefById_.set(expressID, productDef);
72
+ }
73
+ }
74
+ }
75
+ /**
76
+ * Index every NAUO by its parent (`relating_product_definition`) express id
77
+ * and record which product definitions appear as a child
78
+ * (`related_product_definition`) so roots can be identified.
79
+ */
80
+ indexAssemblyUsages() {
81
+ for (const element of this.model.types(next_assembly_usage_occurrence)) {
82
+ const nauo = element;
83
+ const parentId = nauo.relating_product_definition?.expressID;
84
+ const childId = nauo.related_product_definition?.expressID;
85
+ if (parentId === void 0 || childId === void 0) {
86
+ continue;
87
+ }
88
+ this.childProductDefIds_.add(childId);
89
+ let siblings = this.nauosByParent_.get(parentId);
90
+ if (siblings === void 0) {
91
+ siblings = [];
92
+ this.nauosByParent_.set(parentId, siblings);
93
+ }
94
+ siblings.push(nauo);
95
+ }
96
+ }
97
+ /**
98
+ * Link product definitions to their shape representations by walking
99
+ * `shape_definition_representation` → `product_definition_shape` →
100
+ * `product_definition`, and merge any links already present in the
101
+ * geometry-extraction product↔shape map.
102
+ */
103
+ indexShapeRepresentations() {
104
+ for (const element of this.model.types(shape_definition_representation)) {
105
+ const sdr = element;
106
+ const productDefId = AP214ProductStructureExtraction.resolveProductDefinitionId(sdr.definition);
107
+ if (productDefId === void 0) {
108
+ continue;
109
+ }
110
+ // The shape id is the *used_representation* (the geometry), not the SDR's
111
+ // own id — falling back to `sdr.expressID` would store a non-geometry id
112
+ // that a pick-reconciliation consumer could not resolve to a scene mesh.
113
+ const shapeId = sdr.used_representation?.expressID;
114
+ if (shapeId !== void 0) {
115
+ this.addShapeRepresentation(productDefId, shapeId);
116
+ }
117
+ }
118
+ if (this.productShapeMap === void 0) {
119
+ return;
120
+ }
121
+ for (const [productDefId, shapes] of this.productShapeMap.productDefsToShapes()) {
122
+ for (const shapeId of shapes) {
123
+ this.addShapeRepresentation(productDefId, shapeId);
124
+ }
125
+ }
126
+ }
127
+ /**
128
+ * Record a shape-representation id for a product definition, de-duplicating.
129
+ *
130
+ * @param productDefId The product definition express id.
131
+ * @param shapeId The shape representation express id to associate.
132
+ */
133
+ addShapeRepresentation(productDefId, shapeId) {
134
+ let shapes = this.shapeRepsByProductDef_.get(productDefId);
135
+ if (shapes === void 0) {
136
+ shapes = [];
137
+ this.shapeRepsByProductDef_.set(productDefId, shapes);
138
+ }
139
+ if (!shapes.includes(shapeId)) {
140
+ shapes.push(shapeId);
141
+ }
142
+ }
143
+ /**
144
+ * Recursively build a tree node for one product-definition occurrence.
145
+ *
146
+ * @param productDef The product definition this node represents.
147
+ * @param occurrence The NAUO edge that introduced this occurrence, or
148
+ * `undefined` for a root.
149
+ * @param parentPath The occurrence path of the parent node (NAUO ids).
150
+ * @param onPath Product-definition ids currently on the recursion stack;
151
+ * guards against a malformed cyclic assembly causing infinite recursion (a
152
+ * legitimately re-used part in sibling branches is unaffected).
153
+ * @return {ProductStructureNode} The built node, with children.
154
+ */
155
+ buildNode(productDef, occurrence, parentPath, onPath) {
156
+ const productDefId = productDef.expressID;
157
+ const label = this.resolveLabel(productDef, occurrence);
158
+ const occurrenceExpressID = occurrence?.expressID;
159
+ const occurrencePath = occurrenceExpressID !== void 0 ?
160
+ [...parentPath, occurrenceExpressID] : [...parentPath];
161
+ const node = {
162
+ expressID: occurrenceExpressID ?? productDefId,
163
+ type: occurrence !== void 0 ? OCCURRENCE_NODE_TYPE : ROOT_NODE_TYPE,
164
+ name: label,
165
+ productDefinitionExpressID: productDefId,
166
+ occurrenceExpressID,
167
+ occurrencePath,
168
+ shapeRepresentationIds: this.shapeRepsByProductDef_.get(productDefId) ?? [],
169
+ children: [],
170
+ };
171
+ const childUsages = this.nauosByParent_.get(productDefId);
172
+ if (childUsages === void 0 || onPath.has(productDefId)) {
173
+ return node;
174
+ }
175
+ onPath.add(productDefId);
176
+ for (const childUsage of childUsages) {
177
+ const childDefId = childUsage.related_product_definition?.expressID;
178
+ if (childDefId === void 0) {
179
+ continue;
180
+ }
181
+ const childDef = this.productDefById_.get(childDefId);
182
+ if (childDef === void 0) {
183
+ continue;
184
+ }
185
+ node.children.push(this.buildNode(childDef, childUsage, occurrencePath, onPath));
186
+ }
187
+ onPath.delete(productDefId);
188
+ return node;
189
+ }
190
+ /**
191
+ * Resolve a node label, preferring the product name, then the occurrence's
192
+ * own name / reference designator.
193
+ *
194
+ * @param productDef The product definition for the node.
195
+ * @param occurrence The NAUO edge, when this is an occurrence node.
196
+ * @return {string} The best available human-readable label.
197
+ */
198
+ resolveLabel(productDef, occurrence) {
199
+ const productName = productDef.formation?.of_product?.name;
200
+ if (productName !== void 0 && productName.length > 0) {
201
+ return productName;
202
+ }
203
+ if (occurrence !== void 0) {
204
+ if (occurrence.name.length > 0) {
205
+ return occurrence.name;
206
+ }
207
+ const referenceDesignator = occurrence.reference_designator;
208
+ if (referenceDesignator !== null && referenceDesignator.length > 0) {
209
+ return referenceDesignator;
210
+ }
211
+ }
212
+ return productDef.name ?? "";
213
+ }
214
+ /**
215
+ * Resolve the owning `product_definition` express id from a
216
+ * `property_definition`-style `definition` select. Handles the direct
217
+ * `product_definition` case and the `product_definition_shape` indirection
218
+ * (its own `definition` points at the product definition).
219
+ *
220
+ * @param definition The resolved `definition` reference, or `undefined`.
221
+ * @return {number | undefined} The product definition express id, or
222
+ * `undefined` if it does not resolve to one.
223
+ */
224
+ static resolveProductDefinitionId(definition) {
225
+ if (definition === void 0) {
226
+ return void 0;
227
+ }
228
+ if (definition instanceof product_definition) {
229
+ return definition.expressID;
230
+ }
231
+ if (definition instanceof product_definition_shape) {
232
+ return AP214ProductStructureExtraction.resolveProductDefinitionId(definition.definition);
233
+ }
234
+ return void 0;
235
+ }
236
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ap214_product_structure_extraction.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ap214_product_structure_extraction.test.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_product_structure_extraction.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import fs from "fs";
2
+ import { describe, expect, test } from "@jest/globals";
3
+ import AP214StepParser from "./ap214_step_parser.js";
4
+ import ParsingBuffer from "../parsing/parsing_buffer.js";
5
+ import { ParseResult } from "../step/parsing/step_parser.js";
6
+ import { AP214ProductStructureExtraction, } from "./ap214_product_structure_extraction.js";
7
+ const parser = AP214StepParser.Instance;
8
+ /**
9
+ * Parse the hermetic as1 assembly fixture and extract its product structure.
10
+ *
11
+ * @return {ProductStructureNode[]} The extracted assembly forest.
12
+ */
13
+ function extractAs1Structure() {
14
+ const buffer = fs.readFileSync("data/as1-assembly.step");
15
+ const bufferInput = new ParsingBuffer(buffer);
16
+ const headerResult = parser.parseHeader(bufferInput)[1];
17
+ expect(headerResult).toBe(ParseResult.COMPLETE);
18
+ const [result, model] = parser.parseDataToModel(bufferInput);
19
+ expect(model).not.toBe(void 0);
20
+ expect(result === ParseResult.COMPLETE || result === ParseResult.INCOMPLETE).toBe(true);
21
+ return new AP214ProductStructureExtraction(model).extractProductStructure();
22
+ }
23
+ /**
24
+ * Find a direct child of a node by display name.
25
+ *
26
+ * @param node The parent node.
27
+ * @param name The child name to find.
28
+ * @return {ProductStructureNode} The first matching child.
29
+ */
30
+ function child(node, name) {
31
+ const found = node.children.find((candidate) => candidate.name === name);
32
+ expect(found).not.toBe(void 0);
33
+ return found;
34
+ }
35
+ /**
36
+ * Names of the direct children of a node.
37
+ *
38
+ * @param node The parent node.
39
+ * @return {string[]} The child names, in order.
40
+ */
41
+ function childNames(node) {
42
+ return node.children.map((candidate) => candidate.name);
43
+ }
44
+ const NUT_BOLT_ASSEMBLY_INSTANCE_COUNT = 3;
45
+ const AS1_ROOT_CHILD_COUNT = 4;
46
+ describe("AP214ProductStructureExtraction", () => {
47
+ test("extracts a single named root for the as1 assembly", () => {
48
+ const roots = extractAs1Structure();
49
+ expect(roots.length).toBe(1);
50
+ expect(roots[0].name).toBe("as1");
51
+ expect(roots[0].occurrencePath).toEqual([]);
52
+ });
53
+ test("builds the nested nut/rod/bracket/plate hierarchy with names", () => {
54
+ const root = extractAs1Structure()[0];
55
+ expect(childNames(root).sort()).toEqual(["l-bracket-assembly", "l-bracket-assembly", "plate", "rod-assembly"]);
56
+ const rodAssembly = child(root, "rod-assembly");
57
+ expect(childNames(rodAssembly).sort()).toEqual(["nut", "nut", "rod"]);
58
+ const lBracketAssembly = child(root, "l-bracket-assembly");
59
+ expect(childNames(lBracketAssembly).sort()).toEqual(["l-bracket", "nut-bolt-assembly", "nut-bolt-assembly", "nut-bolt-assembly"]);
60
+ const nutBoltAssembly = child(lBracketAssembly, "nut-bolt-assembly");
61
+ expect(childNames(nutBoltAssembly).sort()).toEqual(["bolt", "nut"]);
62
+ });
63
+ test("gives repeated sub-assembly occurrences distinct nodes and paths", () => {
64
+ const root = extractAs1Structure()[0];
65
+ const lBracketAssemblies = root.children.filter((node) => node.name === "l-bracket-assembly");
66
+ // Two occurrences of the SAME product_definition: same part type id...
67
+ expect(lBracketAssemblies.length).toBe(2);
68
+ expect(lBracketAssemblies[0].productDefinitionExpressID)
69
+ .toBe(lBracketAssemblies[1].productDefinitionExpressID);
70
+ // ...but distinct occurrence (NAUO) keys and distinct paths.
71
+ expect(lBracketAssemblies[0].expressID)
72
+ .not.toBe(lBracketAssemblies[1].expressID);
73
+ expect(lBracketAssemblies[0].occurrencePath)
74
+ .not.toEqual(lBracketAssemblies[1].occurrencePath);
75
+ });
76
+ test("disambiguates a reused leaf part by full occurrence path", () => {
77
+ const root = extractAs1Structure()[0];
78
+ const lBracketAssemblies = root.children.filter((node) => node.name === "l-bracket-assembly");
79
+ const boltPaths = lBracketAssemblies.map((assembly) => {
80
+ const nutBoltAssembly = child(assembly, "nut-bolt-assembly");
81
+ return child(nutBoltAssembly, "bolt").occurrencePath;
82
+ });
83
+ // Same leaf NAUO id at the tail, but the path roots differ — exactly the
84
+ // instancing case a scalar expressID cannot represent.
85
+ expect(boltPaths[0]).not.toEqual(boltPaths[1]);
86
+ expect(boltPaths[0][boltPaths[0].length - 1])
87
+ .toBe(boltPaths[1][boltPaths[1].length - 1]);
88
+ expect(boltPaths[0][0]).not.toBe(boltPaths[1][0]);
89
+ });
90
+ test("each nut-bolt-assembly occurrence has its own bolt and nut", () => {
91
+ const root = extractAs1Structure()[0];
92
+ const lBracketAssembly = child(root, "l-bracket-assembly");
93
+ const nutBoltAssemblies = lBracketAssembly.children.filter((node) => node.name === "nut-bolt-assembly");
94
+ expect(nutBoltAssemblies.length).toBe(NUT_BOLT_ASSEMBLY_INSTANCE_COUNT);
95
+ for (const nutBoltAssembly of nutBoltAssemblies) {
96
+ expect(childNames(nutBoltAssembly).sort()).toEqual(["bolt", "nut"]);
97
+ }
98
+ });
99
+ test("links the root part to its shape representation", () => {
100
+ const root = extractAs1Structure()[0];
101
+ expect(root.shapeRepresentationIds.length).toBeGreaterThan(0);
102
+ });
103
+ test("root has the expected number of top-level occurrences", () => {
104
+ const root = extractAs1Structure()[0];
105
+ expect(root.children.length).toBe(AS1_ROOT_CHILD_COUNT);
106
+ });
107
+ });
@@ -0,0 +1,90 @@
1
+ import AP214StepModel from "./ap214_step_model.js";
2
+ /**
3
+ * One extracted key/value property row for a part.
4
+ */
5
+ export interface ExtractedProperty {
6
+ /** Property key, e.g. `'Modeled By'`, `'volume measure'`. */
7
+ name: string;
8
+ /** Stringified value, e.g. `'Engineer'`, `'14644822.6361138'`. */
9
+ value: string;
10
+ /** Numeric value for measure properties (volume/area/…); `undefined` for text. */
11
+ numericValue?: number;
12
+ /**
13
+ * Grouping label from the owning `property_definition.name` — e.g.
14
+ * `'geometric validation property'` for NIST volume/area validation rows.
15
+ * Empty for plain attribute properties.
16
+ */
17
+ group: string;
18
+ /**
19
+ * Express id of the source representation item (the
20
+ * `descriptive_representation_item` / `measure_representation_item`). The
21
+ * compat surface uses it as the property's own express id so the web-ifc
22
+ * `IfcPropertySet.HasProperties` reference handles can be resolved back to
23
+ * this row via `getItemProperties`. `undefined` if the item carried no id.
24
+ */
25
+ expressID?: number;
26
+ }
27
+ /** Properties grouped by the express id of the owning `product_definition`. */
28
+ export type ExtractedPropertyMap = Map<number, ExtractedProperty[]>;
29
+ /** Minimal shape of a representation item needed for property conversion. */
30
+ interface RepresentationItemLike {
31
+ name: string;
32
+ expressID?: number;
33
+ }
34
+ /**
35
+ * Extracts STEP part properties from a populated {@link AP214StepModel}.
36
+ *
37
+ * Walks the property chain
38
+ * `general_property` → (`general_property_association`) → `property_definition`
39
+ * → `property_definition_representation` → `representation` →
40
+ * `descriptive_representation_item` / `measure_representation_item` into
41
+ * per-part key/value rows. Includes the NIST validation properties
42
+ * (`geometric/attribute validation property`, e.g. volume via
43
+ * `measure_representation_item`).
44
+ *
45
+ * Mirrors the IFC precedent (`src/ifc/ifc_property_extraction.ts`); feeds the
46
+ * web-ifc compat surface `ap214_properties.ts` that Share consumes.
47
+ */
48
+ export declare class AP214PropertyExtraction {
49
+ private readonly model;
50
+ private readonly generalPropertyNameByDef_;
51
+ /**
52
+ * @param model The populated AP214/AP242 step model to walk.
53
+ */
54
+ constructor(model: AP214StepModel);
55
+ /**
56
+ * Build the per-part property map.
57
+ *
58
+ * @return {ExtractedPropertyMap} Properties keyed by owning
59
+ * `product_definition` express id. Properties whose owner is a feature
60
+ * (`shape_aspect`, dimensions) rather than a part are skipped at this
61
+ * (Simplified) tier — they belong to the Full PMI tier.
62
+ */
63
+ extractProperties(): ExtractedPropertyMap;
64
+ /**
65
+ * Index general-property names by the express id of the `property_definition`
66
+ * they are associated with, so a property can carry the canonical
67
+ * `general_property` label when one exists.
68
+ */
69
+ private indexGeneralPropertyNames;
70
+ /**
71
+ * Resolve the part owner and value rows for one
72
+ * `property_definition_representation` and append them to the result map.
73
+ *
74
+ * @param pdr The property-definition representation to walk.
75
+ * @param result The accumulating per-part property map.
76
+ */
77
+ private collectFromRepresentation;
78
+ /**
79
+ * Convert a representation item into a property row, or `undefined` for item
80
+ * kinds that carry no key/value (e.g. a centroid `cartesian_point`).
81
+ *
82
+ * @param item The representation item to convert.
83
+ * @param fallbackKey Key to use when the item itself is unnamed.
84
+ * @param group Grouping label from the owning property definition.
85
+ * @return {ExtractedProperty | undefined} The property row, or `undefined`.
86
+ */
87
+ static toProperty(item: RepresentationItemLike, fallbackKey: string, group: string): ExtractedProperty | undefined;
88
+ }
89
+ export {};
90
+ //# sourceMappingURL=ap214_property_extraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ap214_property_extraction.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_property_extraction.ts"],"names":[],"mappings":"AACA,OAAO,cAAc,MAAM,oBAAoB,CAAA;AAU/C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAEhC,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAA;IAEZ,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IAEb,kFAAkF;IAClF,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,+EAA+E;AAC/E,MAAM,MAAM,oBAAoB,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAA;AAEnE,6EAA6E;AAC7E,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,uBAAuB;IAOrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IALnC,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAA4B;IAEtE;;OAEG;gBAC2B,KAAK,EAAE,cAAc;IAGnD;;;;;;;OAOG;IACI,iBAAiB,IAAI,oBAAoB;IAsBhD;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAsBjC;;;;;;OAMG;IACH,OAAO,CAAC,yBAAyB;IAgDjC;;;;;;;;OAQG;IACH,MAAM,CAAC,UAAU,CACb,IAAI,EAAE,sBAAsB,EAC5B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GAAI,iBAAiB,GAAG,SAAS;CAiCnD"}