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.
- package/LICENSE.md +32 -0
- package/README.md +144 -0
- package/dist-kernel/brep-kernel.js +74699 -0
- package/dist-kernel/help/CONTRIBUTING.html +248 -0
- package/dist-kernel/help/LICENSE.html +248 -0
- package/dist-kernel/help/MODELING.png +0 -0
- package/dist-kernel/help/PMI.png +0 -0
- package/dist-kernel/help/SKETCH.png +0 -0
- package/dist-kernel/help/assembly-constraints__Coincident_Constraint_dialog.png +0 -0
- package/dist-kernel/help/assembly-constraints___Angle_Constraint_dialog.png +0 -0
- package/dist-kernel/help/assembly-constraints___Distance_Constraint_dialog.png +0 -0
- package/dist-kernel/help/assembly-constraints___Fixed_Constraint_dialog.png +0 -0
- package/dist-kernel/help/assembly-constraints___Parallel_Constraint_dialog.png +0 -0
- package/dist-kernel/help/assembly-constraints___Touch_Align_Constraint_dialog.png +0 -0
- package/dist-kernel/help/assembly-constraints__angle-constraint.html +248 -0
- package/dist-kernel/help/assembly-constraints__coincident-constraint.html +248 -0
- package/dist-kernel/help/assembly-constraints__distance-constraint.html +248 -0
- package/dist-kernel/help/assembly-constraints__fixed-constraint.html +248 -0
- package/dist-kernel/help/assembly-constraints__parallel-constraint.html +248 -0
- package/dist-kernel/help/assembly-constraints__solver.html +248 -0
- package/dist-kernel/help/assembly-constraints__touch-align-constraint.html +248 -0
- package/dist-kernel/help/brep-api.html +263 -0
- package/dist-kernel/help/brep-kernel.html +258 -0
- package/dist-kernel/help/brep-model.html +248 -0
- package/dist-kernel/help/cylindrical-face-radius-embedding.html +290 -0
- package/dist-kernel/help/dialog-screenshots.html +248 -0
- package/dist-kernel/help/extruded-sketch-radius-embedding.html +336 -0
- package/dist-kernel/help/features__Assembly_Component_dialog.png +0 -0
- package/dist-kernel/help/features__Boolean_dialog.png +0 -0
- package/dist-kernel/help/features__Chamfer_dialog.png +0 -0
- package/dist-kernel/help/features__Datium_dialog.png +0 -0
- package/dist-kernel/help/features__Extrude_dialog.png +0 -0
- package/dist-kernel/help/features__Fillet_dialog.png +0 -0
- package/dist-kernel/help/features__Helix_dialog.png +0 -0
- package/dist-kernel/help/features__Hole_dialog.png +0 -0
- package/dist-kernel/help/features__Image_Heightmap_Solid_dialog.png +0 -0
- package/dist-kernel/help/features__Image_to_Face_dialog.png +0 -0
- package/dist-kernel/help/features__Import_3D_Model_dialog.png +0 -0
- package/dist-kernel/help/features__Loft_dialog.png +0 -0
- package/dist-kernel/help/features__Mirror_dialog.png +0 -0
- package/dist-kernel/help/features__Offset_Shell_dialog.png +0 -0
- package/dist-kernel/help/features__Overlap_Cleanup_dialog.png +0 -0
- package/dist-kernel/help/features__Pattern_Linear_dialog.png +0 -0
- package/dist-kernel/help/features__Pattern_Radial_dialog.png +0 -0
- package/dist-kernel/help/features__Pattern_dialog.png +0 -0
- package/dist-kernel/help/features__Plane_dialog.png +0 -0
- package/dist-kernel/help/features__Primitive_Cone_dialog.png +0 -0
- package/dist-kernel/help/features__Primitive_Cube_dialog.png +0 -0
- package/dist-kernel/help/features__Primitive_Cylinder_dialog.png +0 -0
- package/dist-kernel/help/features__Primitive_Pyramid_dialog.png +0 -0
- package/dist-kernel/help/features__Primitive_Sphere_dialog.png +0 -0
- package/dist-kernel/help/features__Primitive_Torus_dialog.png +0 -0
- package/dist-kernel/help/features__Remesh_dialog.png +0 -0
- package/dist-kernel/help/features__Revolve_dialog.png +0 -0
- package/dist-kernel/help/features__Sheet_Metal_Contour_Flange_dialog.png +0 -0
- package/dist-kernel/help/features__Sheet_Metal_Cutout_dialog.png +0 -0
- package/dist-kernel/help/features__Sheet_Metal_Flange_dialog.png +0 -0
- package/dist-kernel/help/features__Sheet_Metal_Tab_dialog.png +0 -0
- package/dist-kernel/help/features__Sketch_dialog.png +0 -0
- package/dist-kernel/help/features__Spline_dialog.png +0 -0
- package/dist-kernel/help/features__Sweep_dialog.png +0 -0
- package/dist-kernel/help/features__Transform_dialog.png +0 -0
- package/dist-kernel/help/features__Tube_dialog.png +0 -0
- package/dist-kernel/help/features__assembly-component.html +248 -0
- package/dist-kernel/help/features__boolean.html +248 -0
- package/dist-kernel/help/features__chamfer.html +248 -0
- package/dist-kernel/help/features__datium.html +248 -0
- package/dist-kernel/help/features__datum.html +248 -0
- package/dist-kernel/help/features__extrude.html +248 -0
- package/dist-kernel/help/features__fillet.html +248 -0
- package/dist-kernel/help/features__helix.html +248 -0
- package/dist-kernel/help/features__hole.html +248 -0
- package/dist-kernel/help/features__image-heightmap-solid.html +248 -0
- package/dist-kernel/help/features__image-to-face-2D_dialog.png +0 -0
- package/dist-kernel/help/features__image-to-face-3D_dialog.png +0 -0
- package/dist-kernel/help/features__image-to-face.html +248 -0
- package/dist-kernel/help/features__import-3d-model.html +248 -0
- package/dist-kernel/help/features__index.html +248 -0
- package/dist-kernel/help/features__loft.html +248 -0
- package/dist-kernel/help/features__mirror.html +248 -0
- package/dist-kernel/help/features__offset-shell.html +248 -0
- package/dist-kernel/help/features__pattern-linear.html +248 -0
- package/dist-kernel/help/features__pattern-radial.html +248 -0
- package/dist-kernel/help/features__pattern.html +248 -0
- package/dist-kernel/help/features__plane.html +248 -0
- package/dist-kernel/help/features__primitive-cone.html +248 -0
- package/dist-kernel/help/features__primitive-cube.html +248 -0
- package/dist-kernel/help/features__primitive-cylinder.html +248 -0
- package/dist-kernel/help/features__primitive-pyramid.html +248 -0
- package/dist-kernel/help/features__primitive-sphere.html +248 -0
- package/dist-kernel/help/features__primitive-torus.html +248 -0
- package/dist-kernel/help/features__remesh.html +248 -0
- package/dist-kernel/help/features__revolve.html +248 -0
- package/dist-kernel/help/features__sheet-metal-contour-flange.html +248 -0
- package/dist-kernel/help/features__sheet-metal-flange.html +248 -0
- package/dist-kernel/help/features__sheet-metal-tab.html +248 -0
- package/dist-kernel/help/features__sketch.html +248 -0
- package/dist-kernel/help/features__spline.html +248 -0
- package/dist-kernel/help/features__sweep.html +248 -0
- package/dist-kernel/help/features__transform.html +248 -0
- package/dist-kernel/help/features__tube.html +248 -0
- package/dist-kernel/help/file-formats.html +248 -0
- package/dist-kernel/help/getting-started.html +248 -0
- package/dist-kernel/help/highlights.html +248 -0
- package/dist-kernel/help/history-systems.html +248 -0
- package/dist-kernel/help/how-it-works.html +248 -0
- package/dist-kernel/help/index.html +862 -0
- package/dist-kernel/help/input-params-schema.html +363 -0
- package/dist-kernel/help/inspector-improvements.html +248 -0
- package/dist-kernel/help/inspector.html +248 -0
- package/dist-kernel/help/modes__modeling.html +248 -0
- package/dist-kernel/help/modes__pmi.html +248 -0
- package/dist-kernel/help/modes__sketch.html +248 -0
- package/dist-kernel/help/plugins.html +248 -0
- package/dist-kernel/help/pmi-annotations__Angle_Dimension_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__Explode_Body_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__Hole_Callout_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__Leader_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__Linear_Dimension_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__Note_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__Radial_Dimension_dialog.png +0 -0
- package/dist-kernel/help/pmi-annotations__angle-dimension.html +248 -0
- package/dist-kernel/help/pmi-annotations__explode-body.html +248 -0
- package/dist-kernel/help/pmi-annotations__hole-callout.html +248 -0
- package/dist-kernel/help/pmi-annotations__index.html +248 -0
- package/dist-kernel/help/pmi-annotations__leader.html +248 -0
- package/dist-kernel/help/pmi-annotations__linear-dimension.html +248 -0
- package/dist-kernel/help/pmi-annotations__note.html +248 -0
- package/dist-kernel/help/pmi-annotations__radial-dimension.html +248 -0
- package/dist-kernel/help/search-index.json +464 -0
- package/dist-kernel/help/simplified-radial-dimensions.html +298 -0
- package/dist-kernel/help/solid-methods.html +359 -0
- package/dist-kernel/help/table-of-contents.html +330 -0
- package/dist-kernel/help/ui-overview.html +248 -0
- package/dist-kernel/help/whats-new.html +248 -0
- package/package.json +54 -0
- package/src/BREP/AssemblyComponent.js +42 -0
- package/src/BREP/BREP.js +43 -0
- package/src/BREP/BetterSolid.js +805 -0
- package/src/BREP/Edge.js +103 -0
- package/src/BREP/Extrude.js +403 -0
- package/src/BREP/Face.js +187 -0
- package/src/BREP/MeshRepairer.js +634 -0
- package/src/BREP/OffsetShellSolid.js +614 -0
- package/src/BREP/PointCloudWrap.js +302 -0
- package/src/BREP/Revolve.js +345 -0
- package/src/BREP/SolidMethods/authoring.js +112 -0
- package/src/BREP/SolidMethods/booleanOps.js +230 -0
- package/src/BREP/SolidMethods/chamfer.js +122 -0
- package/src/BREP/SolidMethods/edgeResolution.js +25 -0
- package/src/BREP/SolidMethods/fillet.js +792 -0
- package/src/BREP/SolidMethods/index.js +72 -0
- package/src/BREP/SolidMethods/io.js +105 -0
- package/src/BREP/SolidMethods/lifecycle.js +103 -0
- package/src/BREP/SolidMethods/manifoldOps.js +375 -0
- package/src/BREP/SolidMethods/meshCleanup.js +2512 -0
- package/src/BREP/SolidMethods/meshQueries.js +264 -0
- package/src/BREP/SolidMethods/metadata.js +106 -0
- package/src/BREP/SolidMethods/metrics.js +51 -0
- package/src/BREP/SolidMethods/transforms.js +361 -0
- package/src/BREP/SolidMethods/visualize.js +508 -0
- package/src/BREP/SolidShared.js +26 -0
- package/src/BREP/Sweep.js +1596 -0
- package/src/BREP/Tube.js +857 -0
- package/src/BREP/Vertex.js +43 -0
- package/src/BREP/applyBooleanOperation.js +704 -0
- package/src/BREP/boundsUtils.js +48 -0
- package/src/BREP/chamfer.js +551 -0
- package/src/BREP/edgePolylineUtils.js +85 -0
- package/src/BREP/fillets/common.js +388 -0
- package/src/BREP/fillets/fillet.js +1422 -0
- package/src/BREP/fillets/filletGeometry.js +15 -0
- package/src/BREP/fillets/inset.js +389 -0
- package/src/BREP/fillets/offsetHelper.js +143 -0
- package/src/BREP/fillets/outset.js +88 -0
- package/src/BREP/helix.js +193 -0
- package/src/BREP/meshToBrep.js +234 -0
- package/src/BREP/primitives.js +279 -0
- package/src/BREP/setupManifold.js +71 -0
- package/src/BREP/threadGeometry.js +1120 -0
- package/src/BREP/triangleUtils.js +8 -0
- package/src/BREP/triangulate.js +608 -0
- package/src/FeatureRegistry.js +183 -0
- package/src/PartHistory.js +1132 -0
- package/src/UI/AccordionWidget.js +292 -0
- package/src/UI/CADmaterials.js +850 -0
- package/src/UI/EnvMonacoEditor.js +522 -0
- package/src/UI/FloatingWindow.js +396 -0
- package/src/UI/HistoryWidget.js +457 -0
- package/src/UI/MainToolbar.js +131 -0
- package/src/UI/ModelLibraryView.js +194 -0
- package/src/UI/OrthoCameraIdle.js +206 -0
- package/src/UI/PluginsWidget.js +280 -0
- package/src/UI/SceneListing.js +606 -0
- package/src/UI/SelectionFilter.js +629 -0
- package/src/UI/ViewCube.js +389 -0
- package/src/UI/assembly/AssemblyConstraintCollectionWidget.js +329 -0
- package/src/UI/assembly/AssemblyConstraintControlsWidget.js +282 -0
- package/src/UI/assembly/AssemblyConstraintsWidget.css +292 -0
- package/src/UI/assembly/AssemblyConstraintsWidget.js +1373 -0
- package/src/UI/assembly/constraintFaceUtils.js +115 -0
- package/src/UI/assembly/constraintHighlightUtils.js +70 -0
- package/src/UI/assembly/constraintLabelUtils.js +31 -0
- package/src/UI/assembly/constraintPointUtils.js +64 -0
- package/src/UI/assembly/constraintSelectionUtils.js +185 -0
- package/src/UI/assembly/constraintStatusUtils.js +142 -0
- package/src/UI/componentSelectorModal.js +240 -0
- package/src/UI/controls/CombinedTransformControls.js +386 -0
- package/src/UI/dialogs.js +351 -0
- package/src/UI/expressionsManager.js +100 -0
- package/src/UI/featureDialogWidgets/booleanField.js +25 -0
- package/src/UI/featureDialogWidgets/booleanOperationField.js +97 -0
- package/src/UI/featureDialogWidgets/buttonField.js +45 -0
- package/src/UI/featureDialogWidgets/componentSelectorField.js +102 -0
- package/src/UI/featureDialogWidgets/defaultField.js +23 -0
- package/src/UI/featureDialogWidgets/fileField.js +66 -0
- package/src/UI/featureDialogWidgets/index.js +34 -0
- package/src/UI/featureDialogWidgets/numberField.js +165 -0
- package/src/UI/featureDialogWidgets/optionsField.js +33 -0
- package/src/UI/featureDialogWidgets/referenceSelectionField.js +208 -0
- package/src/UI/featureDialogWidgets/stringField.js +24 -0
- package/src/UI/featureDialogWidgets/textareaField.js +28 -0
- package/src/UI/featureDialogWidgets/threadDesignationField.js +160 -0
- package/src/UI/featureDialogWidgets/transformField.js +252 -0
- package/src/UI/featureDialogWidgets/utils.js +43 -0
- package/src/UI/featureDialogWidgets/vec3Field.js +133 -0
- package/src/UI/featureDialogs.js +1414 -0
- package/src/UI/fileManagerWidget.js +615 -0
- package/src/UI/history/HistoryCollectionWidget.js +1294 -0
- package/src/UI/history/historyCollectionWidget.css.js +257 -0
- package/src/UI/history/historyDisplayInfo.js +133 -0
- package/src/UI/mobile.js +28 -0
- package/src/UI/objectDump.js +442 -0
- package/src/UI/pmi/AnnotationCollectionWidget.js +120 -0
- package/src/UI/pmi/AnnotationHistory.js +353 -0
- package/src/UI/pmi/AnnotationRegistry.js +90 -0
- package/src/UI/pmi/BaseAnnotation.js +269 -0
- package/src/UI/pmi/LabelOverlay.css +102 -0
- package/src/UI/pmi/LabelOverlay.js +191 -0
- package/src/UI/pmi/PMIMode.js +1550 -0
- package/src/UI/pmi/PMIViewsWidget.js +1098 -0
- package/src/UI/pmi/annUtils.js +729 -0
- package/src/UI/pmi/dimensions/AngleDimensionAnnotation.js +647 -0
- package/src/UI/pmi/dimensions/ExplodeBodyAnnotation.js +507 -0
- package/src/UI/pmi/dimensions/HoleCalloutAnnotation.js +462 -0
- package/src/UI/pmi/dimensions/LeaderAnnotation.js +403 -0
- package/src/UI/pmi/dimensions/LinearDimensionAnnotation.js +532 -0
- package/src/UI/pmi/dimensions/NoteAnnotation.js +110 -0
- package/src/UI/pmi/dimensions/RadialDimensionAnnotation.js +659 -0
- package/src/UI/pmi/pmiStyle.js +44 -0
- package/src/UI/sketcher/SketchMode3D.js +4095 -0
- package/src/UI/sketcher/dimensions.js +674 -0
- package/src/UI/sketcher/glyphs.js +236 -0
- package/src/UI/sketcher/highlights.js +60 -0
- package/src/UI/toolbarButtons/aboutButton.js +5 -0
- package/src/UI/toolbarButtons/exportButton.js +609 -0
- package/src/UI/toolbarButtons/flatPatternButton.js +307 -0
- package/src/UI/toolbarButtons/importButton.js +160 -0
- package/src/UI/toolbarButtons/inspectorToggleButton.js +12 -0
- package/src/UI/toolbarButtons/metadataButton.js +1063 -0
- package/src/UI/toolbarButtons/orientToFaceButton.js +114 -0
- package/src/UI/toolbarButtons/registerDefaultButtons.js +46 -0
- package/src/UI/toolbarButtons/saveButton.js +99 -0
- package/src/UI/toolbarButtons/scriptRunnerButton.js +302 -0
- package/src/UI/toolbarButtons/testsButton.js +26 -0
- package/src/UI/toolbarButtons/undoRedoButtons.js +25 -0
- package/src/UI/toolbarButtons/wireframeToggleButton.js +5 -0
- package/src/UI/toolbarButtons/zoomToFitButton.js +5 -0
- package/src/UI/triangleDebuggerWindow.js +945 -0
- package/src/UI/viewer.js +4228 -0
- package/src/assemblyConstraints/AssemblyConstraintHistory.js +1576 -0
- package/src/assemblyConstraints/AssemblyConstraintRegistry.js +120 -0
- package/src/assemblyConstraints/BaseAssemblyConstraint.js +66 -0
- package/src/assemblyConstraints/constraintExpressionUtils.js +35 -0
- package/src/assemblyConstraints/constraintUtils/parallelAlignment.js +676 -0
- package/src/assemblyConstraints/constraints/AngleConstraint.js +485 -0
- package/src/assemblyConstraints/constraints/CoincidentConstraint.js +194 -0
- package/src/assemblyConstraints/constraints/DistanceConstraint.js +616 -0
- package/src/assemblyConstraints/constraints/FixedConstraint.js +78 -0
- package/src/assemblyConstraints/constraints/ParallelConstraint.js +252 -0
- package/src/assemblyConstraints/constraints/TouchAlignConstraint.js +961 -0
- package/src/core/entities/HistoryCollectionBase.js +72 -0
- package/src/core/entities/ListEntityBase.js +109 -0
- package/src/core/entities/schemaProcesser.js +121 -0
- package/src/exporters/sheetMetalFlatPattern.js +659 -0
- package/src/exporters/sheetMetalUnfold.js +862 -0
- package/src/exporters/step.js +1135 -0
- package/src/exporters/threeMF.js +575 -0
- package/src/features/assemblyComponent/AssemblyComponentFeature.js +780 -0
- package/src/features/boolean/BooleanFeature.js +94 -0
- package/src/features/chamfer/ChamferFeature.js +116 -0
- package/src/features/datium/DatiumFeature.js +80 -0
- package/src/features/edgeFeatureUtils.js +41 -0
- package/src/features/extrude/ExtrudeFeature.js +143 -0
- package/src/features/fillet/FilletFeature.js +197 -0
- package/src/features/helix/HelixFeature.js +405 -0
- package/src/features/hole/HoleFeature.js +1050 -0
- package/src/features/hole/screwClearance.js +86 -0
- package/src/features/hole/threadDesignationCatalog.js +149 -0
- package/src/features/imageHeightSolid/ImageHeightmapSolidFeature.js +463 -0
- package/src/features/imageToFace/ImageToFaceFeature.js +727 -0
- package/src/features/imageToFace/imageEditor.js +1270 -0
- package/src/features/imageToFace/traceUtils.js +971 -0
- package/src/features/import3dModel/Import3dModelFeature.js +151 -0
- package/src/features/loft/LoftFeature.js +605 -0
- package/src/features/mirror/MirrorFeature.js +151 -0
- package/src/features/offsetFace/OffsetFaceFeature.js +370 -0
- package/src/features/offsetShell/OffsetShellFeature.js +89 -0
- package/src/features/overlapCleanup/OverlapCleanupFeature.js +85 -0
- package/src/features/pattern/PatternFeature.js +275 -0
- package/src/features/patternLinear/PatternLinearFeature.js +120 -0
- package/src/features/patternRadial/PatternRadialFeature.js +186 -0
- package/src/features/plane/PlaneFeature.js +154 -0
- package/src/features/primitiveCone/primitiveConeFeature.js +99 -0
- package/src/features/primitiveCube/primitiveCubeFeature.js +70 -0
- package/src/features/primitiveCylinder/primitiveCylinderFeature.js +91 -0
- package/src/features/primitivePyramid/primitivePyramidFeature.js +72 -0
- package/src/features/primitiveSphere/primitiveSphereFeature.js +62 -0
- package/src/features/primitiveTorus/primitiveTorusFeature.js +109 -0
- package/src/features/remesh/RemeshFeature.js +97 -0
- package/src/features/revolve/RevolveFeature.js +111 -0
- package/src/features/selectionUtils.js +118 -0
- package/src/features/sheetMetal/SheetMetalContourFlangeFeature.js +1656 -0
- package/src/features/sheetMetal/SheetMetalCutoutFeature.js +1056 -0
- package/src/features/sheetMetal/SheetMetalFlangeFeature.js +1568 -0
- package/src/features/sheetMetal/SheetMetalHemFeature.js +43 -0
- package/src/features/sheetMetal/SheetMetalObject.js +141 -0
- package/src/features/sheetMetal/SheetMetalTabFeature.js +176 -0
- package/src/features/sheetMetal/UNFOLD_NEUTRAL_REQUIREMENTS.md +153 -0
- package/src/features/sheetMetal/contour-flange-rebuild-spec.md +261 -0
- package/src/features/sheetMetal/profileUtils.js +25 -0
- package/src/features/sheetMetal/sheetMetalCleanup.js +9 -0
- package/src/features/sheetMetal/sheetMetalFaceTypes.js +146 -0
- package/src/features/sheetMetal/sheetMetalMetadata.js +165 -0
- package/src/features/sheetMetal/sheetMetalPipeline.js +169 -0
- package/src/features/sheetMetal/sheetMetalProfileUtils.js +216 -0
- package/src/features/sheetMetal/sheetMetalTabUtils.js +29 -0
- package/src/features/sheetMetal/sheetMetalTree.js +210 -0
- package/src/features/sketch/SketchFeature.js +955 -0
- package/src/features/sketch/sketchSolver2D/ConstraintEngine.js +800 -0
- package/src/features/sketch/sketchSolver2D/constraintDefinitions.js +704 -0
- package/src/features/sketch/sketchSolver2D/mathHelpersMod.js +307 -0
- package/src/features/spline/SplineEditorSession.js +988 -0
- package/src/features/spline/SplineFeature.js +1388 -0
- package/src/features/spline/splineUtils.js +218 -0
- package/src/features/sweep/SweepFeature.js +110 -0
- package/src/features/transform/TransformFeature.js +152 -0
- package/src/features/tube/TubeFeature.js +635 -0
- package/src/fs.proxy.js +625 -0
- package/src/idbStorage.js +254 -0
- package/src/index.js +12 -0
- package/src/main.js +15 -0
- package/src/metadataManager.js +64 -0
- package/src/path.proxy.js +277 -0
- package/src/plugins/ghLoader.worker.js +151 -0
- package/src/plugins/pluginManager.js +286 -0
- package/src/pmi/PMIViewsManager.js +134 -0
- package/src/services/componentLibrary.js +198 -0
- package/src/tests/ConsoleCapture.js +189 -0
- package/src/tests/S7-diagnostics-2025-12-23T18-37-23-570Z.json +630 -0
- package/src/tests/browserTests.js +597 -0
- package/src/tests/debugBoolean.js +225 -0
- package/src/tests/partFiles/badBoolean.json +957 -0
- package/src/tests/partFiles/extrudeTest.json +88 -0
- package/src/tests/partFiles/filletFail.json +58 -0
- package/src/tests/partFiles/import_TEst.part.part.json +646 -0
- package/src/tests/partFiles/sheetMetalHem.BREP.json +734 -0
- package/src/tests/test_boolean_subtract.js +27 -0
- package/src/tests/test_chamfer.js +17 -0
- package/src/tests/test_extrudeFace.js +24 -0
- package/src/tests/test_fillet.js +17 -0
- package/src/tests/test_fillet_nonClosed.js +45 -0
- package/src/tests/test_filletsMoreDifficult.js +46 -0
- package/src/tests/test_history_features_basic.js +149 -0
- package/src/tests/test_hole.js +282 -0
- package/src/tests/test_mirror.js +16 -0
- package/src/tests/test_offsetShellGrouping.js +85 -0
- package/src/tests/test_plane.js +4 -0
- package/src/tests/test_primitiveCone.js +11 -0
- package/src/tests/test_primitiveCube.js +7 -0
- package/src/tests/test_primitiveCylinder.js +8 -0
- package/src/tests/test_primitivePyramid.js +9 -0
- package/src/tests/test_primitiveSphere.js +17 -0
- package/src/tests/test_primitiveTorus.js +21 -0
- package/src/tests/test_pushFace.js +126 -0
- package/src/tests/test_sheetMetalContourFlange.js +125 -0
- package/src/tests/test_sheetMetal_features.js +80 -0
- package/src/tests/test_sketch_openLoop.js +45 -0
- package/src/tests/test_solidMetrics.js +58 -0
- package/src/tests/test_stlLoader.js +1889 -0
- package/src/tests/test_sweepFace.js +55 -0
- package/src/tests/test_tube.js +45 -0
- package/src/tests/test_tube_closedLoop.js +67 -0
- package/src/tests/tests.js +493 -0
- package/src/tools/assemblyConstraintDialogCapturePage.js +56 -0
- package/src/tools/dialogCapturePageFactory.js +227 -0
- package/src/tools/featureDialogCapturePage.js +47 -0
- package/src/tools/pmiAnnotationDialogCapturePage.js +60 -0
- package/src/utils/axisHelpers.js +99 -0
- package/src/utils/deepClone.js +69 -0
- package/src/utils/geometryTolerance.js +37 -0
- package/src/utils/normalizeTypeString.js +8 -0
- 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
|
+
}
|