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,15 @@
|
|
|
1
|
+
import { computeTriangleArea } from '../triangleUtils.js';
|
|
2
|
+
|
|
3
|
+
export function computeFaceAreaFromTriangles(tris) {
|
|
4
|
+
if (!Array.isArray(tris) || tris.length === 0) return 0;
|
|
5
|
+
let area = 0;
|
|
6
|
+
for (const tri of tris) {
|
|
7
|
+
const p1 = tri?.p1, p2 = tri?.p2, p3 = tri?.p3;
|
|
8
|
+
if (!Array.isArray(p1) || !Array.isArray(p2) || !Array.isArray(p3)) continue;
|
|
9
|
+
const ax = Number(p1[0]) || 0, ay = Number(p1[1]) || 0, az = Number(p1[2]) || 0;
|
|
10
|
+
const bx = Number(p2[0]) || 0, by = Number(p2[1]) || 0, bz = Number(p2[2]) || 0;
|
|
11
|
+
const cx = Number(p3[0]) || 0, cy = Number(p3[1]) || 0, cz = Number(p3[2]) || 0;
|
|
12
|
+
area += computeTriangleArea(ax, ay, az, bx, by, bz, cx, cy, cz);
|
|
13
|
+
}
|
|
14
|
+
return area;
|
|
15
|
+
}
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
|
|
3
|
+
// Scratch vectors
|
|
4
|
+
const __vAB = new THREE.Vector3();
|
|
5
|
+
const __vAC = new THREE.Vector3();
|
|
6
|
+
const __vAP = new THREE.Vector3();
|
|
7
|
+
const __vBP = new THREE.Vector3();
|
|
8
|
+
const __vCP = new THREE.Vector3();
|
|
9
|
+
const __vCB = new THREE.Vector3();
|
|
10
|
+
const __tmp1 = new THREE.Vector3();
|
|
11
|
+
const __tmp2 = new THREE.Vector3();
|
|
12
|
+
const __tmp3 = new THREE.Vector3();
|
|
13
|
+
const __tmp4 = new THREE.Vector3();
|
|
14
|
+
const __tmp5 = new THREE.Vector3();
|
|
15
|
+
const __tmp6 = new THREE.Vector3();
|
|
16
|
+
const __projOut = new THREE.Vector3();
|
|
17
|
+
|
|
18
|
+
function getScaleAdaptiveTolerance(radius, baseEpsilon = 1e-12) {
|
|
19
|
+
return Math.max(baseEpsilon, baseEpsilon * Math.abs(radius));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getDistanceTolerance(radius) {
|
|
23
|
+
return Math.max(1e-9, 1e-6 * Math.abs(radius));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getAngleTolerance() {
|
|
27
|
+
return 1e-6; // radians
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Lightweight spatial index keyed by voxel cells for triangle centroid spheres
|
|
31
|
+
class TriangleSpatialIndex {
|
|
32
|
+
constructor(triangleData, cellSize = null) {
|
|
33
|
+
this.triangleData = triangleData || [];
|
|
34
|
+
this.grid = new Map();
|
|
35
|
+
if (!this.triangleData.length) return;
|
|
36
|
+
if (cellSize == null) {
|
|
37
|
+
const avgRad = this.triangleData.reduce((s, d) => s + (d.rad || 0), 0) / this.triangleData.length;
|
|
38
|
+
cellSize = Math.max(avgRad * 2, 1e-6);
|
|
39
|
+
}
|
|
40
|
+
this.cellSize = cellSize;
|
|
41
|
+
this.invCellSize = 1 / cellSize;
|
|
42
|
+
for (let i = 0; i < this.triangleData.length; i++) {
|
|
43
|
+
for (const key of this.getTriangleCells(this.triangleData[i])) {
|
|
44
|
+
if (!this.grid.has(key)) this.grid.set(key, []);
|
|
45
|
+
this.grid.get(key).push(i);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
cellKey(x, y, z) {
|
|
50
|
+
const ix = Math.floor(x * this.invCellSize);
|
|
51
|
+
const iy = Math.floor(y * this.invCellSize);
|
|
52
|
+
const iz = Math.floor(z * this.invCellSize);
|
|
53
|
+
return `${ix},${iy},${iz}`;
|
|
54
|
+
}
|
|
55
|
+
getTriangleCells({ cx, cy, cz, rad }) {
|
|
56
|
+
const cells = new Set();
|
|
57
|
+
const minX = (cx - rad) * this.invCellSize;
|
|
58
|
+
const maxX = (cx + rad) * this.invCellSize;
|
|
59
|
+
const minY = (cy - rad) * this.invCellSize;
|
|
60
|
+
const maxY = (cy + rad) * this.invCellSize;
|
|
61
|
+
const minZ = (cz - rad) * this.invCellSize;
|
|
62
|
+
const maxZ = (cz + rad) * this.invCellSize;
|
|
63
|
+
for (let ix = Math.floor(minX); ix <= Math.floor(maxX); ix++)
|
|
64
|
+
for (let iy = Math.floor(minY); iy <= Math.floor(maxY); iy++)
|
|
65
|
+
for (let iz = Math.floor(minZ); iz <= Math.floor(maxZ); iz++)
|
|
66
|
+
cells.add(`${ix},${iy},${iz}`);
|
|
67
|
+
return cells;
|
|
68
|
+
}
|
|
69
|
+
getNearbyTriangles(point, maxDistance = Infinity) {
|
|
70
|
+
const key = this.cellKey(point.x, point.y, point.z);
|
|
71
|
+
const list = this.grid.get(key) || [];
|
|
72
|
+
if (maxDistance === Infinity || list.length) return list;
|
|
73
|
+
const R = Math.ceil(maxDistance * this.invCellSize);
|
|
74
|
+
const ix0 = Math.floor(point.x * this.invCellSize);
|
|
75
|
+
const iy0 = Math.floor(point.y * this.invCellSize);
|
|
76
|
+
const iz0 = Math.floor(point.z * this.invCellSize);
|
|
77
|
+
const set = new Set();
|
|
78
|
+
for (let ix = ix0 - R; ix <= ix0 + R; ix++)
|
|
79
|
+
for (let iy = iy0 - R; iy <= iy0 + R; iy++)
|
|
80
|
+
for (let iz = iz0 - R; iz <= iz0 + R; iz++) {
|
|
81
|
+
const l = this.grid.get(`${ix},${iy},${iz}`);
|
|
82
|
+
if (l) for (const i of l) set.add(i);
|
|
83
|
+
}
|
|
84
|
+
return Array.from(set);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const __FACE_DATA_CACHE = new Map();
|
|
89
|
+
const __SPATIAL_INDEX_CACHE = new Map();
|
|
90
|
+
const MAX_CACHE_SIZE = 100;
|
|
91
|
+
|
|
92
|
+
function getCachedFaceDataForTris(tris, faceKey = null) {
|
|
93
|
+
if (!Array.isArray(tris) || tris.length === 0) return [];
|
|
94
|
+
const cacheKey = faceKey || tris;
|
|
95
|
+
const existing = __FACE_DATA_CACHE.get(cacheKey);
|
|
96
|
+
if (existing) return existing;
|
|
97
|
+
if (__FACE_DATA_CACHE.size >= MAX_CACHE_SIZE) {
|
|
98
|
+
const first = __FACE_DATA_CACHE.keys().next().value;
|
|
99
|
+
__FACE_DATA_CACHE.delete(first);
|
|
100
|
+
__SPATIAL_INDEX_CACHE.delete(first);
|
|
101
|
+
}
|
|
102
|
+
const a = __tmp1, b = __tmp2, c = __tmp3;
|
|
103
|
+
const ab = __tmp4, ac = __tmp5, n = __tmp6;
|
|
104
|
+
const faceData = tris.map(t => {
|
|
105
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
106
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
107
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
108
|
+
const cx = (a.x + b.x + c.x) / 3;
|
|
109
|
+
const cy = (a.y + b.y + c.y) / 3;
|
|
110
|
+
const cz = (a.z + b.z + c.z) / 3;
|
|
111
|
+
ab.subVectors(b, a);
|
|
112
|
+
ac.subVectors(c, a);
|
|
113
|
+
n.crossVectors(ab, ac);
|
|
114
|
+
const len = n.length();
|
|
115
|
+
if (len < getScaleAdaptiveTolerance(1.0, 1e-14)) return null;
|
|
116
|
+
n.multiplyScalar(1 / len);
|
|
117
|
+
const dxA = a.x - cx, dyA = a.y - cy, dzA = a.z - cz;
|
|
118
|
+
const dxB = b.x - cx, dyB = b.y - cy, dzB = b.z - cz;
|
|
119
|
+
const dxC = c.x - cx, dyC = c.y - cy, dzC = c.z - cz;
|
|
120
|
+
const rA2 = dxA * dxA + dyA * dyA + dzA * dzA;
|
|
121
|
+
const rB2 = dxB * dxB + dyB * dyB + dzB * dzB;
|
|
122
|
+
const rC2 = dxC * dxC + dyC * dyC + dzC * dzC;
|
|
123
|
+
const rad = Math.sqrt(Math.max(rA2, rB2, rC2));
|
|
124
|
+
return { cx, cy, cz, rad, normal: n.clone(), triangle: t };
|
|
125
|
+
}).filter(Boolean);
|
|
126
|
+
__FACE_DATA_CACHE.set(cacheKey, faceData);
|
|
127
|
+
return faceData;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function getCachedSpatialIndex(faceData, faceKey = null) {
|
|
131
|
+
const key = faceKey || faceData;
|
|
132
|
+
let idx = __SPATIAL_INDEX_CACHE.get(key);
|
|
133
|
+
if (!idx && Array.isArray(faceData) && faceData.length) {
|
|
134
|
+
idx = new TriangleSpatialIndex(faceData);
|
|
135
|
+
__SPATIAL_INDEX_CACHE.set(key, idx);
|
|
136
|
+
}
|
|
137
|
+
return idx;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function clearFilletCaches() {
|
|
141
|
+
__FACE_DATA_CACHE.clear();
|
|
142
|
+
__SPATIAL_INDEX_CACHE.clear();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function trimFilletCaches() {
|
|
146
|
+
if (__FACE_DATA_CACHE.size > MAX_CACHE_SIZE * 2) {
|
|
147
|
+
let count = 0;
|
|
148
|
+
const toDrop = [];
|
|
149
|
+
for (const k of __FACE_DATA_CACHE.keys()) {
|
|
150
|
+
if (count++ > MAX_CACHE_SIZE) toDrop.push(k);
|
|
151
|
+
}
|
|
152
|
+
for (const k of toDrop) {
|
|
153
|
+
__FACE_DATA_CACHE.delete(k);
|
|
154
|
+
__SPATIAL_INDEX_CACHE.delete(k);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function clamp(x, a, b) { return Math.max(a, Math.min(b, x)); }
|
|
160
|
+
function isFiniteVec3(v) { return Number.isFinite(v.x) && Number.isFinite(v.y) && Number.isFinite(v.z); }
|
|
161
|
+
|
|
162
|
+
// Output-parameter version to avoid allocating new vectors per call
|
|
163
|
+
function closestPointOnTriangleToOut(P, A, B, C, out) {
|
|
164
|
+
// Real-Time Collision Detection (Christer Ericson)
|
|
165
|
+
const AB = __vAB.subVectors(B, A);
|
|
166
|
+
const AC = __vAC.subVectors(C, A);
|
|
167
|
+
const AP = __vAP.subVectors(P, A);
|
|
168
|
+
const d1 = AB.dot(AP);
|
|
169
|
+
const d2 = AC.dot(AP);
|
|
170
|
+
if (d1 <= 0 && d2 <= 0) { out.copy(A); return out; }
|
|
171
|
+
const BP = __vBP.subVectors(P, B);
|
|
172
|
+
const d3 = AB.dot(BP);
|
|
173
|
+
const d4 = AC.dot(BP);
|
|
174
|
+
if (d3 >= 0 && d4 <= d3) { out.copy(B); return out; }
|
|
175
|
+
const vc = d1 * d4 - d3 * d2;
|
|
176
|
+
if (vc <= 0 && d1 >= 0 && d3 <= 0) { const v = d1 / (d1 - d3); out.copy(A).addScaledVector(AB, v); return out; }
|
|
177
|
+
const CP = __vCP.subVectors(P, C);
|
|
178
|
+
const d5 = AB.dot(CP);
|
|
179
|
+
const d6 = AC.dot(CP);
|
|
180
|
+
if (d6 >= 0 && d5 <= d6) { out.copy(C); return out; }
|
|
181
|
+
const vb = d5 * d2 - d1 * d6;
|
|
182
|
+
if (vb <= 0 && d2 >= 0 && d6 <= 0) { const w = d2 / (d2 - d6); out.copy(A).addScaledVector(AC, w); return out; }
|
|
183
|
+
const va = d3 * d6 - d5 * d4;
|
|
184
|
+
if (va <= 0 && (d4 - d3) >= 0 && (d5 - d6) >= 0) { const w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); out.copy(B).addScaledVector(__vCB.subVectors(C, B), w); return out; }
|
|
185
|
+
const denom = 1 / (AB.dot(AB) * AC.dot(AC) - Math.pow(AB.dot(AC), 2));
|
|
186
|
+
const v = (AC.dot(AC) * AB.dot(AP) - AB.dot(AC) * AC.dot(AP)) * denom;
|
|
187
|
+
const w = (AB.dot(AB) * AC.dot(AP) - AB.dot(AC) * AB.dot(AP)) * denom;
|
|
188
|
+
out.copy(A).addScaledVector(AB, v).addScaledVector(AC, w); return out;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function projectPointOntoFaceTriangles(tris, point, faceData = null, faceKey = null) {
|
|
192
|
+
if (!Array.isArray(tris) || tris.length === 0) return point.clone();
|
|
193
|
+
const data = faceData && Array.isArray(faceData) ? faceData : getCachedFaceDataForTris(tris, faceKey);
|
|
194
|
+
if (!data || !data.length) return point.clone();
|
|
195
|
+
const spatialIndex = getCachedSpatialIndex(data, faceKey);
|
|
196
|
+
let best = null;
|
|
197
|
+
const a = __tmp1, b = __tmp2, c = __tmp3, q = __projOut;
|
|
198
|
+
if (spatialIndex) {
|
|
199
|
+
const nearby = spatialIndex.getNearbyTriangles(point);
|
|
200
|
+
if (nearby.length) {
|
|
201
|
+
for (const idx of nearby) {
|
|
202
|
+
if (idx >= data.length) continue;
|
|
203
|
+
const t = data[idx].triangle;
|
|
204
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
205
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
206
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
207
|
+
closestPointOnTriangleToOut(point, a, b, c, q);
|
|
208
|
+
const d2 = q.distanceToSquared(point);
|
|
209
|
+
if (!best || d2 < best.d2) best = { d2, q: q.clone() };
|
|
210
|
+
}
|
|
211
|
+
if (best && data.length > 64) {
|
|
212
|
+
const bestDist = Math.sqrt(best.d2);
|
|
213
|
+
const visited = new Set(nearby);
|
|
214
|
+
for (let i = 0; i < data.length; i++) {
|
|
215
|
+
if (visited.has(i)) continue;
|
|
216
|
+
const d = data[i];
|
|
217
|
+
const dx = d.cx - point.x, dy = d.cy - point.y, dz = d.cz - point.z;
|
|
218
|
+
const centerD2 = dx * dx + dy * dy + dz * dz;
|
|
219
|
+
const rad = d.rad || 0;
|
|
220
|
+
const thr = bestDist + rad;
|
|
221
|
+
if (centerD2 > thr * thr) continue;
|
|
222
|
+
const t = d.triangle;
|
|
223
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
224
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
225
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
226
|
+
closestPointOnTriangleToOut(point, a, b, c, q);
|
|
227
|
+
const d2 = q.distanceToSquared(point);
|
|
228
|
+
if (d2 < best.d2) best = { d2, q: q.clone() };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
const candidates = data.map((d, i) => ({ i, d2: (d.cx - point.x) ** 2 + (d.cy - point.y) ** 2 + (d.cz - point.z) ** 2 }));
|
|
233
|
+
candidates.sort((a, b) => a.d2 - b.d2);
|
|
234
|
+
const K = Math.min(16, candidates.length);
|
|
235
|
+
for (let k = 0; k < K; k++) {
|
|
236
|
+
const t = data[candidates[k].i].triangle;
|
|
237
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
238
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
239
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
240
|
+
closestPointOnTriangleToOut(point, a, b, c, q);
|
|
241
|
+
const d2 = q.distanceToSquared(point);
|
|
242
|
+
if (!best || d2 < best.d2) best = { d2, q: q.clone() };
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
const K = Math.min(16, data.length);
|
|
247
|
+
const pairs = data.map((d, i) => ({ i, d2: (d.cx - point.x) ** 2 + (d.cy - point.y) ** 2 + (d.cz - point.z) ** 2 }));
|
|
248
|
+
pairs.sort((a, b) => a.d2 - b.d2);
|
|
249
|
+
for (let k = 0; k < K; k++) {
|
|
250
|
+
const t = data[pairs[k].i].triangle;
|
|
251
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
252
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
253
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
254
|
+
closestPointOnTriangleToOut(point, a, b, c, q);
|
|
255
|
+
const d2 = q.distanceToSquared(point);
|
|
256
|
+
if (!best || d2 < best.d2) best = { d2, q: q.clone() };
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return best ? best.q : point.clone();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function batchProjectPointsOntoFace(tris, points, faceData = null, faceKey = null) {
|
|
263
|
+
if (!Array.isArray(points) || !points.length) return [];
|
|
264
|
+
if (!Array.isArray(tris) || !tris.length) return points.map(p => p.clone());
|
|
265
|
+
const data = faceData && Array.isArray(faceData) ? faceData : getCachedFaceDataForTris(tris, faceKey);
|
|
266
|
+
const spatialIndex = getCachedSpatialIndex(data, faceKey);
|
|
267
|
+
const results = new Array(points.length);
|
|
268
|
+
if (spatialIndex) {
|
|
269
|
+
const cell = new Map(); // cellKey -> indices
|
|
270
|
+
const inv = spatialIndex.invCellSize;
|
|
271
|
+
for (let i = 0; i < points.length; i++) {
|
|
272
|
+
const p = points[i];
|
|
273
|
+
const key = `${Math.floor(p.x * inv)},${Math.floor(p.y * inv)},${Math.floor(p.z * inv)}`;
|
|
274
|
+
let arr = cell.get(key); if (!arr) { arr = []; cell.set(key, arr); }
|
|
275
|
+
arr.push(i);
|
|
276
|
+
}
|
|
277
|
+
for (const [key, indices] of cell.entries()) {
|
|
278
|
+
const [ix, iy, iz] = key.split(',').map(Number);
|
|
279
|
+
const neigh = [];
|
|
280
|
+
for (let dx = -1; dx <= 1; dx++)
|
|
281
|
+
for (let dy = -1; dy <= 1; dy++)
|
|
282
|
+
for (let dz = -1; dz <= 1; dz++) {
|
|
283
|
+
const k = `${ix + dx},${iy + dy},${iz + dz}`;
|
|
284
|
+
const list = spatialIndex.grid.get(k);
|
|
285
|
+
if (list) for (const t of list) neigh.push(t);
|
|
286
|
+
}
|
|
287
|
+
const unique = Array.from(new Set(neigh));
|
|
288
|
+
for (const i of indices) {
|
|
289
|
+
const p = points[i];
|
|
290
|
+
let best = null;
|
|
291
|
+
const a = __tmp1, b = __tmp2, c = __tmp3, q = __projOut;
|
|
292
|
+
for (const idx of unique) {
|
|
293
|
+
const d = data[idx]; if (!d) continue;
|
|
294
|
+
const t = d.triangle;
|
|
295
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
296
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
297
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
298
|
+
closestPointOnTriangleToOut(p, a, b, c, q);
|
|
299
|
+
const d2 = q.distanceToSquared(p);
|
|
300
|
+
if (!best || d2 < best.d2) best = { d2, q: q.clone() };
|
|
301
|
+
}
|
|
302
|
+
results[i] = best ? best.q : p.clone();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
for (let i = 0; i < points.length; i++) {
|
|
307
|
+
results[i] = projectPointOntoFaceTriangles(tris, points[i], data, faceKey);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return results;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function averageFaceNormalObjectSpace(solid, faceName) {
|
|
314
|
+
const tris = solid.getFace(faceName);
|
|
315
|
+
if (!tris || !tris.length) return new THREE.Vector3(0, 1, 0);
|
|
316
|
+
const accum = new THREE.Vector3();
|
|
317
|
+
const a = new THREE.Vector3(), b = new THREE.Vector3(), c = new THREE.Vector3();
|
|
318
|
+
const ab = new THREE.Vector3(), ac = new THREE.Vector3();
|
|
319
|
+
for (const t of tris) {
|
|
320
|
+
a.set(t.p1[0], t.p1[1], t.p1[2]);
|
|
321
|
+
b.set(t.p2[0], t.p2[1], t.p2[2]);
|
|
322
|
+
c.set(t.p3[0], t.p3[1], t.p3[2]);
|
|
323
|
+
ab.subVectors(b, a);
|
|
324
|
+
ac.subVectors(c, a);
|
|
325
|
+
accum.add(ab.clone().cross(ac));
|
|
326
|
+
}
|
|
327
|
+
if (accum.lengthSq() === 0) return new THREE.Vector3(0, 1, 0);
|
|
328
|
+
return accum.normalize();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function localFaceNormalAtPoint(solid, faceName, p, faceData = null, faceKey = null) {
|
|
332
|
+
const point = (p && typeof p.x === 'number') ? p : __tmp5.set(p?.[0] || 0, p?.[1] || 0, p?.[2] || 0);
|
|
333
|
+
let data = (Array.isArray(faceData) && faceData.length) ? faceData : null;
|
|
334
|
+
if (!data) {
|
|
335
|
+
const tris = solid?.getFace ? solid.getFace(faceName) : null;
|
|
336
|
+
if (!Array.isArray(tris) || tris.length === 0) return null;
|
|
337
|
+
data = getCachedFaceDataForTris(tris, faceKey || faceName);
|
|
338
|
+
}
|
|
339
|
+
if (!data || !data.length) return null;
|
|
340
|
+
const spatial = getCachedSpatialIndex(data, faceKey || faceName || null);
|
|
341
|
+
let bestNormal = null;
|
|
342
|
+
let bestDist = Infinity;
|
|
343
|
+
const evalIdx = (idx) => {
|
|
344
|
+
const e = data[idx]; if (!e) return;
|
|
345
|
+
const dx = point.x - e.cx, dy = point.y - e.cy, dz = point.z - e.cz;
|
|
346
|
+
const dist = Math.abs(e.normal.x * dx + e.normal.y * dy + e.normal.z * dz);
|
|
347
|
+
if (dist < bestDist) { bestDist = dist; bestNormal = e.normal; }
|
|
348
|
+
};
|
|
349
|
+
if (spatial) {
|
|
350
|
+
const r = Number.isFinite(spatial.cellSize) ? spatial.cellSize * 1.5 : Infinity;
|
|
351
|
+
const near = spatial.getNearbyTriangles(point, r);
|
|
352
|
+
if (Array.isArray(near)) for (const idx of near) evalIdx(idx);
|
|
353
|
+
}
|
|
354
|
+
if (!bestNormal) {
|
|
355
|
+
const pick = Math.min(16, data.length);
|
|
356
|
+
const candidates = [];
|
|
357
|
+
for (let i = 0; i < data.length; i++) {
|
|
358
|
+
const e = data[i]; if (!e) continue;
|
|
359
|
+
const dx = point.x - e.cx, dy = point.y - e.cy, dz = point.z - e.cz;
|
|
360
|
+
const d2 = dx * dx + dy * dy + dz * dz;
|
|
361
|
+
if (candidates.length < pick) {
|
|
362
|
+
candidates.push({ idx: i, d2 });
|
|
363
|
+
if (candidates.length === pick) candidates.sort((a, b) => a.d2 - b.d2);
|
|
364
|
+
} else if (d2 < candidates[candidates.length - 1].d2) {
|
|
365
|
+
candidates[candidates.length - 1] = { idx: i, d2 };
|
|
366
|
+
candidates.sort((a, b) => a.d2 - b.d2);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
for (const c of candidates) evalIdx(c.idx);
|
|
370
|
+
}
|
|
371
|
+
return bestNormal || null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export {
|
|
375
|
+
getScaleAdaptiveTolerance,
|
|
376
|
+
getDistanceTolerance,
|
|
377
|
+
getAngleTolerance,
|
|
378
|
+
getCachedFaceDataForTris,
|
|
379
|
+
getCachedSpatialIndex,
|
|
380
|
+
clearFilletCaches,
|
|
381
|
+
trimFilletCaches,
|
|
382
|
+
clamp,
|
|
383
|
+
isFiniteVec3,
|
|
384
|
+
projectPointOntoFaceTriangles,
|
|
385
|
+
batchProjectPointsOntoFace,
|
|
386
|
+
averageFaceNormalObjectSpace,
|
|
387
|
+
localFaceNormalAtPoint,
|
|
388
|
+
};
|
|
389
|
+
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Utility vector ops (immutable)
|
|
2
|
+
const v = {
|
|
3
|
+
add: (a, b) => ({ x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }),
|
|
4
|
+
sub: (a, b) => ({ x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }),
|
|
5
|
+
dot: (a, b) => a.x * b.x + a.y * b.y + a.z * b.z,
|
|
6
|
+
cross: (a, b) => ({
|
|
7
|
+
x: a.y * b.z - a.z * b.y,
|
|
8
|
+
y: a.z * b.x - a.x * b.z,
|
|
9
|
+
z: a.x * b.y - a.y * b.x
|
|
10
|
+
}),
|
|
11
|
+
scale: (a, s) => ({ x: a.x * s, y: a.y * s, z: a.z * s }),
|
|
12
|
+
len: (a) => Math.hypot(a.x, a.y, a.z),
|
|
13
|
+
norm: (a) => {
|
|
14
|
+
const L = Math.hypot(a.x, a.y, a.z);
|
|
15
|
+
if (L === 0) return { x: 0, y: 0, z: 0 };
|
|
16
|
+
return { x: a.x / L, y: a.y / L, z: a.z / L };
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// Project a 3D point to a 2D plane basis (origin O, basis e1,e2)
|
|
21
|
+
function project2D(P, O, e1, e2) {
|
|
22
|
+
const OP = v.sub(P, O);
|
|
23
|
+
return { x: v.dot(OP, e1), y: v.dot(OP, e2) };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Lift a 2D point to 3D using plane basis (origin O, basis e1,e2)
|
|
27
|
+
function lift3D(p2, O, e1, e2) {
|
|
28
|
+
return v.add(O, v.add(v.scale(e1, p2.x), v.scale(e2, p2.y)));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// 2D helpers
|
|
32
|
+
const v2 = {
|
|
33
|
+
sub: (a, b) => ({ x: a.x - b.x, y: a.y - b.y }),
|
|
34
|
+
add: (a, b) => ({ x: a.x + b.x, y: a.y + b.y }),
|
|
35
|
+
scale: (a, s) => ({ x: a.x * s, y: a.y * s }),
|
|
36
|
+
dot: (a, b) => a.x * b.x + a.y * b.y,
|
|
37
|
+
len: (a) => Math.hypot(a.x, a.y),
|
|
38
|
+
norm: (a) => {
|
|
39
|
+
const L = Math.hypot(a.x, a.y);
|
|
40
|
+
if (L === 0) return { x: 0, y: 0 };
|
|
41
|
+
return { x: a.x / L, y: a.y / L };
|
|
42
|
+
},
|
|
43
|
+
// rotate +90°: (x,y) -> (-y, x)
|
|
44
|
+
leftNormal: (d) => ({ x: -d.y, y: d.x })
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Intersect two 2D lines given in Hesse form: (n · x = s)
|
|
48
|
+
// Returns a 2D point. Throws if lines are (near) parallel.
|
|
49
|
+
function intersectHesse2D(n1, s1, n2, s2, eps = 1e-12) {
|
|
50
|
+
// Solve:
|
|
51
|
+
// [n1.x n1.y] [x] = [s1]
|
|
52
|
+
// [n2.x n2.y] [y] [s2]
|
|
53
|
+
const det = n1.x * n2.y - n1.y * n2.x;
|
|
54
|
+
if (Math.abs(det) < eps) {
|
|
55
|
+
throw new Error("Offset lines are nearly parallel; check offsets/winding.");
|
|
56
|
+
}
|
|
57
|
+
const x = (s1 * n2.y - n1.y * s2) / det;
|
|
58
|
+
const y = (-s1 * n2.x + n1.x * s2) / det;
|
|
59
|
+
return { x, y };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Offsets each edge of triangle ABC (3D) by given distances, inside the plane.
|
|
64
|
+
* Positive offset moves the edge toward the triangle interior.
|
|
65
|
+
* A, B, C are modified in place to the new (offset) triangle vertices.
|
|
66
|
+
*
|
|
67
|
+
* @param {Object} A {x,y,z}
|
|
68
|
+
* @param {Object} B {x,y,z}
|
|
69
|
+
* @param {Object} C {x,y,z}
|
|
70
|
+
* @param {number} offsetAB distance for edge AB (toward interior if positive)
|
|
71
|
+
* @param {number} offsetBC distance for edge BC (toward interior if positive)
|
|
72
|
+
* @param {number} offsetCA distance for edge CA (toward interior if positive)
|
|
73
|
+
*/
|
|
74
|
+
export function offsetAndMovePoints(A, B, C, offsetAB, offsetBC, offsetCA) {
|
|
75
|
+
const EPS = 1e-12;
|
|
76
|
+
|
|
77
|
+
// 1) Build plane basis from triangle
|
|
78
|
+
const AB = v.sub(B, A);
|
|
79
|
+
const AC = v.sub(C, A);
|
|
80
|
+
const n = v.cross(AB, AC);
|
|
81
|
+
const nL = v.len(n);
|
|
82
|
+
if (nL < EPS) {
|
|
83
|
+
throw new Error("Degenerate triangle: points are collinear or identical.");
|
|
84
|
+
}
|
|
85
|
+
const nHat = v.norm(n);
|
|
86
|
+
|
|
87
|
+
// Choose e1 along AB (or fallback to AC if AB is tiny), e2 = n × e1
|
|
88
|
+
let e1 = v.norm(AB);
|
|
89
|
+
if (v.len(e1) < EPS) {
|
|
90
|
+
e1 = v.norm(AC);
|
|
91
|
+
if (v.len(e1) < EPS) {
|
|
92
|
+
throw new Error("Degenerate triangle: zero-length edges.");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const e2 = v.norm(v.cross(nHat, e1)); // in-plane, perpendicular to e1
|
|
96
|
+
|
|
97
|
+
// 2) Project triangle to 2D (plane coords)
|
|
98
|
+
const a2 = project2D(A, A, e1, e2); // becomes (0,0)
|
|
99
|
+
const b2 = project2D(B, A, e1, e2);
|
|
100
|
+
const c2 = project2D(C, A, e1, e2);
|
|
101
|
+
// a2 is origin (0,0) by construction
|
|
102
|
+
|
|
103
|
+
// Helper to compute offset line for edge P->Q with opposite point R, offset d
|
|
104
|
+
// Returns { n: normal (unit), s: scalar } for Hesse form (n · x = s)
|
|
105
|
+
function edgeOffsetLine2D(P, Q, R, d) {
|
|
106
|
+
const dir = v2.norm(v2.sub(Q, P)); // along edge
|
|
107
|
+
if (v2.len(dir) < EPS) throw new Error("Degenerate edge encountered.");
|
|
108
|
+
let n2 = v2.leftNormal(dir); // left normal
|
|
109
|
+
// Ensure n2 points toward interior (toward R)
|
|
110
|
+
const toOpp = v2.sub(R, P);
|
|
111
|
+
if (v2.dot(toOpp, n2) < 0) {
|
|
112
|
+
n2 = v2.scale(n2, -1);
|
|
113
|
+
}
|
|
114
|
+
// Normalize n2 (leftNormal already unit if dir is unit, but be safe)
|
|
115
|
+
n2 = v2.norm(n2);
|
|
116
|
+
|
|
117
|
+
// Offset inward by +d: line equation n2 · x = n2 · P + d
|
|
118
|
+
const s = v2.dot(n2, P) + d;
|
|
119
|
+
return { n: n2, s };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 3) Build three offset lines (2D)
|
|
123
|
+
const lineAB = edgeOffsetLine2D(a2, b2, c2, offsetAB); // for edge AB
|
|
124
|
+
const lineBC = edgeOffsetLine2D(b2, c2, a2, offsetBC); // for edge BC
|
|
125
|
+
const lineCA = edgeOffsetLine2D(c2, a2, b2, offsetCA); // for edge CA
|
|
126
|
+
|
|
127
|
+
// 4) Intersections give new vertices (2D)
|
|
128
|
+
// New A' is intersection of offset lines for CA and AB
|
|
129
|
+
const a2p = intersectHesse2D(lineCA.n, lineCA.s, lineAB.n, lineAB.s);
|
|
130
|
+
// New B' is intersection of AB and BC
|
|
131
|
+
const b2p = intersectHesse2D(lineAB.n, lineAB.s, lineBC.n, lineBC.s);
|
|
132
|
+
// New C' is intersection of BC and CA
|
|
133
|
+
const c2p = intersectHesse2D(lineBC.n, lineBC.s, lineCA.n, lineCA.s);
|
|
134
|
+
|
|
135
|
+
// 5) Lift back to 3D and write in place
|
|
136
|
+
const Ap = lift3D(a2p, A, e1, e2);
|
|
137
|
+
const Bp = lift3D(b2p, A, e1, e2);
|
|
138
|
+
const Cp = lift3D(c2p, A, e1, e2);
|
|
139
|
+
|
|
140
|
+
A.x = Ap.x; A.y = Ap.y; A.z = Ap.z;
|
|
141
|
+
B.x = Bp.x; B.y = Bp.y; B.z = Bp.z;
|
|
142
|
+
C.x = Cp.x; C.y = Cp.y; C.z = Cp.z;
|
|
143
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { MeshRepairer } from "../MeshRepairer.js";
|
|
3
|
+
|
|
4
|
+
const __tmp1 = new THREE.Vector3();
|
|
5
|
+
const __tmp2 = new THREE.Vector3();
|
|
6
|
+
const __tmp3 = new THREE.Vector3();
|
|
7
|
+
|
|
8
|
+
// Solve center C using anchored offset planes:
|
|
9
|
+
// nA·C = nA·qA + sA*r
|
|
10
|
+
// nB·C = nB·qB + sB*r
|
|
11
|
+
// t ·C = t ·p
|
|
12
|
+
// Returns THREE.Vector3 or null
|
|
13
|
+
function solveCenterFromOffsetPlanesAnchored(p, t, nA, qA, sA, nB, qB, sB, r) {
|
|
14
|
+
const dA = nA.dot(qA) + sA * r;
|
|
15
|
+
const dB = nB.dot(qB) + sB * r;
|
|
16
|
+
const dT = t.dot(p);
|
|
17
|
+
// Intersection of three planes using vector triple products:
|
|
18
|
+
// C = ( (nB×t)*dA + (t×nA)*dB + (nA×nB)*dT ) / ( nA·(nB×t) )
|
|
19
|
+
const nbxt = __tmp1.copy(nB).cross(t);
|
|
20
|
+
const txnA = __tmp2.copy(t).cross(nA);
|
|
21
|
+
const nAxnB = __tmp3.copy(nA).cross(nB);
|
|
22
|
+
const denom = nA.dot(nbxt);
|
|
23
|
+
if (!Number.isFinite(denom) || Math.abs(denom) < 1e-14) {
|
|
24
|
+
// Fallback to Gaussian elimination for near-degenerate configuration
|
|
25
|
+
const A = [[nA.x, nA.y, nA.z], [nB.x, nB.y, nB.z], [t.x, t.y, t.z]];
|
|
26
|
+
const b = [dA, dB, dT];
|
|
27
|
+
const x = solve3(A, b);
|
|
28
|
+
return x ? new THREE.Vector3(x[0], x[1], x[2]) : null;
|
|
29
|
+
}
|
|
30
|
+
const num = nbxt.multiplyScalar(dA).add(txnA.multiplyScalar(dB)).add(nAxnB.multiplyScalar(dT));
|
|
31
|
+
return new THREE.Vector3(num.x / denom, num.y / denom, num.z / denom);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Solve 3x3 linear system A x = b (Gaussian elimination with partial pivoting)
|
|
35
|
+
function solve3(A, b) {
|
|
36
|
+
const n = 3;
|
|
37
|
+
const mat = A.map(row => [...row]);
|
|
38
|
+
const vec = [...b];
|
|
39
|
+
for (let i = 0; i < n; i++) {
|
|
40
|
+
let maxRow = i;
|
|
41
|
+
for (let k = i + 1; k < n; k++) if (Math.abs(mat[k][i]) > Math.abs(mat[maxRow][i])) maxRow = k;
|
|
42
|
+
if (maxRow !== i) { [mat[i], mat[maxRow]] = [mat[maxRow], mat[i]]; [vec[i], vec[maxRow]] = [vec[maxRow], vec[i]]; }
|
|
43
|
+
if (Math.abs(mat[i][i]) < 1e-12) return null;
|
|
44
|
+
for (let k = i + 1; k < n; k++) {
|
|
45
|
+
const factor = mat[k][i] / mat[i][i];
|
|
46
|
+
for (let j = i; j < n; j++) mat[k][j] -= factor * mat[i][j];
|
|
47
|
+
vec[k] -= factor * vec[i];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const x = new Array(n);
|
|
51
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
52
|
+
x[i] = vec[i];
|
|
53
|
+
for (let j = i + 1; j < n; j++) x[i] -= mat[i][j] * x[j];
|
|
54
|
+
x[i] /= mat[i][i];
|
|
55
|
+
}
|
|
56
|
+
return x;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Mesh repair helper kept for external use; does not generate solids.
|
|
60
|
+
function fixTJunctionsAndPatchHoles(geometry, {
|
|
61
|
+
weldEps = 5e-4,
|
|
62
|
+
lineEps = 5e-4,
|
|
63
|
+
gridCell = 0.01,
|
|
64
|
+
fixNormals = true,
|
|
65
|
+
patchHoles = true,
|
|
66
|
+
doTJunctions = true,
|
|
67
|
+
doWeld = true,
|
|
68
|
+
doRemoveOverlaps = true,
|
|
69
|
+
} = {}) {
|
|
70
|
+
if (!geometry || !(geometry.isBufferGeometry)) return geometry;
|
|
71
|
+
const repairer = new MeshRepairer();
|
|
72
|
+
let g = geometry;
|
|
73
|
+
if (doWeld) { try { g = repairer.weldVertices(g, weldEps); } catch {} }
|
|
74
|
+
if (doTJunctions) { try { g = repairer.fixTJunctions(g, lineEps, gridCell); } catch {} }
|
|
75
|
+
if (doRemoveOverlaps) { try { g = repairer.removeOverlappingTriangles(g); } catch {} }
|
|
76
|
+
if (patchHoles) { try { g = repairer.fillHoles(g); } catch {} }
|
|
77
|
+
if (fixNormals) {
|
|
78
|
+
try { g = repairer.fixTriangleNormals(g); } catch {}
|
|
79
|
+
try { g.computeVertexNormals(); } catch {}
|
|
80
|
+
}
|
|
81
|
+
return g;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
solveCenterFromOffsetPlanesAnchored,
|
|
86
|
+
fixTJunctionsAndPatchHoles,
|
|
87
|
+
};
|
|
88
|
+
|