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,193 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
const EPS = 1e-9;
|
|
4
|
+
|
|
5
|
+
const finiteOr = (value, fallback) => {
|
|
6
|
+
const n = Number(value);
|
|
7
|
+
return Number.isFinite(n) ? n : fallback;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const toVec3 = (value, fallback = [0, 0, 0]) => {
|
|
11
|
+
if (value && typeof value.x === 'number') {
|
|
12
|
+
return new THREE.Vector3(
|
|
13
|
+
Number(value.x) || 0,
|
|
14
|
+
Number(value.y) || 0,
|
|
15
|
+
Number(value.z) || 0,
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
if (Array.isArray(value)) {
|
|
19
|
+
return new THREE.Vector3(
|
|
20
|
+
Number(value[0]) || 0,
|
|
21
|
+
Number(value[1]) || 0,
|
|
22
|
+
Number(value[2]) || 0,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return new THREE.Vector3(
|
|
26
|
+
Number(fallback?.[0]) || 0,
|
|
27
|
+
Number(fallback?.[1]) || 0,
|
|
28
|
+
Number(fallback?.[2]) || 0,
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const normalizedOr = (vec, fallback = new THREE.Vector3(0, 0, 1)) => {
|
|
33
|
+
const out = vec.clone();
|
|
34
|
+
if (out.lengthSq() < EPS) return fallback.clone().normalize();
|
|
35
|
+
return out.normalize();
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const matrixFromTransform = (transform) => {
|
|
39
|
+
if (!transform) return null;
|
|
40
|
+
if (transform.isMatrix4) return transform.clone();
|
|
41
|
+
|
|
42
|
+
const pos = Array.isArray(transform.position) ? transform.position : [0, 0, 0];
|
|
43
|
+
const rot = Array.isArray(transform.rotationEuler) ? transform.rotationEuler : [0, 0, 0];
|
|
44
|
+
const scl = Array.isArray(transform.scale) ? transform.scale : [1, 1, 1];
|
|
45
|
+
|
|
46
|
+
const position = new THREE.Vector3(
|
|
47
|
+
Number(pos[0]) || 0,
|
|
48
|
+
Number(pos[1]) || 0,
|
|
49
|
+
Number(pos[2]) || 0,
|
|
50
|
+
);
|
|
51
|
+
const euler = new THREE.Euler(
|
|
52
|
+
THREE.MathUtils.degToRad(Number(rot[0]) || 0),
|
|
53
|
+
THREE.MathUtils.degToRad(Number(rot[1]) || 0),
|
|
54
|
+
THREE.MathUtils.degToRad(Number(rot[2]) || 0),
|
|
55
|
+
'XYZ',
|
|
56
|
+
);
|
|
57
|
+
const quat = new THREE.Quaternion().setFromEuler(euler);
|
|
58
|
+
const scale = new THREE.Vector3(
|
|
59
|
+
Math.abs(Number(scl[0]) || 1),
|
|
60
|
+
Math.abs(Number(scl[1]) || 1),
|
|
61
|
+
Math.abs(Number(scl[2]) || 1),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
return new THREE.Matrix4().compose(position, quat, scale);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const buildPlacementMatrix = (opts = {}) => {
|
|
68
|
+
const fromTransform = matrixFromTransform(opts.transform);
|
|
69
|
+
if (fromTransform) return fromTransform;
|
|
70
|
+
|
|
71
|
+
const origin = toVec3(opts.origin, [0, 0, 0]);
|
|
72
|
+
const axisDir = normalizedOr(toVec3(opts.axis, [0, 0, 1]), new THREE.Vector3(0, 0, 1));
|
|
73
|
+
|
|
74
|
+
let xDir = opts.xDirection ? toVec3(opts.xDirection) : null;
|
|
75
|
+
if (!xDir || xDir.lengthSq() < EPS) {
|
|
76
|
+
const fallback = Math.abs(axisDir.y) < 0.9 ? new THREE.Vector3(0, 1, 0) : new THREE.Vector3(1, 0, 0);
|
|
77
|
+
xDir = new THREE.Vector3().crossVectors(fallback, axisDir);
|
|
78
|
+
} else {
|
|
79
|
+
// Remove any component along the axis so we remain perpendicular
|
|
80
|
+
xDir = xDir.addScaledVector(axisDir, -xDir.dot(axisDir));
|
|
81
|
+
}
|
|
82
|
+
if (xDir.lengthSq() < EPS) {
|
|
83
|
+
const fallback = Math.abs(axisDir.z) < 0.9 ? new THREE.Vector3(0, 0, 1) : new THREE.Vector3(0, 1, 0);
|
|
84
|
+
xDir = new THREE.Vector3().crossVectors(axisDir, fallback);
|
|
85
|
+
}
|
|
86
|
+
xDir.normalize();
|
|
87
|
+
const yDir = new THREE.Vector3().crossVectors(axisDir, xDir).normalize();
|
|
88
|
+
|
|
89
|
+
const m = new THREE.Matrix4().makeBasis(xDir, yDir, axisDir);
|
|
90
|
+
m.setPosition(origin);
|
|
91
|
+
return m;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Build a helix polyline in 3D.
|
|
96
|
+
* - Generates points for a right/left-handed helix with optional taper.
|
|
97
|
+
* - Orientation is controlled by a transform matrix, or by origin/axis/xDirection.
|
|
98
|
+
* - Returns world-space polyline points for reuse by features (threads, sweep paths, etc.).
|
|
99
|
+
* Options: radius/endRadius, height + pitch with mode (turns|pitch) controlling which value is derived, startAngleDeg/startAngle, clockwise,
|
|
100
|
+
* segmentsPerTurn (or resolution), and placement via `transform` or `{ origin, axis, xDirection }`.
|
|
101
|
+
*/
|
|
102
|
+
export function buildHelixPolyline(opts = {}) {
|
|
103
|
+
const r0 = Math.max(1e-6, Math.abs(finiteOr(opts.radius, 5)));
|
|
104
|
+
const hasEndRadius = opts.endRadius != null && Number.isFinite(Number(opts.endRadius));
|
|
105
|
+
const r1 = hasEndRadius ? Math.max(1e-6, Math.abs(finiteOr(opts.endRadius, r0))) : r0;
|
|
106
|
+
|
|
107
|
+
const minPitch = 1e-6;
|
|
108
|
+
const rawPitch = finiteOr(opts.pitch, finiteOr(opts.pitchDefault, NaN));
|
|
109
|
+
if (!Number.isFinite(rawPitch) || Math.abs(rawPitch) < minPitch) {
|
|
110
|
+
throw new Error('[buildHelixPolyline] pitch must be a finite, non-zero number.');
|
|
111
|
+
}
|
|
112
|
+
let pitch = Math.abs(rawPitch);
|
|
113
|
+
const modeRaw = String(opts.lengthMode || opts.mode || 'turns').toLowerCase();
|
|
114
|
+
const lengthMode = modeRaw === 'pitch' || modeRaw === 'height' ? 'pitch' : 'turns';
|
|
115
|
+
let turns = finiteOr(opts.turns, NaN);
|
|
116
|
+
let height = finiteOr(opts.height, NaN);
|
|
117
|
+
|
|
118
|
+
// Allow negative height to flip the axis direction while keeping a positive magnitude
|
|
119
|
+
let axisSign = 1;
|
|
120
|
+
if (Number.isFinite(height) && height < 0) {
|
|
121
|
+
axisSign = -1;
|
|
122
|
+
height = Math.abs(height);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (lengthMode === 'pitch' && Number.isFinite(height) && height > EPS) {
|
|
126
|
+
turns = height / pitch;
|
|
127
|
+
} else {
|
|
128
|
+
if (!Number.isFinite(turns) || turns <= 0) {
|
|
129
|
+
if (Number.isFinite(height) && height > EPS) turns = height / pitch;
|
|
130
|
+
else turns = 1;
|
|
131
|
+
}
|
|
132
|
+
height = Number.isFinite(height) && height > EPS ? height : pitch * turns;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Keep pitch consistent with the resolved height/turns
|
|
136
|
+
if (Number.isFinite(turns) && turns > EPS) pitch = height / turns;
|
|
137
|
+
else {
|
|
138
|
+
turns = 1;
|
|
139
|
+
height = pitch;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const segsPerTurn = Math.max(8, Math.floor(finiteOr(opts.segmentsPerTurn, finiteOr(opts.resolution, 64))));
|
|
143
|
+
const totalSeg = Math.max(1, Math.round(segsPerTurn * Math.max(turns, EPS)));
|
|
144
|
+
|
|
145
|
+
const startAngleDeg = finiteOr(opts.startAngleDeg, NaN);
|
|
146
|
+
const startAngleRad = Number.isFinite(startAngleDeg)
|
|
147
|
+
? THREE.MathUtils.degToRad(startAngleDeg)
|
|
148
|
+
: finiteOr(opts.startAngle, 0);
|
|
149
|
+
const handedRaw = String(opts.handedness || (opts.clockwise ? 'left' : 'right')).toLowerCase();
|
|
150
|
+
const clockwise = handedRaw === 'left' || opts.clockwise === true;
|
|
151
|
+
const angleSign = clockwise ? -1 : 1;
|
|
152
|
+
|
|
153
|
+
const placement = buildPlacementMatrix(opts);
|
|
154
|
+
const normalMat = new THREE.Matrix3();
|
|
155
|
+
normalMat.getNormalMatrix(placement);
|
|
156
|
+
|
|
157
|
+
const origin = new THREE.Vector3().setFromMatrixPosition(placement);
|
|
158
|
+
const axisDir = new THREE.Vector3(0, 0, axisSign).applyMatrix3(normalMat).normalize();
|
|
159
|
+
|
|
160
|
+
const polyline = [];
|
|
161
|
+
// Keep winding direction stable even if the helix height is negative by folding the axis sign into angular direction
|
|
162
|
+
const angularSign = angleSign * axisSign;
|
|
163
|
+
const tmp = new THREE.Vector3();
|
|
164
|
+
for (let i = 0; i <= totalSeg; i++) {
|
|
165
|
+
const t = i / totalSeg;
|
|
166
|
+
const theta = startAngleRad + angularSign * (turns * t * Math.PI * 2);
|
|
167
|
+
const radius = r0 + (r1 - r0) * t;
|
|
168
|
+
tmp.set(Math.cos(theta) * radius, Math.sin(theta) * radius, height * t * axisSign);
|
|
169
|
+
tmp.applyMatrix4(placement);
|
|
170
|
+
polyline.push([tmp.x, tmp.y, tmp.z]);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const axisEnd = origin.clone().addScaledVector(axisDir, height);
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
polyline,
|
|
177
|
+
closedLoop: false,
|
|
178
|
+
pitch,
|
|
179
|
+
turns,
|
|
180
|
+
height,
|
|
181
|
+
radiusStart: r0,
|
|
182
|
+
radiusEnd: r1,
|
|
183
|
+
clockwise,
|
|
184
|
+
handedness: clockwise ? 'left' : 'right',
|
|
185
|
+
startAngleRad,
|
|
186
|
+
origin: [origin.x, origin.y, origin.z],
|
|
187
|
+
axisDirection: [axisDir.x, axisDir.y, axisDir.z],
|
|
188
|
+
axisLine: [
|
|
189
|
+
[origin.x, origin.y, origin.z],
|
|
190
|
+
[axisEnd.x, axisEnd.y, axisEnd.z],
|
|
191
|
+
],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
import { Solid } from "./BetterSolid.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* MeshToBrep: Builds a Solid from a triangle mesh by grouping triangles
|
|
6
|
+
* into face labels based on the deflection angle between neighboring
|
|
7
|
+
* triangle normals.
|
|
8
|
+
*
|
|
9
|
+
* Usage
|
|
10
|
+
* const solid = new MeshToBrep(geometryOrMesh, 15 deg );
|
|
11
|
+
* solid.name = "ImportedSTL";
|
|
12
|
+
* solid.visualize();
|
|
13
|
+
*
|
|
14
|
+
* Notes
|
|
15
|
+
* - Accepts a THREE.BufferGeometry or a THREE.Mesh (uses its geometry).
|
|
16
|
+
* - Triangles are welded to a grid (weldTolerance) so shared edges use
|
|
17
|
+
* identical vertex positions for manifoldization.
|
|
18
|
+
* - If the input geometry has a `normal` attribute (STLLoader does),
|
|
19
|
+
* those normals are used for deflection. Otherwise, per-triangle
|
|
20
|
+
* normals are computed from positions.
|
|
21
|
+
*/
|
|
22
|
+
export class MeshToBrep extends Solid {
|
|
23
|
+
/**
|
|
24
|
+
* @param {THREE.BufferGeometry|THREE.Mesh} geometryOrMesh
|
|
25
|
+
* @param {number} faceDeflectionAngle Degrees; neighbors within this angle join a face
|
|
26
|
+
* @param {number} weldTolerance Vertex welding tolerance (units). Default 1e-5.
|
|
27
|
+
*/
|
|
28
|
+
constructor(geometryOrMesh, faceDeflectionAngle = 30, weldTolerance = 1e-5) {
|
|
29
|
+
super();
|
|
30
|
+
const geom = (geometryOrMesh && geometryOrMesh.isMesh)
|
|
31
|
+
? geometryOrMesh.geometry
|
|
32
|
+
: geometryOrMesh;
|
|
33
|
+
if (!geom || !geom.isBufferGeometry) {
|
|
34
|
+
throw new Error("MeshToBrep requires a THREE.BufferGeometry or THREE.Mesh");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
this.faceDeflectionAngle = Number(faceDeflectionAngle) || 0;
|
|
38
|
+
this.weldTolerance = Number(weldTolerance) || 0;
|
|
39
|
+
|
|
40
|
+
// Build internal mesh arrays and face labels
|
|
41
|
+
this._buildFromGeometry(geom);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
toBrep() { return this; }
|
|
45
|
+
|
|
46
|
+
_buildFromGeometry(geometry) {
|
|
47
|
+
// Ensure we have positions
|
|
48
|
+
const posAttr = geometry.getAttribute('position');
|
|
49
|
+
if (!posAttr) throw new Error("Geometry has no 'position' attribute");
|
|
50
|
+
|
|
51
|
+
const idxAttr = geometry.getIndex();
|
|
52
|
+
const norAttr = geometry.getAttribute('normal');
|
|
53
|
+
|
|
54
|
+
// Accessor helpers
|
|
55
|
+
const getPos = (i, out) => {
|
|
56
|
+
out.x = posAttr.getX(i);
|
|
57
|
+
out.y = posAttr.getY(i);
|
|
58
|
+
out.z = posAttr.getZ(i);
|
|
59
|
+
return out;
|
|
60
|
+
};
|
|
61
|
+
const getTri = (t) => {
|
|
62
|
+
if (idxAttr) {
|
|
63
|
+
const i0 = idxAttr.getX(3 * t + 0) >>> 0;
|
|
64
|
+
const i1 = idxAttr.getX(3 * t + 1) >>> 0;
|
|
65
|
+
const i2 = idxAttr.getX(3 * t + 2) >>> 0;
|
|
66
|
+
return [i0, i1, i2];
|
|
67
|
+
} else {
|
|
68
|
+
const base = 3 * t;
|
|
69
|
+
return [base + 0, base + 1, base + 2];
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const triCount = idxAttr ? ((idxAttr.count / 3) | 0) : ((posAttr.count / 3) | 0);
|
|
74
|
+
if (triCount <= 0) return;
|
|
75
|
+
|
|
76
|
+
// Build canonical vertices using a weld grid so that shared edges truly share indices
|
|
77
|
+
const q = Math.max(0, this.weldTolerance) || 0;
|
|
78
|
+
const gridKey = (x, y, z) => {
|
|
79
|
+
if (q <= 0) return `${x},${y},${z}`; // exact
|
|
80
|
+
const rx = Math.round(x / q);
|
|
81
|
+
const ry = Math.round(y / q);
|
|
82
|
+
const rz = Math.round(z / q);
|
|
83
|
+
return `${rx},${ry},${rz}`;
|
|
84
|
+
};
|
|
85
|
+
const tmpA = new THREE.Vector3();
|
|
86
|
+
const tmpB = new THREE.Vector3();
|
|
87
|
+
const tmpC = new THREE.Vector3();
|
|
88
|
+
|
|
89
|
+
// Vertex dictionary and arrays
|
|
90
|
+
const keyToIndex = new Map();
|
|
91
|
+
const indexToPos = []; // [ [x,y,z], ... ] matching canonical vertices
|
|
92
|
+
|
|
93
|
+
// Triangle data arrays
|
|
94
|
+
const triVerts = new Array(triCount);
|
|
95
|
+
const triNormals = new Array(triCount);
|
|
96
|
+
|
|
97
|
+
// Grab per-vertex normals if available (STL facet normals replicated per-vertex)
|
|
98
|
+
const getTriNormal = (t) => {
|
|
99
|
+
if (norAttr && norAttr.count === posAttr.count) {
|
|
100
|
+
const [i0] = getTri(t);
|
|
101
|
+
// normals are constant per tri for STL; use any vertex's normal
|
|
102
|
+
const nx = norAttr.getX(i0);
|
|
103
|
+
const ny = norAttr.getY(i0);
|
|
104
|
+
const nz = norAttr.getZ(i0);
|
|
105
|
+
const n = new THREE.Vector3(nx, ny, nz);
|
|
106
|
+
if (n.lengthSq() > 0) return n.normalize();
|
|
107
|
+
}
|
|
108
|
+
// Fallback: compute from positions
|
|
109
|
+
const [a, b, c] = getTri(t);
|
|
110
|
+
getPos(a, tmpA); getPos(b, tmpB); getPos(c, tmpC);
|
|
111
|
+
tmpB.sub(tmpA); tmpC.sub(tmpA);
|
|
112
|
+
const n = tmpB.clone().cross(tmpC);
|
|
113
|
+
if (n.lengthSq() > 0) return n.normalize();
|
|
114
|
+
return new THREE.Vector3(0, 0, 1);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Build canonical vertices and triangle index triplets
|
|
118
|
+
for (let t = 0; t < triCount; t++) {
|
|
119
|
+
const [ia, ib, ic] = getTri(t);
|
|
120
|
+
const a = getPos(ia, tmpA.clone());
|
|
121
|
+
const b = getPos(ib, tmpB.clone());
|
|
122
|
+
const c = getPos(ic, tmpC.clone());
|
|
123
|
+
|
|
124
|
+
const keyA = gridKey(a.x, a.y, a.z);
|
|
125
|
+
const keyB = gridKey(b.x, b.y, b.z);
|
|
126
|
+
const keyC = gridKey(c.x, c.y, c.z);
|
|
127
|
+
|
|
128
|
+
let ai = keyToIndex.get(keyA);
|
|
129
|
+
if (ai === undefined) {
|
|
130
|
+
ai = indexToPos.length;
|
|
131
|
+
keyToIndex.set(keyA, ai);
|
|
132
|
+
const [xr, yr, zr] = (q <= 0) ? [a.x, a.y, a.z] : [Math.round(a.x / q) * q, Math.round(a.y / q) * q, Math.round(a.z / q) * q];
|
|
133
|
+
indexToPos.push([xr, yr, zr]);
|
|
134
|
+
}
|
|
135
|
+
let bi = keyToIndex.get(keyB);
|
|
136
|
+
if (bi === undefined) {
|
|
137
|
+
bi = indexToPos.length;
|
|
138
|
+
keyToIndex.set(keyB, bi);
|
|
139
|
+
const [xr, yr, zr] = (q <= 0) ? [b.x, b.y, b.z] : [Math.round(b.x / q) * q, Math.round(b.y / q) * q, Math.round(b.z / q) * q];
|
|
140
|
+
indexToPos.push([xr, yr, zr]);
|
|
141
|
+
}
|
|
142
|
+
let ci = keyToIndex.get(keyC);
|
|
143
|
+
if (ci === undefined) {
|
|
144
|
+
ci = indexToPos.length;
|
|
145
|
+
keyToIndex.set(keyC, ci);
|
|
146
|
+
const [xr, yr, zr] = (q <= 0) ? [c.x, c.y, c.z] : [Math.round(c.x / q) * q, Math.round(c.y / q) * q, Math.round(c.z / q) * q];
|
|
147
|
+
indexToPos.push([xr, yr, zr]);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
triVerts[t] = [ai, bi, ci];
|
|
151
|
+
triNormals[t] = getTriNormal(t);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Build adjacency via undirected edge -> list of triangle indices
|
|
155
|
+
const ek = (u, v) => (u < v ? `${u},${v}` : `${v},${u}`);
|
|
156
|
+
const edgeToTris = new Map();
|
|
157
|
+
for (let t = 0; t < triCount; t++) {
|
|
158
|
+
const [a, b, c] = triVerts[t];
|
|
159
|
+
const edges = [[a, b], [b, c], [c, a]];
|
|
160
|
+
for (const [u, v] of edges) {
|
|
161
|
+
const key = ek(u, v);
|
|
162
|
+
let list = edgeToTris.get(key);
|
|
163
|
+
if (!list) { list = []; edgeToTris.set(key, list); }
|
|
164
|
+
list.push(t);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Convert to per-triangle neighbor lists
|
|
169
|
+
const neighbors = new Array(triCount);
|
|
170
|
+
for (let i = 0; i < triCount; i++) neighbors[i] = [];
|
|
171
|
+
for (const list of edgeToTris.values()) {
|
|
172
|
+
if (list.length < 2) continue;
|
|
173
|
+
// each pair of triangles sharing this edge are neighbors
|
|
174
|
+
for (let i = 0; i < list.length; i++) {
|
|
175
|
+
for (let j = i + 1; j < list.length; j++) {
|
|
176
|
+
const a = list[i], b = list[j];
|
|
177
|
+
neighbors[a].push(b);
|
|
178
|
+
neighbors[b].push(a);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Region grow faces by deflection angle between neighboring triangle normals
|
|
184
|
+
const maxAngleRad = Math.max(0, this.faceDeflectionAngle) * Math.PI / 180.0;
|
|
185
|
+
const cosThresh = Math.cos(maxAngleRad);
|
|
186
|
+
const visited = new Uint8Array(triCount);
|
|
187
|
+
let faceCounter = 0;
|
|
188
|
+
const triFaceName = new Array(triCount);
|
|
189
|
+
|
|
190
|
+
const dot = (a, b) => {
|
|
191
|
+
const d = a.x * b.x + a.y * b.y + a.z * b.z;
|
|
192
|
+
const la = Math.hypot(a.x, a.y, a.z);
|
|
193
|
+
const lb = Math.hypot(b.x, b.y, b.z);
|
|
194
|
+
if (la === 0 || lb === 0) return 1; // treat degenerate as same
|
|
195
|
+
return d / (la * lb);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
for (let seed = 0; seed < triCount; seed++) {
|
|
199
|
+
if (visited[seed]) continue;
|
|
200
|
+
const faceName = `STL_FACE_${++faceCounter}`;
|
|
201
|
+
// BFS using pairwise deflection with the parent triangle
|
|
202
|
+
const queue = [seed];
|
|
203
|
+
visited[seed] = 1;
|
|
204
|
+
triFaceName[seed] = faceName;
|
|
205
|
+
while (queue.length) {
|
|
206
|
+
const t = queue.shift();
|
|
207
|
+
const nrmT = triNormals[t];
|
|
208
|
+
for (const nb of neighbors[t]) {
|
|
209
|
+
if (visited[nb]) continue;
|
|
210
|
+
const nrmN = triNormals[nb];
|
|
211
|
+
// If normals are close (angle <= threshold), grow region
|
|
212
|
+
if (dot(nrmT, nrmN) >= cosThresh) {
|
|
213
|
+
visited[nb] = 1;
|
|
214
|
+
triFaceName[nb] = faceName;
|
|
215
|
+
queue.push(nb);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Author triangles into this Solid with their face labels
|
|
222
|
+
for (let t = 0; t < triCount; t++) {
|
|
223
|
+
const name = triFaceName[t] || `STL_FACE_${faceCounter + 1}`;
|
|
224
|
+
const [a, b, c] = triVerts[t];
|
|
225
|
+
const pa = indexToPos[a];
|
|
226
|
+
const pb = indexToPos[b];
|
|
227
|
+
const pc = indexToPos[c];
|
|
228
|
+
this.addTriangle(name, pa, pb, pc);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Let downstream visualization build per-face meshes and edges
|
|
232
|
+
// We'll leave winding correction/orientation to _manifoldize()
|
|
233
|
+
}
|
|
234
|
+
}
|