@bldrs-ai/conway 0.23.977 → 1.22.969

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 (30) hide show
  1. package/README.md +68 -40
  2. package/compiled/Dist/ConwayGeomWasm.d.ts +2 -0
  3. package/compiled/Dist/ConwayGeomWasmNode.d.ts +2 -0
  4. package/compiled/Dist/ConwayGeomWasmNodeMT.d.ts +2 -0
  5. package/compiled/Dist/ConwayGeomWasmWeb.d.ts +2 -0
  6. package/compiled/Dist/ConwayGeomWasmWebMT.d.ts +2 -0
  7. package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
  8. package/compiled/dependencies/conway-geom/interface/conway_geometry.js +0 -15
  9. package/compiled/examples/browser-bundled.cjs +1 -1
  10. package/compiled/examples/cli-bundled.cjs +1 -14
  11. package/compiled/examples/validator-bundled.cjs +1 -1
  12. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +33 -3
  13. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
  14. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +156 -111
  15. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +79 -0
  16. package/compiled/src/AP214E3_2010/ap214_scene_builder.d.ts +10 -5
  17. package/compiled/src/AP214E3_2010/ap214_scene_builder.d.ts.map +1 -1
  18. package/compiled/src/AP214E3_2010/ap214_scene_builder.js +10 -5
  19. package/compiled/src/AP214E3_2010/ap214_transform_helpers.test.d.ts +2 -0
  20. package/compiled/src/AP214E3_2010/ap214_transform_helpers.test.d.ts.map +1 -0
  21. package/compiled/src/AP214E3_2010/ap214_transform_helpers.test.js +112 -0
  22. package/compiled/src/format_detection/model_format_detector.d.ts +2 -1
  23. package/compiled/src/format_detection/model_format_detector.d.ts.map +1 -1
  24. package/compiled/src/format_detection/model_format_detector.js +12 -11
  25. package/compiled/src/format_detection/model_format_detector.test.js +11 -0
  26. package/compiled/src/loaders/conway_model_loader.d.ts.map +1 -1
  27. package/compiled/src/loaders/conway_model_loader.js +8 -1
  28. package/compiled/src/version/version.js +1 -1
  29. package/compiled/tsconfig.tsbuildinfo +1 -1
  30. package/package.json +4 -3
