brep-io-kernel 1.0.0

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 (403) hide show
  1. package/LICENSE.md +32 -0
  2. package/README.md +144 -0
  3. package/dist-kernel/brep-kernel.js +74699 -0
  4. package/dist-kernel/help/CONTRIBUTING.html +248 -0
  5. package/dist-kernel/help/LICENSE.html +248 -0
  6. package/dist-kernel/help/MODELING.png +0 -0
  7. package/dist-kernel/help/PMI.png +0 -0
  8. package/dist-kernel/help/SKETCH.png +0 -0
  9. package/dist-kernel/help/assembly-constraints__Coincident_Constraint_dialog.png +0 -0
  10. package/dist-kernel/help/assembly-constraints___Angle_Constraint_dialog.png +0 -0
  11. package/dist-kernel/help/assembly-constraints___Distance_Constraint_dialog.png +0 -0
  12. package/dist-kernel/help/assembly-constraints___Fixed_Constraint_dialog.png +0 -0
  13. package/dist-kernel/help/assembly-constraints___Parallel_Constraint_dialog.png +0 -0
  14. package/dist-kernel/help/assembly-constraints___Touch_Align_Constraint_dialog.png +0 -0
  15. package/dist-kernel/help/assembly-constraints__angle-constraint.html +248 -0
  16. package/dist-kernel/help/assembly-constraints__coincident-constraint.html +248 -0
  17. package/dist-kernel/help/assembly-constraints__distance-constraint.html +248 -0
  18. package/dist-kernel/help/assembly-constraints__fixed-constraint.html +248 -0
  19. package/dist-kernel/help/assembly-constraints__parallel-constraint.html +248 -0
  20. package/dist-kernel/help/assembly-constraints__solver.html +248 -0
  21. package/dist-kernel/help/assembly-constraints__touch-align-constraint.html +248 -0
  22. package/dist-kernel/help/brep-api.html +263 -0
  23. package/dist-kernel/help/brep-kernel.html +258 -0
  24. package/dist-kernel/help/brep-model.html +248 -0
  25. package/dist-kernel/help/cylindrical-face-radius-embedding.html +290 -0
  26. package/dist-kernel/help/dialog-screenshots.html +248 -0
  27. package/dist-kernel/help/extruded-sketch-radius-embedding.html +336 -0
  28. package/dist-kernel/help/features__Assembly_Component_dialog.png +0 -0
  29. package/dist-kernel/help/features__Boolean_dialog.png +0 -0
  30. package/dist-kernel/help/features__Chamfer_dialog.png +0 -0
  31. package/dist-kernel/help/features__Datium_dialog.png +0 -0
  32. package/dist-kernel/help/features__Extrude_dialog.png +0 -0
  33. package/dist-kernel/help/features__Fillet_dialog.png +0 -0
  34. package/dist-kernel/help/features__Helix_dialog.png +0 -0
  35. package/dist-kernel/help/features__Hole_dialog.png +0 -0
  36. package/dist-kernel/help/features__Image_Heightmap_Solid_dialog.png +0 -0
  37. package/dist-kernel/help/features__Image_to_Face_dialog.png +0 -0
  38. package/dist-kernel/help/features__Import_3D_Model_dialog.png +0 -0
  39. package/dist-kernel/help/features__Loft_dialog.png +0 -0
  40. package/dist-kernel/help/features__Mirror_dialog.png +0 -0
  41. package/dist-kernel/help/features__Offset_Shell_dialog.png +0 -0
  42. package/dist-kernel/help/features__Overlap_Cleanup_dialog.png +0 -0
  43. package/dist-kernel/help/features__Pattern_Linear_dialog.png +0 -0
  44. package/dist-kernel/help/features__Pattern_Radial_dialog.png +0 -0
  45. package/dist-kernel/help/features__Pattern_dialog.png +0 -0
  46. package/dist-kernel/help/features__Plane_dialog.png +0 -0
  47. package/dist-kernel/help/features__Primitive_Cone_dialog.png +0 -0
  48. package/dist-kernel/help/features__Primitive_Cube_dialog.png +0 -0
  49. package/dist-kernel/help/features__Primitive_Cylinder_dialog.png +0 -0
  50. package/dist-kernel/help/features__Primitive_Pyramid_dialog.png +0 -0
  51. package/dist-kernel/help/features__Primitive_Sphere_dialog.png +0 -0
  52. package/dist-kernel/help/features__Primitive_Torus_dialog.png +0 -0
  53. package/dist-kernel/help/features__Remesh_dialog.png +0 -0
  54. package/dist-kernel/help/features__Revolve_dialog.png +0 -0
  55. package/dist-kernel/help/features__Sheet_Metal_Contour_Flange_dialog.png +0 -0
  56. package/dist-kernel/help/features__Sheet_Metal_Cutout_dialog.png +0 -0
  57. package/dist-kernel/help/features__Sheet_Metal_Flange_dialog.png +0 -0
  58. package/dist-kernel/help/features__Sheet_Metal_Tab_dialog.png +0 -0
  59. package/dist-kernel/help/features__Sketch_dialog.png +0 -0
  60. package/dist-kernel/help/features__Spline_dialog.png +0 -0
  61. package/dist-kernel/help/features__Sweep_dialog.png +0 -0
  62. package/dist-kernel/help/features__Transform_dialog.png +0 -0
  63. package/dist-kernel/help/features__Tube_dialog.png +0 -0
  64. package/dist-kernel/help/features__assembly-component.html +248 -0
  65. package/dist-kernel/help/features__boolean.html +248 -0
  66. package/dist-kernel/help/features__chamfer.html +248 -0
  67. package/dist-kernel/help/features__datium.html +248 -0
  68. package/dist-kernel/help/features__datum.html +248 -0
  69. package/dist-kernel/help/features__extrude.html +248 -0
  70. package/dist-kernel/help/features__fillet.html +248 -0
  71. package/dist-kernel/help/features__helix.html +248 -0
  72. package/dist-kernel/help/features__hole.html +248 -0
  73. package/dist-kernel/help/features__image-heightmap-solid.html +248 -0
  74. package/dist-kernel/help/features__image-to-face-2D_dialog.png +0 -0
  75. package/dist-kernel/help/features__image-to-face-3D_dialog.png +0 -0
  76. package/dist-kernel/help/features__image-to-face.html +248 -0
  77. package/dist-kernel/help/features__import-3d-model.html +248 -0
  78. package/dist-kernel/help/features__index.html +248 -0
  79. package/dist-kernel/help/features__loft.html +248 -0
  80. package/dist-kernel/help/features__mirror.html +248 -0
  81. package/dist-kernel/help/features__offset-shell.html +248 -0
  82. package/dist-kernel/help/features__pattern-linear.html +248 -0
  83. package/dist-kernel/help/features__pattern-radial.html +248 -0
  84. package/dist-kernel/help/features__pattern.html +248 -0
  85. package/dist-kernel/help/features__plane.html +248 -0
  86. package/dist-kernel/help/features__primitive-cone.html +248 -0
  87. package/dist-kernel/help/features__primitive-cube.html +248 -0
  88. package/dist-kernel/help/features__primitive-cylinder.html +248 -0
  89. package/dist-kernel/help/features__primitive-pyramid.html +248 -0
  90. package/dist-kernel/help/features__primitive-sphere.html +248 -0
  91. package/dist-kernel/help/features__primitive-torus.html +248 -0
  92. package/dist-kernel/help/features__remesh.html +248 -0
  93. package/dist-kernel/help/features__revolve.html +248 -0
  94. package/dist-kernel/help/features__sheet-metal-contour-flange.html +248 -0
  95. package/dist-kernel/help/features__sheet-metal-flange.html +248 -0
  96. package/dist-kernel/help/features__sheet-metal-tab.html +248 -0
  97. package/dist-kernel/help/features__sketch.html +248 -0
  98. package/dist-kernel/help/features__spline.html +248 -0
  99. package/dist-kernel/help/features__sweep.html +248 -0
  100. package/dist-kernel/help/features__transform.html +248 -0
  101. package/dist-kernel/help/features__tube.html +248 -0
  102. package/dist-kernel/help/file-formats.html +248 -0
  103. package/dist-kernel/help/getting-started.html +248 -0
  104. package/dist-kernel/help/highlights.html +248 -0
  105. package/dist-kernel/help/history-systems.html +248 -0
  106. package/dist-kernel/help/how-it-works.html +248 -0
  107. package/dist-kernel/help/index.html +862 -0
  108. package/dist-kernel/help/input-params-schema.html +363 -0
  109. package/dist-kernel/help/inspector-improvements.html +248 -0
  110. package/dist-kernel/help/inspector.html +248 -0
  111. package/dist-kernel/help/modes__modeling.html +248 -0
  112. package/dist-kernel/help/modes__pmi.html +248 -0
  113. package/dist-kernel/help/modes__sketch.html +248 -0
  114. package/dist-kernel/help/plugins.html +248 -0
  115. package/dist-kernel/help/pmi-annotations__Angle_Dimension_dialog.png +0 -0
  116. package/dist-kernel/help/pmi-annotations__Explode_Body_dialog.png +0 -0
  117. package/dist-kernel/help/pmi-annotations__Hole_Callout_dialog.png +0 -0
  118. package/dist-kernel/help/pmi-annotations__Leader_dialog.png +0 -0
  119. package/dist-kernel/help/pmi-annotations__Linear_Dimension_dialog.png +0 -0
  120. package/dist-kernel/help/pmi-annotations__Note_dialog.png +0 -0
  121. package/dist-kernel/help/pmi-annotations__Radial_Dimension_dialog.png +0 -0
  122. package/dist-kernel/help/pmi-annotations__angle-dimension.html +248 -0
  123. package/dist-kernel/help/pmi-annotations__explode-body.html +248 -0
  124. package/dist-kernel/help/pmi-annotations__hole-callout.html +248 -0
  125. package/dist-kernel/help/pmi-annotations__index.html +248 -0
  126. package/dist-kernel/help/pmi-annotations__leader.html +248 -0
  127. package/dist-kernel/help/pmi-annotations__linear-dimension.html +248 -0
  128. package/dist-kernel/help/pmi-annotations__note.html +248 -0
  129. package/dist-kernel/help/pmi-annotations__radial-dimension.html +248 -0
  130. package/dist-kernel/help/search-index.json +464 -0
  131. package/dist-kernel/help/simplified-radial-dimensions.html +298 -0
  132. package/dist-kernel/help/solid-methods.html +359 -0
  133. package/dist-kernel/help/table-of-contents.html +330 -0
  134. package/dist-kernel/help/ui-overview.html +248 -0
  135. package/dist-kernel/help/whats-new.html +248 -0
  136. package/package.json +54 -0
  137. package/src/BREP/AssemblyComponent.js +42 -0
  138. package/src/BREP/BREP.js +43 -0
  139. package/src/BREP/BetterSolid.js +805 -0
  140. package/src/BREP/Edge.js +103 -0
  141. package/src/BREP/Extrude.js +403 -0
  142. package/src/BREP/Face.js +187 -0
  143. package/src/BREP/MeshRepairer.js +634 -0
  144. package/src/BREP/OffsetShellSolid.js +614 -0
  145. package/src/BREP/PointCloudWrap.js +302 -0
  146. package/src/BREP/Revolve.js +345 -0
  147. package/src/BREP/SolidMethods/authoring.js +112 -0
  148. package/src/BREP/SolidMethods/booleanOps.js +230 -0
  149. package/src/BREP/SolidMethods/chamfer.js +122 -0
  150. package/src/BREP/SolidMethods/edgeResolution.js +25 -0
  151. package/src/BREP/SolidMethods/fillet.js +792 -0
  152. package/src/BREP/SolidMethods/index.js +72 -0
  153. package/src/BREP/SolidMethods/io.js +105 -0
  154. package/src/BREP/SolidMethods/lifecycle.js +103 -0
  155. package/src/BREP/SolidMethods/manifoldOps.js +375 -0
  156. package/src/BREP/SolidMethods/meshCleanup.js +2512 -0
  157. package/src/BREP/SolidMethods/meshQueries.js +264 -0
  158. package/src/BREP/SolidMethods/metadata.js +106 -0
  159. package/src/BREP/SolidMethods/metrics.js +51 -0
  160. package/src/BREP/SolidMethods/transforms.js +361 -0
  161. package/src/BREP/SolidMethods/visualize.js +508 -0
  162. package/src/BREP/SolidShared.js +26 -0
  163. package/src/BREP/Sweep.js +1596 -0
  164. package/src/BREP/Tube.js +857 -0
  165. package/src/BREP/Vertex.js +43 -0
  166. package/src/BREP/applyBooleanOperation.js +704 -0
  167. package/src/BREP/boundsUtils.js +48 -0
  168. package/src/BREP/chamfer.js +551 -0
  169. package/src/BREP/edgePolylineUtils.js +85 -0
  170. package/src/BREP/fillets/common.js +388 -0
  171. package/src/BREP/fillets/fillet.js +1422 -0
  172. package/src/BREP/fillets/filletGeometry.js +15 -0
  173. package/src/BREP/fillets/inset.js +389 -0
  174. package/src/BREP/fillets/offsetHelper.js +143 -0
  175. package/src/BREP/fillets/outset.js +88 -0
  176. package/src/BREP/helix.js +193 -0
  177. package/src/BREP/meshToBrep.js +234 -0
  178. package/src/BREP/primitives.js +279 -0
  179. package/src/BREP/setupManifold.js +71 -0
  180. package/src/BREP/threadGeometry.js +1120 -0
  181. package/src/BREP/triangleUtils.js +8 -0
  182. package/src/BREP/triangulate.js +608 -0
  183. package/src/FeatureRegistry.js +183 -0
  184. package/src/PartHistory.js +1132 -0
  185. package/src/UI/AccordionWidget.js +292 -0
  186. package/src/UI/CADmaterials.js +850 -0
  187. package/src/UI/EnvMonacoEditor.js +522 -0
  188. package/src/UI/FloatingWindow.js +396 -0
  189. package/src/UI/HistoryWidget.js +457 -0
  190. package/src/UI/MainToolbar.js +131 -0
  191. package/src/UI/ModelLibraryView.js +194 -0
  192. package/src/UI/OrthoCameraIdle.js +206 -0
  193. package/src/UI/PluginsWidget.js +280 -0
  194. package/src/UI/SceneListing.js +606 -0
  195. package/src/UI/SelectionFilter.js +629 -0
  196. package/src/UI/ViewCube.js +389 -0
  197. package/src/UI/assembly/AssemblyConstraintCollectionWidget.js +329 -0
  198. package/src/UI/assembly/AssemblyConstraintControlsWidget.js +282 -0
  199. package/src/UI/assembly/AssemblyConstraintsWidget.css +292 -0
  200. package/src/UI/assembly/AssemblyConstraintsWidget.js +1373 -0
  201. package/src/UI/assembly/constraintFaceUtils.js +115 -0
  202. package/src/UI/assembly/constraintHighlightUtils.js +70 -0
  203. package/src/UI/assembly/constraintLabelUtils.js +31 -0
  204. package/src/UI/assembly/constraintPointUtils.js +64 -0
  205. package/src/UI/assembly/constraintSelectionUtils.js +185 -0
  206. package/src/UI/assembly/constraintStatusUtils.js +142 -0
  207. package/src/UI/componentSelectorModal.js +240 -0
  208. package/src/UI/controls/CombinedTransformControls.js +386 -0
  209. package/src/UI/dialogs.js +351 -0
  210. package/src/UI/expressionsManager.js +100 -0
  211. package/src/UI/featureDialogWidgets/booleanField.js +25 -0
  212. package/src/UI/featureDialogWidgets/booleanOperationField.js +97 -0
  213. package/src/UI/featureDialogWidgets/buttonField.js +45 -0
  214. package/src/UI/featureDialogWidgets/componentSelectorField.js +102 -0
  215. package/src/UI/featureDialogWidgets/defaultField.js +23 -0
  216. package/src/UI/featureDialogWidgets/fileField.js +66 -0
  217. package/src/UI/featureDialogWidgets/index.js +34 -0
  218. package/src/UI/featureDialogWidgets/numberField.js +165 -0
  219. package/src/UI/featureDialogWidgets/optionsField.js +33 -0
  220. package/src/UI/featureDialogWidgets/referenceSelectionField.js +208 -0
  221. package/src/UI/featureDialogWidgets/stringField.js +24 -0
  222. package/src/UI/featureDialogWidgets/textareaField.js +28 -0
  223. package/src/UI/featureDialogWidgets/threadDesignationField.js +160 -0
  224. package/src/UI/featureDialogWidgets/transformField.js +252 -0
  225. package/src/UI/featureDialogWidgets/utils.js +43 -0
  226. package/src/UI/featureDialogWidgets/vec3Field.js +133 -0
  227. package/src/UI/featureDialogs.js +1414 -0
  228. package/src/UI/fileManagerWidget.js +615 -0
  229. package/src/UI/history/HistoryCollectionWidget.js +1294 -0
  230. package/src/UI/history/historyCollectionWidget.css.js +257 -0
  231. package/src/UI/history/historyDisplayInfo.js +133 -0
  232. package/src/UI/mobile.js +28 -0
  233. package/src/UI/objectDump.js +442 -0
  234. package/src/UI/pmi/AnnotationCollectionWidget.js +120 -0
  235. package/src/UI/pmi/AnnotationHistory.js +353 -0
  236. package/src/UI/pmi/AnnotationRegistry.js +90 -0
  237. package/src/UI/pmi/BaseAnnotation.js +269 -0
  238. package/src/UI/pmi/LabelOverlay.css +102 -0
  239. package/src/UI/pmi/LabelOverlay.js +191 -0
  240. package/src/UI/pmi/PMIMode.js +1550 -0
  241. package/src/UI/pmi/PMIViewsWidget.js +1098 -0
  242. package/src/UI/pmi/annUtils.js +729 -0
  243. package/src/UI/pmi/dimensions/AngleDimensionAnnotation.js +647 -0
  244. package/src/UI/pmi/dimensions/ExplodeBodyAnnotation.js +507 -0
  245. package/src/UI/pmi/dimensions/HoleCalloutAnnotation.js +462 -0
  246. package/src/UI/pmi/dimensions/LeaderAnnotation.js +403 -0
  247. package/src/UI/pmi/dimensions/LinearDimensionAnnotation.js +532 -0
  248. package/src/UI/pmi/dimensions/NoteAnnotation.js +110 -0
  249. package/src/UI/pmi/dimensions/RadialDimensionAnnotation.js +659 -0
  250. package/src/UI/pmi/pmiStyle.js +44 -0
  251. package/src/UI/sketcher/SketchMode3D.js +4095 -0
  252. package/src/UI/sketcher/dimensions.js +674 -0
  253. package/src/UI/sketcher/glyphs.js +236 -0
  254. package/src/UI/sketcher/highlights.js +60 -0
  255. package/src/UI/toolbarButtons/aboutButton.js +5 -0
  256. package/src/UI/toolbarButtons/exportButton.js +609 -0
  257. package/src/UI/toolbarButtons/flatPatternButton.js +307 -0
  258. package/src/UI/toolbarButtons/importButton.js +160 -0
  259. package/src/UI/toolbarButtons/inspectorToggleButton.js +12 -0
  260. package/src/UI/toolbarButtons/metadataButton.js +1063 -0
  261. package/src/UI/toolbarButtons/orientToFaceButton.js +114 -0
  262. package/src/UI/toolbarButtons/registerDefaultButtons.js +46 -0
  263. package/src/UI/toolbarButtons/saveButton.js +99 -0
  264. package/src/UI/toolbarButtons/scriptRunnerButton.js +302 -0
  265. package/src/UI/toolbarButtons/testsButton.js +26 -0
  266. package/src/UI/toolbarButtons/undoRedoButtons.js +25 -0
  267. package/src/UI/toolbarButtons/wireframeToggleButton.js +5 -0
  268. package/src/UI/toolbarButtons/zoomToFitButton.js +5 -0
  269. package/src/UI/triangleDebuggerWindow.js +945 -0
  270. package/src/UI/viewer.js +4228 -0
  271. package/src/assemblyConstraints/AssemblyConstraintHistory.js +1576 -0
  272. package/src/assemblyConstraints/AssemblyConstraintRegistry.js +120 -0
  273. package/src/assemblyConstraints/BaseAssemblyConstraint.js +66 -0
  274. package/src/assemblyConstraints/constraintExpressionUtils.js +35 -0
  275. package/src/assemblyConstraints/constraintUtils/parallelAlignment.js +676 -0
  276. package/src/assemblyConstraints/constraints/AngleConstraint.js +485 -0
  277. package/src/assemblyConstraints/constraints/CoincidentConstraint.js +194 -0
  278. package/src/assemblyConstraints/constraints/DistanceConstraint.js +616 -0
  279. package/src/assemblyConstraints/constraints/FixedConstraint.js +78 -0
  280. package/src/assemblyConstraints/constraints/ParallelConstraint.js +252 -0
  281. package/src/assemblyConstraints/constraints/TouchAlignConstraint.js +961 -0
  282. package/src/core/entities/HistoryCollectionBase.js +72 -0
  283. package/src/core/entities/ListEntityBase.js +109 -0
  284. package/src/core/entities/schemaProcesser.js +121 -0
  285. package/src/exporters/sheetMetalFlatPattern.js +659 -0
  286. package/src/exporters/sheetMetalUnfold.js +862 -0
  287. package/src/exporters/step.js +1135 -0
  288. package/src/exporters/threeMF.js +575 -0
  289. package/src/features/assemblyComponent/AssemblyComponentFeature.js +780 -0
  290. package/src/features/boolean/BooleanFeature.js +94 -0
  291. package/src/features/chamfer/ChamferFeature.js +116 -0
  292. package/src/features/datium/DatiumFeature.js +80 -0
  293. package/src/features/edgeFeatureUtils.js +41 -0
  294. package/src/features/extrude/ExtrudeFeature.js +143 -0
  295. package/src/features/fillet/FilletFeature.js +197 -0
  296. package/src/features/helix/HelixFeature.js +405 -0
  297. package/src/features/hole/HoleFeature.js +1050 -0
  298. package/src/features/hole/screwClearance.js +86 -0
  299. package/src/features/hole/threadDesignationCatalog.js +149 -0
  300. package/src/features/imageHeightSolid/ImageHeightmapSolidFeature.js +463 -0
  301. package/src/features/imageToFace/ImageToFaceFeature.js +727 -0
  302. package/src/features/imageToFace/imageEditor.js +1270 -0
  303. package/src/features/imageToFace/traceUtils.js +971 -0
  304. package/src/features/import3dModel/Import3dModelFeature.js +151 -0
  305. package/src/features/loft/LoftFeature.js +605 -0
  306. package/src/features/mirror/MirrorFeature.js +151 -0
  307. package/src/features/offsetFace/OffsetFaceFeature.js +370 -0
  308. package/src/features/offsetShell/OffsetShellFeature.js +89 -0
  309. package/src/features/overlapCleanup/OverlapCleanupFeature.js +85 -0
  310. package/src/features/pattern/PatternFeature.js +275 -0
  311. package/src/features/patternLinear/PatternLinearFeature.js +120 -0
  312. package/src/features/patternRadial/PatternRadialFeature.js +186 -0
  313. package/src/features/plane/PlaneFeature.js +154 -0
  314. package/src/features/primitiveCone/primitiveConeFeature.js +99 -0
  315. package/src/features/primitiveCube/primitiveCubeFeature.js +70 -0
  316. package/src/features/primitiveCylinder/primitiveCylinderFeature.js +91 -0
  317. package/src/features/primitivePyramid/primitivePyramidFeature.js +72 -0
  318. package/src/features/primitiveSphere/primitiveSphereFeature.js +62 -0
  319. package/src/features/primitiveTorus/primitiveTorusFeature.js +109 -0
  320. package/src/features/remesh/RemeshFeature.js +97 -0
  321. package/src/features/revolve/RevolveFeature.js +111 -0
  322. package/src/features/selectionUtils.js +118 -0
  323. package/src/features/sheetMetal/SheetMetalContourFlangeFeature.js +1656 -0
  324. package/src/features/sheetMetal/SheetMetalCutoutFeature.js +1056 -0
  325. package/src/features/sheetMetal/SheetMetalFlangeFeature.js +1568 -0
  326. package/src/features/sheetMetal/SheetMetalHemFeature.js +43 -0
  327. package/src/features/sheetMetal/SheetMetalObject.js +141 -0
  328. package/src/features/sheetMetal/SheetMetalTabFeature.js +176 -0
  329. package/src/features/sheetMetal/UNFOLD_NEUTRAL_REQUIREMENTS.md +153 -0
  330. package/src/features/sheetMetal/contour-flange-rebuild-spec.md +261 -0
  331. package/src/features/sheetMetal/profileUtils.js +25 -0
  332. package/src/features/sheetMetal/sheetMetalCleanup.js +9 -0
  333. package/src/features/sheetMetal/sheetMetalFaceTypes.js +146 -0
  334. package/src/features/sheetMetal/sheetMetalMetadata.js +165 -0
  335. package/src/features/sheetMetal/sheetMetalPipeline.js +169 -0
  336. package/src/features/sheetMetal/sheetMetalProfileUtils.js +216 -0
  337. package/src/features/sheetMetal/sheetMetalTabUtils.js +29 -0
  338. package/src/features/sheetMetal/sheetMetalTree.js +210 -0
  339. package/src/features/sketch/SketchFeature.js +955 -0
  340. package/src/features/sketch/sketchSolver2D/ConstraintEngine.js +800 -0
  341. package/src/features/sketch/sketchSolver2D/constraintDefinitions.js +704 -0
  342. package/src/features/sketch/sketchSolver2D/mathHelpersMod.js +307 -0
  343. package/src/features/spline/SplineEditorSession.js +988 -0
  344. package/src/features/spline/SplineFeature.js +1388 -0
  345. package/src/features/spline/splineUtils.js +218 -0
  346. package/src/features/sweep/SweepFeature.js +110 -0
  347. package/src/features/transform/TransformFeature.js +152 -0
  348. package/src/features/tube/TubeFeature.js +635 -0
  349. package/src/fs.proxy.js +625 -0
  350. package/src/idbStorage.js +254 -0
  351. package/src/index.js +12 -0
  352. package/src/main.js +15 -0
  353. package/src/metadataManager.js +64 -0
  354. package/src/path.proxy.js +277 -0
  355. package/src/plugins/ghLoader.worker.js +151 -0
  356. package/src/plugins/pluginManager.js +286 -0
  357. package/src/pmi/PMIViewsManager.js +134 -0
  358. package/src/services/componentLibrary.js +198 -0
  359. package/src/tests/ConsoleCapture.js +189 -0
  360. package/src/tests/S7-diagnostics-2025-12-23T18-37-23-570Z.json +630 -0
  361. package/src/tests/browserTests.js +597 -0
  362. package/src/tests/debugBoolean.js +225 -0
  363. package/src/tests/partFiles/badBoolean.json +957 -0
  364. package/src/tests/partFiles/extrudeTest.json +88 -0
  365. package/src/tests/partFiles/filletFail.json +58 -0
  366. package/src/tests/partFiles/import_TEst.part.part.json +646 -0
  367. package/src/tests/partFiles/sheetMetalHem.BREP.json +734 -0
  368. package/src/tests/test_boolean_subtract.js +27 -0
  369. package/src/tests/test_chamfer.js +17 -0
  370. package/src/tests/test_extrudeFace.js +24 -0
  371. package/src/tests/test_fillet.js +17 -0
  372. package/src/tests/test_fillet_nonClosed.js +45 -0
  373. package/src/tests/test_filletsMoreDifficult.js +46 -0
  374. package/src/tests/test_history_features_basic.js +149 -0
  375. package/src/tests/test_hole.js +282 -0
  376. package/src/tests/test_mirror.js +16 -0
  377. package/src/tests/test_offsetShellGrouping.js +85 -0
  378. package/src/tests/test_plane.js +4 -0
  379. package/src/tests/test_primitiveCone.js +11 -0
  380. package/src/tests/test_primitiveCube.js +7 -0
  381. package/src/tests/test_primitiveCylinder.js +8 -0
  382. package/src/tests/test_primitivePyramid.js +9 -0
  383. package/src/tests/test_primitiveSphere.js +17 -0
  384. package/src/tests/test_primitiveTorus.js +21 -0
  385. package/src/tests/test_pushFace.js +126 -0
  386. package/src/tests/test_sheetMetalContourFlange.js +125 -0
  387. package/src/tests/test_sheetMetal_features.js +80 -0
  388. package/src/tests/test_sketch_openLoop.js +45 -0
  389. package/src/tests/test_solidMetrics.js +58 -0
  390. package/src/tests/test_stlLoader.js +1889 -0
  391. package/src/tests/test_sweepFace.js +55 -0
  392. package/src/tests/test_tube.js +45 -0
  393. package/src/tests/test_tube_closedLoop.js +67 -0
  394. package/src/tests/tests.js +493 -0
  395. package/src/tools/assemblyConstraintDialogCapturePage.js +56 -0
  396. package/src/tools/dialogCapturePageFactory.js +227 -0
  397. package/src/tools/featureDialogCapturePage.js +47 -0
  398. package/src/tools/pmiAnnotationDialogCapturePage.js +60 -0
  399. package/src/utils/axisHelpers.js +99 -0
  400. package/src/utils/deepClone.js +69 -0
  401. package/src/utils/geometryTolerance.js +37 -0
  402. package/src/utils/normalizeTypeString.js +8 -0
  403. package/src/utils/xformMath.js +51 -0
