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,248 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
6
+ <title>Plugins and Examples - BREP</title>
7
+ <style>
8
+ :root{
9
+ --bg:#0b0f14; --panel:#0f141b; --text:#d7dde6; --muted:#9aa7b2;
10
+ --border:#1b2430; --accent:#5cc8ff; --chip:#121823;
11
+ }
12
+ *{box-sizing:border-box}
13
+ html,body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono','Courier New',monospace}
14
+ main{max-width:1100px;margin:0 auto;padding:28px}
15
+ h1{margin:0 0 18px;font-size:22px;color:var(--accent);font-weight:700}
16
+ .summary{color:var(--muted);margin-bottom:22px}
17
+ .card{background:var(--panel);border:1px solid var(--border);border-radius:14px;padding:18px;margin:0 0 18px}
18
+ .readme{padding:0}
19
+ .readme .header{padding:16px 18px;border-bottom:1px solid var(--border)}
20
+ .readme .content{padding:18px}
21
+ .doc-card{padding:18px}
22
+ .doc-nav{margin:0 0 18px;display:flex;gap:12px;flex-wrap:wrap;align-items:center;color:var(--muted)}
23
+ .doc-nav-links{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
24
+ .doc-nav a{color:var(--accent);font-weight:600}
25
+ .doc-list{list-style:none;margin:18px 0;padding:0}
26
+ .doc-list li{margin:6px 0}
27
+ .doc-list a{color:var(--accent)}
28
+ .nav-search{margin-left:auto;position:relative;display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end;min-width:240px;max-width:520px}
29
+ .search-title{font-weight:700;font-size:14px;margin-bottom:4px}
30
+ .search-hint{color:var(--muted);font-size:12px;margin:0}
31
+ .search-input-row{display:flex;gap:8px;align-items:center;width:100%}
32
+ .search-input{flex:1;border:1px solid var(--border);border-radius:10px;background:var(--chip);color:var(--text);padding:10px 12px}
33
+ .search-input:focus{outline:1px solid var(--accent);box-shadow:0 0 0 3px rgba(92,200,255,0.15)}
34
+ .search-clear{border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:10px;padding:9px 12px;cursor:pointer;font-weight:600}
35
+ .search-clear:hover{border-color:var(--accent);color:var(--accent)}
36
+ .search-status{color:var(--muted);font-size:12px;margin-top:4px;width:100%;text-align:right}
37
+ .search-results{position:absolute;top:100%;right:0;margin-top:10px;border:1px solid var(--border);border-radius:12px;background:var(--panel);max-height:360px;overflow:auto;min-width:320px;max-width:520px;box-shadow:0 12px 30px rgba(0,0,0,0.35);z-index:25}
38
+ .search-results ul{list-style:none;margin:0;padding:0}
39
+ .search-item{padding:10px 12px;border-bottom:1px solid var(--border)}
40
+ .search-item:last-child{border-bottom:none}
41
+ .search-item a{display:block;color:var(--accent);font-weight:600}
42
+ .search-snippet{color:var(--muted);font-size:13px;margin-top:4px}
43
+ .search-results mark{background:rgba(92,200,255,0.2);color:var(--text);border-radius:4px;padding:0 2px}
44
+ .prose h1{font-size:24px;margin:0 0 12px}
45
+ .prose h2{font-size:18px;margin:18px 0 8px}
46
+ .prose h3{font-size:16px;margin:14px 0 6px}
47
+ .prose p{margin:0 0 10px}
48
+ .prose ul,.prose ol{margin:0 0 10px 18px}
49
+ .prose li{margin:4px 0}
50
+ .prose code{background:#0d1520;border:1px solid var(--border);padding:1px 5px;border-radius:6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono','Courier New',monospace;font-size:12px}
51
+ .prose pre{background:#0d1520;border:1px solid var(--border);padding:12px;border-radius:12px;overflow:auto}
52
+ .prose a{color:var(--accent)}
53
+ .prose img{max-width:100%;height:auto;}
54
+ .prose table{border-collapse:collapse;width:100%;margin:16px 0;background:var(--panel);border:1px solid var(--border);border-radius:8px;overflow:hidden}
55
+ .prose th,.prose td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--border)}
56
+ .prose th{background:var(--chip);color:var(--text);font-weight:600;font-size:13px}
57
+ .prose tr:last-child td{border-bottom:none}
58
+ .prose tbody tr:hover{background:rgba(92,200,255,0.05)}
59
+ .license{
60
+ background:var(--panel);border:1px solid var(--border);border-radius:14px;
61
+ padding:16px 16px 8px;margin:0 0 18px;
62
+ }
63
+ .license > h2{margin:0 0 10px;font-size:16px;font-weight:700}
64
+ .pkg{
65
+ border-top:1px solid var(--border);padding:10px 0;
66
+ display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;
67
+ }
68
+ .pkg:first-of-type{border-top:none}
69
+ .pkg .meta{display:flex;gap:10px;flex-wrap:wrap}
70
+ .pkg .name{font-weight:600}
71
+ .pkg .desc{color:var(--muted);margin-top:2px}
72
+ a{color:var(--accent);text-decoration:none} a:hover{text-decoration:underline}
73
+ .chip{background:var(--chip);border:1px solid var(--border);border-radius:999px;padding:2px 8px;font-size:12px;color:var(--muted)}
74
+ .footer{margin-top:26px;color:var(--muted);font-size:12px}
75
+ </style>
76
+ </head>
77
+ <body>
78
+ <main>
79
+ <nav class="doc-nav">
80
+ <div class="doc-nav-links">
81
+ <a href="index.html">Help Home</a><span>&middot;</span><a href="/help/table-of-contents.html">Table of Contents</a><span>&middot;</span><a href="https://github.com/mmiscool/BREP" target="_blank" rel="noopener noreferrer">GitHub</a>
82
+ </div>
83
+ <div class="nav-search">
84
+ <div class="search-input-row">
85
+ <input type="search" id="doc-search" class="search-input" placeholder="Search docs... Type at least 2 characters to search" autocomplete="off" spellcheck="false" />
86
+ <button type="button" class="search-clear" id="doc-search-clear">Clear</button>
87
+ </div>
88
+ <div class="search-status" id="doc-search-status"></div>
89
+ <div class="search-results" id="doc-search-results" hidden>
90
+ <ul id="doc-search-list"></ul>
91
+ </div>
92
+ </div>
93
+ </nav>
94
+ <section class="card doc-card">
95
+
96
+ <div class="prose">
97
+ <h1>Plugins and Examples</h1><ul><li>Example plugin repository: <a href="https://github.com/mmiscool/BREPpluginExample" target="_blank" rel="noopener noreferrer">https://github.com/mmiscool/BREPpluginExample</a></li><li>Example plugin README: <a href="https://github.com/mmiscool/BREPpluginExample/blob/master/README.md" target="_blank" rel="noopener noreferrer">https://github.com/mmiscool/BREPpluginExample/blob/master/README.md</a></li><li>Entrypoint: <a href="https://github.com/mmiscool/BREPpluginExample/blob/master/plugin.js" target="_blank" rel="noopener noreferrer">https://github.com/mmiscool/BREPpluginExample/blob/master/plugin.js</a></li><li>Feature example: <a href="https://github.com/mmiscool/BREPpluginExample/blob/master/exampleFeature.js" target="_blank" rel="noopener noreferrer">https://github.com/mmiscool/BREPpluginExample/blob/master/exampleFeature.js</a></li></ul><p>Use the plugin system to extend BREP with custom features, toolbar buttons, or automation pipelines sourced from GitHub.</p><p>When adding dialogs for your feature, follow the shared <code>inputParamsSchema</code> format described in <a href="input-params-schema.html">Input Params Schema</a> to pick field types, defaults, and reference-selection rules.</p>
98
+ </div>
99
+ </section>
100
+ </main>
101
+ <script>
102
+ (() => {
103
+ const searchInput = document.getElementById("doc-search");
104
+ const resultsBox = document.getElementById("doc-search-results");
105
+ const resultsList = document.getElementById("doc-search-list");
106
+ const statusEl = document.getElementById("doc-search-status");
107
+ const clearBtn = document.getElementById("doc-search-clear");
108
+ if (!searchInput || !resultsBox || !resultsList || !statusEl || !clearBtn) return;
109
+ const indexUrl = "./search-index.json";
110
+ let indexPromise = null;
111
+ let cachedEntries = null;
112
+
113
+ const escapeHtml = (text = "") =>
114
+ text
115
+ .replace(/&/g, "&amp;")
116
+ .replace(/</g, "&lt;")
117
+ .replace(/>/g, "&gt;");
118
+
119
+ const escapeRegExp = (text = "") => text.replace(/[.*+?^{}()|[]\$]/g, "\$&");
120
+
121
+ const highlight = (text, terms) => {
122
+ if (!terms.length) return escapeHtml(text);
123
+ const pattern = terms.map(escapeRegExp).join("|");
124
+ const regex = new RegExp(`(${pattern})`, "gi");
125
+ return escapeHtml(text).replace(regex, "<mark>$1</mark>");
126
+ };
127
+
128
+ const buildSnippet = (entry, terms) => {
129
+ const source = entry.content || entry.summary || "";
130
+ if (!source) return { plain: "", highlighted: "" };
131
+ let hit = source.length;
132
+ for (const term of terms) {
133
+ const idx = entry.contentLower.indexOf(term);
134
+ if (idx !== -1 && idx < hit) hit = idx;
135
+ }
136
+ if (!Number.isFinite(hit) || hit === source.length) hit = 0;
137
+ const start = Math.max(0, hit - 60);
138
+ const end = Math.min(source.length, hit + 140);
139
+ const snippet = source.slice(start, end);
140
+ return { plain: snippet, highlighted: highlight(snippet, terms) };
141
+ };
142
+
143
+ const updateStatus = (message) => {
144
+ statusEl.textContent = message;
145
+ };
146
+
147
+ const loadIndex = async () => {
148
+ if (cachedEntries) return cachedEntries;
149
+ if (!indexPromise) {
150
+ indexPromise = fetch(indexUrl, { cache: "no-store" })
151
+ .then((res) => {
152
+ if (!res.ok) throw new Error("Failed to load search index");
153
+ return res.json();
154
+ })
155
+ .then((json) => {
156
+ cachedEntries = Array.isArray(json)
157
+ ? json.map((entry) => ({
158
+ ...entry,
159
+ contentLower: (entry.content || "").toLowerCase(),
160
+ titleLower: (entry.title || "").toLowerCase(),
161
+ }))
162
+ : [];
163
+ return cachedEntries;
164
+ })
165
+ .catch((err) => {
166
+ console.error("Search index load failed", err);
167
+ cachedEntries = [];
168
+ throw err;
169
+ });
170
+ }
171
+ return indexPromise;
172
+ };
173
+
174
+ const renderResults = (entries, terms) => {
175
+ if (!terms.length) {
176
+ resultsBox.hidden = true;
177
+ return;
178
+ }
179
+ if (!entries.length) {
180
+ resultsList.innerHTML = '<li class="search-item"><div class="search-snippet">No matches found.</div></li>';
181
+ resultsBox.hidden = false;
182
+ return;
183
+ }
184
+ const rendered = entries
185
+ .slice(0, 30)
186
+ .map((entry) => {
187
+ const snippet = buildSnippet(entry, terms);
188
+ const title = highlight(entry.title || entry.href, terms);
189
+ const hasFragment = snippet.plain && snippet.plain.trim().length > 0;
190
+ const fragment = hasFragment ? `#:~:text=${encodeURIComponent(snippet.plain.trim())}` : "";
191
+ const hrefWithFragment = hasFragment
192
+ ? (entry.href.includes("#") ? `${entry.href}&:~:text=${encodeURIComponent(snippet.plain.trim())}` : `${entry.href}${fragment}`)
193
+ : entry.href;
194
+ const snippetHtml = snippet.highlighted ? `<div class="search-snippet">${snippet.highlighted}</div>` : "";
195
+ return `<li class="search-item"><a href="${hrefWithFragment}">${title}</a>${snippetHtml}</li>`;
196
+ })
197
+ .join("");
198
+ resultsList.innerHTML = rendered;
199
+ resultsBox.hidden = false;
200
+ };
201
+
202
+ const performSearch = async () => {
203
+ const rawQuery = searchInput.value.trim();
204
+ if (rawQuery.length < 2) {
205
+ updateStatus("Type at least 2 characters to search.");
206
+ resultsBox.hidden = true;
207
+ return;
208
+ }
209
+ const terms = rawQuery.toLowerCase().split(/\s+/).filter(Boolean);
210
+ updateStatus("Searching...");
211
+ try {
212
+ const entries = await loadIndex();
213
+ const matches = entries.filter((entry) =>
214
+ terms.every((term) => entry.contentLower.includes(term) || entry.titleLower.includes(term))
215
+ );
216
+ renderResults(matches, terms);
217
+ updateStatus(matches.length ? `${matches.length} result${matches.length === 1 ? "" : "s"} for "${rawQuery}"` : "No matches found.");
218
+ } catch (err) {
219
+ updateStatus("Search unavailable (could not load index).");
220
+ }
221
+ };
222
+
223
+ searchInput.addEventListener("input", performSearch);
224
+
225
+ searchInput.addEventListener("focus", () => {
226
+ if (!cachedEntries) {
227
+ loadIndex().catch(() => updateStatus("Search unavailable (could not load index)."));
228
+ }
229
+ });
230
+
231
+ clearBtn.addEventListener("click", () => {
232
+ searchInput.value = "";
233
+ resultsBox.hidden = true;
234
+ updateStatus("Type at least 2 characters to search.");
235
+ searchInput.focus();
236
+ });
237
+
238
+ document.addEventListener("keydown", (evt) => {
239
+ if (evt.key === "Escape" && document.activeElement === searchInput) {
240
+ searchInput.value = "";
241
+ resultsBox.hidden = true;
242
+ updateStatus("Type at least 2 characters to search.");
243
+ }
244
+ });
245
+ })();
246
+ </script>
247
+ </body>
248
+ </html>
@@ -0,0 +1,248 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
6
+ <title>Angle Dimension - BREP</title>
7
+ <style>
8
+ :root{
9
+ --bg:#0b0f14; --panel:#0f141b; --text:#d7dde6; --muted:#9aa7b2;
10
+ --border:#1b2430; --accent:#5cc8ff; --chip:#121823;
11
+ }
12
+ *{box-sizing:border-box}
13
+ html,body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono','Courier New',monospace}
14
+ main{max-width:1100px;margin:0 auto;padding:28px}
15
+ h1{margin:0 0 18px;font-size:22px;color:var(--accent);font-weight:700}
16
+ .summary{color:var(--muted);margin-bottom:22px}
17
+ .card{background:var(--panel);border:1px solid var(--border);border-radius:14px;padding:18px;margin:0 0 18px}
18
+ .readme{padding:0}
19
+ .readme .header{padding:16px 18px;border-bottom:1px solid var(--border)}
20
+ .readme .content{padding:18px}
21
+ .doc-card{padding:18px}
22
+ .doc-nav{margin:0 0 18px;display:flex;gap:12px;flex-wrap:wrap;align-items:center;color:var(--muted)}
23
+ .doc-nav-links{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
24
+ .doc-nav a{color:var(--accent);font-weight:600}
25
+ .doc-list{list-style:none;margin:18px 0;padding:0}
26
+ .doc-list li{margin:6px 0}
27
+ .doc-list a{color:var(--accent)}
28
+ .nav-search{margin-left:auto;position:relative;display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end;min-width:240px;max-width:520px}
29
+ .search-title{font-weight:700;font-size:14px;margin-bottom:4px}
30
+ .search-hint{color:var(--muted);font-size:12px;margin:0}
31
+ .search-input-row{display:flex;gap:8px;align-items:center;width:100%}
32
+ .search-input{flex:1;border:1px solid var(--border);border-radius:10px;background:var(--chip);color:var(--text);padding:10px 12px}
33
+ .search-input:focus{outline:1px solid var(--accent);box-shadow:0 0 0 3px rgba(92,200,255,0.15)}
34
+ .search-clear{border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:10px;padding:9px 12px;cursor:pointer;font-weight:600}
35
+ .search-clear:hover{border-color:var(--accent);color:var(--accent)}
36
+ .search-status{color:var(--muted);font-size:12px;margin-top:4px;width:100%;text-align:right}
37
+ .search-results{position:absolute;top:100%;right:0;margin-top:10px;border:1px solid var(--border);border-radius:12px;background:var(--panel);max-height:360px;overflow:auto;min-width:320px;max-width:520px;box-shadow:0 12px 30px rgba(0,0,0,0.35);z-index:25}
38
+ .search-results ul{list-style:none;margin:0;padding:0}
39
+ .search-item{padding:10px 12px;border-bottom:1px solid var(--border)}
40
+ .search-item:last-child{border-bottom:none}
41
+ .search-item a{display:block;color:var(--accent);font-weight:600}
42
+ .search-snippet{color:var(--muted);font-size:13px;margin-top:4px}
43
+ .search-results mark{background:rgba(92,200,255,0.2);color:var(--text);border-radius:4px;padding:0 2px}
44
+ .prose h1{font-size:24px;margin:0 0 12px}
45
+ .prose h2{font-size:18px;margin:18px 0 8px}
46
+ .prose h3{font-size:16px;margin:14px 0 6px}
47
+ .prose p{margin:0 0 10px}
48
+ .prose ul,.prose ol{margin:0 0 10px 18px}
49
+ .prose li{margin:4px 0}
50
+ .prose code{background:#0d1520;border:1px solid var(--border);padding:1px 5px;border-radius:6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono','Courier New',monospace;font-size:12px}
51
+ .prose pre{background:#0d1520;border:1px solid var(--border);padding:12px;border-radius:12px;overflow:auto}
52
+ .prose a{color:var(--accent)}
53
+ .prose img{max-width:100%;height:auto;}
54
+ .prose table{border-collapse:collapse;width:100%;margin:16px 0;background:var(--panel);border:1px solid var(--border);border-radius:8px;overflow:hidden}
55
+ .prose th,.prose td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--border)}
56
+ .prose th{background:var(--chip);color:var(--text);font-weight:600;font-size:13px}
57
+ .prose tr:last-child td{border-bottom:none}
58
+ .prose tbody tr:hover{background:rgba(92,200,255,0.05)}
59
+ .license{
60
+ background:var(--panel);border:1px solid var(--border);border-radius:14px;
61
+ padding:16px 16px 8px;margin:0 0 18px;
62
+ }
63
+ .license > h2{margin:0 0 10px;font-size:16px;font-weight:700}
64
+ .pkg{
65
+ border-top:1px solid var(--border);padding:10px 0;
66
+ display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;
67
+ }
68
+ .pkg:first-of-type{border-top:none}
69
+ .pkg .meta{display:flex;gap:10px;flex-wrap:wrap}
70
+ .pkg .name{font-weight:600}
71
+ .pkg .desc{color:var(--muted);margin-top:2px}
72
+ a{color:var(--accent);text-decoration:none} a:hover{text-decoration:underline}
73
+ .chip{background:var(--chip);border:1px solid var(--border);border-radius:999px;padding:2px 8px;font-size:12px;color:var(--muted)}
74
+ .footer{margin-top:26px;color:var(--muted);font-size:12px}
75
+ </style>
76
+ </head>
77
+ <body>
78
+ <main>
79
+ <nav class="doc-nav">
80
+ <div class="doc-nav-links">
81
+ <a href="index.html">Help Home</a><span>&middot;</span><a href="/help/table-of-contents.html">Table of Contents</a><span>&middot;</span><a href="https://github.com/mmiscool/BREP" target="_blank" rel="noopener noreferrer">GitHub</a>
82
+ </div>
83
+ <div class="nav-search">
84
+ <div class="search-input-row">
85
+ <input type="search" id="doc-search" class="search-input" placeholder="Search docs... Type at least 2 characters to search" autocomplete="off" spellcheck="false" />
86
+ <button type="button" class="search-clear" id="doc-search-clear">Clear</button>
87
+ </div>
88
+ <div class="search-status" id="doc-search-status"></div>
89
+ <div class="search-results" id="doc-search-results" hidden>
90
+ <ul id="doc-search-list"></ul>
91
+ </div>
92
+ </div>
93
+ </nav>
94
+ <section class="card doc-card">
95
+
96
+ <div class="prose">
97
+ <h1>Angle Dimension</h1><p>Status: Implemented</p><p><img src="pmi-annotations__Angle_Dimension_dialog.png" alt="Angle Dimension dialog" width="280" loading="lazy" /></p><p>Angle dimensions measure the sweep between two faces or edges and display the result on the active PMI sheet. Use them for chamfers, draft checks, and assembly alignment callouts.</p><h2>Inputs</h2><ul><li><code>annotationID</code> – optional identifier retained in PMI exports.</li><li><code>decimals</code> – decimal precision; defaults to the PMI <code>angleDecimals</code> preference.</li><li><code>elementARefName</code> / <code>elementBRefName</code> – face or edge selections that define the angle.</li><li><code>planeRefName</code> – optional face or datum to override the projection plane.</li><li><code>reverseElementOrder</code> – flips the measured side when the automatic choice is not desired.</li><li><code>angleType</code> – choose <code>acute</code>, <code>obtuse</code>, or <code>reflex</code> sweep to control value formatting.</li><li><code>isReference</code> – encloses the output in parentheses and signals downstream reference handling.</li></ul><h2>Behaviour</h2><ul><li>Derives edge or face directions, constructs a local 2D basis, and draws an arc with adjustable radius.</li><li>Arrowheads, witness lines, and arc radius scale in screen space to remain readable while zooming.</li><li>Labels can be dragged; the world-space location is persisted and reused on reload.</li><li>Responds to PMI formatting callbacks so custom units or tolerancing schemes propagate to the label text.</li></ul><h2>Usage Tips</h2><ul><li>Provide a projection plane when measuring between non-parallel faces to control which cross-section drives the angle.</li><li>Toggle <code>reverseElementOrder</code> if the drawn arc lands on the wrong side of the intersection.</li><li>Use the <code>reflex</code> option to call out angles greater than 180° without recomputing geometry.</li></ul>
98
+ </div>
99
+ </section>
100
+ </main>
101
+ <script>
102
+ (() => {
103
+ const searchInput = document.getElementById("doc-search");
104
+ const resultsBox = document.getElementById("doc-search-results");
105
+ const resultsList = document.getElementById("doc-search-list");
106
+ const statusEl = document.getElementById("doc-search-status");
107
+ const clearBtn = document.getElementById("doc-search-clear");
108
+ if (!searchInput || !resultsBox || !resultsList || !statusEl || !clearBtn) return;
109
+ const indexUrl = "./search-index.json";
110
+ let indexPromise = null;
111
+ let cachedEntries = null;
112
+
113
+ const escapeHtml = (text = "") =>
114
+ text
115
+ .replace(/&/g, "&amp;")
116
+ .replace(/</g, "&lt;")
117
+ .replace(/>/g, "&gt;");
118
+
119
+ const escapeRegExp = (text = "") => text.replace(/[.*+?^{}()|[]\$]/g, "\$&");
120
+
121
+ const highlight = (text, terms) => {
122
+ if (!terms.length) return escapeHtml(text);
123
+ const pattern = terms.map(escapeRegExp).join("|");
124
+ const regex = new RegExp(`(${pattern})`, "gi");
125
+ return escapeHtml(text).replace(regex, "<mark>$1</mark>");
126
+ };
127
+
128
+ const buildSnippet = (entry, terms) => {
129
+ const source = entry.content || entry.summary || "";
130
+ if (!source) return { plain: "", highlighted: "" };
131
+ let hit = source.length;
132
+ for (const term of terms) {
133
+ const idx = entry.contentLower.indexOf(term);
134
+ if (idx !== -1 && idx < hit) hit = idx;
135
+ }
136
+ if (!Number.isFinite(hit) || hit === source.length) hit = 0;
137
+ const start = Math.max(0, hit - 60);
138
+ const end = Math.min(source.length, hit + 140);
139
+ const snippet = source.slice(start, end);
140
+ return { plain: snippet, highlighted: highlight(snippet, terms) };
141
+ };
142
+
143
+ const updateStatus = (message) => {
144
+ statusEl.textContent = message;
145
+ };
146
+
147
+ const loadIndex = async () => {
148
+ if (cachedEntries) return cachedEntries;
149
+ if (!indexPromise) {
150
+ indexPromise = fetch(indexUrl, { cache: "no-store" })
151
+ .then((res) => {
152
+ if (!res.ok) throw new Error("Failed to load search index");
153
+ return res.json();
154
+ })
155
+ .then((json) => {
156
+ cachedEntries = Array.isArray(json)
157
+ ? json.map((entry) => ({
158
+ ...entry,
159
+ contentLower: (entry.content || "").toLowerCase(),
160
+ titleLower: (entry.title || "").toLowerCase(),
161
+ }))
162
+ : [];
163
+ return cachedEntries;
164
+ })
165
+ .catch((err) => {
166
+ console.error("Search index load failed", err);
167
+ cachedEntries = [];
168
+ throw err;
169
+ });
170
+ }
171
+ return indexPromise;
172
+ };
173
+
174
+ const renderResults = (entries, terms) => {
175
+ if (!terms.length) {
176
+ resultsBox.hidden = true;
177
+ return;
178
+ }
179
+ if (!entries.length) {
180
+ resultsList.innerHTML = '<li class="search-item"><div class="search-snippet">No matches found.</div></li>';
181
+ resultsBox.hidden = false;
182
+ return;
183
+ }
184
+ const rendered = entries
185
+ .slice(0, 30)
186
+ .map((entry) => {
187
+ const snippet = buildSnippet(entry, terms);
188
+ const title = highlight(entry.title || entry.href, terms);
189
+ const hasFragment = snippet.plain && snippet.plain.trim().length > 0;
190
+ const fragment = hasFragment ? `#:~:text=${encodeURIComponent(snippet.plain.trim())}` : "";
191
+ const hrefWithFragment = hasFragment
192
+ ? (entry.href.includes("#") ? `${entry.href}&:~:text=${encodeURIComponent(snippet.plain.trim())}` : `${entry.href}${fragment}`)
193
+ : entry.href;
194
+ const snippetHtml = snippet.highlighted ? `<div class="search-snippet">${snippet.highlighted}</div>` : "";
195
+ return `<li class="search-item"><a href="${hrefWithFragment}">${title}</a>${snippetHtml}</li>`;
196
+ })
197
+ .join("");
198
+ resultsList.innerHTML = rendered;
199
+ resultsBox.hidden = false;
200
+ };
201
+
202
+ const performSearch = async () => {
203
+ const rawQuery = searchInput.value.trim();
204
+ if (rawQuery.length < 2) {
205
+ updateStatus("Type at least 2 characters to search.");
206
+ resultsBox.hidden = true;
207
+ return;
208
+ }
209
+ const terms = rawQuery.toLowerCase().split(/\s+/).filter(Boolean);
210
+ updateStatus("Searching...");
211
+ try {
212
+ const entries = await loadIndex();
213
+ const matches = entries.filter((entry) =>
214
+ terms.every((term) => entry.contentLower.includes(term) || entry.titleLower.includes(term))
215
+ );
216
+ renderResults(matches, terms);
217
+ updateStatus(matches.length ? `${matches.length} result${matches.length === 1 ? "" : "s"} for "${rawQuery}"` : "No matches found.");
218
+ } catch (err) {
219
+ updateStatus("Search unavailable (could not load index).");
220
+ }
221
+ };
222
+
223
+ searchInput.addEventListener("input", performSearch);
224
+
225
+ searchInput.addEventListener("focus", () => {
226
+ if (!cachedEntries) {
227
+ loadIndex().catch(() => updateStatus("Search unavailable (could not load index)."));
228
+ }
229
+ });
230
+
231
+ clearBtn.addEventListener("click", () => {
232
+ searchInput.value = "";
233
+ resultsBox.hidden = true;
234
+ updateStatus("Type at least 2 characters to search.");
235
+ searchInput.focus();
236
+ });
237
+
238
+ document.addEventListener("keydown", (evt) => {
239
+ if (evt.key === "Escape" && document.activeElement === searchInput) {
240
+ searchInput.value = "";
241
+ resultsBox.hidden = true;
242
+ updateStatus("Type at least 2 characters to search.");
243
+ }
244
+ });
245
+ })();
246
+ </script>
247
+ </body>
248
+ </html>