@@ -1581,11 +1581,55 @@ export class AP214GeometryExtraction {
1581
1581
  extractMappedItem(from, owningElementLocalID, parents = void 0) {
1582
1582
  const representationMap = from.mapping_source;
1583
1583
  const mappingTarget = from.mapping_target;
1584
- let popTransform = false;
1584
+ const mappingOrigin = representationMap.mapping_origin;
1585
+ let pushedTransforms = 0;
1586
+ const pushTransform = (nativeTransform) => {
1587
+ this.scene.addTransform(from.localID, nativeTransform.getValues(), nativeTransform, true);
1588
+ ++pushedTransforms;
1589
+ };
1585
1590
  if (mappingTarget instanceof cartesian_transformation_operator_3d) {
1586
1591
  const nativeCartesianTransform = this.extractCartesianTransformOperator3D(mappingTarget);
1587
- this.scene.addTransform(from.localID, nativeCartesianTransform.getValues(), nativeCartesianTransform, true);
1588
- popTransform = true;
1592
+ const originTransform = mappingOrigin instanceof placement ?
1593
+ this.extractRawPlacement(mappingOrigin) : void 0;
1594
+ let combinedTransform;
1595
+ if (originTransform !== void 0) {
1596
+ // Use the same semantics as doTransforms: from = origin^-1, to = target
1597
+ const from = originTransform.invert();
1598
+ const to = nativeCartesianTransform;
1599
+ const params = {
1600
+ useRelPlacement: true,
1601
+ axis2Placement: from,
1602
+ relPlacement: to,
1603
+ };
1604
+ combinedTransform = this.conwayModel.getLocalPlacement(params);
1605
+ }
1606
+ else {
1607
+ combinedTransform = nativeCartesianTransform;
1608
+ }
1609
+ pushTransform(combinedTransform);
1610
+ }
1611
+ else if (mappingTarget instanceof placement) {
1612
+ const targetTransform = this.extractRawPlacement(mappingTarget);
1613
+ const originTransform = mappingOrigin instanceof placement ?
1614
+ this.extractRawPlacement(mappingOrigin) : void 0;
1615
+ if (targetTransform !== void 0) {
1616
+ let combinedTransform;
1617
+ if (originTransform !== void 0) {
1618
+ // Again, same semantics as doTransforms
1619
+ const from = originTransform.invert();
1620
+ const to = targetTransform;
1621
+ const params = {
1622
+ useRelPlacement: true,
1623
+ axis2Placement: from,
1624
+ relPlacement: to,
1625
+ };
1626
+ combinedTransform = this.conwayModel.getLocalPlacement(params);
1627
+ }
1628
+ else {
1629
+ combinedTransform = targetTransform;
1630
+ }
1631
+ pushTransform(combinedTransform);
1632
+ }
1589
1633
  }
1590
1634
  for (const representationItem of representationMap.mapped_representation.items) {
1591
1635
  if (representationItem instanceof mapped_item) {
@@ -1623,7 +1667,7 @@ export class AP214GeometryExtraction {
1623
1667
  this.scene.addGeometry(representationItem.localID, owningElementLocalID, materialOverrideID);
1624
1668
  }
1625
1669
  }
1626
- if (popTransform) {
1670
+ for (; pushedTransforms > 0; --pushedTransforms) {
1627
1671
  this.scene.popTransform();
1628
1672
  }
1629
1673
  }
@@ -2534,23 +2578,22 @@ export class AP214GeometryExtraction {
2534
2578
  return this.scene.addTransform(parentLocalId, axis2PlacementTransform.getValues(), axis2PlacementTransform, true);
2535
2579
  }
2536
2580
  /**
2581
+ * Extract a placement, adding it to the scene.
2537
2582
  *
2538
- * @param from
2539
- * @param mappedItem
2583
+ * @param from The placement to extract.
2584
+ * @param mappedItem Whether the placement is a mapped item.
2585
+ * @return The extracted placement or undefined if the placement is not a axis2_placement_3d.
2540
2586
  */
2541
2587
  extractPlacement(from, mappedItem = false) {
2542
- // if ( !mappedItem ) {
2543
- // const result: AP214SceneTransform | undefined =
2544
- // this.scene.getTransform(from.localID)
2545
- // if (result !== void 0) {
2546
- // this.scene.pushTransform(result)
2547
- // return result
2548
- // }
2549
- // }
2588
+ if (from instanceof axis2_placement_3d) {
2589
+ const placementTransform = this.extractRawPlacement(from);
2590
+ if (placementTransform) {
2591
+ this.scene.addTransform(from.localID, placementTransform.getValues(), placementTransform, true);
2592
+ }
2593
+ }
2550
2594
  if (from instanceof axis2_placement_3d) {
2551
2595
  return this.extractAxis2Placement3D(from, from.localID, false, true);
2552
2596
  }
2553
- return;
2554
2597
  }
2555
2598
  extractRawPlacement(from) {
2556
2599
  if (from instanceof axis2_placement_3d) {
@@ -2559,6 +2602,42 @@ export class AP214GeometryExtraction {
2559
2602
  }
2560
2603
  return;
2561
2604
  }
2605
+ /**
2606
+ * Multiply a native 4x4 transform by a uniform scale factor in affine
2607
+ * semantics: scale both the 3x3 basis and the translation column,
2608
+ * leaving the bottom row at [0,0,0,1]. Equivalent to `factor * mat`
2609
+ * for any affine input.
2610
+ *
2611
+ * Used in preference to the native `uniformScale` binding for unit
2612
+ * conversion, where the placement's translation also needs to be
2613
+ * scaled. See https://github.com/bldrs-ai/conway/issues/308.
2614
+ *
2615
+ * @param mat Source column-major Glmdmat4 transform; not mutated.
2616
+ * @param factor Scalar applied to every affine entry.
2617
+ * @return A freshly allocated 4x4 with the scale applied.
2618
+ */
2619
+ uniformScaleAffine(mat, factor) {
2620
+ const v = mat.getValues().slice();
2621
+ // Column-major Glmdmat4 layout:
2622
+ // basis at 0,1,2 / 4,5,6 / 8,9,10
2623
+ // translation at 12,13,14
2624
+ // bottom row at 3,7,11,15 (untouched: [0,0,0,1])
2625
+ v[0] *= factor;
2626
+ v[1] *= factor;
2627
+ v[2] *= factor;
2628
+ v[4] *= factor;
2629
+ v[5] *= factor;
2630
+ v[6] *= factor;
2631
+ v[8] *= factor;
2632
+ v[9] *= factor;
2633
+ v[10] *= factor;
2634
+ v[12] *= factor;
2635
+ v[13] *= factor;
2636
+ v[14] *= factor;
2637
+ const result = (new (this.wasmModule.Glmdmat4));
2638
+ result.setValues(v);
2639
+ return result;
2640
+ }
2562
2641
  /**
2563
2642
  *
2564
2643
  */
@@ -2768,53 +2847,9 @@ export class AP214GeometryExtraction {
2768
2847
  shapeRepresentationRelationshipsSeen.add(shapeRelationship.localID);
2769
2848
  const sourceShape = shapeRelationship.rep_1;
2770
2849
  const targetShape = shapeRelationship.rep_2;
2771
- const transformInstance = shapeRelationship.findVariant(representation_relationship_with_transformation);
2772
- let transform = void 0;
2773
- let scaleTransform = void 0;
2774
- if (transformInstance !== void 0) {
2775
- const transformOperator = transformInstance.transformation_operator;
2776
- if (!(transformOperator instanceof item_defined_transformation)) {
2777
- continue;
2778
- }
2779
- const placement1 = transformOperator.transform_item_1;
2780
- if (!(placement1 instanceof placement)) {
2781
- continue;
2782
- }
2783
- const placement2 = transformOperator.transform_item_2;
2784
- if (!(placement2 instanceof placement)) {
2785
- continue;
2786
- }
2787
- const from = this.extractRawPlacement(placement1)?.invert() ?? this.identity3DNativeMatrix;
2788
- const to = this.extractRawPlacement(placement2) ?? this.identity3DNativeMatrix;
2789
- const localPlacementParameters = {
2790
- useRelPlacement: true,
2791
- axis2Placement: from,
2792
- relPlacement: to,
2793
- };
2794
- transform = this.conwayModel.getLocalPlacement(localPlacementParameters);
2795
- }
2796
- const sourceShapeContext = sourceShape.context_of_items.findVariant(global_unit_assigned_context)?.units?.
2797
- find(unit => unit.findVariant(length_unit))?.findVariant(length_unit);
2798
- const targetShapeContext = targetShape.context_of_items.findVariant(global_unit_assigned_context)?.units?.
2799
- find(unit => unit.findVariant(length_unit))?.findVariant(length_unit);
2800
- if (sourceShapeContext !== void 0 && targetShapeContext !== void 0) {
2801
- const scaleRatio = this.lengthUnitConversionRatio(sourceShapeContext, targetShapeContext);
2802
- if (scaleRatio !== void 0 && scaleRatio !== 1) {
2803
- scaleTransform = this.identity3DNativeMatrix.uniformScale(scaleRatio);
2804
- }
2805
- }
2806
- if (scaleTransform !== void 0) {
2807
- if (transform !== void 0) {
2808
- const localPlacementParameters = {
2809
- useRelPlacement: true,
2810
- axis2Placement: transform,
2811
- relPlacement: scaleTransform,
2812
- };
2813
- transform = this.conwayModel.getLocalPlacement(localPlacementParameters);
2814
- }
2815
- else {
2816
- transform = scaleTransform;
2817
- }
2850
+ const [transform, isContinue] = this.doTransforms(shapeRelationship, sourceShape, targetShape, owningLocalID);
2851
+ if (isContinue) {
2852
+ continue;
2818
2853
  }
2819
2854
  const sourceID = sourceShape.localID;
2820
2855
  const targetID = targetShape.localID;
@@ -2853,53 +2888,9 @@ export class AP214GeometryExtraction {
2853
2888
  */
2854
2889
  const sourceShape = shapeRelationship.rep_2;
2855
2890
  const targetShape = shapeRelationship.rep_1;
2856
- const transformInstance = shapeRelationship.findVariant(representation_relationship_with_transformation);
2857
- let transform = void 0;
2858
- let scaleTransform = void 0;
2859
- if (transformInstance !== void 0) {
2860
- const transformOperator = transformInstance.transformation_operator;
2861
- if (!(transformOperator instanceof item_defined_transformation)) {
2862
- continue;
2863
- }
2864
- const placement1 = transformOperator.transform_item_1;
2865
- if (!(placement1 instanceof placement)) {
2866
- continue;
2867
- }
2868
- const placement2 = transformOperator.transform_item_2;
2869
- if (!(placement2 instanceof placement)) {
2870
- continue;
2871
- }
2872
- const from = this.extractRawPlacement(placement1)?.invert() ?? this.identity3DNativeMatrix;
2873
- const to = this.extractRawPlacement(placement2) ?? this.identity3DNativeMatrix;
2874
- const localPlacementParameters = {
2875
- useRelPlacement: true,
2876
- axis2Placement: from,
2877
- relPlacement: to,
2878
- };
2879
- transform = this.conwayModel.getLocalPlacement(localPlacementParameters);
2880
- }
2881
- const sourceShapeContext = sourceShape.context_of_items.findVariant(global_unit_assigned_context)?.units?.
2882
- find(unit => unit.findVariant(length_unit))?.findVariant(length_unit);
2883
- const targetShapeContext = targetShape.context_of_items.findVariant(global_unit_assigned_context)?.units?.
2884
- find(unit => unit.findVariant(length_unit))?.findVariant(length_unit);
2885
- if (sourceShapeContext !== void 0 && targetShapeContext !== void 0) {
2886
- const scaleRatio = this.lengthUnitConversionRatio(sourceShapeContext, targetShapeContext);
2887
- if (scaleRatio !== void 0 && scaleRatio !== 1) {
2888
- scaleTransform = this.identity3DNativeMatrix.uniformScale(scaleRatio);
2889
- }
2890
- }
2891
- if (scaleTransform !== void 0) {
2892
- if (transform !== void 0) {
2893
- const localPlacementParameters = {
2894
- useRelPlacement: true,
2895
- axis2Placement: transform,
2896
- relPlacement: scaleTransform,
2897
- };
2898
- transform = this.conwayModel.getLocalPlacement(localPlacementParameters);
2899
- }
2900
- else {
2901
- transform = scaleTransform;
2902
- }
2891
+ const [transform, isContinue] = this.doTransforms(shapeRelationship, sourceShape, targetShape, owningLocalID);
2892
+ if (isContinue) {
2893
+ continue;
2903
2894
  }
2904
2895
  const sourceID = sourceShape.localID;
2905
2896
  const targetID = targetShape.localID;
@@ -2951,7 +2942,8 @@ export class AP214GeometryExtraction {
2951
2942
  let scaleTransform = void 0;
2952
2943
  if (sourceShapeContext !== void 0) {
2953
2944
  const sourceUnitInM = (this.convertToMetres(sourceShapeContext) ?? 1);
2954
- scaleTransform = this.identity3DNativeMatrix.uniformScale(1 / sourceUnitInM);
2945
+ scaleTransform =
2946
+ this.uniformScaleAffine(this.identity3DNativeMatrix, 1 / sourceUnitInM);
2955
2947
  }
2956
2948
  // not an assembly mapped item, just extract the representation
2957
2949
  thunk(void 0, scaleTransform);
@@ -2984,7 +2976,8 @@ export class AP214GeometryExtraction {
2984
2976
  let scaleTransform = void 0;
2985
2977
  if (sourceShapeContext !== void 0) {
2986
2978
  const sourceUnitInM = (this.convertToMetres(sourceShapeContext) ?? 1);
2987
- scaleTransform = this.identity3DNativeMatrix.uniformScale(1 / sourceUnitInM);
2979
+ scaleTransform =
2980
+ this.uniformScaleAffine(this.identity3DNativeMatrix, 1 / sourceUnitInM);
2988
2981
  }
2989
2982
  // not an assembly mapped item, just extract the representation
2990
2983
  mappedNode.thunk(void 0, scaleTransform);
@@ -3005,4 +2998,56 @@ export class AP214GeometryExtraction {
3005
2998
  this.model.elementMemoization = previousMemoizationState;
3006
2999
  }
3007
3000
  }
3001
+ /**
3002
+ * Process the transforms for a shape relationship.
3003
+ *
3004
+ * @param shapeRelationship The shape relationship to process.
3005
+ * @param sourceShape The source shape.
3006
+ * @param targetShape The target shape.
3007
+ * @param owningLocalID The owning local ID.
3008
+ * @return The transform and a boolean indicating if the processing should continue inside the loop.
3009
+ */
3010
+ doTransforms(shapeRelationship, sourceShape, targetShape, owningLocalID) {
3011
+ const transformInstance = shapeRelationship.findVariant(representation_relationship_with_transformation);
3012
+ let transform = void 0;
3013
+ if (transformInstance !== void 0) {
3014
+ const transformOperator = transformInstance.transformation_operator;
3015
+ if (transformOperator instanceof item_defined_transformation) {
3016
+ const placement1 = transformOperator.transform_item_1;
3017
+ const placement2 = transformOperator.transform_item_2;
3018
+ if (!(placement1 instanceof placement) || !(placement2 instanceof placement)) {
3019
+ return [void 0, true];
3020
+ }
3021
+ const from = this.extractRawPlacement(placement1)?.invert() ?? this.identity3DNativeMatrix;
3022
+ const to = this.extractRawPlacement(placement2) ?? this.identity3DNativeMatrix;
3023
+ const localPlacementParameters = {
3024
+ useRelPlacement: true,
3025
+ axis2Placement: from,
3026
+ relPlacement: to,
3027
+ };
3028
+ transform = this.conwayModel.getLocalPlacement(localPlacementParameters);
3029
+ }
3030
+ else if (transformOperator instanceof cartesian_transformation_operator_3d) {
3031
+ transform = this.extractCartesianTransformOperator3D(transformOperator);
3032
+ }
3033
+ }
3034
+ const sourceShapeContext = sourceShape.context_of_items.findVariant(global_unit_assigned_context)?.units?.
3035
+ find(unit => unit.findVariant(length_unit))?.findVariant(length_unit);
3036
+ const targetShapeContext = targetShape.context_of_items.findVariant(global_unit_assigned_context)?.units?.
3037
+ find(unit => unit.findVariant(length_unit))?.findVariant(length_unit);
3038
+ let scaleRatio = 1;
3039
+ let needsScale = false;
3040
+ if (sourceShapeContext !== void 0 && targetShapeContext !== void 0) {
3041
+ const sr = this.lengthUnitConversionRatio(sourceShapeContext, targetShapeContext);
3042
+ if (sr !== void 0 && sr !== 1) {
3043
+ scaleRatio = sr;
3044
+ needsScale = true;
3045
+ }
3046
+ }
3047
+ if (needsScale) {
3048
+ transform =
3049
+ this.uniformScaleAffine(transform ?? this.identity3DNativeMatrix, scaleRatio);
3050
+ }
3051
+ return [transform, false];
3052
+ }
3008
3053
  }
@@ -112,6 +112,85 @@ describe("AP214 Geometry Extraction", () => {
112
112
  const testParameter = 48108;
113
113
  expect(getGearMeshSize()).toBe(testParameter);
114
114
  });
115
+ test("uniformScaleAffine scales basis AND translation, preserves bottom row", () => {
116
+ // Direct unit test for the affine scale helper used by the unit-conversion
117
+ // path in doTransforms (see https://github.com/bldrs-ai/conway/issues/308).
118
+ // Models a placement in mm with a 1000 mm x-translation, 50 mm
119
+ // y-translation, converted to metres (factor = 1/MM_PER_M).
120
+ const MM_PER_M = 1000;
121
+ const TX_MM = 1000;
122
+ const TY_MM = 50;
123
+ const factor = 1 / MM_PER_M;
124
+ const model = conwayTubeModel;
125
+ const input = new model.wasmModule.Glmdmat4();
126
+ // Column-major: cols 0..2 = basis (identity), col 3 = translation
127
+ input.setValues([
128
+ 1,
129
+ 0,
130
+ 0,
131
+ 0,
132
+ 0,
133
+ 1,
134
+ 0,
135
+ 0,
136
+ 0,
137
+ 0,
138
+ 1,
139
+ 0,
140
+ TX_MM,
141
+ TY_MM,
142
+ 0,
143
+ 1,
144
+ ]);
145
+ const v = model.uniformScaleAffine(input, factor).getValues();
146
+ // Basis diagonal scaled by factor.
147
+ expect(v[0]).toBeCloseTo(factor);
148
+ expect(v[5]).toBeCloseTo(factor);
149
+ expect(v[10]).toBeCloseTo(factor);
150
+ // Translation scaled by factor (mm -> m). This is the bug the C++
151
+ // `uniformScale` left in source units before; the helper fixes it.
152
+ expect(v[12]).toBeCloseTo(TX_MM * factor);
153
+ expect(v[13]).toBeCloseTo(TY_MM * factor);
154
+ expect(v[14]).toBeCloseTo(0);
155
+ // Bottom row left at [0, 0, 0, 1].
156
+ expect(v[3]).toBe(0);
157
+ expect(v[7]).toBe(0);
158
+ expect(v[11]).toBe(0);
159
+ expect(v[15]).toBe(1);
160
+ });
161
+ test("uniformScaleAffine with factor=1 returns the original matrix entries", () => {
162
+ const model = conwayTubeModel;
163
+ // A column-major rotation+translation matrix with non-trivial entries
164
+ // (60-degree z-rotation, arbitrary translation).
165
+ const COS60 = Math.cos(Math.PI / 3);
166
+ const SIN60 = Math.sin(Math.PI / 3);
167
+ const TY = 20;
168
+ const TZ = 30;
169
+ const original = [
170
+ COS60,
171
+ SIN60,
172
+ 0,
173
+ 0,
174
+ -SIN60,
175
+ COS60,
176
+ 0,
177
+ 0,
178
+ 0,
179
+ 0,
180
+ 1,
181
+ 0,
182
+ 10,
183
+ TY,
184
+ TZ,
185
+ 1,
186
+ ];
187
+ const input = new model.wasmModule.Glmdmat4();
188
+ input.setValues(original);
189
+ const v = model.uniformScaleAffine(input, 1).getValues();
190
+ for (let i = 0; i < original.length; ++i) {
191
+ expect(v[i]).toBeCloseTo(original[i]);
192
+ }
193
+ });
115
194
  test("destroy()", () => {
116
195
  expect(destroy()).toBe(false);
117
196
  });
@@ -180,12 +180,17 @@ export declare class AP214SceneBuilder implements WalkableScene<StepEntityBase<E
180
180
  */
181
181
  addGeometry(localID: number, owningElementLocalID?: number, materialOverridLocalID?: number): AP214SceneGeometry;
182
182
  /**
183
+ * Add a transform node and make the current transform stack parent its parent.
183
184
  *
184
- * @param localID
185
- * @param transform
186
- * @param nativeTransform
187
- * @param mappedItem
188
- * @return {AP214SceneTransform}
185
+ * Items added will be made the top of the transform stack.
186
+ *
187
+ * To prevent a node being used as a parent, pop it subsequently.
188
+ *
189
+ * @param localID The local ID of the transform.
190
+ * @param transform The transform matrix.
191
+ * @param nativeTransform The native transform matrix.
192
+ * @param mappedItem Whether the transform is a mapped item.
193
+ * @return The added transform node.
189
194
  */
190
195
  addTransform(localID: number, transform: ReadonlyArray<number>, nativeTransform: NativeTransform4x4, mappedItem?: boolean): AP214SceneTransform;
191
196
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ap214_scene_builder.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_scene_builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ap214_scene_builder.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_scene_builder.ts"],"names":[],"mappings":"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"}
@@ -372,12 +372,17 @@ export class AP214SceneBuilder {
372
372
  return result;
373
373
  }
374
374
  /**
375
+ * Add a transform node and make the current transform stack parent its parent.
375
376
  *
376
- * @param localID
377
- * @param transform
378
- * @param nativeTransform
379
- * @param mappedItem
380
- * @return {AP214SceneTransform}
377
+ * Items added will be made the top of the transform stack.
378
+ *
379
+ * To prevent a node being used as a parent, pop it subsequently.
380
+ *
381
+ * @param localID The local ID of the transform.
382
+ * @param transform The transform matrix.
383
+ * @param nativeTransform The native transform matrix.
384
+ * @param mappedItem Whether the transform is a mapped item.
385
+ * @return The added transform node.
381
386
  */
382
387
  addTransform(localID, transform, nativeTransform, mappedItem = false) {
383
388
  if (!mappedItem && this.sceneLocalIdMap_.has(localID)) {
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ap214_transform_helpers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ap214_transform_helpers.test.d.ts","sourceRoot":"","sources":["../../../src/AP214E3_2010/ap214_transform_helpers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,112 @@
1
+ import fs from "fs";
2
+ import { describe, expect, test, beforeAll, afterAll } from "@jest/globals";
3
+ import { AP214GeometryExtraction } from "./ap214_geometry_extraction.js";
4
+ import { AP214SceneTransform } from "./ap214_scene_builder.js";
5
+ import { ParseResult } from "../step/parsing/step_parser.js";
6
+ import IfcStepParser from "./ap214_step_parser.js";
7
+ import ParsingBuffer from "../parsing/parsing_buffer.js";
8
+ import { ConwayGeometry } from "../../dependencies/conway-geom/index.js";
9
+ import { cartesian_transformation_operator_3d, mapped_item, } from "./AP214E3_2010_gen/index.js";
10
+ let extraction;
11
+ let conwayGeometry;
12
+ /**
13
+ * Parse data/ap214-mapped-item-test.step and create an AP214GeometryExtraction
14
+ * for testing transform helpers (extractMappedItem origin-inversion semantics
15
+ * from PR #309 and extractCartesianTransformOperator3D parameter packaging).
16
+ *
17
+ * @return {Promise<boolean>} True iff parse + WASM init succeeded.
18
+ */
19
+ async function initialize() {
20
+ const parser = IfcStepParser.Instance;
21
+ const buffer = fs.readFileSync("data/ap214-mapped-item-test.step");
22
+ const input = new ParsingBuffer(buffer);
23
+ if (parser.parseHeader(input)[1] !== ParseResult.COMPLETE) {
24
+ return false;
25
+ }
26
+ conwayGeometry = new ConwayGeometry();
27
+ if (!(await conwayGeometry.initialize())) {
28
+ return false;
29
+ }
30
+ const [, model] = parser.parseDataToModel(input);
31
+ if (model === void 0) {
32
+ return false;
33
+ }
34
+ extraction = new AP214GeometryExtraction(conwayGeometry, model);
35
+ return extraction.isInitialized();
36
+ }
37
+ describe("AP214 transform helpers", () => {
38
+ beforeAll(async () => {
39
+ await initialize();
40
+ });
41
+ afterAll(() => {
42
+ extraction?.destroy();
43
+ });
44
+ test("parses fixture and finds the mapped_item + CTO3D entities", () => {
45
+ const mappedItems = Array.from(extraction.model.types(mapped_item));
46
+ const ctos = Array.from(extraction.model.types(cartesian_transformation_operator_3d));
47
+ expect(mappedItems.length).toBe(1);
48
+ expect(ctos.length).toBe(1);
49
+ });
50
+ test("extractCartesianTransformOperator3D produces a non-trivial matrix with the entity origin", () => {
51
+ // Fixture has CARTESIAN_TRANSFORMATION_OPERATOR_3D('',$,$,#13,2.,$)
52
+ // with #13 = CARTESIAN_POINT('',(50.,0.,0.)). Verifies the helper
53
+ // packages local_origin into the returned matrix's translation
54
+ // column (column-major v[12..14]).
55
+ const CTO_ORIGIN_X = 50;
56
+ const MAT_4X4_ENTRIES = 16;
57
+ const ctos = Array.from(extraction.model.types(cartesian_transformation_operator_3d));
58
+ const cto = ctos[0];
59
+ const result = extraction.extractCartesianTransformOperator3D(cto);
60
+ const v = result.getValues();
61
+ expect(v.length).toBe(MAT_4X4_ENTRIES);
62
+ // Translation reflects the entity's local_origin.
63
+ expect(v[12]).toBeCloseTo(CTO_ORIGIN_X);
64
+ expect(v[13]).toBeCloseTo(0);
65
+ expect(v[14]).toBeCloseTo(0);
66
+ // Bottom row sane for an affine 4x4.
67
+ expect(v[3]).toBeCloseTo(0);
68
+ expect(v[7]).toBeCloseTo(0);
69
+ expect(v[11]).toBeCloseTo(0);
70
+ });
71
+ test("extractMappedItem composes target * origin^-1 for a placement target", () => {
72
+ // Fixture has:
73
+ // origin placement #30 at (10, 0, 0)
74
+ // target placement #31 at (100, 0, 0)
75
+ // mapped_item #60 mapping #30 -> #31
76
+ //
77
+ // Per PR #309 (line 2298-2308 of ap214_geometry_extraction.ts): the
78
+ // pushed transform is `target * origin^-1`. With identity rotations
79
+ // and translations as above, the result's translation column should
80
+ // be (100 - 10, 0, 0) = (90, 0, 0).
81
+ //
82
+ // Regression guard: if origin^-1 were dropped, the result would be
83
+ // the bare target translation (100, 0, 0).
84
+ const EXPECTED_TX = 90;
85
+ const TARGET_ONLY_TX = 100;
86
+ const mappedItems = Array.from(extraction.model.types(mapped_item));
87
+ const mi = mappedItems[0];
88
+ const sceneInternal = extraction.scene;
89
+ const indexBefore = sceneInternal.scene_.length;
90
+ extraction.extractMappedItem(mi);
91
+ // The first scene node added by extractMappedItem is the combined
92
+ // transform itself (pushed with mapped_item's localID); subsequent
93
+ // nodes come from the recursive extraction of mapped_representation.
94
+ let pushed;
95
+ for (let i = indexBefore; i < sceneInternal.scene_.length; ++i) {
96
+ const node = sceneInternal.scene_[i];
97
+ if (node instanceof AP214SceneTransform && node.localID === mi.localID) {
98
+ pushed = node;
99
+ break;
100
+ }
101
+ }
102
+ expect(pushed).toBeDefined();
103
+ const v = pushed.transform;
104
+ // Combined translation = target - origin = 100 - 10 = 90 along X.
105
+ expect(v[12]).toBeCloseTo(EXPECTED_TX);
106
+ expect(v[13]).toBeCloseTo(0);
107
+ expect(v[14]).toBeCloseTo(0);
108
+ // If the origin inversion were ever removed, v[12] would land at
109
+ // TARGET_ONLY_TX. Spell that out so a regressed value reads clearly.
110
+ expect(v[12]).not.toBeCloseTo(TARGET_ONLY_TX);
111
+ });
112
+ });
@@ -4,7 +4,8 @@
4
4
  import ParsingBuffer from "../parsing/parsing_buffer.js";
5
5
  export declare enum ModelFormatType {
6
6
  IFC = 0,
7
- AP214 = 1
7
+ AP214 = 1,
8
+ AP203 = 2
8
9
  }
9
10
  /**
10
11
  * Format detector for finding the format of a model from a buffer in conway.
@@ -1 +1 @@
1
- {"version":3,"file":"model_format_detector.d.ts","sourceRoot":"","sources":["../../../src/format_detection/model_format_detector.ts"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,aAAa,MAAM,2BAA2B,CAAA;AAIrD,oBAAY,eAAe;IAEzB,GAAG,IAAI;IAEP,KAAK,IAAI;CACV;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAEtC;;;;;;OAMG;WACW,MAAM,CAAE,KAAK,EAAE,aAAa,GAAI,eAAe,GAAG,SAAS;CAsC1E"}
1
+ {"version":3,"file":"model_format_detector.d.ts","sourceRoot":"","sources":["../../../src/format_detection/model_format_detector.ts"],"names":[],"mappings":"AACA;;GAEG;AAEH,OAAO,aAAa,MAAM,2BAA2B,CAAA;AAIrD,oBAAY,eAAe;IAEzB,GAAG,IAAI;IAEP,KAAK,IAAI;IAET,KAAK,IAAI;CACV;AAED;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAmB;IAEtC;;;;;;OAMG;WACW,MAAM,CAAE,KAAK,EAAE,aAAa,GAAI,eAAe,GAAG,SAAS;CAiC1E"}