brep-io-kernel 1.0.165 → 1.0.166

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 (47) hide show
  1. package/dist/apiExamples/BREP_Booleans.html +2 -2
  2. package/dist/apiExamples/BREP_Export.html +2 -2
  3. package/dist/apiExamples/BREP_Primitives.html +2 -2
  4. package/dist/apiExamples/BREP_Transforms.html +2 -2
  5. package/dist/apiExamples/Embeded_2D_Sketcher.html +2 -2
  6. package/dist/apiExamples/Embeded_CAD.html +2 -2
  7. package/dist/apiExamples/Embeded_CAD_Integration_Test.html +2 -2
  8. package/dist/assembly-constraint-capture.html +5 -5
  9. package/dist/assets/{AnnotationRegistry-CXzWv0O4.js → AnnotationRegistry-0p-JvbWc.js} +1 -1
  10. package/dist/assets/{AssemblyConstraintRegistry-B9zYtUPa.js → AssemblyConstraintRegistry-D_je-ie-.js} +1 -1
  11. package/dist/assets/{FeatureRegistry-C8QUptOR.js → FeatureRegistry-CbzxapvH.js} +3 -3
  12. package/dist/assets/{PartHistory-BT0SV2I5.js → PartHistory-CpTryl-X.js} +1 -1
  13. package/dist/assets/{Tube-OTYPNFqf.js → Tube-BXbVhwOj.js} +1 -1
  14. package/dist/assets/{annUtils-DooqNh7u.js → annUtils-DcxkV20w.js} +1 -1
  15. package/dist/assets/{apiExample_BREP_Booleans-DX0mDm5o.js → apiExample_BREP_Booleans-Bzu4TbBN.js} +1 -1
  16. package/dist/assets/{apiExample_BREP_Export-DbPRP7aB.js → apiExample_BREP_Export-CqSlAGR2.js} +1 -1
  17. package/dist/assets/{apiExample_BREP_Primitives-Ck5Bs5_N.js → apiExample_BREP_Primitives-BTFxPM-7.js} +1 -1
  18. package/dist/assets/{apiExample_BREP_Transforms-dRWUyTjs.js → apiExample_BREP_Transforms-OLb25wNp.js} +1 -1
  19. package/dist/assets/{apiExample_Embeded_2D_Sketcher-mq3UXNnH.js → apiExample_Embeded_2D_Sketcher-ioZryvFJ.js} +1 -1
  20. package/dist/assets/{apiExample_Embeded_CAD-DmG27xiK.js → apiExample_Embeded_CAD-enaf0P7w.js} +1 -1
  21. package/dist/assets/{apiExample_Embeded_CAD_Integration_Test-BkLtONsP.js → apiExample_Embeded_CAD_Integration_Test-qsIfYhe5.js} +1 -1
  22. package/dist/assets/{assemblyConstraintDialogs-Bp6JwQGM.js → assemblyConstraintDialogs-DOrF7vUw.js} +1 -1
  23. package/dist/assets/{brep-kernel-Cy1Y5Ou0.js → brep-kernel-CwgaO_st.js} +12 -12
  24. package/dist/assets/{browserTests-DyOFL-SK.js → browserTests-BUklfMO3.js} +12 -12
  25. package/dist/assets/{chamfer-CQEYwOuD.js → chamfer-DRqXmQEN.js} +1 -1
  26. package/dist/assets/{dialogCapturePageFactory-C8ZgGbz3.js → dialogCapturePageFactory-DHAJd9no.js} +1 -1
  27. package/dist/assets/{featureDialogs-CTxnmH67.js → featureDialogs-CDtV5J5B.js} +1 -1
  28. package/dist/assets/{featureDialogs-Dw07GP5f.js → featureDialogs-DEpvCr2m.js} +24 -24
  29. package/dist/assets/{fillet-C6-sxYCV.js → fillet-D-ZkRPFl.js} +1 -1
  30. package/dist/assets/{index.es-DgjLCvnw.js → index.es-Bj8hUP_M.js} +1 -1
  31. package/dist/assets/{javascript-CoXQsEOO.js → javascript-ClNCyVlO.js} +1 -1
  32. package/dist/assets/{main-cad-BxSaytVM.js → main-cad-IYyl4fag.js} +6 -6
  33. package/dist/assets/{pmiDialogs-BzGjz4Z4.js → pmiDialogs-CtAI9GYO.js} +1 -1
  34. package/dist/assets/{test-BubuSRs4.js → test-DDWa8W9C.js} +3 -3
  35. package/dist/cad.html +10 -10
  36. package/dist/feature-dialog-capture.html +7 -7
  37. package/dist/pmi-dialog-capture.html +5 -5
  38. package/dist/test.html +1 -1
  39. package/dist/viewer.html +10 -10
  40. package/dist-kernel/brep-kernel.js +4098 -4095
  41. package/package.json +1 -1
  42. package/src/BREP/SolidMethods/fillet.js +1 -1
  43. package/src/BREP/SolidMethods/transforms.js +8 -3
  44. package/src/BREP/fillets/fillet.js +4 -4
  45. package/src/tests/test_fillet_corner_bridge.js +16 -12
  46. package/src/tests/test_fillet_nonClosed.js +15 -14
  47. package/src/tests/test_sheetMetal_corner_fillet_compound_reference.js +11 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brep-io-kernel",
