brep-io-kernel 1.0.0-ci.9

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 (271) hide show
  1. package/LICENSE.md +32 -0
  2. package/README.md +154 -0
  3. package/dist-kernel/brep-kernel.js +74699 -0
  4. package/package.json +58 -0
  5. package/src/BREP/AssemblyComponent.js +42 -0
  6. package/src/BREP/BREP.js +43 -0
  7. package/src/BREP/BetterSolid.js +805 -0
  8. package/src/BREP/Edge.js +103 -0
  9. package/src/BREP/Extrude.js +403 -0
  10. package/src/BREP/Face.js +187 -0
  11. package/src/BREP/MeshRepairer.js +634 -0
  12. package/src/BREP/OffsetShellSolid.js +614 -0
  13. package/src/BREP/PointCloudWrap.js +302 -0
  14. package/src/BREP/Revolve.js +345 -0
  15. package/src/BREP/SolidMethods/authoring.js +112 -0
  16. package/src/BREP/SolidMethods/booleanOps.js +230 -0
  17. package/src/BREP/SolidMethods/chamfer.js +122 -0
  18. package/src/BREP/SolidMethods/edgeResolution.js +25 -0
  19. package/src/BREP/SolidMethods/fillet.js +792 -0
  20. package/src/BREP/SolidMethods/index.js +72 -0
  21. package/src/BREP/SolidMethods/io.js +105 -0
  22. package/src/BREP/SolidMethods/lifecycle.js +103 -0
  23. package/src/BREP/SolidMethods/manifoldOps.js +375 -0
  24. package/src/BREP/SolidMethods/meshCleanup.js +2512 -0
  25. package/src/BREP/SolidMethods/meshQueries.js +264 -0
  26. package/src/BREP/SolidMethods/metadata.js +106 -0
  27. package/src/BREP/SolidMethods/metrics.js +51 -0
  28. package/src/BREP/SolidMethods/transforms.js +361 -0
  29. package/src/BREP/SolidMethods/visualize.js +508 -0
  30. package/src/BREP/SolidShared.js +26 -0
  31. package/src/BREP/Sweep.js +1596 -0
  32. package/src/BREP/Tube.js +857 -0
  33. package/src/BREP/Vertex.js +43 -0
  34. package/src/BREP/applyBooleanOperation.js +704 -0
  35. package/src/BREP/boundsUtils.js +48 -0
  36. package/src/BREP/chamfer.js +551 -0
  37. package/src/BREP/edgePolylineUtils.js +85 -0
  38. package/src/BREP/fillets/common.js +388 -0
  39. package/src/BREP/fillets/fillet.js +1422 -0
  40. package/src/BREP/fillets/filletGeometry.js +15 -0
  41. package/src/BREP/fillets/inset.js +389 -0
  42. package/src/BREP/fillets/offsetHelper.js +143 -0
  43. package/src/BREP/fillets/outset.js +88 -0
  44. package/src/BREP/helix.js +193 -0
  45. package/src/BREP/meshToBrep.js +234 -0
  46. package/src/BREP/primitives.js +279 -0
  47. package/src/BREP/setupManifold.js +71 -0
  48. package/src/BREP/threadGeometry.js +1120 -0
  49. package/src/BREP/triangleUtils.js +8 -0
  50. package/src/BREP/triangulate.js +608 -0
  51. package/src/FeatureRegistry.js +183 -0
  52. package/src/PartHistory.js +1132 -0
  53. package/src/UI/AccordionWidget.js +292 -0
  54. package/src/UI/CADmaterials.js +850 -0
  55. package/src/UI/EnvMonacoEditor.js +522 -0
  56. package/src/UI/FloatingWindow.js +396 -0
  57. package/src/UI/HistoryWidget.js +457 -0
  58. package/src/UI/MainToolbar.js +131 -0
  59. package/src/UI/ModelLibraryView.js +194 -0
  60. package/src/UI/OrthoCameraIdle.js +206 -0
  61. package/src/UI/PluginsWidget.js +280 -0
  62. package/src/UI/SceneListing.js +606 -0
  63. package/src/UI/SelectionFilter.js +629 -0
  64. package/src/UI/ViewCube.js +389 -0
  65. package/src/UI/assembly/AssemblyConstraintCollectionWidget.js +329 -0
  66. package/src/UI/assembly/AssemblyConstraintControlsWidget.js +282 -0
  67. package/src/UI/assembly/AssemblyConstraintsWidget.css +292 -0
  68. package/src/UI/assembly/AssemblyConstraintsWidget.js +1373 -0
  69. package/src/UI/assembly/constraintFaceUtils.js +115 -0
  70. package/src/UI/assembly/constraintHighlightUtils.js +70 -0
  71. package/src/UI/assembly/constraintLabelUtils.js +31 -0
  72. package/src/UI/assembly/constraintPointUtils.js +64 -0
  73. package/src/UI/assembly/constraintSelectionUtils.js +185 -0
  74. package/src/UI/assembly/constraintStatusUtils.js +142 -0
  75. package/src/UI/componentSelectorModal.js +240 -0
  76. package/src/UI/controls/CombinedTransformControls.js +386 -0
  77. package/src/UI/dialogs.js +351 -0
  78. package/src/UI/expressionsManager.js +100 -0
  79. package/src/UI/featureDialogWidgets/booleanField.js +25 -0
  80. package/src/UI/featureDialogWidgets/booleanOperationField.js +97 -0
  81. package/src/UI/featureDialogWidgets/buttonField.js +45 -0
  82. package/src/UI/featureDialogWidgets/componentSelectorField.js +102 -0
  83. package/src/UI/featureDialogWidgets/defaultField.js +23 -0
  84. package/src/UI/featureDialogWidgets/fileField.js +66 -0
  85. package/src/UI/featureDialogWidgets/index.js +34 -0
  86. package/src/UI/featureDialogWidgets/numberField.js +165 -0
  87. package/src/UI/featureDialogWidgets/optionsField.js +33 -0
  88. package/src/UI/featureDialogWidgets/referenceSelectionField.js +208 -0
  89. package/src/UI/featureDialogWidgets/stringField.js +24 -0
  90. package/src/UI/featureDialogWidgets/textareaField.js +28 -0
  91. package/src/UI/featureDialogWidgets/threadDesignationField.js +160 -0
  92. package/src/UI/featureDialogWidgets/transformField.js +252 -0
  93. package/src/UI/featureDialogWidgets/utils.js +43 -0
  94. package/src/UI/featureDialogWidgets/vec3Field.js +133 -0
  95. package/src/UI/featureDialogs.js +1414 -0
  96. package/src/UI/fileManagerWidget.js +615 -0
  97. package/src/UI/history/HistoryCollectionWidget.js +1294 -0
  98. package/src/UI/history/historyCollectionWidget.css.js +257 -0
  99. package/src/UI/history/historyDisplayInfo.js +133 -0
  100. package/src/UI/mobile.js +28 -0
  101. package/src/UI/objectDump.js +442 -0
  102. package/src/UI/pmi/AnnotationCollectionWidget.js +120 -0
  103. package/src/UI/pmi/AnnotationHistory.js +353 -0
  104. package/src/UI/pmi/AnnotationRegistry.js +90 -0
  105. package/src/UI/pmi/BaseAnnotation.js +269 -0
  106. package/src/UI/pmi/LabelOverlay.css +102 -0
  107. package/src/UI/pmi/LabelOverlay.js +191 -0
  108. package/src/UI/pmi/PMIMode.js +1550 -0
  109. package/src/UI/pmi/PMIViewsWidget.js +1098 -0
  110. package/src/UI/pmi/annUtils.js +729 -0
  111. package/src/UI/pmi/dimensions/AngleDimensionAnnotation.js +647 -0
  112. package/src/UI/pmi/dimensions/ExplodeBodyAnnotation.js +507 -0
  113. package/src/UI/pmi/dimensions/HoleCalloutAnnotation.js +462 -0
  114. package/src/UI/pmi/dimensions/LeaderAnnotation.js +403 -0
  115. package/src/UI/pmi/dimensions/LinearDimensionAnnotation.js +532 -0
  116. package/src/UI/pmi/dimensions/NoteAnnotation.js +110 -0
  117. package/src/UI/pmi/dimensions/RadialDimensionAnnotation.js +659 -0
  118. package/src/UI/pmi/pmiStyle.js +44 -0
  119. package/src/UI/sketcher/SketchMode3D.js +4095 -0
  120. package/src/UI/sketcher/dimensions.js +674 -0
  121. package/src/UI/sketcher/glyphs.js +236 -0
  122. package/src/UI/sketcher/highlights.js +60 -0
  123. package/src/UI/toolbarButtons/aboutButton.js +5 -0
  124. package/src/UI/toolbarButtons/exportButton.js +609 -0
  125. package/src/UI/toolbarButtons/flatPatternButton.js +307 -0
  126. package/src/UI/toolbarButtons/importButton.js +160 -0
  127. package/src/UI/toolbarButtons/inspectorToggleButton.js +12 -0
  128. package/src/UI/toolbarButtons/metadataButton.js +1063 -0
  129. package/src/UI/toolbarButtons/orientToFaceButton.js +114 -0
  130. package/src/UI/toolbarButtons/registerDefaultButtons.js +46 -0
  131. package/src/UI/toolbarButtons/saveButton.js +99 -0
  132. package/src/UI/toolbarButtons/scriptRunnerButton.js +302 -0
  133. package/src/UI/toolbarButtons/testsButton.js +26 -0
  134. package/src/UI/toolbarButtons/undoRedoButtons.js +25 -0
  135. package/src/UI/toolbarButtons/wireframeToggleButton.js +5 -0
  136. package/src/UI/toolbarButtons/zoomToFitButton.js +5 -0
  137. package/src/UI/triangleDebuggerWindow.js +945 -0
  138. package/src/UI/viewer.js +4228 -0
  139. package/src/assemblyConstraints/AssemblyConstraintHistory.js +1576 -0
  140. package/src/assemblyConstraints/AssemblyConstraintRegistry.js +120 -0
  141. package/src/assemblyConstraints/BaseAssemblyConstraint.js +66 -0
  142. package/src/assemblyConstraints/constraintExpressionUtils.js +35 -0
  143. package/src/assemblyConstraints/constraintUtils/parallelAlignment.js +676 -0
  144. package/src/assemblyConstraints/constraints/AngleConstraint.js +485 -0
  145. package/src/assemblyConstraints/constraints/CoincidentConstraint.js +194 -0
  146. package/src/assemblyConstraints/constraints/DistanceConstraint.js +616 -0
  147. package/src/assemblyConstraints/constraints/FixedConstraint.js +78 -0
  148. package/src/assemblyConstraints/constraints/ParallelConstraint.js +252 -0
  149. package/src/assemblyConstraints/constraints/TouchAlignConstraint.js +961 -0
  150. package/src/core/entities/HistoryCollectionBase.js +72 -0
  151. package/src/core/entities/ListEntityBase.js +109 -0
  152. package/src/core/entities/schemaProcesser.js +121 -0
  153. package/src/exporters/sheetMetalFlatPattern.js +659 -0
  154. package/src/exporters/sheetMetalUnfold.js +862 -0
  155. package/src/exporters/step.js +1135 -0
  156. package/src/exporters/threeMF.js +575 -0
  157. package/src/features/assemblyComponent/AssemblyComponentFeature.js +780 -0
  158. package/src/features/boolean/BooleanFeature.js +94 -0
  159. package/src/features/chamfer/ChamferFeature.js +116 -0
  160. package/src/features/datium/DatiumFeature.js +80 -0
  161. package/src/features/edgeFeatureUtils.js +41 -0
  162. package/src/features/extrude/ExtrudeFeature.js +143 -0
  163. package/src/features/fillet/FilletFeature.js +197 -0
  164. package/src/features/helix/HelixFeature.js +405 -0
  165. package/src/features/hole/HoleFeature.js +1050 -0
  166. package/src/features/hole/screwClearance.js +86 -0
  167. package/src/features/hole/threadDesignationCatalog.js +149 -0
  168. package/src/features/imageHeightSolid/ImageHeightmapSolidFeature.js +463 -0
  169. package/src/features/imageToFace/ImageToFaceFeature.js +727 -0
  170. package/src/features/imageToFace/imageEditor.js +1270 -0
  171. package/src/features/imageToFace/traceUtils.js +971 -0
  172. package/src/features/import3dModel/Import3dModelFeature.js +151 -0
  173. package/src/features/loft/LoftFeature.js +605 -0
  174. package/src/features/mirror/MirrorFeature.js +151 -0
  175. package/src/features/offsetFace/OffsetFaceFeature.js +370 -0
  176. package/src/features/offsetShell/OffsetShellFeature.js +89 -0
  177. package/src/features/overlapCleanup/OverlapCleanupFeature.js +85 -0
  178. package/src/features/pattern/PatternFeature.js +275 -0
  179. package/src/features/patternLinear/PatternLinearFeature.js +120 -0
  180. package/src/features/patternRadial/PatternRadialFeature.js +186 -0
  181. package/src/features/plane/PlaneFeature.js +154 -0
  182. package/src/features/primitiveCone/primitiveConeFeature.js +99 -0
  183. package/src/features/primitiveCube/primitiveCubeFeature.js +70 -0
  184. package/src/features/primitiveCylinder/primitiveCylinderFeature.js +91 -0
  185. package/src/features/primitivePyramid/primitivePyramidFeature.js +72 -0
  186. package/src/features/primitiveSphere/primitiveSphereFeature.js +62 -0
  187. package/src/features/primitiveTorus/primitiveTorusFeature.js +109 -0
  188. package/src/features/remesh/RemeshFeature.js +97 -0
  189. package/src/features/revolve/RevolveFeature.js +111 -0
  190. package/src/features/selectionUtils.js +118 -0
  191. package/src/features/sheetMetal/SheetMetalContourFlangeFeature.js +1656 -0
  192. package/src/features/sheetMetal/SheetMetalCutoutFeature.js +1056 -0
  193. package/src/features/sheetMetal/SheetMetalFlangeFeature.js +1568 -0
  194. package/src/features/sheetMetal/SheetMetalHemFeature.js +43 -0
  195. package/src/features/sheetMetal/SheetMetalObject.js +141 -0
  196. package/src/features/sheetMetal/SheetMetalTabFeature.js +176 -0
  197. package/src/features/sheetMetal/UNFOLD_NEUTRAL_REQUIREMENTS.md +153 -0
  198. package/src/features/sheetMetal/contour-flange-rebuild-spec.md +261 -0
  199. package/src/features/sheetMetal/profileUtils.js +25 -0
  200. package/src/features/sheetMetal/sheetMetalCleanup.js +9 -0
  201. package/src/features/sheetMetal/sheetMetalFaceTypes.js +146 -0
  202. package/src/features/sheetMetal/sheetMetalMetadata.js +165 -0
  203. package/src/features/sheetMetal/sheetMetalPipeline.js +169 -0
  204. package/src/features/sheetMetal/sheetMetalProfileUtils.js +216 -0
  205. package/src/features/sheetMetal/sheetMetalTabUtils.js +29 -0
  206. package/src/features/sheetMetal/sheetMetalTree.js +210 -0
  207. package/src/features/sketch/SketchFeature.js +955 -0
  208. package/src/features/sketch/sketchSolver2D/ConstraintEngine.js +800 -0
  209. package/src/features/sketch/sketchSolver2D/constraintDefinitions.js +704 -0
  210. package/src/features/sketch/sketchSolver2D/mathHelpersMod.js +307 -0
  211. package/src/features/spline/SplineEditorSession.js +988 -0
  212. package/src/features/spline/SplineFeature.js +1388 -0
  213. package/src/features/spline/splineUtils.js +218 -0
  214. package/src/features/sweep/SweepFeature.js +110 -0
  215. package/src/features/transform/TransformFeature.js +152 -0
  216. package/src/features/tube/TubeFeature.js +635 -0
  217. package/src/fs.proxy.js +625 -0
  218. package/src/idbStorage.js +254 -0
  219. package/src/index.js +12 -0
  220. package/src/main.js +15 -0
  221. package/src/metadataManager.js +64 -0
  222. package/src/path.proxy.js +277 -0
  223. package/src/plugins/ghLoader.worker.js +151 -0
  224. package/src/plugins/pluginManager.js +286 -0
  225. package/src/pmi/PMIViewsManager.js +134 -0
  226. package/src/services/componentLibrary.js +198 -0
  227. package/src/tests/ConsoleCapture.js +189 -0
  228. package/src/tests/S7-diagnostics-2025-12-23T18-37-23-570Z.json +630 -0
  229. package/src/tests/browserTests.js +597 -0
  230. package/src/tests/debugBoolean.js +225 -0
  231. package/src/tests/partFiles/badBoolean.json +957 -0
  232. package/src/tests/partFiles/extrudeTest.json +88 -0
  233. package/src/tests/partFiles/filletFail.json +58 -0
  234. package/src/tests/partFiles/import_TEst.part.part.json +646 -0
  235. package/src/tests/partFiles/sheetMetalHem.BREP.json +734 -0
  236. package/src/tests/test_boolean_subtract.js +27 -0
  237. package/src/tests/test_chamfer.js +17 -0
  238. package/src/tests/test_extrudeFace.js +24 -0
  239. package/src/tests/test_fillet.js +17 -0
  240. package/src/tests/test_fillet_nonClosed.js +45 -0
  241. package/src/tests/test_filletsMoreDifficult.js +46 -0
  242. package/src/tests/test_history_features_basic.js +149 -0
  243. package/src/tests/test_hole.js +282 -0
  244. package/src/tests/test_mirror.js +16 -0
  245. package/src/tests/test_offsetShellGrouping.js +85 -0
  246. package/src/tests/test_plane.js +4 -0
  247. package/src/tests/test_primitiveCone.js +11 -0
  248. package/src/tests/test_primitiveCube.js +7 -0
  249. package/src/tests/test_primitiveCylinder.js +8 -0
  250. package/src/tests/test_primitivePyramid.js +9 -0
  251. package/src/tests/test_primitiveSphere.js +17 -0
  252. package/src/tests/test_primitiveTorus.js +21 -0
  253. package/src/tests/test_pushFace.js +126 -0
  254. package/src/tests/test_sheetMetalContourFlange.js +125 -0
  255. package/src/tests/test_sheetMetal_features.js +80 -0
  256. package/src/tests/test_sketch_openLoop.js +45 -0
  257. package/src/tests/test_solidMetrics.js +58 -0
  258. package/src/tests/test_stlLoader.js +1889 -0
  259. package/src/tests/test_sweepFace.js +55 -0
  260. package/src/tests/test_tube.js +45 -0
  261. package/src/tests/test_tube_closedLoop.js +67 -0
  262. package/src/tests/tests.js +493 -0
  263. package/src/tools/assemblyConstraintDialogCapturePage.js +56 -0
  264. package/src/tools/dialogCapturePageFactory.js +227 -0
  265. package/src/tools/featureDialogCapturePage.js +47 -0
  266. package/src/tools/pmiAnnotationDialogCapturePage.js +60 -0
  267. package/src/utils/axisHelpers.js +99 -0
  268. package/src/utils/deepClone.js +69 -0
  269. package/src/utils/geometryTolerance.js +37 -0
  270. package/src/utils/normalizeTypeString.js +8 -0
  271. package/src/utils/xformMath.js +51 -0
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Mesh queries and face utilities.
3
+ */
4
+
5
+ /** Return the underlying MeshGL (fresh from Manifold so it reflects any CSG). */
6
+ export function getMesh() {
7
+ return this._manifoldize().getMesh();
8
+ }
9
+
10
+ /** Build a cache: faceID -> array of triangle indices. */
11
+ export function _ensureFaceIndex() {
12
+ if (this._faceIndex) return;
13
+ const mesh = this.getMesh();
14
+ const { triVerts, faceID } = mesh;
15
+ const triCount = (triVerts.length / 3) | 0;
16
+ const map = new Map();
17
+ if (faceID && faceID.length === triCount) {
18
+ for (let t = 0; t < triCount; t++) {
19
+ const id = faceID[t];
20
+ let arr = map.get(id);
21
+ if (!arr) { arr = []; map.set(id, arr); }
22
+ arr.push(t);
23
+ }
24
+ }
25
+ this._faceIndex = map;
26
+ try { if (mesh && typeof mesh.delete === 'function') mesh.delete(); } catch { }
27
+ }
28
+
29
+ /**
30
+ * Get all triangles belonging to a face by name.
31
+ * Returns objects with positions; also includes vertex indices.
32
+ */
33
+ export function getFace(name) {
34
+ const id = this._faceNameToID.get(name);
35
+ if (id === undefined) return [];
36
+
37
+ this._ensureFaceIndex();
38
+ const mesh = this.getMesh();
39
+ const { vertProperties, triVerts } = mesh;
40
+ const tris = this._faceIndex.get(id) || [];
41
+
42
+ const out = [];
43
+ for (let idx = 0; idx < tris.length; idx++) {
44
+ const t = tris[idx];
45
+ const base = t * 3;
46
+ const i0 = triVerts[base + 0];
47
+ const i1 = triVerts[base + 1];
48
+ const i2 = triVerts[base + 2];
49
+
50
+ const p0 = [
51
+ vertProperties[i0 * 3 + 0],
52
+ vertProperties[i0 * 3 + 1],
53
+ vertProperties[i0 * 3 + 2],
54
+ ];
55
+ const p1 = [
56
+ vertProperties[i1 * 3 + 0],
57
+ vertProperties[i1 * 3 + 1],
58
+ vertProperties[i1 * 3 + 2],
59
+ ];
60
+ const p2 = [
61
+ vertProperties[i2 * 3 + 0],
62
+ vertProperties[i2 * 3 + 1],
63
+ vertProperties[i2 * 3 + 2],
64
+ ];
65
+
66
+ out.push({ faceName: name, indices: [i0, i1, i2], p1: p0, p2: p1, p3: p2 });
67
+ }
68
+ try { return out; } finally { try { if (mesh && typeof mesh.delete === 'function') mesh.delete(); } catch { } }
69
+ }
70
+
71
+ /**
72
+ * Enumerate faces with their triangles in one pass.
73
+ */
74
+ export function getFaces(includeEmpty = false) {
75
+ this._ensureFaceIndex();
76
+ const mesh = this.getMesh();
77
+ const { vertProperties, triVerts } = mesh;
78
+
79
+ const out = [];
80
+ const nameToTris = new Map();
81
+ if (includeEmpty) {
82
+ for (const fname of this.getFaceNames()) nameToTris.set(fname, []);
83
+ }
84
+
85
+ for (const [id, triList] of this._faceIndex.entries()) {
86
+ const name = this._idToFaceName.get(id) || `FACE_${id}`;
87
+ let arr = nameToTris.get(name);
88
+ if (!arr) { arr = []; nameToTris.set(name, arr); }
89
+ for (let idx = 0; idx < triList.length; idx++) {
90
+ const t = triList[idx];
91
+ const base = t * 3;
92
+ const i0 = triVerts[base + 0];
93
+ const i1 = triVerts[base + 1];
94
+ const i2 = triVerts[base + 2];
95
+ const p0 = [
96
+ vertProperties[i0 * 3 + 0],
97
+ vertProperties[i0 * 3 + 1],
98
+ vertProperties[i0 * 3 + 2],
99
+ ];
100
+ const p1 = [
101
+ vertProperties[i1 * 3 + 0],
102
+ vertProperties[i1 * 3 + 1],
103
+ vertProperties[i1 * 3 + 2],
104
+ ];
105
+ const p2 = [
106
+ vertProperties[i2 * 3 + 0],
107
+ vertProperties[i2 * 3 + 1],
108
+ vertProperties[i2 * 3 + 2],
109
+ ];
110
+ arr.push({ faceName: name, indices: [i0, i1, i2], p1: p0, p2: p1, p3: p2 });
111
+ }
112
+ }
113
+
114
+ for (const [faceName, triangles] of nameToTris.entries()) {
115
+ out.push({ faceName, triangles });
116
+ }
117
+ return out;
118
+ }
119
+
120
+ /**
121
+ * Compute connected polylines for boundary edges between pairs of face labels.
122
+ */
123
+ export function getBoundaryEdgePolylines() {
124
+ const mesh = this.getMesh();
125
+ try {
126
+ const { vertProperties, triVerts, faceID } = mesh;
127
+ const triCount = (triVerts.length / 3) | 0;
128
+ const nv = (vertProperties.length / 3) | 0;
129
+ const NV = BigInt(nv);
130
+ const ukey = (a, b) => {
131
+ const A = BigInt(a); const B = BigInt(b);
132
+ return A < B ? A * NV + B : B * NV + A;
133
+ };
134
+
135
+ const e2t = new Map(); // key -> [{id, a, b, tri}...]
136
+ for (let t = 0; t < triCount; t++) {
137
+ const id = faceID ? faceID[t] : undefined;
138
+ const base = t * 3;
139
+ const i0 = triVerts[base + 0], i1 = triVerts[base + 1], i2 = triVerts[base + 2];
140
+ const edges = [[i0, i1], [i1, i2], [i2, i0]];
141
+ for (let k = 0; k < 3; k++) {
142
+ const a = edges[k][0], b = edges[k][1];
143
+ const key = ukey(a, b);
144
+ let arr = e2t.get(key);
145
+ if (!arr) { arr = []; e2t.set(key, arr); }
146
+ arr.push({ id, a, b, tri: t });
147
+ }
148
+ }
149
+
150
+ const pairToEdges = new Map(); // pairKey(JSON '[nameA,nameB]') -> array of [u,v]
151
+ for (const [, arr] of e2t.entries()) {
152
+ if (arr.length !== 2) continue;
153
+ const a = arr[0], b = arr[1];
154
+ if (a.id === b.id) continue;
155
+ const nameA = this._idToFaceName.get(a.id) || `FACE_${a.id}`;
156
+ const nameB = this._idToFaceName.get(b.id) || `FACE_${b.id}`;
157
+ const pair = nameA < nameB ? [nameA, nameB] : [nameB, nameA];
158
+ const pairKey = JSON.stringify(pair);
159
+ let list = pairToEdges.get(pairKey);
160
+ if (!list) { list = []; pairToEdges.set(pairKey, list); }
161
+ const v0 = Math.min(a.a, a.b);
162
+ const v1 = Math.max(a.a, a.b);
163
+ list.push([v0, v1]);
164
+ }
165
+
166
+ const polylines = [];
167
+ for (const [pairKey, edges] of pairToEdges.entries()) {
168
+ const adj = new Map(); // v -> Set(neighbors)
169
+ const edgeVisited = new Set(); // `${min},${max}`
170
+ const ek = (u, v) => (u < v ? `${u},${v}` : `${v},${u}`);
171
+ for (const [u, v] of edges) {
172
+ if (!adj.has(u)) adj.set(u, new Set());
173
+ if (!adj.has(v)) adj.set(v, new Set());
174
+ adj.get(u).add(v);
175
+ adj.get(v).add(u);
176
+ }
177
+
178
+ const [faceA, faceB] = JSON.parse(pairKey);
179
+ let idx = 0;
180
+
181
+ const visitChainFrom = (start) => {
182
+ const chain = [];
183
+ let prev = -1;
184
+ let curr = start;
185
+ chain.push(curr);
186
+ while (true) {
187
+ const nbrs = adj.get(curr) || new Set();
188
+ let next = undefined;
189
+ for (const n of nbrs) {
190
+ const key = ek(curr, n);
191
+ if (edgeVisited.has(key)) continue;
192
+ if (n === prev) continue;
193
+ next = n; edgeVisited.add(key); break;
194
+ }
195
+ if (next === undefined) break;
196
+ prev = curr; curr = next; chain.push(curr);
197
+ }
198
+ return chain;
199
+ };
200
+
201
+ for (const [v, nbrs] of adj.entries()) {
202
+ if ((nbrs.size | 0) === 1) {
203
+ const n = [...nbrs][0];
204
+ const key = ek(v, n);
205
+ if (edgeVisited.has(key)) continue;
206
+ const chain = visitChainFrom(v);
207
+ const positions = chain.map(vi => [
208
+ vertProperties[vi * 3 + 0],
209
+ vertProperties[vi * 3 + 1],
210
+ vertProperties[vi * 3 + 2],
211
+ ]);
212
+ polylines.push({ name: `${faceA}|${faceB}[${idx++}]`, faceA, faceB, indices: chain, positions, closedLoop: false });
213
+ }
214
+ }
215
+
216
+ const buildLoopFromEdge = (startU, startV) => {
217
+ const chain = [startU, startV];
218
+ let prev = startU;
219
+ let curr = startV;
220
+ edgeVisited.add(ek(startU, startV));
221
+ while (true) {
222
+ const nbrs = adj.get(curr) || new Set();
223
+ let next = undefined;
224
+ for (const n of nbrs) {
225
+ if (n === prev) continue;
226
+ const key = ek(curr, n);
227
+ if (edgeVisited.has(key)) continue;
228
+ next = n; break;
229
+ }
230
+ if (next === undefined) break;
231
+ edgeVisited.add(ek(curr, next));
232
+ chain.push(next);
233
+ prev = curr; curr = next;
234
+ }
235
+ const start = chain[0];
236
+ const last = chain[chain.length - 1];
237
+ const nbrsLast = adj.get(last) || new Set();
238
+ if (nbrsLast.has(start)) {
239
+ edgeVisited.add(ek(last, start));
240
+ chain.push(start);
241
+ }
242
+ return chain;
243
+ };
244
+
245
+ for (const [u, nbrs] of adj.entries()) {
246
+ for (const v of nbrs) {
247
+ const key = ek(u, v);
248
+ if (edgeVisited.has(key)) continue;
249
+ const chain = buildLoopFromEdge(u, v);
250
+ const positions = chain.map(vi => [
251
+ vertProperties[vi * 3 + 0],
252
+ vertProperties[vi * 3 + 1],
253
+ vertProperties[vi * 3 + 2],
254
+ ]);
255
+ const closed = chain.length >= 3 && chain[0] === chain[chain.length - 1];
256
+ polylines.push({ name: `${faceA}|${faceB}[${idx++}]`, faceA, faceB, indices: chain, positions, closedLoop: closed });
257
+ }
258
+ }
259
+ }
260
+
261
+ return polylines;
262
+ } finally { try { if (mesh && typeof mesh.delete === 'function') mesh.delete(); } catch { } }
263
+ }
264
+
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Face and edge metadata helpers.
3
+ */
4
+
5
+ /** Set metadata for a face (e.g., radius for cylindrical faces). */
6
+ export function setFaceMetadata(faceName, metadata) {
7
+ if (!metadata || typeof metadata !== 'object') return this;
8
+ const existing = this.getFaceMetadata(faceName);
9
+ const base = existing && typeof existing === 'object' ? existing : {};
10
+ this._faceMetadata.set(faceName, { ...base, ...metadata });
11
+ return this;
12
+ }
13
+
14
+ /** Get metadata for a face. */
15
+ export function getFaceMetadata(faceName) {
16
+ return this._faceMetadata.get(faceName) || {};
17
+ }
18
+
19
+ /** Convenience: list all face names present in this solid. */
20
+ export function getFaceNames() {
21
+ return [...this._faceNameToID.keys()];
22
+ }
23
+
24
+ /** Rename a face; if newName exists, merge triangles/metadata into it. */
25
+ export function renameFace(oldName, newName) {
26
+ if (!oldName || !newName || oldName === newName) return this;
27
+ const oldId = this._faceNameToID.get(oldName);
28
+ if (oldId === undefined) return this;
29
+
30
+ const newId = this._faceNameToID.get(newName);
31
+ const oldMeta = (this._faceMetadata && this._faceMetadata.get(oldName));
32
+ const newMeta = (this._faceMetadata && this._faceMetadata.get(newName));
33
+ const mergedMeta = (oldMeta || newMeta) ? { ...(oldMeta || {}), ...(newMeta || {}) } : null;
34
+
35
+ // Simple rename when the target name is unused (or maps to the same ID).
36
+ if (newId === undefined || newId === oldId) {
37
+ this._faceNameToID.delete(oldName);
38
+ this._faceNameToID.set(newName, oldId);
39
+ if (this._idToFaceName) this._idToFaceName.set(oldId, newName);
40
+ if (this._faceMetadata) {
41
+ if (mergedMeta) this._faceMetadata.set(newName, mergedMeta);
42
+ this._faceMetadata.delete(oldName);
43
+ }
44
+ return this;
45
+ }
46
+
47
+ // Merge: retarget all triangles using oldId to the existing newId.
48
+ let changed = false;
49
+ for (let i = 0; i < this._triIDs.length; i++) {
50
+ if (this._triIDs[i] === oldId) {
51
+ this._triIDs[i] = newId;
52
+ changed = true;
53
+ }
54
+ }
55
+
56
+ this._faceNameToID.delete(oldName);
57
+ if (this._idToFaceName) {
58
+ this._idToFaceName.delete(oldId);
59
+ this._idToFaceName.set(newId, newName);
60
+ }
61
+ if (this._faceMetadata) {
62
+ if (mergedMeta) this._faceMetadata.set(newName, mergedMeta);
63
+ this._faceMetadata.delete(oldName);
64
+ }
65
+ if (changed) {
66
+ this._dirty = true;
67
+ this._faceIndex = null;
68
+ }
69
+ return this;
70
+ }
71
+
72
+ /** Set metadata for an edge. */
73
+ export function setEdgeMetadata(edgeName, metadata) {
74
+ if (!metadata || typeof metadata !== 'object') return this;
75
+ const existing = this.getEdgeMetadata(edgeName);
76
+ const base = existing && typeof existing === 'object' ? existing : {};
77
+ this._edgeMetadata.set(edgeName, { ...base, ...metadata });
78
+ return this;
79
+ }
80
+
81
+ /** Get metadata for an edge. */
82
+ export function getEdgeMetadata(edgeName) {
83
+ return this._edgeMetadata.get(edgeName) || null;
84
+ }
85
+
86
+ /** Combine face metadata maps across two solids. */
87
+ export function _combineFaceMetadata(other) {
88
+ const merged = new Map(this._faceMetadata);
89
+ if (other && other._faceMetadata) {
90
+ for (const [faceName, metadata] of other._faceMetadata.entries()) {
91
+ merged.set(faceName, { ...metadata });
92
+ }
93
+ }
94
+ return merged;
95
+ }
96
+
97
+ /** Combine edge metadata maps across two solids. */
98
+ export function _combineEdgeMetadata(other) {
99
+ const merged = new Map(this._edgeMetadata);
100
+ if (other && other._edgeMetadata) {
101
+ for (const [edgeName, metadata] of other._edgeMetadata.entries()) {
102
+ merged.set(edgeName, { ...metadata });
103
+ }
104
+ }
105
+ return merged;
106
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Geometric measurements.
3
+ */
4
+ import { computeTriangleArea } from '../triangleUtils.js';
5
+
6
+ export function volume() {
7
+ const mesh = this.getMesh();
8
+ try {
9
+ const vp = mesh.vertProperties;
10
+ const tv = mesh.triVerts;
11
+ let vol6 = 0;
12
+ for (let t = 0; t < tv.length; t += 3) {
13
+ const i0 = tv[t] * 3, i1 = tv[t + 1] * 3, i2 = tv[t + 2] * 3;
14
+ const x0 = vp[i0], y0 = vp[i0 + 1], z0 = vp[i0 + 2];
15
+ const x1 = vp[i1], y1 = vp[i1 + 1], z1 = vp[i1 + 2];
16
+ const x2 = vp[i2], y2 = vp[i2 + 1], z2 = vp[i2 + 2];
17
+ vol6 += x0 * (y1 * z2 - z1 * y2)
18
+ - y0 * (x1 * z2 - z1 * x2)
19
+ + z0 * (x1 * y2 - y1 * x2);
20
+ }
21
+ return Math.abs(vol6) / 6.0;
22
+ } finally { try { if (mesh && typeof mesh.delete === 'function') mesh.delete(); } catch { } }
23
+ }
24
+
25
+ export function surfaceArea() {
26
+ const mesh = this.getMesh();
27
+ try {
28
+ const vp = mesh.vertProperties;
29
+ const tv = mesh.triVerts;
30
+ let area = 0;
31
+ for (let t = 0; t < tv.length; t += 3) {
32
+ const i0 = tv[t] * 3, i1 = tv[t + 1] * 3, i2 = tv[t + 2] * 3;
33
+ const ax = vp[i0], ay = vp[i0 + 1], az = vp[i0 + 2];
34
+ const bx = vp[i1], by = vp[i1 + 1], bz = vp[i1 + 2];
35
+ const cx = vp[i2], cy = vp[i2 + 1], cz = vp[i2 + 2];
36
+ area += computeTriangleArea(ax, ay, az, bx, by, bz, cx, cy, cz);
37
+ }
38
+ return area;
39
+ } finally { try { if (mesh && typeof mesh.delete === 'function') mesh.delete(); } catch { } }
40
+ }
41
+
42
+ /**
43
+ * Count triangles in the current mesh.
44
+ */
45
+ export function getTriangleCount() {
46
+ const mesh = this.getMesh();
47
+ try {
48
+ const tv = mesh.triVerts;
49
+ return (tv.length / 3) | 0;
50
+ } finally { try { if (mesh && typeof mesh.delete === 'function') mesh.delete(); } catch { } }
51
+ }