@@ -0,0 +1,261 @@
1
+ # Sheet Metal Contour Flange - Complete Specification
2
+
3
+ ## Overview
4
+ The Sheet Metal Contour Flange feature creates a sheet metal part by extruding a strip along a path with optional bend radii at corners. This document provides a complete specification for rebuilding the feature from scratch.
5
+
6
+ ## Input Parameters
7
+
8
+ | Parameter | Type | Default | Description |
9
+ |-----------|------|---------|-------------|
10
+ | `id` | string | null | Unique identifier for the feature |
11
+ | `path` | reference_selection | null | Open sketch or connected edges defining the flange path |
12
+ | `distance` | number | 20 | Extrusion height (perpendicular to sketch plane) |
13
+ | `thickness` | number | 2 | Sheet metal thickness (width of the strip) |
14
+ | `reverseSheetSide` | boolean | false | Flip the strip to opposite side of path |
15
+ | `bendRadius` | number | 1 | Inside bend radius at corners |
16
+ | `consumePathSketch` | boolean | true | Remove sketch after feature creation |
17
+
18
+ ## Core Concept
19
+
20
+ ### Geometry Definition
21
+ The contour flange creates a **strip** (rectangular cross-section) that follows a path:
22
+
23
+ 1. **Path**: A 2D polyline in a sketch plane (e.g., an L-shape, U-shape, etc.)
24
+ 2. **Strip Width**: The `thickness` parameter defines how wide the strip is
25
+ 3. **Strip Placement**:
26
+ - When `reverseSheetSide = false` (unchecked): Strip is offset to the LEFT of the path
27
+ - When `reverseSheetSide = true` (checked): Strip is offset to the RIGHT of the path
28
+ 4. **Extrusion**: The strip is extruded perpendicular to the sketch plane by `distance`
29
+
30
+ ### Bend Radius Behavior
31
+
32
+ The `bendRadius` parameter represents the **INSIDE radius** of any bend in the final sheet metal part.
33
+
34
+ #### Critical Rule: Path Position vs Bend Geometry
35
+
36
+ **When reverseSheetSide = true (checked):**
37
+ - The path travels along the INSIDE of the bend
38
+ - Inside radius = `bendRadius`
39
+ - Outside radius = `bendRadius + thickness`
40
+ - Path is at radius `bendRadius` from the corner
41
+ - Arc center is at radius `bendRadius` from corner
42
+
43
+ **When reverseSheetSide = false (unchecked):**
44
+ - The path travels along the OUTSIDE of the bend
45
+ - Inside radius = `bendRadius` (still!)
46
+ - Outside radius = `bendRadius + thickness`
47
+ - Path is at radius `bendRadius + thickness` from the corner
48
+ - Arc center is at radius `bendRadius + thickness` from corner
49
+
50
+ This ensures the **inside bend radius is always constant** regardless of which side the sheet is on.
51
+
52
+ ## Algorithm Overview
53
+
54
+ ### Phase 1: Path Extraction
55
+ 1. Resolve selected sketch or edges to 3D polyline points
56
+ 2. Extract or compute sketch plane basis (origin, xAxis, yAxis, planeNormal)
57
+ 3. Convert 3D path to 2D coordinates in sketch plane
58
+
59
+ ### Phase 2: Path Processing with Fillets
60
+
61
+ For each corner in the path:
62
+
63
+ #### Step 1: Determine Bend Geometry
64
+ ```
65
+ corner_angle = angle between incoming and outgoing segments
66
+ turn_direction = cross product sign (left turn vs right turn)
67
+ ```
68
+
69
+ #### Step 2: Calculate Path Radius
70
+ ```
71
+ if reverseSheetSide == true:
72
+ path_radius = bendRadius
73
+ else:
74
+ path_radius = bendRadius + thickness
75
+ ```
76
+
77
+ #### Step 3: Calculate Tangent Points
78
+ The tangent points where the arc meets the straight segments are **always** based on the bend radius geometry at the corner:
79
+
80
+ ```
81
+ tangent_offset = bendRadius / tan(corner_angle / 2)
82
+ tangent_offset = min(tangent_offset, 0.9 * segment_lengths)
83
+
84
+ arc_start = corner - incoming_direction * tangent_offset
85
+ arc_end = corner + outgoing_direction * tangent_offset
86
+ ```
87
+
88
+ #### Step 4: Calculate Arc Center
89
+ The center is positioned so the arc has radius `path_radius`:
90
+
91
+ ```
92
+ perpendicular_direction = rotate incoming/outgoing direction by 90° (toward inside of turn)
93
+ center_offset = path_radius
94
+ arc_center = average of:
95
+ - arc_start + perpendicular * center_offset
96
+ - arc_end + perpendicular * center_offset
97
+ ```
98
+
99
+ #### Step 5: Generate Arc Points
100
+ ```
101
+ arc_radius = path_radius
102
+ start_angle = atan2(arc_start - arc_center)
103
+ end_angle = atan2(arc_end - arc_center)
104
+ sweep_direction = based on turn_direction
105
+
106
+ Generate points along arc from start_angle to end_angle
107
+ ```
108
+
109
+ ### Phase 3: Strip Face Creation
110
+
111
+ #### Step 1: Offset Path
112
+ Create parallel offset path at distance `thickness`:
113
+ - If `reverseSheetSide = true`: offset to LEFT (negative perpendicular)
114
+ - If `reverseSheetSide = false`: offset to RIGHT (positive perpendicular)
115
+
116
+ At corners with arcs, the offset must account for tangent directions.
117
+
118
+ #### Step 2: Build Strip Polygon
119
+ For each segment of the path:
120
+ ```
121
+ polygon = [
122
+ path_points[i],
123
+ path_points[i+1],
124
+ ...,
125
+ offset_points[i+1] (reversed order),
126
+ offset_points[i] (reversed order)
127
+ ]
128
+ ```
129
+
130
+ #### Step 3: Triangulate
131
+ Convert polygon to triangulated mesh (BufferGeometry).
132
+
133
+ ### Phase 4: Extrusion
134
+
135
+ 1. Extrude each strip face by `distance` in the `planeNormal` direction
136
+ 2. Use BREP.Sweep with mode "translate"
137
+ 3. Union multiple sweeps if path has multiple segments
138
+
139
+ ### Phase 5: Metadata
140
+
141
+ #### Face Type Tagging
142
+ - **Type A faces**: Sidewalls from original path edges
143
+ - **Type B faces**: Sidewalls from offset path edges
144
+ - **Thickness faces**: End caps and closure faces
145
+
146
+ #### Cylindrical Face Metadata
147
+ For bend regions, detect curved sidewalls and tag with:
148
+ ```javascript
149
+ {
150
+ type: "cylindrical",
151
+ radius: measured_radius,
152
+ height: extrusion_distance,
153
+ axis: [x, y, z],
154
+ center: [x, y, z],
155
+ pmiRadiusOverride: bendRadius // Always report inside radius
156
+ }
157
+ ```
158
+
159
+ ## Key Geometric Relationships
160
+
161
+ ### Corner Geometry (90° bend example)
162
+
163
+ ```
164
+ For 90° bend with bendRadius=3, thickness=1:
165
+
166
+ When checked (reverseSheetSide=true):
167
+ path_radius = 3
168
+ tangent_offset = 3 / tan(45°) = 3
169
+ arc drawn at radius 3
170
+ center at radius 3 from corner
171
+
172
+ When unchecked (reverseSheetSide=false):
173
+ path_radius = 4 (3 + 1)
174
+ tangent_offset = 3 / tan(45°) = 3 ← SAME!
175
+ arc drawn at radius 4
176
+ center at radius 4 from corner
177
+
178
+ The tangent offset is ALWAYS based on bendRadius geometry,
179
+ NOT on where the path/arc travels!
180
+ ```
181
+
182
+ ### Why Tangent Offset is Constant
183
+
184
+ The tangent offset represents the geometric distance from the corner where a circular arc of a given bend radius would naturally meet a straight line. This is a property of the bend geometry itself and is independent of which surface (inside or outside) the path follows.
185
+
186
+ ## Implementation Notes
187
+
188
+ ### 2D/3D Coordinate Handling
189
+ - All fillet/offset operations done in 2D (u,v) coordinates
190
+ - Convert to 3D for final geometry creation
191
+ - Maintain w-coordinate for points slightly off-plane
192
+
193
+ ### Edge Cases
194
+ - Acute angles: Clamp tangent offset to 90% of segment length
195
+ - Collinear segments: Skip filleting
196
+ - Self-intersecting paths: Allow but may produce unexpected results
197
+
198
+ ### Performance
199
+ - Fillet multiple corners in single pass
200
+ - Minimize 2D-3D coordinate conversions
201
+ - Reuse computed tangent directions for offset calculation
202
+
203
+ ## Testing Checklist
204
+
205
+ - [ ] Simple L-shape, checked: Inside radius = bendRadius
206
+ - [ ] Simple L-shape, unchecked: Inside radius = bendRadius
207
+ - [ ] U-shape with multiple bends
208
+ - [ ] Path with acute angles (< 30°)
209
+ - [ ] Path with obtuse angles (> 150°)
210
+ - [ ] Very small bend radius (0.1)
211
+ - [ ] Very large bend radius (> segment length)
212
+ - [ ] Zero bend radius (sharp corners)
213
+ - [ ] Verify cylindrical face metadata reports correct inside radius
214
+ - [ ] Verify visual appearance: arcs connect smoothly at tangent points
215
+
216
+ ## Dependencies
217
+
218
+ ### Required Imports
219
+ ```javascript
220
+ import { BREP } from "../../BREP/BREP.js";
221
+ import { normalizeThickness, normalizeBendRadius, applySheetMetalMetadata } from "./sheetMetalMetadata.js";
222
+ import { setSheetMetalFaceTypeMetadata, SHEET_METAL_FACE_TYPES, propagateSheetMetalFaceTypesToEdges } from "./sheetMetalFaceTypes.js";
223
+ ```
224
+
225
+ ### External Functions Used
226
+ - `BREP.Sweep` - Extrude faces
227
+ - `BREP.applyBooleanOperation` - Union operations
228
+ - `THREE.Vector3` - 3D vector math
229
+ - `THREE.BufferGeometry` - Mesh creation
230
+ - `THREE.ShapeUtils.triangulateShape` - Polygon triangulation
231
+
232
+ ## Function Structure (Suggested)
233
+
234
+ ```
235
+ SheetMetalContourFlangeFeature.run()
236
+
237
+ resolvePathSelection() - Extract edges/sketches
238
+
239
+ buildPathPoints() - Chain edges into connected path
240
+
241
+ computePlaneBasis() - Determine sketch plane
242
+
243
+ filletPolyline() - Add bend radii at corners
244
+
245
+ buildContourFlangeStripFaces() - Create strip faces
246
+
247
+ BREP.Sweep() - Extrude strip
248
+
249
+ tagContourFlangeFaceTypes() - Metadata
250
+
251
+ addCylMetadataToSideFaces() - Cylindrical metadata
252
+ ```
253
+
254
+ ## Known Issues to Avoid
255
+
256
+ 1. **Tangent offset calculation**: Must always use `bendRadius`, not `path_radius`
257
+ 2. **Arc radius**: Must use `path_radius` which varies by sheet side
258
+ 3. **Center positioning**: Must match `path_radius`
259
+ 4. **Metadata**: Always report `bendRadius` as inside radius, not measured radius
260
+ 5. **Offset direction**: Must account for tangent directions at arc endpoints
261
+
@@ -0,0 +1,25 @@
1
+ export function resolveProfileFace(profileRef, partHistory) {
2
+ if (!profileRef) return null;
3
+ const selection = Array.isArray(profileRef) ? (profileRef[0] || null) : profileRef;
4
+ let obj = selection;
5
+ if ((!obj || typeof obj !== "object") && selection && partHistory?.scene?.getObjectByName) {
6
+ obj = partHistory.scene.getObjectByName(selection) || null;
7
+ }
8
+ if (!obj) return null;
9
+
10
+ if (obj.type === "FACE") return obj;
11
+ if (obj.type === "SKETCH" && Array.isArray(obj.children)) {
12
+ const faceChild = obj.children.find((ch) => ch?.type === "FACE");
13
+ if (faceChild) return faceChild;
14
+ return obj.children.find((ch) => ch?.userData?.faceName) || null;
15
+ }
16
+ return obj;
17
+ }
18
+
19
+ export function collectSketchParents(face) {
20
+ const targets = [];
21
+ if (face && face.type === "FACE" && face.parent && face.parent.type === "SKETCH") {
22
+ targets.push(face.parent);
23
+ }
24
+ return targets;
25
+ }
@@ -0,0 +1,9 @@
1
+ export function cleanupSheetMetalOppositeEdgeFaces(solids, options = {}) {
2
+ const list = Array.isArray(solids) ? solids : (solids ? [solids] : []);
3
+ for (const solid of list) {
4
+ if (!solid || typeof solid.removeOppositeSingleEdgeFaces !== "function") continue;
5
+ try {
6
+ solid.removeOppositeSingleEdgeFaces(options);
7
+ } catch { /* best effort */ }
8
+ }
9
+ }
@@ -0,0 +1,146 @@
1
+ export const SHEET_METAL_FACE_TYPES = {
2
+ A: "A",
3
+ B: "B",
4
+ THICKNESS: "THICKNESS",
5
+ };
6
+
7
+ export function setSheetMetalFaceTypeMetadata(solid, faceNames, type) {
8
+ if (!solid || !faceNames || !type) return;
9
+ const list = Array.isArray(faceNames) ? faceNames : [faceNames];
10
+ for (const name of list) {
11
+ if (!name || typeof solid.setFaceMetadata !== "function") continue;
12
+ const existing = typeof solid.getFaceMetadata === "function"
13
+ ? (solid.getFaceMetadata(name) || {})
14
+ : {};
15
+ solid.setFaceMetadata(name, {
16
+ ...existing,
17
+ sheetMetalFaceType: type,
18
+ });
19
+ }
20
+ }
21
+
22
+ export function resolveSheetMetalFaceType(faceObj) {
23
+ if (!faceObj) return null;
24
+ const direct = faceObj.userData?.sheetMetalFaceType;
25
+ const solid = faceObj.parentSolid || findAncestorSolid(faceObj);
26
+ const faceName = faceObj.userData?.faceName || faceObj.name;
27
+ if (!solid || typeof solid.getFaceMetadata !== "function" || !faceName) {
28
+ return direct || null;
29
+ }
30
+ try {
31
+ const metadata = solid.getFaceMetadata(faceName);
32
+ if (metadata && typeof metadata.sheetMetalFaceType === "string") {
33
+ return metadata.sheetMetalFaceType;
34
+ }
35
+ } catch { /* ignore metadata lookup errors */ }
36
+ return direct || null;
37
+ }
38
+
39
+ export function propagateSheetMetalFaceTypesToEdges(targets) {
40
+ const solids = [];
41
+ const push = (item) => {
42
+ if (!item) return;
43
+ if (Array.isArray(item)) {
44
+ for (const it of item) push(it);
45
+ } else if (item.type === "SOLID") {
46
+ solids.push(item);
47
+ }
48
+ };
49
+ push(targets);
50
+ for (const solid of solids) {
51
+ let faces = [];
52
+ try {
53
+ faces = typeof solid.getFaces === "function" ? solid.getFaces() : [];
54
+ } catch { faces = []; }
55
+ if (!Array.isArray(faces) || !faces.length) continue;
56
+ const edgeMap = new Map(); // edge -> {faces:Set(types)}
57
+ const applied = [];
58
+ const missing = [];
59
+
60
+ for (const face of faces) {
61
+ const type = resolveSheetMetalFaceType(face);
62
+ if (type !== SHEET_METAL_FACE_TYPES.A && type !== SHEET_METAL_FACE_TYPES.B) continue;
63
+ const edges = Array.isArray(face.edges) ? face.edges : [];
64
+ for (const edge of edges) {
65
+ if (!edge) continue;
66
+ let entry = edgeMap.get(edge);
67
+ if (!entry) { entry = new Set(); edgeMap.set(edge, entry); }
68
+ entry.add(type);
69
+ }
70
+ }
71
+
72
+ for (const [edge, types] of edgeMap.entries()) {
73
+ if (!edge) continue;
74
+ const hasA = types.has(SHEET_METAL_FACE_TYPES.A);
75
+ const hasB = types.has(SHEET_METAL_FACE_TYPES.B);
76
+ let finalType = null;
77
+ if (hasA) finalType = SHEET_METAL_FACE_TYPES.A;
78
+ else if (hasB) finalType = SHEET_METAL_FACE_TYPES.B;
79
+ edge.userData = edge.userData || {};
80
+ edge.userData.sheetMetalEdgeType = finalType;
81
+ const name = typeof edge.name === "string" ? edge.name : null;
82
+ const parent = edge.parentSolid || findAncestorSolid(edge) || solid;
83
+ const faceNames = Array.isArray(edge.faces)
84
+ ? edge.faces.map((f) => f?.userData?.faceName || f?.name).filter(Boolean)
85
+ : [];
86
+ const pairName = faceNames.length === 2
87
+ ? faceNames.slice().sort().join("|")
88
+ : null;
89
+ if (finalType && name && parent && typeof parent.setEdgeMetadata === "function") {
90
+ parent.setEdgeMetadata(name, { ...(parent.getEdgeMetadata(name) || {}), sheetMetalEdgeType: finalType });
91
+ }
92
+ if (finalType && pairName && parent && typeof parent.setEdgeMetadata === "function") {
93
+ parent.setEdgeMetadata(pairName, { ...(parent.getEdgeMetadata(pairName) || {}), sheetMetalEdgeType: finalType });
94
+ }
95
+ applied.push({ edgeName: name || "UNNAMED", type: finalType || "NONE" });
96
+ if (!finalType) {
97
+ console.warn("[SheetMetal] Edge with no sheetMetalEdgeType after propagation", { edge: name || "UNNAMED" });
98
+ }
99
+ }
100
+
101
+ for (const face of faces) {
102
+ const type = resolveSheetMetalFaceType(face);
103
+ if (type !== SHEET_METAL_FACE_TYPES.A && type !== SHEET_METAL_FACE_TYPES.B) continue;
104
+ const edges = Array.isArray(face.edges) ? face.edges : [];
105
+ for (const edge of edges) {
106
+ const et = edge?.userData?.sheetMetalEdgeType;
107
+ if (et !== type) {
108
+ edge.userData = { ...(edge.userData || {}), sheetMetalEdgeType: type };
109
+ const name = typeof edge?.name === "string" ? edge.name : null;
110
+ const parent = edge?.parentSolid || findAncestorSolid(edge) || solid;
111
+ const faceNames = Array.isArray(edge?.faces)
112
+ ? edge.faces.map((f) => f?.userData?.faceName || f?.name).filter(Boolean)
113
+ : [];
114
+ const pairName = faceNames.length === 2
115
+ ? faceNames.slice().sort().join("|")
116
+ : null;
117
+ if (name && parent && typeof parent.setEdgeMetadata === "function") {
118
+ parent.setEdgeMetadata(name, { ...(parent.getEdgeMetadata(name) || {}), sheetMetalEdgeType: type });
119
+ }
120
+ if (pairName && parent && typeof parent.setEdgeMetadata === "function") {
121
+ parent.setEdgeMetadata(pairName, { ...(parent.getEdgeMetadata(pairName) || {}), sheetMetalEdgeType: type });
122
+ }
123
+ missing.push({ edgeName: name || "UNNAMED", expected: type, actual: et });
124
+ }
125
+ }
126
+ }
127
+
128
+ console.log("[SheetMetal] Edge type propagation summary", {
129
+ solid: solid?.name || solid,
130
+ appliedCount: applied.length,
131
+ missingCount: missing.length,
132
+ });
133
+ if (missing.length) {
134
+ console.warn("[SheetMetal] Missing edge sheet-metal types after propagation (corrected)", missing);
135
+ }
136
+ }
137
+ }
138
+
139
+ function findAncestorSolid(obj) {
140
+ let current = obj;
141
+ while (current) {
142
+ if (current.type === "SOLID") return current;
143
+ current = current.parent;
144
+ }
145
+ return null;
146
+ }
@@ -0,0 +1,165 @@
1
+ import { deepClone } from '../../utils/deepClone.js';
2
+
3
+ const MIN_THICKNESS = 1e-6;
4
+ const MIN_BEND_RADIUS = 0;
5
+ const MIN_NEUTRAL_FACTOR = 0;
6
+ const MAX_NEUTRAL_FACTOR = 1;
7
+
8
+ function isValidThickness(value) {
9
+ const num = Number(value);
10
+ return Number.isFinite(num) && Math.abs(num) > MIN_THICKNESS;
11
+ }
12
+
13
+ function isValidBendRadius(value) {
14
+ const num = Number(value);
15
+ return Number.isFinite(num) && num >= MIN_BEND_RADIUS;
16
+ }
17
+
18
+ function isValidNeutralFactor(value) {
19
+ const num = Number(value);
20
+ return Number.isFinite(num) && num >= MIN_NEUTRAL_FACTOR && num <= MAX_NEUTRAL_FACTOR;
21
+ }
22
+
23
+ function pickPersistentValue(existingValue, incomingValue, validator) {
24
+ const existing = validator(existingValue) ? Number(existingValue) : null;
25
+ if (existing != null) return existing;
26
+ const incoming = validator(incomingValue) ? Number(incomingValue) : null;
27
+ return incoming;
28
+ }
29
+
30
+ export function normalizeThickness(rawValue) {
31
+ const num = Number(rawValue);
32
+ if (!Number.isFinite(num)) {
33
+ throw new Error('Sheet metal thickness must be a finite number.');
34
+ }
35
+ const magnitude = Math.abs(num);
36
+ if (magnitude < MIN_THICKNESS) {
37
+ throw new Error('Sheet metal thickness must be greater than zero.');
38
+ }
39
+ return { magnitude, signed: num };
40
+ }
41
+
42
+ export function normalizeBendRadius(rawValue, fallback = 0.5) {
43
+ if (rawValue == null || rawValue === '') {
44
+ return Math.max(fallback, MIN_BEND_RADIUS);
45
+ }
46
+ const num = Number(rawValue);
47
+ if (!Number.isFinite(num)) {
48
+ throw new Error('Sheet metal bend radius must be a finite number.');
49
+ }
50
+ if (num < MIN_BEND_RADIUS) {
51
+ throw new Error('Sheet metal bend radius must be zero or greater.');
52
+ }
53
+ return num;
54
+ }
55
+
56
+ export function normalizeNeutralFactor(rawValue, fallback = 0.5) {
57
+ if (rawValue == null || rawValue === '') {
58
+ return clampNeutralFactor(fallback);
59
+ }
60
+ const num = Number(rawValue);
61
+ if (!Number.isFinite(num)) {
62
+ throw new Error('Sheet metal neutral factor must be a finite number.');
63
+ }
64
+ if (num < MIN_NEUTRAL_FACTOR || num > MAX_NEUTRAL_FACTOR) {
65
+ throw new Error('Sheet metal neutral factor must be between 0 and 1.');
66
+ }
67
+ return num;
68
+ }
69
+
70
+ function clampNeutralFactor(value) {
71
+ const num = Number(value);
72
+ if (!Number.isFinite(num)) return 0.5;
73
+ return Math.max(MIN_NEUTRAL_FACTOR, Math.min(MAX_NEUTRAL_FACTOR, num));
74
+ }
75
+
76
+ export function applySheetMetalMetadata(
77
+ solids,
78
+ metadataManager,
79
+ {
80
+ featureID = null,
81
+ thickness = null,
82
+ bendRadius = null,
83
+ neutralFactor = null,
84
+ baseType = null,
85
+ extra = null,
86
+ forceBaseOverwrite = false,
87
+ } = {},
88
+ ) {
89
+ if (!Array.isArray(solids) || !solids.length) return;
90
+ for (const solid of solids) {
91
+ if (!solid || typeof solid !== 'object') continue;
92
+ const incomingThickness = isValidThickness(thickness) ? Number(thickness) : null;
93
+ const incomingBendRadius = isValidBendRadius(bendRadius) ? Number(bendRadius) : null;
94
+ const incomingNeutral = isValidNeutralFactor(neutralFactor) ? Number(neutralFactor) : null;
95
+ let lockedThickness = null;
96
+ let lockedBendRadius = null;
97
+ let lockedNeutral = null;
98
+ try {
99
+ solid.userData = solid.userData || {};
100
+ const existingSM = solid.userData.sheetMetal || {};
101
+ lockedThickness = pickPersistentValue(
102
+ existingSM.baseThickness ?? solid.userData.sheetThickness ?? existingSM.thickness,
103
+ thickness,
104
+ isValidThickness,
105
+ );
106
+ lockedBendRadius = pickPersistentValue(
107
+ existingSM.baseBendRadius ?? solid.userData.sheetBendRadius ?? existingSM.bendRadius,
108
+ bendRadius,
109
+ isValidBendRadius,
110
+ );
111
+ lockedNeutral = pickPersistentValue(
112
+ existingSM.baseNeutralFactor ?? solid.userData.sheetMetalNeutralFactor ?? existingSM.neutralFactor,
113
+ neutralFactor,
114
+ isValidNeutralFactor,
115
+ );
116
+ if (forceBaseOverwrite && incomingThickness != null) lockedThickness = incomingThickness;
117
+ if (forceBaseOverwrite && incomingBendRadius != null) lockedBendRadius = incomingBendRadius;
118
+ if (forceBaseOverwrite && incomingNeutral != null) lockedNeutral = incomingNeutral;
119
+
120
+ solid.userData.sheetMetal = {
121
+ ...(existingSM || {}),
122
+ baseType: baseType || existingSM.baseType || null,
123
+ thickness: lockedThickness ?? null,
124
+ bendRadius: lockedBendRadius ?? null,
125
+ neutralFactor: lockedNeutral ?? null,
126
+ baseThickness: lockedThickness ?? null,
127
+ baseBendRadius: lockedBendRadius ?? null,
128
+ baseNeutralFactor: lockedNeutral ?? null,
129
+ featureID,
130
+ ...(extra || {}),
131
+ };
132
+ if (lockedThickness != null) solid.userData.sheetThickness = lockedThickness;
133
+ if (lockedBendRadius != null) solid.userData.sheetBendRadius = lockedBendRadius;
134
+ if (lockedNeutral != null) solid.userData.sheetMetalNeutralFactor = lockedNeutral;
135
+ } catch { /* metadata best-effort */ }
136
+
137
+ const metaTarget = solid.name || featureID;
138
+ if (metaTarget && metadataManager && typeof metadataManager.setMetadata === 'function') {
139
+ const existing = metadataManager.getOwnMetadata(metaTarget);
140
+ const merged = existing ? deepClone(existing) : {};
141
+ if (
142
+ (forceBaseOverwrite && incomingThickness != null)
143
+ || (!isValidThickness(merged.sheetMetalThickness) && isValidThickness(lockedThickness))
144
+ ) {
145
+ merged.sheetMetalThickness = incomingThickness != null ? incomingThickness : Number(lockedThickness);
146
+ }
147
+ if (
148
+ (forceBaseOverwrite && incomingBendRadius != null)
149
+ || (!isValidBendRadius(merged.sheetMetalBendRadius) && isValidBendRadius(lockedBendRadius))
150
+ ) {
151
+ merged.sheetMetalBendRadius = incomingBendRadius != null ? incomingBendRadius : Number(lockedBendRadius);
152
+ }
153
+ if (
154
+ (forceBaseOverwrite && incomingNeutral != null)
155
+ || (!isValidNeutralFactor(merged.sheetMetalNeutralFactor) && isValidNeutralFactor(lockedNeutral))
156
+ ) {
157
+ merged.sheetMetalNeutralFactor = incomingNeutral != null ? incomingNeutral : Number(lockedNeutral);
158
+ }
159
+ if (baseType && (forceBaseOverwrite || !merged.sheetMetalBaseType)) merged.sheetMetalBaseType = baseType;
160
+ merged.sheetMetalFeatureId = featureID ?? merged.sheetMetalFeatureId ?? null;
161
+ if (extra !== undefined) merged.sheetMetalExtra = extra || null;
162
+ metadataManager.setMetadataObject(metaTarget, merged);
163
+ }
164
+ }
165
+ }