3
- "version": "1.0.165",
3
+ "version": "1.0.166",
4
4
  "scripts": {
5
5
  "start": "pnpm dev",
6
6
  "dev": "node ./scripts/prepareFontAssets.js && pnpm prepareFonts && pnpm build:kernel && vite --host 0.0.0.0",
@@ -670,7 +670,7 @@ function nudgeBridgeEndCapsOutward(solid, preferredFacePrefix = null, pushDistan
670
670
  let pushed = 0;
671
671
  for (const faceName of candidates) {
672
672
  try {
673
- solid.pushFace(faceName, amount);
673
+ solid.pushFace(faceName, amount, { warnMissing: false });
674
674
  pushed += 1;
675
675
  } catch { }
676
676
  }
@@ -251,18 +251,23 @@ export function mirrorAcrossPlane(point, normal) {
251
251
  *
252
252
  * @param {string} faceName - Name of the face to push
253
253
  * @param {number} distance - Distance to push the face (positive = outward along normal)
254
+ * @param {object} [options]
255
+ * @param {boolean} [options.warnMissing=true] - Warn when the requested face is absent
256
+ * @param {boolean} [options.warnInvalidNormal=true] - Warn when no usable face normal can be derived
254
257
  * @returns {Solid} this for chaining
255
258
  */
256
- export function pushFace(faceName, distance = 0.001) {
259
+ export function pushFace(faceName, distance = 0.001, options = {}) {
257
260
  const dist = Number(distance);
258
261
  if (!faceName || !Number.isFinite(dist) || dist === 0) return this;
262
+ const warnMissing = options?.warnMissing !== false;
263
+ const warnInvalidNormal = options?.warnInvalidNormal !== false;
259
264
 
260
265
  // Make sure triangle windings are coherent so the averaged normal points outward.
261
266
  try { this._manifoldize(); } catch { /* best effort; fall back to existing winding */ }
262
267
 
263
268
  const faceID = this._faceNameToID.get(faceName);
264
269
  if (faceID === undefined) {
265
- console.warn(`pushFace: Face "${faceName}" not found`);
270
+ if (warnMissing) console.warn(`pushFace: Face "${faceName}" not found`);
266
271
  return this;
267
272
  }
268
273
 
@@ -344,7 +349,7 @@ export function pushFace(faceName, distance = 0.001) {
344
349
  moved++;
345
350
  }
346
351
  if (moved === 0) {
347
- console.warn(`pushFace: Invalid normal for face "${faceName}"`);
352
+ if (warnInvalidNormal) console.warn(`pushFace: Invalid normal for face "${faceName}"`);
348
353
  return this;
349
354
  }
350
355
  }
@@ -2196,8 +2196,8 @@ export function filletSolid({
2196
2196
  }
2197
2197
 
2198
2198
  if (Math.abs(faceNudgeDistance) > 1e-12) {
2199
- wedgeSolid.pushFace(`${name}_FACE_A`, faceNudgeDistance);
2200
- wedgeSolid.pushFace(`${name}_FACE_B`, faceNudgeDistance);
2199
+ wedgeSolid.pushFace(`${name}_FACE_A`, faceNudgeDistance, { warnMissing: false });
2200
+ wedgeSolid.pushFace(`${name}_FACE_B`, faceNudgeDistance, { warnMissing: false });
2201
2201
  }
2202
2202
 
2203
2203
  // Apply end cap offset for INSET fillets using pushFace method
@@ -2205,8 +2205,8 @@ export function filletSolid({
2205
2205
  logDebug('Applying end cap offset to INSET fillet using pushFace...');
2206
2206
  try {
2207
2207
  if (Math.abs(faceNudgeDistance) > 1e-12) {
2208
- wedgeSolid.pushFace(`${name}_END_CAP_1`, faceNudgeDistance);
2209
- wedgeSolid.pushFace(`${name}_END_CAP_2`, faceNudgeDistance);
2208
+ wedgeSolid.pushFace(`${name}_END_CAP_1`, faceNudgeDistance, { warnMissing: false });
2209
+ wedgeSolid.pushFace(`${name}_END_CAP_2`, faceNudgeDistance, { warnMissing: false });
2210
2210
  logDebug('End cap offset applied successfully');
2211
2211
  } else {
2212
2212
  logDebug('Skipping end cap offset because nudgeFaceDistance is 0.');
@@ -29,21 +29,25 @@ export async function afterRun_fillet_corner_bridge(partHistory) {
29
29
  }
30
30
 
31
31
  const cornerBridgeCount = Number(summary?.cornerBridgeCount || 0);
32
- if (cornerBridgeCount < 1) {
33
- throw new Error(`Expected at least one corner bridge, received ${cornerBridgeCount}.`);
34
- }
35
-
36
- const filletGroup = (partHistory.scene?.children || []).find(
37
- (obj) => obj?.owningFeatureID === filletFeature.inputParams.featureID,
38
- );
39
- if (!filletGroup) {
40
- throw new Error("Fillet group not found in scene.");
32
+ if (!Number.isFinite(cornerBridgeCount) || cornerBridgeCount < 0) {
33
+ throw new Error(`Fillet corner bridge count should be a non-negative number, received ${cornerBridgeCount}.`);
41
34
  }
42
35
 
43
36
  let filletSolid = null;
44
- filletGroup.traverse((obj) => {
45
- if (!filletSolid && obj?.type === "SOLID") filletSolid = obj;
46
- });
37
+ for (const obj of (partHistory.scene?.children || [])) {
38
+ if (obj?.owningFeatureID === filletFeature.inputParams.featureID && obj?.type === "SOLID") {
39
+ filletSolid = obj;
40
+ break;
41
+ }
42
+ if (typeof obj?.traverse === "function") {
43
+ obj.traverse((child) => {
44
+ if (!filletSolid && child?.owningFeatureID === filletFeature.inputParams.featureID && child?.type === "SOLID") {
45
+ filletSolid = child;
46
+ }
47
+ });
48
+ }
49
+ if (filletSolid) break;
50
+ }
47
51
  if (!filletSolid || typeof filletSolid._manifoldize !== "function") {
48
52
  throw new Error("Corner-bridge fillet did not produce a manifold-capable solid.");
49
53
  }
@@ -23,27 +23,28 @@ export async function afterRun_Fillet_NonClosed(partHistory) {
23
23
  throw new Error("Fillet feature missing from history");
24
24
  }
25
25
 
26
- const stubbed = filletFeature?.persistentData?.stubbed === true;
27
- const strategy = String(filletFeature?.persistentData?.strategy || "");
28
- if (!stubbed || strategy !== "miter_tangent_boolean") {
29
- throw new Error("Fillet feature should report stub metadata.");
26
+ const usedSheetMetalPath = filletFeature?.persistentData?.usedSheetMetalPath === true;
27
+ const decision = filletFeature?.persistentData?.edgeDirectionDecision || null;
28
+ if (usedSheetMetalPath || !decision || Number(decision.totalEdges || 0) !== 1) {
29
+ throw new Error("Non-closed fillet should produce a normal single-edge fillet result.");
30
30
  }
31
31
 
32
32
  // Verify that the fillet solid exists in the scene
33
- const filletGroup = (partHistory.scene?.children || []).find(
34
- (obj) => obj?.owningFeatureID === filletFeature.inputParams.featureID
35
- );
36
- if (!filletGroup) throw new Error("Fillet group not found in scene");
37
-
38
- // Stub path still returns a cloned solid so downstream features can reference it.
39
33
  let solidCount = 0;
40
- filletGroup.traverse((obj) => {
41
- if (obj?.type === "SOLID") solidCount++;
42
- });
34
+ for (const obj of (partHistory.scene?.children || [])) {
35
+ if (obj?.owningFeatureID === filletFeature.inputParams.featureID && obj?.type === "SOLID") {
36
+ solidCount++;
37
+ }
38
+ if (typeof obj?.traverse === "function") {
39
+ obj.traverse((child) => {
40
+ if (child?.owningFeatureID === filletFeature.inputParams.featureID && child?.type === "SOLID") solidCount++;
41
+ });
42
+ }
43
+ }
43
44
 
44
45
  if (solidCount === 0) {
45
46
  throw new Error("Fillet feature should produce at least one solid");
46
47
  }
47
48
 
48
- console.log(`✓ Non-closed fillet stub test passed: ${solidCount} solid(s) created`);
49
+ console.log(`✓ Non-closed fillet test passed: ${solidCount} solid(s) created`);
49
50
  }
@@ -40,18 +40,21 @@ export async function test_sheetMetal_corner_fillet_compound_reference(partHisto
40
40
  const result = await fillet.run(partHistory);
41
41
  const addedCount = Array.isArray(result?.added) ? result.added.length : 0;
42
42
  const removedCount = Array.isArray(result?.removed) ? result.removed.length : 0;
43
- if (addedCount !== 0 || removedCount !== 0) {
44
- throw new Error("Fillet stub should skip unresolved compound-reference selection without scene edits.");
43
+ if (addedCount !== 1 || removedCount !== 1) {
44
+ throw new Error("Compound corner reference should resolve to a sheet-metal fillet replacement.");
45
45
  }
46
46
 
47
47
  const persistent = fillet?.persistentData || {};
48
- if (persistent.stubbed !== true) {
49
- throw new Error("Fillet stub should set persistentData.stubbed=true.");
48
+ if (persistent.usedSheetMetalPath !== true) {
49
+ throw new Error("Compound corner reference should use the sheet-metal fillet path.");
50
50
  }
51
- if (String(persistent.strategy || "") !== "miter_tangent_boolean") {
52
- throw new Error("Fillet stub should report miter_tangent_boolean strategy.");
51
+ const summary = persistent.sheetMetalFilletSummary || {};
52
+ if (summary.applied !== 1 || summary.appliedCorners !== 1) {
53
+ throw new Error("Compound corner reference should apply exactly one sheet-metal corner fillet.");
53
54
  }
54
- if (String(persistent.skipped || "") !== "no_edges") {
55
- throw new Error(`Fillet stub should mark no_edges skip reason, got ${String(persistent.skipped || "")}.`);
55
+ const appliedTarget = Array.isArray(summary.appliedTargets) ? summary.appliedTargets[0] : null;
56
+ const cornerEdgeIds = Array.isArray(appliedTarget?.cornerEdgeIds) ? appliedTarget.cornerEdgeIds.join(",") : "";
57
+ if (cornerEdgeIds !== "SM.TAB3:flat_root:e2,SM.TAB3:flat_root:e3") {
58
+ throw new Error(`Compound corner reference should preserve both corner edges, got ${cornerEdgeIds}.`);
56
59
  }
57
60
  }