@faicad/faijs 0.19.0 → 0.29.3
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 +202 -28
- package/dist/api/api-namespace.d.ts +5 -5
- package/dist/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +4 -4
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/assert.d.ts +2 -2
- package/dist/api/assert.js +8 -8
- package/dist/api/assert.js.map +1 -1
- package/dist/api/asset.d.ts +1 -1
- package/dist/api/asset.js +2 -2
- package/dist/api/asset.js.map +1 -1
- package/dist/api/boolean.d.ts +1 -1
- package/dist/api/boolean.d.ts.map +1 -1
- package/dist/api/boolean.js +128 -16
- package/dist/api/boolean.js.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.js +3 -1
- package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
- package/dist/api/cadquery-selectors/borrow-bridge.d.ts +14 -0
- package/dist/api/cadquery-selectors/borrow-bridge.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/borrow-bridge.js +52 -0
- package/dist/api/cadquery-selectors/borrow-bridge.js.map +1 -0
- package/dist/api/cadquery-selectors/edge.d.ts +40 -0
- package/dist/api/cadquery-selectors/edge.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/edge.js +70 -0
- package/dist/api/cadquery-selectors/edge.js.map +1 -0
- package/dist/api/cadquery-selectors/entity.d.ts +121 -0
- package/dist/api/cadquery-selectors/entity.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/entity.js +167 -0
- package/dist/api/cadquery-selectors/entity.js.map +1 -0
- package/dist/api/cadquery-selectors/face.d.ts +33 -0
- package/dist/api/cadquery-selectors/face.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/face.js +353 -0
- package/dist/api/cadquery-selectors/face.js.map +1 -0
- package/dist/api/cadquery-selectors/grammar.d.ts +50 -0
- package/dist/api/cadquery-selectors/grammar.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/grammar.js +345 -0
- package/dist/api/cadquery-selectors/grammar.js.map +1 -0
- package/dist/api/cadquery-selectors/index.d.ts +18 -0
- package/dist/api/cadquery-selectors/index.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/index.js +17 -0
- package/dist/api/cadquery-selectors/index.js.map +1 -0
- package/dist/api/cadquery-selectors/predicates.d.ts +76 -0
- package/dist/api/cadquery-selectors/predicates.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/predicates.js +85 -0
- package/dist/api/cadquery-selectors/predicates.js.map +1 -0
- package/dist/api/cadquery-selectors/resolve.d.ts +41 -0
- package/dist/api/cadquery-selectors/resolve.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/resolve.js +243 -0
- package/dist/api/cadquery-selectors/resolve.js.map +1 -0
- package/dist/api/cadquery-selectors/types.d.ts +96 -0
- package/dist/api/cadquery-selectors/types.d.ts.map +1 -0
- package/dist/api/cadquery-selectors/types.js +11 -0
- package/dist/api/cadquery-selectors/types.js.map +1 -0
- package/dist/api/chamfer.d.ts +13 -5
- package/dist/api/chamfer.d.ts.map +1 -1
- package/dist/api/chamfer.js +63 -7
- package/dist/api/chamfer.js.map +1 -1
- package/dist/api/compound-geom.d.ts +1 -1
- package/dist/api/compound-geom.js +1 -1
- package/dist/api/compound-geom.js.map +1 -1
- package/dist/api/draft.d.ts +1 -1
- package/dist/api/draft.js +1 -1
- package/dist/api/draft.js.map +1 -1
- package/dist/api/edge-ref.d.ts +1 -1
- package/dist/api/edge-ref.d.ts.map +1 -1
- package/dist/api/edge-ref.js +11 -3
- package/dist/api/edge-ref.js.map +1 -1
- package/dist/api/engrave.d.ts +1 -1
- package/dist/api/engrave.js +7 -7
- package/dist/api/engrave.js.map +1 -1
- package/dist/api/extrude.d.ts +6 -1
- package/dist/api/extrude.d.ts.map +1 -1
- package/dist/api/extrude.js +59 -5
- package/dist/api/extrude.js.map +1 -1
- package/dist/api/face-ref.d.ts +1 -1
- package/dist/api/face-ref.js +1 -1
- package/dist/api/face-ref.js.map +1 -1
- package/dist/api/feature-repair.d.ts +1 -1
- package/dist/api/feature-repair.js +1 -1
- package/dist/api/feature-repair.js.map +1 -1
- package/dist/api/fillet-variable.d.ts +1 -1
- package/dist/api/fillet-variable.js +1 -1
- package/dist/api/fillet-variable.js.map +1 -1
- package/dist/api/fillet.d.ts +28 -8
- package/dist/api/fillet.d.ts.map +1 -1
- package/dist/api/fillet.js +64 -9
- package/dist/api/fillet.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts +4 -0
- package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/geom.d.ts +1 -1
- package/dist/api/geom.js +1 -1
- package/dist/api/geom.js.map +1 -1
- package/dist/api/helix.d.ts +1 -1
- package/dist/api/helix.js +1 -1
- package/dist/api/helix.js.map +1 -1
- package/dist/api/import-brep.d.ts +20 -2
- package/dist/api/import-brep.d.ts.map +1 -1
- package/dist/api/import-brep.js +28 -3
- package/dist/api/import-brep.js.map +1 -1
- package/dist/api/import-step.d.ts +17 -2
- package/dist/api/import-step.d.ts.map +1 -1
- package/dist/api/import-step.js +23 -3
- package/dist/api/import-step.js.map +1 -1
- package/dist/api/index.d.ts +2 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +5 -2
- package/dist/api/index.js.map +1 -1
- package/dist/api/internal/compat-op.js +1 -1
- package/dist/api/internal/compat-op.js.map +1 -1
- package/dist/api/internal/mesh-solid-op.d.ts +236 -0
- package/dist/api/internal/mesh-solid-op.d.ts.map +1 -0
- package/dist/api/internal/mesh-solid-op.js +352 -0
- package/dist/api/internal/mesh-solid-op.js.map +1 -0
- package/dist/api/internal/svg-asset-resolver.d.ts +1 -1
- package/dist/api/internal/svg-asset-resolver.js +1 -1
- package/dist/api/internal/svg-asset-resolver.js.map +1 -1
- package/dist/api/knurl.d.ts +1 -1
- package/dist/api/knurl.d.ts.map +1 -1
- package/dist/api/knurl.js +3 -2
- package/dist/api/knurl.js.map +1 -1
- package/dist/api/loft.d.ts +1 -1
- package/dist/api/loft.js +1 -1
- package/dist/api/loft.js.map +1 -1
- package/dist/api/measurement/index.d.ts +9 -5
- package/dist/api/measurement/index.d.ts.map +1 -1
- package/dist/api/measurement/index.js +47 -20
- package/dist/api/measurement/index.js.map +1 -1
- package/dist/api/pattern.d.ts +5 -3
- package/dist/api/pattern.d.ts.map +1 -1
- package/dist/api/pattern.js +32 -4
- package/dist/api/pattern.js.map +1 -1
- package/dist/api/place.d.ts +1 -1
- package/dist/api/place.js +1 -1
- package/dist/api/place.js.map +1 -1
- package/dist/api/primitives.d.ts +5 -4
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +11 -5
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/profile.d.ts +64 -8
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +61 -10
- package/dist/api/profile.js.map +1 -1
- package/dist/api/punch-hole.d.ts +3 -0
- package/dist/api/punch-hole.d.ts.map +1 -1
- package/dist/api/punch-hole.js.map +1 -1
- package/dist/api/reconcile.d.ts +1 -1
- package/dist/api/reconcile.js +1 -1
- package/dist/api/reconcile.js.map +1 -1
- package/dist/api/replicate.d.ts.map +1 -1
- package/dist/api/replicate.js +122 -1
- package/dist/api/replicate.js.map +1 -1
- package/dist/api/screw.d.ts +1 -1
- package/dist/api/screw.js +3 -3
- package/dist/api/screw.js.map +1 -1
- package/dist/api/sdf.d.ts +1 -1
- package/dist/api/sdf.js +2 -2
- package/dist/api/sdf.js.map +1 -1
- package/dist/api/section-by-plane.d.ts +1 -1
- package/dist/api/section-by-plane.d.ts.map +1 -1
- package/dist/api/section-by-plane.js +2 -1
- package/dist/api/section-by-plane.js.map +1 -1
- package/dist/api/shell.d.ts +11 -4
- package/dist/api/shell.d.ts.map +1 -1
- package/dist/api/shell.js +53 -7
- package/dist/api/shell.js.map +1 -1
- package/dist/api/sketch-on-face.d.ts +41 -0
- package/dist/api/sketch-on-face.d.ts.map +1 -1
- package/dist/api/sketch-on-face.js +100 -1
- package/dist/api/sketch-on-face.js.map +1 -1
- package/dist/api/sketch-on-plane.d.ts +17 -9
- package/dist/api/sketch-on-plane.d.ts.map +1 -1
- package/dist/api/sketch-on-plane.js +12 -10
- package/dist/api/sketch-on-plane.js.map +1 -1
- package/dist/api/split-by-plane.d.ts +1 -1
- package/dist/api/split-by-plane.d.ts.map +1 -1
- package/dist/api/split-by-plane.js +2 -1
- package/dist/api/split-by-plane.js.map +1 -1
- package/dist/api/split.d.ts +1 -1
- package/dist/api/split.js +2 -2
- package/dist/api/split.js.map +1 -1
- package/dist/api/surface/arg-spec.d.ts +8 -0
- package/dist/api/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/sweep.d.ts +1 -1
- package/dist/api/sweep.js +1 -1
- package/dist/api/sweep.js.map +1 -1
- package/dist/api/thicken.d.ts +1 -1
- package/dist/api/thicken.js +1 -1
- package/dist/api/thicken.js.map +1 -1
- package/dist/api/topo-resolve.d.ts +74 -1
- package/dist/api/topo-resolve.d.ts.map +1 -1
- package/dist/api/topo-resolve.js +180 -2
- package/dist/api/topo-resolve.js.map +1 -1
- package/dist/api/transform.d.ts +10 -6
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +74 -21
- package/dist/api/transform.js.map +1 -1
- package/dist/api/wire.d.ts +1 -1
- package/dist/api/wire.js +1 -1
- package/dist/api/wire.js.map +1 -1
- package/dist/api/xml-dom.d.ts +27 -0
- package/dist/api/xml-dom.d.ts.map +1 -0
- package/dist/api/xml-dom.js +45 -0
- package/dist/api/xml-dom.js.map +1 -0
- package/dist/brep/brep-ops.d.ts +13 -11
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +31 -30
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/brep-topology.d.ts +5 -4
- package/dist/brep/brep-topology.d.ts.map +1 -1
- package/dist/brep/brep-topology.js +9 -6
- package/dist/brep/brep-topology.js.map +1 -1
- package/dist/brep/effective-deflection.d.ts +35 -0
- package/dist/brep/effective-deflection.d.ts.map +1 -0
- package/dist/brep/effective-deflection.js +49 -0
- package/dist/brep/effective-deflection.js.map +1 -0
- package/dist/brep/engine/adapters/brep-mock.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brep-mock.js +27 -0
- package/dist/brep/engine/adapters/brep-mock.js.map +1 -1
- package/dist/brep/engine/adapters/brepkit.d.ts +18 -0
- package/dist/brep/engine/adapters/brepkit.d.ts.map +1 -1
- package/dist/brep/engine/adapters/brepkit.js +46 -1
- package/dist/brep/engine/adapters/brepkit.js.map +1 -1
- package/dist/brep/engine/adapters/occt.d.ts +1 -1
- package/dist/brep/engine/adapters/occt.d.ts.map +1 -1
- package/dist/brep/engine/adapters/occt.js +3 -1
- package/dist/brep/engine/adapters/occt.js.map +1 -1
- package/dist/brep/engine/primitives.d.ts +29 -7
- package/dist/brep/engine/primitives.d.ts.map +1 -1
- package/dist/brep/engine/primitives.js.map +1 -1
- package/dist/brep/engine/registry.d.ts +24 -1
- package/dist/brep/engine/registry.d.ts.map +1 -1
- package/dist/brep/engine/registry.js +24 -0
- package/dist/brep/engine/registry.js.map +1 -1
- package/dist/brep/engine/types.d.ts +54 -3
- package/dist/brep/engine/types.d.ts.map +1 -1
- package/dist/brep/engine/types.js +10 -0
- package/dist/brep/engine/types.js.map +1 -1
- package/dist/brep/export/export-model.d.ts +79 -0
- package/dist/brep/export/export-model.d.ts.map +1 -0
- package/dist/brep/export/export-model.js +336 -0
- package/dist/brep/export/export-model.js.map +1 -0
- package/dist/brep/face-evolution.d.ts +1 -1
- package/dist/brep/face-evolution.d.ts.map +1 -1
- package/dist/brep/face-evolution.js +20 -1
- package/dist/brep/face-evolution.js.map +1 -1
- package/dist/brep/handle-bridge.d.ts +1 -1
- package/dist/brep/handle-bridge.js +1 -1
- package/dist/brep/handle-bridge.js.map +1 -1
- package/dist/brep/mesh-solid.d.ts +218 -0
- package/dist/brep/mesh-solid.d.ts.map +1 -0
- package/dist/brep/mesh-solid.js +229 -0
- package/dist/brep/mesh-solid.js.map +1 -0
- package/dist/brep/primitives-brep.d.ts.map +1 -1
- package/dist/brep/primitives-brep.js +3 -1
- package/dist/brep/primitives-brep.js.map +1 -1
- package/dist/brep/text/fontRegistry.d.ts +32 -1
- package/dist/brep/text/fontRegistry.d.ts.map +1 -1
- package/dist/brep/text/fontRegistry.js +51 -1
- package/dist/brep/text/fontRegistry.js.map +1 -1
- package/dist/brep/text/text-to-solid.d.ts.map +1 -1
- package/dist/brep/text/text-to-solid.js +8 -3
- package/dist/brep/text/text-to-solid.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts +18 -2
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +453 -125
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.d.ts +8 -0
- package/dist/brepkit-kernel/brepkitWasm.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitWasm.js +10 -0
- package/dist/brepkit-kernel/brepkitWasm.js.map +1 -1
- package/dist/browser-host/browser-font-provider.d.ts +12 -0
- package/dist/browser-host/browser-font-provider.d.ts.map +1 -1
- package/dist/browser-host/browser-font-provider.js +25 -0
- package/dist/browser-host/browser-font-provider.js.map +1 -1
- package/dist/browser.d.ts +6 -3
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +10 -3
- package/dist/browser.js.map +1 -1
- package/dist/cad-runtime/backend-dispatch.d.ts +28 -3
- package/dist/cad-runtime/backend-dispatch.d.ts.map +1 -1
- package/dist/cad-runtime/backend-dispatch.js +119 -4
- package/dist/cad-runtime/backend-dispatch.js.map +1 -1
- package/dist/cad-runtime/browser-lib-loader.js.map +1 -1
- package/dist/cad-runtime/direct-executor.d.ts +19 -3
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +49 -1
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +3 -3
- package/dist/cad-runtime/ports.d.ts.map +1 -1
- package/dist/cad-runtime/ports.js.map +1 -1
- package/dist/cad-runtime/preview-exec.d.ts +4 -4
- package/dist/cad-runtime/preview-exec.js +2 -2
- package/dist/cad-runtime/preview-exec.js.map +1 -1
- package/dist/cad-runtime/runtime.d.ts +66 -8
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +121 -8
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +37 -1
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +25 -1
- package/dist/define-op.js.map +1 -1
- package/dist/env-agnostic.d.ts +7 -7
- package/dist/env-agnostic.d.ts.map +1 -1
- package/dist/env-agnostic.js +3 -3
- package/dist/env-agnostic.js.map +1 -1
- package/dist/geometry2d/adapt.d.ts +39 -4
- package/dist/geometry2d/adapt.d.ts.map +1 -1
- package/dist/geometry2d/adapt.js +14 -3
- package/dist/geometry2d/adapt.js.map +1 -1
- package/dist/geometry2d/blueprint.d.ts +2 -2
- package/dist/geometry2d/blueprint.js +2 -2
- package/dist/geometry2d/blueprint.js.map +1 -1
- package/dist/geometry2d/bridge/lift-on-plane.d.ts +18 -8
- package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -1
- package/dist/geometry2d/bridge/lift-on-plane.js +71 -12
- package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -1
- package/dist/geometry2d/bridge/plane.d.ts +17 -0
- package/dist/geometry2d/bridge/plane.d.ts.map +1 -1
- package/dist/geometry2d/bridge/plane.js +22 -0
- package/dist/geometry2d/bridge/plane.js.map +1 -1
- package/dist/geometry2d/curve2d.d.ts +25 -0
- package/dist/geometry2d/curve2d.d.ts.map +1 -1
- package/dist/geometry2d/curve2d.js +41 -5
- package/dist/geometry2d/curve2d.js.map +1 -1
- package/dist/geometry2d/pen-sketcher.d.ts +25 -0
- package/dist/geometry2d/pen-sketcher.d.ts.map +1 -1
- package/dist/geometry2d/pen-sketcher.js +43 -0
- package/dist/geometry2d/pen-sketcher.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/io/bytes-node.d.ts +11 -0
- package/dist/io/bytes-node.d.ts.map +1 -0
- package/dist/io/bytes-node.js +28 -0
- package/dist/io/bytes-node.js.map +1 -0
- package/dist/io/bytes.d.ts +33 -0
- package/dist/io/bytes.d.ts.map +1 -0
- package/dist/io/bytes.js +41 -0
- package/dist/io/bytes.js.map +1 -0
- package/dist/io/fai-zip/container-read.d.ts +102 -0
- package/dist/io/fai-zip/container-read.d.ts.map +1 -0
- package/dist/io/fai-zip/container-read.js +305 -0
- package/dist/io/fai-zip/container-read.js.map +1 -0
- package/dist/io/fai-zip/container-write.d.ts +70 -0
- package/dist/io/fai-zip/container-write.d.ts.map +1 -0
- package/dist/io/fai-zip/container-write.js +186 -0
- package/dist/io/fai-zip/container-write.js.map +1 -0
- package/dist/io/fai-zip/container.d.ts +107 -0
- package/dist/io/fai-zip/container.d.ts.map +1 -0
- package/dist/io/fai-zip/container.js +89 -0
- package/dist/io/fai-zip/container.js.map +1 -0
- package/dist/io/fai-zip/index.d.ts +18 -0
- package/dist/io/fai-zip/index.d.ts.map +1 -0
- package/dist/io/fai-zip/index.js +4 -0
- package/dist/io/fai-zip/index.js.map +1 -0
- package/dist/io/index.d.ts +10 -0
- package/dist/io/index.d.ts.map +1 -0
- package/dist/io/index.js +13 -0
- package/dist/io/index.js.map +1 -0
- package/dist/io/zip.d.ts +68 -0
- package/dist/io/zip.d.ts.map +1 -0
- package/dist/io/zip.js +147 -0
- package/dist/io/zip.js.map +1 -0
- package/dist/lang/code-to-args.d.ts +30 -4
- package/dist/lang/code-to-args.d.ts.map +1 -1
- package/dist/lang/code-to-args.js +42 -3
- package/dist/lang/code-to-args.js.map +1 -1
- package/dist/lang/codegen.d.ts +45 -1
- package/dist/lang/codegen.d.ts.map +1 -1
- package/dist/lang/codegen.js +135 -6
- package/dist/lang/codegen.js.map +1 -1
- package/dist/lang/host-arg.d.ts +6 -0
- package/dist/lang/host-arg.d.ts.map +1 -1
- package/dist/lang/host-arg.js.map +1 -1
- package/dist/lang/metadata-extractor.d.ts +25 -0
- package/dist/lang/metadata-extractor.d.ts.map +1 -1
- package/dist/lang/metadata-extractor.js +289 -25
- package/dist/lang/metadata-extractor.js.map +1 -1
- package/dist/lang/parse-error.d.ts +7 -1
- package/dist/lang/parse-error.d.ts.map +1 -1
- package/dist/lang/parse-error.js.map +1 -1
- package/dist/lang/security-scanner.d.ts +9 -1
- package/dist/lang/security-scanner.d.ts.map +1 -1
- package/dist/lang/security-scanner.js +38 -1
- package/dist/lang/security-scanner.js.map +1 -1
- package/dist/lang/statement-summary.d.ts +1 -1
- package/dist/lang/statement-summary.js +1 -1
- package/dist/lang/statement-summary.js.map +1 -1
- package/dist/lang/types.d.ts +1 -1
- package/dist/lang/types.js +1 -1
- package/dist/lang/types.js.map +1 -1
- package/dist/mesh/index.d.ts +2 -1
- package/dist/mesh/index.d.ts.map +1 -1
- package/dist/mesh/index.js +2 -1
- package/dist/mesh/index.js.map +1 -1
- package/dist/mesh/io.d.ts +69 -9
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +121 -17
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/reconcile.d.ts +1 -1
- package/dist/mesh/reconcile.js +1 -1
- package/dist/mesh/reconcile.js.map +1 -1
- package/dist/mesh/rigid-transform.d.ts +3 -3
- package/dist/mesh/rigid-transform.js +3 -3
- package/dist/mesh/rigid-transform.js.map +1 -1
- package/dist/mesh/stl-unit.d.ts +24 -0
- package/dist/mesh/stl-unit.d.ts.map +1 -0
- package/dist/mesh/stl-unit.js +17 -0
- package/dist/mesh/stl-unit.js.map +1 -0
- package/dist/mesh/threemf-bambu.d.ts +142 -0
- package/dist/mesh/threemf-bambu.d.ts.map +1 -0
- package/dist/mesh/threemf-bambu.js +334 -0
- package/dist/mesh/threemf-bambu.js.map +1 -0
- package/dist/mesh/threemf-loader.d.ts +50 -0
- package/dist/mesh/threemf-loader.d.ts.map +1 -0
- package/dist/mesh/threemf-loader.js +628 -0
- package/dist/mesh/threemf-loader.js.map +1 -0
- package/dist/mesh/threemf-view.d.ts +71 -0
- package/dist/mesh/threemf-view.d.ts.map +1 -0
- package/dist/mesh/threemf-view.js +100 -0
- package/dist/mesh/threemf-view.js.map +1 -0
- package/dist/mesh/transform.d.ts +2 -2
- package/dist/mesh/transform.d.ts.map +1 -1
- package/dist/mesh/transform.js +3 -3
- package/dist/mesh/transform.js.map +1 -1
- package/dist/mesh/types.d.ts +1 -1
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.js.map +1 -1
- package/dist/node-host/cli.d.ts +44 -6
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +127 -50
- package/dist/node-host/cli.js.map +1 -1
- package/dist/node-host/font-family-index.d.ts +93 -0
- package/dist/node-host/font-family-index.d.ts.map +1 -0
- package/dist/node-host/font-family-index.js +273 -0
- package/dist/node-host/font-family-index.js.map +1 -0
- package/dist/node-host/fs-asset-resolver.d.ts +8 -3
- package/dist/node-host/fs-asset-resolver.d.ts.map +1 -1
- package/dist/node-host/fs-asset-resolver.js +13 -5
- package/dist/node-host/fs-asset-resolver.js.map +1 -1
- package/dist/node-host/index.d.ts +8 -0
- package/dist/node-host/index.d.ts.map +1 -1
- package/dist/node-host/index.js +1 -0
- package/dist/node-host/index.js.map +1 -1
- package/dist/node-host/node-font-provider.d.ts +28 -0
- package/dist/node-host/node-font-provider.d.ts.map +1 -1
- package/dist/node-host/node-font-provider.js +49 -0
- package/dist/node-host/node-font-provider.js.map +1 -1
- package/dist/node.d.ts +1 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +1 -0
- package/dist/node.js.map +1 -1
- package/dist/occt-kernel/occt-primitives.d.ts.map +1 -1
- package/dist/occt-kernel/occt-primitives.js +35 -2
- package/dist/occt-kernel/occt-primitives.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts +18 -13
- package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
- package/dist/occt-kernel/occtKernel.js +20 -31
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/dist/occt-kernel/stepColorParser.d.ts +18 -0
- package/dist/occt-kernel/stepColorParser.d.ts.map +1 -1
- package/dist/occt-kernel/stepColorParser.js +38 -0
- package/dist/occt-kernel/stepColorParser.js.map +1 -1
- package/dist/occt-kernel/topologyExt.d.ts +1 -1
- package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
- package/dist/occt-kernel/topologyExt.js +8 -6
- package/dist/occt-kernel/topologyExt.js.map +1 -1
- package/dist/primitives/text/cjk-font.d.ts +2 -15
- package/dist/primitives/text/cjk-font.d.ts.map +1 -1
- package/dist/primitives/text/cjk-font.js +13 -1
- package/dist/primitives/text/cjk-font.js.map +1 -1
- package/dist/runtime-state.d.ts +103 -9
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +95 -2
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdk.d.ts +4 -4
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +6 -6
- package/dist/sdk.js.map +1 -1
- package/dist/shape.d.ts +97 -2
- package/dist/shape.d.ts.map +1 -1
- package/dist/shape.js +126 -1
- package/dist/shape.js.map +1 -1
- package/dist/tolerance.d.ts +38 -0
- package/dist/tolerance.d.ts.map +1 -0
- package/dist/tolerance.js +40 -0
- package/dist/tolerance.js.map +1 -0
- package/dist/topology/naming/lineage.d.ts +6 -0
- package/dist/topology/naming/lineage.d.ts.map +1 -1
- package/dist/topology/naming/lineage.js +8 -0
- package/dist/topology/naming/lineage.js.map +1 -1
- package/dist/topology/naming/resolve-edge.d.ts +20 -1
- package/dist/topology/naming/resolve-edge.d.ts.map +1 -1
- package/dist/topology/naming/resolve-edge.js +54 -20
- package/dist/topology/naming/resolve-edge.js.map +1 -1
- package/dist/topology/naming/score.js +3 -3
- package/dist/topology/naming/score.js.map +1 -1
- package/dist/units.d.ts +248 -0
- package/dist/units.d.ts.map +1 -0
- package/dist/units.js +397 -0
- package/dist/units.js.map +1 -0
- package/dist/weapp.d.ts +6 -2
- package/dist/weapp.d.ts.map +1 -1
- package/dist/weapp.js +7 -1
- package/dist/weapp.js.map +1 -1
- package/package.json +28 -3
|
@@ -18,10 +18,55 @@
|
|
|
18
18
|
* - 链纪律:kernel.meshFallbackCount 计数差 > 0 → getMeshFallbackCount 暴露给宿主,
|
|
19
19
|
* 由宿主标记 BREP 链中断(不在此层静默处理)。
|
|
20
20
|
*/
|
|
21
|
-
import { initBrepkitWasm } from './brepkitWasm.js';
|
|
22
|
-
|
|
21
|
+
import { initBrepkitWasm, resetBrepkitWasm } from './brepkitWasm.js';
|
|
22
|
+
import { DEFAULT_LINEAR_DEFLECTION } from '../tolerance.js';
|
|
23
|
+
import { mm } from '../units.js';
|
|
24
|
+
import { BREP_HASH_BOUND } from '../brep/engine/types.js';
|
|
25
|
+
// ── 句柄桥接:brepkit number 句柄 ↔ BrepHandle ──
|
|
26
|
+
//
|
|
27
|
+
// GOTCHA(2026-10-01 实测,本文件最容易踩的坑):brepkit 句柄是**按类型分命名空间的裸 u32**
|
|
28
|
+
// ——同一个 box 上 solid=0、face=0..5、edge=0..11 同时存在,且**内核没有任何可靠的类型判别式**:
|
|
29
|
+
// getEdgeCurveType(0) / edgeLength(0) → 命中 edge 0
|
|
30
|
+
// getFaceEdges(0) / getFaceNormal(0) → 命中 face 0
|
|
31
|
+
// getSolidFaces(0) → 命中 solid 0
|
|
32
|
+
// 三者对同一个数字 0 各自返回「自己命名空间里 0 号」的数据,谁都不抛错(`getSolidFaces(1)` 才抛)。
|
|
33
|
+
// 因此「拿句柄去问内核它是什么类型」在 brepkit 上**不可能实现**。
|
|
34
|
+
//
|
|
35
|
+
// 但 L1 契约里 `hashCode(handle)` 只收到一个数字,必须知道类型才能选面/边指纹函数。
|
|
36
|
+
// 解法:适配器在**出口**把类型编进句柄高位。类型随句柄流动,`asNum()` 剥掉标签后仍是内核
|
|
37
|
+
// 裸句柄号——内部集合(knownFaces/knownEdges/…)、hashRegistry、全部 `kernel.*` 调用语义不变。
|
|
38
|
+
// 高 3 位(bit 26..28)放类型;虚拟 compound 句柄从 bit 29(0x20000000)起分配,互不干扰。
|
|
39
|
+
// 注意 `asNum` 用**算术减法**而非 `& ~KIND_MASK`:后者把 ≥2^31 的虚拟句柄按 int32 截断成负数。
|
|
40
|
+
const KIND_SHIFT = 26;
|
|
41
|
+
const KIND_MASK = 7 << KIND_SHIFT;
|
|
42
|
+
const KIND_SOLID = 0 << KIND_SHIFT; // 也是 compound / 未登记句柄的默认类
|
|
43
|
+
const KIND_FACE = 1 << KIND_SHIFT;
|
|
44
|
+
const KIND_EDGE = 2 << KIND_SHIFT;
|
|
45
|
+
const KIND_WIRE = 3 << KIND_SHIFT;
|
|
46
|
+
const KIND_VERTEX = 4 << KIND_SHIFT;
|
|
47
|
+
/** 句柄类型标签(0 = SOLID/COMPOUND 默认类)。 */
|
|
48
|
+
const kindOf = (h) => h & KIND_MASK;
|
|
49
|
+
/** 剥掉类型标签,得到 brepkit 内核裸句柄号——所有 `kernel.*` 调用必须用这个。 */
|
|
50
|
+
const asNum = (h) => {
|
|
51
|
+
const n = h;
|
|
52
|
+
return n - (n & KIND_MASK);
|
|
53
|
+
};
|
|
54
|
+
/** 实体/compound 句柄(默认类,保持历史行为:无标签 ⇒ 内核按 solid 路径分发)。 */
|
|
23
55
|
const asHandle = (n) => n;
|
|
24
|
-
const
|
|
56
|
+
const asFace = (n) => (n | KIND_FACE);
|
|
57
|
+
const asEdge = (n) => (n | KIND_EDGE);
|
|
58
|
+
const asWire = (n) => (n | KIND_WIRE);
|
|
59
|
+
const asVertex = (n) => (n | KIND_VERTEX);
|
|
60
|
+
/** 按已有类型标签给裸句柄重新打标签(copy/transform 族保持入参类型)。 */
|
|
61
|
+
const withKind = (kind, n) => {
|
|
62
|
+
switch (kind) {
|
|
63
|
+
case KIND_FACE: return asFace(n);
|
|
64
|
+
case KIND_EDGE: return asEdge(n);
|
|
65
|
+
case KIND_WIRE: return asWire(n);
|
|
66
|
+
case KIND_VERTEX: return asVertex(n);
|
|
67
|
+
default: return asHandle(n);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
25
70
|
const arr = (x) => Array.from(x);
|
|
26
71
|
/** 适配器内部的显式失败(替代旧 unsupported 桩:能力缺失一律在静态判定拦截,不在实现体里伪装)。 */
|
|
27
72
|
function fail(detail) {
|
|
@@ -77,6 +122,26 @@ function toNumArray(v) {
|
|
|
77
122
|
}
|
|
78
123
|
return [];
|
|
79
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* brepkit 无任何 hash API(228 个方法里没有 hashCode/subShapeHashes)——faijs 侧的
|
|
127
|
+
* 面/边 hash 全部由适配器**合成指纹**,因此「合成函数」与「消费函数的取模上界」
|
|
128
|
+
* 必须同源:
|
|
129
|
+
* - 消费端 `topologyExt.buildSelectorManifestCore` 用
|
|
130
|
+
* `kernel.hashCode(subShape, BREP_HASH_BOUND)` 回查 faceGroups/edgeGroups 里的 hash;
|
|
131
|
+
* - 生产端(本文件的 solidMesh / faceMesh / compoundMesh / wireframe)必须用**同一个**
|
|
132
|
+
* `BREP_HASH_BOUND` 生成,否则查表恒 miss。
|
|
133
|
+
*
|
|
134
|
+
* GOTCHA(2026-10-01 实测修复):本文件此前生产端用 1e9、消费端用 2147483647,
|
|
135
|
+
* 导致 brepkit 引擎下面行的 triStart/triCount 恒为 0(面积/法向随之丢失)。
|
|
136
|
+
*/
|
|
137
|
+
function fnv1a(basis, upperBound) {
|
|
138
|
+
let h = 0x811c9dc5;
|
|
139
|
+
for (let i = 0; i < basis.length; i++) {
|
|
140
|
+
h ^= basis.charCodeAt(i);
|
|
141
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
142
|
+
}
|
|
143
|
+
return upperBound > 0 ? h % upperBound : h;
|
|
144
|
+
}
|
|
80
145
|
/** 面稳定指纹:解析曲面参数 + 面积 → FNV-1a → 取模上界(跨操作可追溯,与句柄无关)。 */
|
|
81
146
|
function faceFingerprint(kernel, face, upperBound) {
|
|
82
147
|
let params = '';
|
|
@@ -89,13 +154,45 @@ function faceFingerprint(kernel, face, upperBound) {
|
|
|
89
154
|
area = Number(kernel.faceArea?.(face, 0.1) ?? 0);
|
|
90
155
|
}
|
|
91
156
|
catch { /* 查询失败用 0 */ }
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
157
|
+
return fnv1a(`${params}|${area.toFixed(6)}`, upperBound);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* 边稳定指纹:曲线类型 + 参数区间 + 两端/中点采样 + 长度 → FNV-1a。
|
|
161
|
+
*
|
|
162
|
+
* 为什么不能用 `faceFingerprint`:它对边恒得同一个值(`getAnalyticSurfaceParams`
|
|
163
|
+
* 与 `faceArea` 对 edge 句柄都抛错)——旧实现在 box 上 12 条边 hash 全同,
|
|
164
|
+
* 使 `topologyExt` 的 edgeGroupByHash 只留最后一条折线(实测 2026-10-01)。
|
|
165
|
+
*
|
|
166
|
+
* 为什么不能只用端点:整圆(圆柱端盖)首末点重合,z 不同的两个圆会撞 —
|
|
167
|
+
* 故补 UV 中点采样。`getBoundingBox(edge)` 在 brepkit 上抛错,不可用。
|
|
168
|
+
*/
|
|
169
|
+
function edgeFingerprint(kernel, edge, upperBound) {
|
|
170
|
+
let curveType = '';
|
|
171
|
+
try {
|
|
172
|
+
curveType = String(kernel.getEdgeCurveType(edge) ?? '');
|
|
97
173
|
}
|
|
98
|
-
|
|
174
|
+
catch { /* 非边 */ }
|
|
175
|
+
let range = '';
|
|
176
|
+
let mid = '';
|
|
177
|
+
try {
|
|
178
|
+
// 方言:`getEdgeCurveParameters` 返回 **Float64Array**(如 [0, 10]),不是 JSON 字符串
|
|
179
|
+
// (见本文件头的返回值归一化说明)。曾误用 JSON.parse → 恒定抛错 → range/mid 恒空,
|
|
180
|
+
// 于是所有同类型同长度的边(box 的 12 条棱)挤成同一个指纹(2026-10-01 实测)。
|
|
181
|
+
const p = toNumArray(kernel.getEdgeCurveParameters(edge));
|
|
182
|
+
const first = p[0] ?? 0;
|
|
183
|
+
const last = p[1] ?? 0;
|
|
184
|
+
range = `${first.toFixed(9)},${last.toFixed(9)}`;
|
|
185
|
+
const midT = (first + last) / 2;
|
|
186
|
+
const sample = (t) => toNumArray(kernel.evaluateEdgeCurve(edge, t)).map((x) => x.toFixed(6)).join(',');
|
|
187
|
+
mid = `${sample(first)}|${sample(midT)}|${sample(last)}`;
|
|
188
|
+
}
|
|
189
|
+
catch { /* 采样失败 → 退化为类型 + 空几何 */ }
|
|
190
|
+
let length = 0;
|
|
191
|
+
try {
|
|
192
|
+
length = Number(kernel.edgeLength(edge) ?? 0);
|
|
193
|
+
}
|
|
194
|
+
catch { /* 长度不可用用 0 */ }
|
|
195
|
+
return fnv1a(`${curveType}|${range}|${mid}|${length.toFixed(6)}`, upperBound);
|
|
99
196
|
}
|
|
100
197
|
/** 面演化数据(BrepEvolutionData):brepkit evolution JSON → hash 编码三元组。 */
|
|
101
198
|
function mapEvolution(kernel, raw, resultHandle, inputFaceHashes, hashUpperBound) {
|
|
@@ -146,7 +243,18 @@ function mapEvolution(kernel, raw, resultHandle, inputFaceHashes, hashUpperBound
|
|
|
146
243
|
}
|
|
147
244
|
/** per-kernel 的 hash↔handle 登记表(fuseWithHistory 溯源对齐用)。 */
|
|
148
245
|
const hashRegistry = new WeakMap();
|
|
149
|
-
/**
|
|
246
|
+
/**
|
|
247
|
+
* 三点外接圆(makeArcEdge 方言消化:occt 吃 3 点,brepkit 吃圆心+轴)。
|
|
248
|
+
*
|
|
249
|
+
* 圆心偏移取标准式 `d = ( |ab|²·(ac×n) + |ac|²·(n×ab) ) / (2·|n|²)`,`n = ab×ac`。
|
|
250
|
+
* GOTCHA(弧缺陷,2026-09-30 实证):旧式 `( |ac|²·(ab×n) + |ab|²·(n×ac) ) / (2·|n|²)`
|
|
251
|
+
* 把两项的系数对调,等于整体取反——圆心落到弦的另一侧(实测 quarter arc 圆心 (20,0,0)
|
|
252
|
+
* 而非 (0,0,0),三点不等距),brepkit 据此生成 333° 的补弧(弧长 58.195 而非 πr/2)。
|
|
253
|
+
* 判据是等距不变量 `|center−a| = |center−b| = |center−c|`。
|
|
254
|
+
*
|
|
255
|
+
* axis = n/|n| 即三点逆时针扫掠方向的右手法向;brepkit `makeCircleArc3d` 语义为
|
|
256
|
+
* "沿法向看从 start 逆时针到 end",故该轴向同时正确表达 ccw 与 cw 弧。
|
|
257
|
+
*/
|
|
150
258
|
function circumcircle(a, b, c) {
|
|
151
259
|
const abx = b.x - a.x, aby = b.y - a.y, abz = b.z - a.z;
|
|
152
260
|
const acx = c.x - a.x, acy = c.y - a.y, acz = c.z - a.z;
|
|
@@ -158,16 +266,16 @@ function circumcircle(a, b, c) {
|
|
|
158
266
|
fail('makeArcEdge: 3 points are collinear (no circumscribed circle)');
|
|
159
267
|
const ab2 = abx * abx + aby * aby + abz * abz;
|
|
160
268
|
const ac2 = acx * acx + acy * acy + acz * acz;
|
|
161
|
-
// center = a + (
|
|
162
|
-
const
|
|
163
|
-
const
|
|
269
|
+
// center = a + ( ab2·(ac×n) + ac2·(n×ab) ) / (2·n²)
|
|
270
|
+
const acxnx = acy * nz - acz * ny, acxny = acz * nx - acx * nz, acxnz = acx * ny - acy * nx;
|
|
271
|
+
const nxabx = ny * abz - nz * aby, nxaby = nz * abx - nx * abz, nxabz = nx * aby - ny * abx;
|
|
164
272
|
const denom = 2 * n2;
|
|
165
273
|
const len = Math.sqrt(n2);
|
|
166
274
|
return {
|
|
167
275
|
center: {
|
|
168
|
-
x: a.x + (
|
|
169
|
-
y: a.y + (
|
|
170
|
-
z: a.z + (
|
|
276
|
+
x: a.x + (ab2 * acxnx + ac2 * nxabx) / denom,
|
|
277
|
+
y: a.y + (ab2 * acxny + ac2 * nxaby) / denom,
|
|
278
|
+
z: a.z + (ab2 * acxnz + ac2 * nxabz) / denom,
|
|
171
279
|
},
|
|
172
280
|
axis: { x: nx / len, y: ny / len, z: nz / len },
|
|
173
281
|
};
|
|
@@ -190,6 +298,13 @@ function flattenPoints(points) {
|
|
|
190
298
|
*/
|
|
191
299
|
export async function createBrepkitPrimitives() {
|
|
192
300
|
const kernel = await initBrepkitWasm();
|
|
301
|
+
// GOTCHA(2026-10-01):本函数此前每次调用都新建一套闭包(knownFaces/knownSolids/
|
|
302
|
+
// derivedFaces…)——即**新建一套句柄桥接层**。句柄号虽然对同一个 wasm 内核全局有效,
|
|
303
|
+
// 但桥接层侧的类型登记表不同:A 层枚举出的面句柄交给 B 层做 getSubShapes,会被当
|
|
304
|
+
// 实体走 tessellateSolidGrouped。BREP 引擎装配点与网格后端装配点都调本函数,必须
|
|
305
|
+
// 拿到**同一个**对象。故按内核实例 memo 化(disposeBrepkit 会清掉)。
|
|
306
|
+
if (memoizedPrimitives && memoizedKernel === kernel)
|
|
307
|
+
return memoizedPrimitives;
|
|
193
308
|
liveKernel = kernel;
|
|
194
309
|
let lastFallbackCount = 0;
|
|
195
310
|
// 已知面句柄集合:getSubShapes(shape,'face') / makeRectangle / makeFace / buildTriFace
|
|
@@ -223,14 +338,45 @@ export async function createBrepkitPrimitives() {
|
|
|
223
338
|
// (实测 box makeBox 返回 solid 2,撞 profile 早先的 face 2 → cloneShape 走 copyFace 崩溃)。
|
|
224
339
|
// 建 solid 时必须从 knownFaces/knownWires/knownEdges/derivedFaces 抹掉该编号,让默认 solid 路径生效。
|
|
225
340
|
// derivedFaces 也必须清:getSubShapes(solid,'edge') 会查 derivedFaces.has(s) 误走 getFaceEdges。
|
|
341
|
+
// GOTCHA(2026-10-01 实测):`derivedFaces` 是**全局**面句柄号集合,枚举 solid A 的面会把
|
|
342
|
+
// 面号 0..N 写进去;此后对**裸句柄号恰好相同的另一个 solid**做 getSubShapes(...,'edge')
|
|
343
|
+
// 时,`derivedFaces.has(s)` 为真 → isFaceLike 误判 → 走 getFaceEdges 只拿到一张面的 4 条边
|
|
344
|
+
// (实测 box:12 条边变 4 条)。故必须显式登记 solid 句柄:实体永远不是 face-like。
|
|
345
|
+
const knownSolids = new Set();
|
|
226
346
|
const markSolid = (h) => {
|
|
227
347
|
knownFaces.delete(h);
|
|
228
348
|
knownWires.delete(h);
|
|
229
349
|
knownEdges.delete(h);
|
|
230
350
|
knownCompounds.delete(h);
|
|
231
351
|
derivedFaces.delete(h);
|
|
352
|
+
knownSolids.add(h);
|
|
232
353
|
return h;
|
|
233
354
|
};
|
|
355
|
+
/** 实体数组批量登记(阵列族返回多个实体)。 */
|
|
356
|
+
const markSolids = (list) => list.map(markSolid);
|
|
357
|
+
/**
|
|
358
|
+
* 句柄类型解析:**标签优先**,无标签时退回已知集合(历史行为)。
|
|
359
|
+
*
|
|
360
|
+
* 标签是权威来源——集合的 key 是**裸句柄号**,face 3 与 edge 3 会共存于不同集合,
|
|
361
|
+
* 靠集合无法区分。故有标签(非 0)时直接用标签,集合里的同名条目一律忽略;
|
|
362
|
+
* 只有无标签句柄(实体/compound/构造 API 外传入)才走集合分发,行为与加标签前一致。
|
|
363
|
+
*/
|
|
364
|
+
const resolveKind = (shape, s) => {
|
|
365
|
+
const tagged = kindOf(shape);
|
|
366
|
+
if (tagged !== KIND_SOLID)
|
|
367
|
+
return tagged;
|
|
368
|
+
// 已登记的实体优先:knownFaces/knownEdges 的 key 是裸句柄号,历史登记(如
|
|
369
|
+
// getSubShapes(face,'edge') 写 knownEdges)与后来新建的 solid 号同号时会把实体判成边。
|
|
370
|
+
if (knownSolids.has(s))
|
|
371
|
+
return KIND_SOLID;
|
|
372
|
+
if (knownFaces.has(s))
|
|
373
|
+
return KIND_FACE;
|
|
374
|
+
if (knownWires.has(s))
|
|
375
|
+
return KIND_WIRE;
|
|
376
|
+
if (knownEdges.has(s))
|
|
377
|
+
return KIND_EDGE;
|
|
378
|
+
return KIND_SOLID;
|
|
379
|
+
};
|
|
234
380
|
const readFallback = () => {
|
|
235
381
|
try {
|
|
236
382
|
return typeof kernel.meshFallbackCount === 'function' ? Number(kernel.meshFallbackCount()) : 0;
|
|
@@ -262,7 +408,7 @@ export async function createBrepkitPrimitives() {
|
|
|
262
408
|
indices: new Uint32Array(indices),
|
|
263
409
|
vertexCount: positions.length / 3,
|
|
264
410
|
triangleCount: triCount,
|
|
265
|
-
faceGroups: new Int32Array([0,
|
|
411
|
+
faceGroups: new Int32Array([0, indices.length, faceFingerprint(kernel, f, BREP_HASH_BOUND)]),
|
|
266
412
|
faceCount: 1,
|
|
267
413
|
};
|
|
268
414
|
};
|
|
@@ -302,21 +448,24 @@ export async function createBrepkitPrimitives() {
|
|
|
302
448
|
const solidMesh = (solid, deflection, angular) => {
|
|
303
449
|
const raw = kernel.tessellateSolidGrouped(solid, deflection, angular);
|
|
304
450
|
const m = JSON.parse(raw);
|
|
305
|
-
// faceOffsets 形如 [start0, start1, ..., totalEnd]
|
|
306
|
-
//
|
|
451
|
+
// faceOffsets 形如 [start0, start1, ..., totalEnd]:以「索引数组单位」计的每面偏移
|
|
452
|
+
// (2026-09-19 实测)。**L1 契约的 faceGroups 就是索引单位**(与 OCCT 一致,
|
|
453
|
+
// 见 brep/engine/types.BrepMeshResult)——此处原样透传,不得再除以 3。
|
|
454
|
+
// GOTCHA(2026-10-01):旧实现除以 3 换成三角形单位,与 topologyExt 的 `/3`
|
|
455
|
+
// 叠加 → 面行区间缩小 3 倍。
|
|
307
456
|
const fo = m.faceOffsets;
|
|
308
457
|
const faceCount = Math.max(0, fo.length - 1);
|
|
309
458
|
const faceHashes = [];
|
|
310
459
|
try {
|
|
311
460
|
const faces = arr(kernel.getSolidFaces(solid));
|
|
312
461
|
for (let i = 0; i < faceCount && i < faces.length; i++)
|
|
313
|
-
faceHashes.push(faceFingerprint(kernel, faces[i],
|
|
462
|
+
faceHashes.push(faceFingerprint(kernel, faces[i], BREP_HASH_BOUND));
|
|
314
463
|
}
|
|
315
464
|
catch { /* 非实体:faceHash 置 0 */ }
|
|
316
465
|
const faceGroups = new Int32Array(faceCount * 3);
|
|
317
466
|
for (let i = 0; i < faceCount; i++) {
|
|
318
|
-
faceGroups[i * 3] = fo[i]
|
|
319
|
-
faceGroups[i * 3 + 1] =
|
|
467
|
+
faceGroups[i * 3] = fo[i];
|
|
468
|
+
faceGroups[i * 3 + 1] = fo[i + 1] - fo[i];
|
|
320
469
|
faceGroups[i * 3 + 2] = faceHashes[i] ?? 0;
|
|
321
470
|
}
|
|
322
471
|
return {
|
|
@@ -335,7 +484,7 @@ export async function createBrepkitPrimitives() {
|
|
|
335
484
|
const normals = [];
|
|
336
485
|
const indices = [];
|
|
337
486
|
const faceGroups = [];
|
|
338
|
-
let
|
|
487
|
+
let indexOffset = 0;
|
|
339
488
|
for (const c of children) {
|
|
340
489
|
let sub;
|
|
341
490
|
if (knownFaces.has(c)) {
|
|
@@ -360,10 +509,10 @@ export async function createBrepkitPrimitives() {
|
|
|
360
509
|
indices.push(sub.indices[i] + vOffset);
|
|
361
510
|
if (sub.faceGroups) {
|
|
362
511
|
for (let i = 0; i < sub.faceGroups.length; i += 3) {
|
|
363
|
-
faceGroups.push((sub.faceGroups[i] ?? 0) +
|
|
512
|
+
faceGroups.push((sub.faceGroups[i] ?? 0) + indexOffset, sub.faceGroups[i + 1] ?? 0, sub.faceGroups[i + 2] ?? 0);
|
|
364
513
|
}
|
|
365
514
|
}
|
|
366
|
-
|
|
515
|
+
indexOffset += sub.indices.length;
|
|
367
516
|
}
|
|
368
517
|
return {
|
|
369
518
|
positions: new Float32Array(positions),
|
|
@@ -380,13 +529,15 @@ export async function createBrepkitPrimitives() {
|
|
|
380
529
|
// 传错即崩溃;transformSolid/transformFace/transformWire 均为「原地修改」void。
|
|
381
530
|
// place/translate 等会作用在 profile 产出的 face 上(sew 用例 place 两张 face),
|
|
382
531
|
// 故必须按 knownFaces/knownWires 分发,不能一律 copySolid。
|
|
383
|
-
|
|
384
|
-
|
|
532
|
+
// kind 为调用方句柄的类型标签(0 = solid):句柄标签是**权威判定**,knownFaces/knownWires
|
|
533
|
+
// 只作无标签时的兜底(枚举出的面句柄只进 derivedFaces,不在 knownFaces 里)。
|
|
534
|
+
const cloneShape = (shape, kind = KIND_SOLID) => {
|
|
535
|
+
if (kind === KIND_FACE || knownFaces.has(shape)) {
|
|
385
536
|
const c = kernel.copyFace(shape);
|
|
386
537
|
knownFaces.add(c);
|
|
387
538
|
return c;
|
|
388
539
|
}
|
|
389
|
-
if (knownWires.has(shape)) {
|
|
540
|
+
if (kind === KIND_WIRE || knownWires.has(shape)) {
|
|
390
541
|
const c = kernel.copyWire(shape);
|
|
391
542
|
knownWires.add(c);
|
|
392
543
|
return c;
|
|
@@ -394,12 +545,12 @@ export async function createBrepkitPrimitives() {
|
|
|
394
545
|
return markSolid(kernel.copySolid(shape));
|
|
395
546
|
};
|
|
396
547
|
/** 深拷贝 + 原地仿射变换(matrix 已经 toKernelMatrix 归一为 16 元素 4×4)。 */
|
|
397
|
-
const cloneAndTransform = (shape, matrix16) => {
|
|
398
|
-
const c = cloneShape(shape);
|
|
548
|
+
const cloneAndTransform = (shape, matrix16, kind = KIND_SOLID) => {
|
|
549
|
+
const c = cloneShape(shape, kind);
|
|
399
550
|
const m = Float64Array.from(matrix16);
|
|
400
|
-
if (knownFaces.has(c))
|
|
551
|
+
if (kind === KIND_FACE || knownFaces.has(c))
|
|
401
552
|
kernel.transformFace(c, m);
|
|
402
|
-
else if (knownWires.has(c))
|
|
553
|
+
else if (kind === KIND_WIRE || knownWires.has(c))
|
|
403
554
|
kernel.transformWire(c, m);
|
|
404
555
|
else
|
|
405
556
|
kernel.transformSolid(c, m);
|
|
@@ -433,11 +584,11 @@ export async function createBrepkitPrimitives() {
|
|
|
433
584
|
makeRectangle(width, height) {
|
|
434
585
|
const f = kernel.makeRectangle(width, height);
|
|
435
586
|
knownFaces.add(f);
|
|
436
|
-
return
|
|
587
|
+
return asFace(f);
|
|
437
588
|
},
|
|
438
589
|
makeEllipsoid(rx, ry, rz) { return asHandle(markSolid(kernel.makeEllipsoid(rx, ry, rz))); },
|
|
439
590
|
makeTorus(majorRadius, minorRadius) { return asHandle(markSolid(kernel.makeTorus(majorRadius, minorRadius, 64))); },
|
|
440
|
-
makeVertex(x, y, z) { return
|
|
591
|
+
makeVertex(x, y, z) { return asVertex(kernel.makeVertex(x, y, z)); },
|
|
441
592
|
// ── 造型运算 ──
|
|
442
593
|
extrude(shape, dx, dy, dz) {
|
|
443
594
|
// 方言归一(§3.6-1):L1 口径是挤出向量;brepkit 原生吃 (face, dir, distance)。
|
|
@@ -459,7 +610,7 @@ export async function createBrepkitPrimitives() {
|
|
|
459
610
|
return asHandle(markSolid(kernel.revolve(s, center.x, center.y, center.z, direction.x, direction.y, direction.z, angleDeg)));
|
|
460
611
|
},
|
|
461
612
|
sew(shapesList, tolerance) {
|
|
462
|
-
return asHandle(kernel.sewFaces(Uint32Array.from(shapesList.map(asNum)), tolerance ?? 1e-6));
|
|
613
|
+
return asHandle(markSolid(kernel.sewFaces(Uint32Array.from(shapesList.map(asNum)), tolerance ?? 1e-6)));
|
|
463
614
|
},
|
|
464
615
|
sewAndSolidify(faces, _tolerance) {
|
|
465
616
|
// brepkit 的 makeSolid 即「缝合并固化成实体」(sewFaces + 建 solid)。
|
|
@@ -467,10 +618,10 @@ export async function createBrepkitPrimitives() {
|
|
|
467
618
|
},
|
|
468
619
|
shell(solid, facesToRemove, thickness, _tolerance) {
|
|
469
620
|
// brepkit 参数序 (solid, thickness, open_faces);tolerance 内核固定。
|
|
470
|
-
return asHandle(kernel.shell(asNum(solid), thickness, Uint32Array.from(facesToRemove.map(asNum))));
|
|
621
|
+
return asHandle(markSolid(kernel.shell(asNum(solid), thickness, Uint32Array.from(facesToRemove.map(asNum)))));
|
|
471
622
|
},
|
|
472
623
|
hullFromPoints(points, _tolerance) {
|
|
473
|
-
return asHandle(kernel.convexHull(flattenPoints(points)));
|
|
624
|
+
return asHandle(markSolid(kernel.convexHull(flattenPoints(points))));
|
|
474
625
|
},
|
|
475
626
|
// ── 布尔与分割 ──
|
|
476
627
|
fuse(a, b) { return asHandle(markSolid(trackFallback(kernel.fuse(asNum(a), asNum(b))))); },
|
|
@@ -479,7 +630,7 @@ export async function createBrepkitPrimitives() {
|
|
|
479
630
|
// brepkit 无 `common` 原生名;交集语义由 `intersect` 承担(method-map: dialect)。
|
|
480
631
|
return asHandle(markSolid(trackFallback(kernel.intersect(asNum(a), asNum(b)))));
|
|
481
632
|
},
|
|
482
|
-
intersect(a, b) { return asHandle(trackFallback(kernel.intersect(asNum(a), asNum(b)))); },
|
|
633
|
+
intersect(a, b) { return asHandle(markSolid(trackFallback(kernel.intersect(asNum(a), asNum(b))))); },
|
|
483
634
|
fuseAll(shapesList) {
|
|
484
635
|
return asHandle(markSolid(trackFallback(kernel.fuseAll(Int32Array.from(shapesList.map(asNum))))));
|
|
485
636
|
},
|
|
@@ -513,24 +664,24 @@ export async function createBrepkitPrimitives() {
|
|
|
513
664
|
},
|
|
514
665
|
// ── 倒角与圆角(Q7:只对齐等距 + 距角两种粒度)──
|
|
515
666
|
chamfer(solid, edges, distance) {
|
|
516
|
-
return asHandle(trackFallback(kernel.chamfer(asNum(solid), Uint32Array.from(edges.map(asNum)), distance)));
|
|
667
|
+
return asHandle(markSolid(trackFallback(kernel.chamfer(asNum(solid), Uint32Array.from(edges.map(asNum)), distance))));
|
|
517
668
|
},
|
|
518
669
|
chamferDistAngle(solid, edges, distance, angleDeg) {
|
|
519
670
|
// 方言映射:L1 chamferDistAngle ↔ brepkit chamferDistanceAngle。
|
|
520
671
|
// ⚠️ 单位方言:L1 口径是**度**(`AddDA(distance, angleDeg, E, F)`),brepkit 内核吃**弧度**
|
|
521
672
|
// (2026-09-25 实证:传 45 抛 "angle must be less than π/2";传 π/4 正常倒角)。
|
|
522
673
|
const angleRad = (angleDeg * Math.PI) / 180;
|
|
523
|
-
return asHandle(trackFallback(kernel.chamferDistanceAngle(asNum(solid), Uint32Array.from(edges.map(asNum)), distance, angleRad)));
|
|
674
|
+
return asHandle(markSolid(trackFallback(kernel.chamferDistanceAngle(asNum(solid), Uint32Array.from(edges.map(asNum)), distance, angleRad))));
|
|
524
675
|
},
|
|
525
676
|
fillet(solid, edges, radius) {
|
|
526
|
-
return asHandle(trackFallback(kernel.fillet(asNum(solid), Uint32Array.from(edges.map(asNum)), radius)));
|
|
677
|
+
return asHandle(markSolid(trackFallback(kernel.fillet(asNum(solid), Uint32Array.from(edges.map(asNum)), radius))));
|
|
527
678
|
},
|
|
528
679
|
filletVariable(solid, edge, startRadius, endRadius) {
|
|
529
680
|
// 方言映射:L1 filletVariable(solid, edge, startRadius, endRadius)(单边变半径)
|
|
530
681
|
// ↔ brepkit filletVariable(solid, json) 吃**序列** `[{edge, radius1, radius2}, ...]`。
|
|
531
682
|
// ⚠️ 直接传 4 个位置参数会触发 wasm memory out of bounds(2026-09-25 实证)。
|
|
532
683
|
const spec = JSON.stringify([{ edge: asNum(edge), radius1: startRadius, radius2: endRadius }]);
|
|
533
|
-
return asHandle(trackFallback(kernel.filletVariable(asNum(solid), spec)));
|
|
684
|
+
return asHandle(markSolid(trackFallback(kernel.filletVariable(asNum(solid), spec))));
|
|
534
685
|
},
|
|
535
686
|
filletWithHistory(solid, edges, radius, inputFaceHashes, hashUpperBound) {
|
|
536
687
|
const raw = kernel.filletWithEvolution(asNum(solid), Int32Array.from(edges.map(asNum)), radius);
|
|
@@ -543,61 +694,62 @@ export async function createBrepkitPrimitives() {
|
|
|
543
694
|
// brepkit transformSolid 吃 4×4 行主序 16 元素。所有 transformSolid 调用一律经
|
|
544
695
|
// toKernelMatrix 归一(下方唯一转换点),禁止直出 16 元素旁路。
|
|
545
696
|
translate(shape, dx, dy, dz) {
|
|
546
|
-
return
|
|
697
|
+
return withKind(kindOf(shape), cloneAndTransform(asNum(shape), toKernelMatrix(translationMatrix(dx, dy, dz)), kindOf(shape)));
|
|
547
698
|
},
|
|
548
699
|
scale(shape, center, factor) {
|
|
549
|
-
return
|
|
700
|
+
return withKind(kindOf(shape), cloneAndTransform(asNum(shape), toKernelMatrix(scaleMatrix(center, factor)), kindOf(shape)));
|
|
550
701
|
},
|
|
551
702
|
transform(shape, matrix) {
|
|
552
|
-
return
|
|
703
|
+
return withKind(kindOf(shape), cloneAndTransform(asNum(shape), toKernelMatrix(matrix), kindOf(shape)));
|
|
553
704
|
},
|
|
554
705
|
located(shape, matrix) {
|
|
555
|
-
return
|
|
706
|
+
return withKind(kindOf(shape), cloneAndTransform(asNum(shape), toKernelMatrix(matrix), kindOf(shape)));
|
|
556
707
|
},
|
|
557
708
|
locate(shape, matrix) {
|
|
558
|
-
return
|
|
709
|
+
return withKind(kindOf(shape), cloneAndTransform(asNum(shape), toKernelMatrix(matrix), kindOf(shape)));
|
|
559
710
|
},
|
|
560
711
|
generalTransform(shape, matrix) {
|
|
561
|
-
return
|
|
712
|
+
return withKind(kindOf(shape), cloneAndTransform(asNum(shape), toKernelMatrix(matrix), kindOf(shape)));
|
|
562
713
|
},
|
|
563
|
-
copy(shape) { return
|
|
564
|
-
copyShape(shape) { return
|
|
714
|
+
copy(shape) { return withKind(kindOf(shape), cloneShape(asNum(shape), kindOf(shape))); },
|
|
715
|
+
copyShape(shape) { return withKind(kindOf(shape), cloneShape(asNum(shape), kindOf(shape))); },
|
|
565
716
|
composeTransform(m1, m2) {
|
|
566
717
|
// 方言:L1 是 3×4 行主序 12 元素;brepkit composeTransforms 吃/回 4×4 16 元素。
|
|
567
718
|
const r = kernel.composeTransforms(Float64Array.from(toKernelMatrix(m1)), Float64Array.from(toKernelMatrix(m2)));
|
|
568
719
|
return Array.from(r).slice(0, 12);
|
|
569
720
|
},
|
|
570
721
|
mirror(shape, point, normal) {
|
|
571
|
-
return
|
|
722
|
+
return withKind(kindOf(shape), kernel.mirror(asNum(shape), point.x, point.y, point.z, normal.x, normal.y, normal.z));
|
|
572
723
|
},
|
|
573
724
|
// ── 阵列 ──
|
|
574
725
|
// brepkit wasm 的 pattern 内核函数都返回 compound(含全部副本)→ 经 getCompoundSolids 拆成数组。
|
|
575
726
|
linearPattern(shape, direction, spacing, count) {
|
|
576
727
|
const compound = kernel.linearPattern(asNum(shape), direction.x, direction.y, direction.z, spacing, count);
|
|
577
|
-
|
|
728
|
+
// 阵列内核返回 compound(原始句柄)→ 拆成实体数组并逐个登记(见 markSolid GOTCHA)。
|
|
729
|
+
return markSolids(arr(kernel.getCompoundSolids(compound))).map(asHandle);
|
|
578
730
|
},
|
|
579
731
|
circularPattern(shape, _center, axis, _angleStep, count) {
|
|
580
732
|
// ⚠️ brepkit wasm circularPattern(solid, ax, ay, az, count) 无 center/angle 参数:
|
|
581
733
|
// 固定整圆均分(每份 360°/count)。fullAngle=360 时与 vendored/occt 语义一致;
|
|
582
734
|
// 其它角度跨度无法表达(语义限制记录于此,parity 测试用整圆)。
|
|
583
735
|
const compound = kernel.circularPattern(asNum(shape), axis.x, axis.y, axis.z, count);
|
|
584
|
-
return arr(kernel.getCompoundSolids(compound)).map(asHandle);
|
|
736
|
+
return markSolids(arr(kernel.getCompoundSolids(compound))).map(asHandle);
|
|
585
737
|
},
|
|
586
738
|
gridPattern(shape, directionX, directionY, spacingX, spacingY, countX, countY) {
|
|
587
|
-
return asHandle(kernel.gridPattern(asNum(shape), directionX.x, directionX.y, directionX.z, directionY.x, directionY.y, directionY.z, spacingX, spacingY, countX, countY));
|
|
739
|
+
return asHandle(markSolid(kernel.gridPattern(asNum(shape), directionX.x, directionX.y, directionX.z, directionY.x, directionY.y, directionY.z, spacingX, spacingY, countX, countY)));
|
|
588
740
|
},
|
|
589
741
|
// ── 曲线构造 ──
|
|
590
742
|
makeLineEdge(start, end) {
|
|
591
743
|
const e = kernel.makeLineEdge(start.x, start.y, start.z, end.x, end.y, end.z);
|
|
592
744
|
knownEdges.add(e);
|
|
593
|
-
return
|
|
745
|
+
return asEdge(e);
|
|
594
746
|
},
|
|
595
747
|
makeArcEdge(start, mid, end) {
|
|
596
748
|
// 方言消化:occt 吃 3 点;brepkit makeCircleArc3d 吃 (start,end,center,axis)。
|
|
597
749
|
const { center, axis } = circumcircle(start, mid, end);
|
|
598
750
|
const e = kernel.makeCircleArc3d(start.x, start.y, start.z, end.x, end.y, end.z, center.x, center.y, center.z, axis.x, axis.y, axis.z);
|
|
599
751
|
knownEdges.add(e);
|
|
600
|
-
return
|
|
752
|
+
return asEdge(e);
|
|
601
753
|
},
|
|
602
754
|
makeBezierEdge(controlPoints) {
|
|
603
755
|
// 方言消化:L1 吃控制点(Bezier);brepkit 原生 makeNurbsEdge 吃
|
|
@@ -615,34 +767,59 @@ export async function createBrepkitPrimitives() {
|
|
|
615
767
|
const last = controlPoints[n - 1];
|
|
616
768
|
const e = kernel.makeNurbsEdge(first.x, first.y, first.z, last.x, last.y, last.z, degree, knots, flattenPoints(controlPoints), weights);
|
|
617
769
|
knownEdges.add(e);
|
|
618
|
-
return
|
|
770
|
+
return asEdge(e);
|
|
771
|
+
},
|
|
772
|
+
makeBSplineEdge(poles, weights, knots, multiplicities, degree, periodic = false) {
|
|
773
|
+
// 方言消化:L1 吃 occt 形态 (poles, weights, knots, multiplicities, degree),
|
|
774
|
+
// brepkit makeNurbsEdge 吃 (start,end,degree, **展开后** knots, control_points, weights)。
|
|
775
|
+
// 两侧 knots 的表示不同:occt 给「去重值 + 多重度」两个平行数组,brepkit 要
|
|
776
|
+
// 逐项重复后的整条节点向量(与 makeBezierEdge 里手工铺 [0]×n+[1]×n 同一口径)。
|
|
777
|
+
const controlPoints = [];
|
|
778
|
+
for (let i = 0; i + 2 < poles.length; i += 3) {
|
|
779
|
+
controlPoints.push({ x: poles[i], y: poles[i + 1], z: poles[i + 2] });
|
|
780
|
+
}
|
|
781
|
+
const n = controlPoints.length;
|
|
782
|
+
if (n < 2)
|
|
783
|
+
fail('makeBSplineEdge: need at least 2 poles');
|
|
784
|
+
const expanded = [];
|
|
785
|
+
for (let i = 0; i < knots.length; i++) {
|
|
786
|
+
const rep = multiplicities[i] ?? 1;
|
|
787
|
+
for (let j = 0; j < rep; j++)
|
|
788
|
+
expanded.push(knots[i]);
|
|
789
|
+
}
|
|
790
|
+
const first = controlPoints[0];
|
|
791
|
+
const last = controlPoints[n - 1];
|
|
792
|
+
const e = kernel.makeNurbsEdge(first.x, first.y, first.z, last.x, last.y, last.z, degree, Float64Array.from(expanded), flattenPoints(controlPoints), weights.length === n ? Float64Array.from(weights) : new Float64Array(n).fill(1));
|
|
793
|
+
void periodic;
|
|
794
|
+
knownEdges.add(e);
|
|
795
|
+
return asEdge(e);
|
|
619
796
|
},
|
|
620
797
|
makeCircleEdge(center, normal, radius) {
|
|
621
798
|
const e = kernel.makeCircleEdge(center.x, center.y, center.z, normal.x, normal.y, normal.z, radius);
|
|
622
799
|
knownEdges.add(e);
|
|
623
|
-
return
|
|
800
|
+
return asEdge(e);
|
|
624
801
|
},
|
|
625
802
|
// ── 拓扑构造 ──
|
|
626
803
|
makeWire(edges) {
|
|
627
804
|
const w = kernel.makeWire(Int32Array.from(edges.map(asNum)), false);
|
|
628
805
|
knownWires.add(w);
|
|
629
|
-
return
|
|
806
|
+
return asWire(w);
|
|
630
807
|
},
|
|
631
808
|
makeFace(wire) {
|
|
632
809
|
const f = kernel.makeFaceFromWire(asNum(wire));
|
|
633
810
|
knownFaces.add(f);
|
|
634
|
-
return
|
|
811
|
+
return asFace(f);
|
|
635
812
|
},
|
|
636
813
|
makeCompound(shapesList) {
|
|
637
814
|
const kids = arr(shapesList.map(asNum));
|
|
638
815
|
// GOTCHA(2026-09-26):brepkit makeCompound 只接受 **solid** 句柄——把 face/wire
|
|
639
816
|
// (sectionByPlane 截面面组)塞进去即抛 "invalid solid handle"。非实体子句柄时
|
|
640
|
-
// 不调内核,改用高段虚拟句柄(
|
|
817
|
+
// 不调内核,改用高段虚拟句柄(0x20000000+,避开类型标签 bit26..28),仅靠 knownCompounds 表分发
|
|
641
818
|
// meshShape/wireframe/getSubShapes/getBoundingBox,不触达内核。
|
|
642
819
|
const hasNonSolid = kids.some((k) => knownFaces.has(k) || knownWires.has(k) || knownEdges.has(k) || knownCompounds.has(k));
|
|
643
820
|
if (hasNonSolid) {
|
|
644
821
|
virtualCompoundCounter++;
|
|
645
|
-
const v =
|
|
822
|
+
const v = 0x20000000 + virtualCompoundCounter;
|
|
646
823
|
knownCompounds.set(v, kids);
|
|
647
824
|
return asHandle(v);
|
|
648
825
|
}
|
|
@@ -655,25 +832,26 @@ export async function createBrepkitPrimitives() {
|
|
|
655
832
|
// 否则 profile(op) 带孔面送 meshShape 会落到 solid 路径崩溃。
|
|
656
833
|
const f = kernel.addHolesToFace(asNum(face), Int32Array.from(holeWires.map(asNum)));
|
|
657
834
|
knownFaces.add(f);
|
|
658
|
-
return
|
|
835
|
+
return asFace(f);
|
|
659
836
|
},
|
|
660
837
|
buildTriFace(a, b, c) {
|
|
661
838
|
const f = kernel.makePolygon(flattenPoints([a, b, c]));
|
|
662
839
|
knownFaces.add(f);
|
|
663
|
-
return
|
|
840
|
+
return asFace(f);
|
|
664
841
|
},
|
|
665
842
|
// ── 三角化(BREP→mesh 唯一出口) ──
|
|
666
843
|
meshShape(shape, options) {
|
|
667
|
-
const deflection = options?.linearDeflection ??
|
|
844
|
+
const deflection = options?.linearDeflection ?? DEFAULT_LINEAR_DEFLECTION.as(mm);
|
|
668
845
|
const angular = options?.angularDeflection ?? 0.5;
|
|
669
846
|
const s = asNum(shape);
|
|
670
|
-
//
|
|
847
|
+
// 非实体句柄按类型静态分发(标签优先,见文件头 GOTCHA:brepkit 无 shape-type 分类 API)。
|
|
671
848
|
// 顺序:face → wire → edge → compound → solid。实体创建不入任何集合,天然落 solid 路径。
|
|
672
|
-
|
|
849
|
+
const kind = resolveKind(shape, s);
|
|
850
|
+
if (kind === KIND_FACE)
|
|
673
851
|
return faceMesh(s, deflection, angular);
|
|
674
|
-
if (
|
|
852
|
+
if (kind === KIND_WIRE)
|
|
675
853
|
return wireMesh(s, deflection);
|
|
676
|
-
if (
|
|
854
|
+
if (kind === KIND_EDGE)
|
|
677
855
|
return edgesToLineMesh([s], deflection);
|
|
678
856
|
const compoundChildren = knownCompounds.get(s);
|
|
679
857
|
if (compoundChildren)
|
|
@@ -682,17 +860,18 @@ export async function createBrepkitPrimitives() {
|
|
|
682
860
|
return solidMesh(s, deflection, angular);
|
|
683
861
|
},
|
|
684
862
|
wireframe(shape, deflection) {
|
|
685
|
-
const d = deflection ??
|
|
863
|
+
const d = deflection ?? DEFAULT_LINEAR_DEFLECTION.as(mm);
|
|
686
864
|
const s = asNum(shape);
|
|
687
865
|
// GOTCHA:meshEdgesAll 是 solid-only API——buildTopologyFromMesh 会对 face/wire/edge
|
|
688
866
|
// 产物调 wireframe(...),传入非实体句柄即抛 "invalid solid handle"。按已知集合分发:
|
|
689
867
|
// face -> getFaceEdges;wire -> getWireEdges;edge -> [self];否则 solid 走 meshEdgesAll。
|
|
690
868
|
let edgeHandles = null;
|
|
691
|
-
|
|
869
|
+
const kind = resolveKind(shape, s);
|
|
870
|
+
if (kind === KIND_FACE)
|
|
692
871
|
edgeHandles = arr(kernel.getFaceEdges(s));
|
|
693
|
-
else if (
|
|
872
|
+
else if (kind === KIND_WIRE)
|
|
694
873
|
edgeHandles = arr(kernel.getWireEdges(s));
|
|
695
|
-
else if (
|
|
874
|
+
else if (kind === KIND_EDGE)
|
|
696
875
|
edgeHandles = [s];
|
|
697
876
|
else if (knownCompounds.has(s)) {
|
|
698
877
|
// compound(sectionByPlane 面组):逐子面收集边。
|
|
@@ -709,20 +888,22 @@ export async function createBrepkitPrimitives() {
|
|
|
709
888
|
if (edgeHandles) {
|
|
710
889
|
const nPts = Math.max(12, Math.round(4 / Math.max(d, 0.01)));
|
|
711
890
|
const positions = [];
|
|
891
|
+
// offsets 为**浮点单位**(L1 契约:edgeGroups = [pointStart_float, pointCount_float, hash])
|
|
712
892
|
const offsets = [0];
|
|
713
893
|
for (const e of edgeHandles) {
|
|
714
894
|
const pts = arr(kernel.tessellateEdge(e, nPts));
|
|
715
895
|
for (const p of pts)
|
|
716
896
|
positions.push(p);
|
|
717
|
-
offsets.push(positions.length
|
|
897
|
+
offsets.push(positions.length);
|
|
718
898
|
}
|
|
719
899
|
const edgeGroups = new Int32Array(edgeHandles.length * 3);
|
|
720
900
|
for (let i = 0; i < edgeHandles.length; i++) {
|
|
721
901
|
edgeGroups[i * 3] = offsets[i] ?? 0;
|
|
722
|
-
edgeGroups[i * 3 + 1] = (offsets[i + 1] ?? positions.length
|
|
723
|
-
|
|
902
|
+
edgeGroups[i * 3 + 1] = (offsets[i + 1] ?? positions.length) - (offsets[i] ?? 0);
|
|
903
|
+
// hash 必须与 hashCode(edge, BREP_HASH_BOUND) 同源,否则 topologyExt 查不到折线。
|
|
904
|
+
edgeGroups[i * 3 + 2] = edgeFingerprint(kernel, edgeHandles[i], BREP_HASH_BOUND);
|
|
724
905
|
}
|
|
725
|
-
return { points: new Float32Array(positions), edgeGroups, pointCount: positions.length
|
|
906
|
+
return { points: new Float32Array(positions), edgeGroups, pointCount: positions.length, edgeCount: edgeHandles.length };
|
|
726
907
|
}
|
|
727
908
|
// solid(或未登记句柄):走原 meshEdgesAll 路径。
|
|
728
909
|
// JsEdgeLines:edgeCount/offsets/positions 均为属性(offsets/positions 为 TypedArray,2026-09-19 实测)
|
|
@@ -730,13 +911,25 @@ export async function createBrepkitPrimitives() {
|
|
|
730
911
|
const edgeCount = Number(me.edgeCount);
|
|
731
912
|
const offsets = arr(me.offsets);
|
|
732
913
|
const positions = arr(me.positions);
|
|
914
|
+
// hash:meshEdgesAll 与 getSolidEdges 同序(同一次遍历),据此回填真实边指纹;
|
|
915
|
+
// 取不到(数量不符)时退化为序号——此时 topologyExt 查不到折线,曲面边走
|
|
916
|
+
// 曲线采样兜底(功能可用,只是丢掉内核线框数据)。
|
|
917
|
+
let solidEdges = null;
|
|
918
|
+
try {
|
|
919
|
+
const es = arr(kernel.getSolidEdges(s));
|
|
920
|
+
if (es.length === edgeCount)
|
|
921
|
+
solidEdges = es;
|
|
922
|
+
}
|
|
923
|
+
catch { /* 非实体 */ }
|
|
733
924
|
const edgeGroups = new Int32Array(edgeCount * 3);
|
|
734
925
|
for (let i = 0; i < edgeCount; i++) {
|
|
735
926
|
const start = offsets[i] ?? 0;
|
|
736
|
-
const count = (offsets[i + 1] ?? positions.length
|
|
927
|
+
const count = (offsets[i + 1] ?? positions.length) - start;
|
|
737
928
|
edgeGroups[i * 3] = start;
|
|
738
929
|
edgeGroups[i * 3 + 1] = count;
|
|
739
|
-
edgeGroups[i * 3 + 2] =
|
|
930
|
+
edgeGroups[i * 3 + 2] = solidEdges
|
|
931
|
+
? edgeFingerprint(kernel, solidEdges[i], BREP_HASH_BOUND)
|
|
932
|
+
: i;
|
|
740
933
|
}
|
|
741
934
|
return { points: new Float32Array(positions), edgeGroups, pointCount: positions.length, edgeCount };
|
|
742
935
|
},
|
|
@@ -749,49 +942,104 @@ export async function createBrepkitPrimitives() {
|
|
|
749
942
|
// edge/vertex 查询时按句柄是否在 knownFaces 里分发到 face 级或 solid 级 API。
|
|
750
943
|
getSubShapes(shape, type) {
|
|
751
944
|
const s = asNum(shape);
|
|
945
|
+
// 出口一律按 **type 参数**打类型标签(`type` 就是调用方声明的子形类型,是权威来源;
|
|
946
|
+
// 不用内核反查——brepkit 无法反查类型,见文件头句柄桥接 GOTCHA)。
|
|
947
|
+
const tag = (list) => {
|
|
948
|
+
switch (type) {
|
|
949
|
+
case 'face': return list.map(asFace);
|
|
950
|
+
case 'edge': return list.map(asEdge);
|
|
951
|
+
case 'vertex': return list.map(asVertex);
|
|
952
|
+
case 'wire': return list.map(asWire);
|
|
953
|
+
default: return list.map(asHandle);
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
// ── A. 有类型标签:按标签分发,**不登记 knownEdges** ──
|
|
957
|
+
// GOTCHA(2026-10-01 实测回归):历史分支里 `es.forEach(e => knownEdges.add(e))` 会把
|
|
958
|
+
// 面/线的边号写进 knownEdges,而 knownEdges 的 key 是**裸句柄号**、会与后来新建的
|
|
959
|
+
// solid 号相撞 → resolveKind 把实体判成边 → getBoundingBox 返回边的退化 bbox
|
|
960
|
+
// (实测 8 个 op 的 AABB 全错)。标签句柄自带类型,登记已无必要,故这里一律不登记。
|
|
961
|
+
const tagged = kindOf(shape);
|
|
962
|
+
if (tagged === KIND_FACE) {
|
|
963
|
+
if (type === 'face')
|
|
964
|
+
return [asFace(s)];
|
|
965
|
+
if (type === 'edge')
|
|
966
|
+
return tag(arr(kernel.getFaceEdges(s)));
|
|
967
|
+
if (type === 'vertex')
|
|
968
|
+
return tag(arr(kernel.getFaceVertices(s)));
|
|
969
|
+
return [];
|
|
970
|
+
}
|
|
971
|
+
if (tagged === KIND_WIRE) {
|
|
972
|
+
if (type === 'edge')
|
|
973
|
+
return tag(arr(kernel.getWireEdges(s)));
|
|
974
|
+
return [];
|
|
975
|
+
}
|
|
976
|
+
if (tagged === KIND_EDGE) {
|
|
977
|
+
// input is itself an edge (wire.ts smooth path: interpolatePoints returns edge)
|
|
978
|
+
if (type === 'edge')
|
|
979
|
+
return [asEdge(s)];
|
|
980
|
+
return [];
|
|
981
|
+
}
|
|
982
|
+
// ── B. 无标签:逐字沿用历史集合分发(含 knownEdges 登记),行为与加标签前一致 ──
|
|
752
983
|
// GOTCHA(2026-09-26 非实体句柄修复):buildTopologyFromMesh 会对**面产物**
|
|
753
984
|
// 调 getSubShapes(face,'face')。brepkit 的 getSolidFaces/getShellFaces 是 solid-only,
|
|
754
985
|
// 对面句柄一个抛 "invalid solid handle"、catch 里再抛 "invalid shell handle"——
|
|
755
|
-
//
|
|
756
|
-
// 输入本身就是 knownFaces 里的一张面时,'face' 返回 [s],edge/vertex 走 face 级 API。
|
|
986
|
+
// 两跳都不被捕获即崩溃。无标签时靠已知集合先分发。
|
|
757
987
|
if (knownFaces.has(s)) {
|
|
758
988
|
if (type === 'face')
|
|
759
|
-
return [
|
|
989
|
+
return [asFace(s)];
|
|
760
990
|
if (type === 'edge') {
|
|
761
991
|
const es = arr(kernel.getFaceEdges(s));
|
|
762
992
|
es.forEach((e) => knownEdges.add(e));
|
|
763
|
-
return es
|
|
993
|
+
return tag(es);
|
|
764
994
|
}
|
|
765
995
|
if (type === 'vertex')
|
|
766
|
-
return arr(kernel.getFaceVertices(s))
|
|
996
|
+
return tag(arr(kernel.getFaceVertices(s)));
|
|
767
997
|
return [];
|
|
768
998
|
}
|
|
769
999
|
if (knownWires.has(s)) {
|
|
770
1000
|
if (type === 'edge') {
|
|
771
1001
|
const es = arr(kernel.getWireEdges(s));
|
|
772
1002
|
es.forEach((e) => knownEdges.add(e));
|
|
773
|
-
return es
|
|
1003
|
+
return tag(es);
|
|
774
1004
|
}
|
|
775
1005
|
return [];
|
|
776
1006
|
}
|
|
777
1007
|
if (knownEdges.has(s)) {
|
|
778
|
-
// input is itself an edge (wire.ts smooth path: interpolatePoints returns edge)
|
|
779
1008
|
if (type === 'edge')
|
|
780
|
-
return [
|
|
1009
|
+
return [asEdge(s)];
|
|
781
1010
|
return [];
|
|
782
1011
|
}
|
|
783
1012
|
const compKids = knownCompounds.get(s);
|
|
784
1013
|
if (compKids) {
|
|
785
1014
|
// compound(sectionByPlane 面组 / makeCompound 多实体 / importStep 多实体):
|
|
786
|
-
// 'face' 返回子面,'solid'
|
|
1015
|
+
// 'face' 返回子面,'solid' 返回子实体,'edge' 返回各子句柄的边,其余空。
|
|
787
1016
|
if (type === 'face')
|
|
788
|
-
return compKids.filter((k) => knownFaces.has(k))
|
|
1017
|
+
return tag(compKids.filter((k) => knownFaces.has(k)));
|
|
789
1018
|
if (type === 'solid')
|
|
790
|
-
return compKids.filter((k) => !knownFaces.has(k) && !knownWires.has(k) && !knownEdges.has(k))
|
|
1019
|
+
return tag(compKids.filter((k) => !knownFaces.has(k) && !knownWires.has(k) && !knownEdges.has(k)));
|
|
1020
|
+
if (type === 'edge') {
|
|
1021
|
+
// 2026-10-02 补:此前 compound 的边查询落到 `return []`,会让归一化后的
|
|
1022
|
+
// getLength(compound) 静默变 0。按子句柄的已知类型分发,与 occt 的
|
|
1023
|
+
// getSubShapes(compound,'edge')(返回全部子边)对齐。
|
|
1024
|
+
const out = [];
|
|
1025
|
+
for (const kid of compKids) {
|
|
1026
|
+
if (knownFaces.has(kid))
|
|
1027
|
+
out.push(...arr(kernel.getFaceEdges(kid)));
|
|
1028
|
+
else if (knownWires.has(kid))
|
|
1029
|
+
out.push(...arr(kernel.getWireEdges(kid)));
|
|
1030
|
+
else if (knownEdges.has(kid))
|
|
1031
|
+
out.push(kid);
|
|
1032
|
+
else
|
|
1033
|
+
out.push(...arr(kernel.getSolidEdges(kid)));
|
|
1034
|
+
}
|
|
1035
|
+
return tag(out);
|
|
1036
|
+
}
|
|
791
1037
|
return [];
|
|
792
1038
|
}
|
|
793
1039
|
let list;
|
|
794
|
-
|
|
1040
|
+
// 实体句柄(knownSolids)永远不是 face-like——`derivedFaces` 只装「枚举出来的面号」,
|
|
1041
|
+
// 与 solid 号共用一个裸数字空间,不排除会造成误判(见 knownSolids 注释)。
|
|
1042
|
+
const isFaceLike = knownFaces.has(s) || (derivedFaces.has(s) && !knownSolids.has(s));
|
|
795
1043
|
if (type === 'face') {
|
|
796
1044
|
// 输入可能是 solid 或 shell。枚举到的子面登记到 derivedFaces(不进 knownFaces,
|
|
797
1045
|
// 避免与 solid 句柄撞号——见 derivedFaces 注释)。
|
|
@@ -829,18 +1077,19 @@ export async function createBrepkitPrimitives() {
|
|
|
829
1077
|
else {
|
|
830
1078
|
fail(`getSubShapes(${type}): unsupported sub-shape type`);
|
|
831
1079
|
}
|
|
832
|
-
return list
|
|
1080
|
+
return tag(list);
|
|
833
1081
|
},
|
|
834
1082
|
subShapeHashes(shape, type, hashUpperBound) {
|
|
835
1083
|
if (type !== 'face')
|
|
836
1084
|
fail(`subShapeHashes(${type}): only 'face' is supported by brepkit`);
|
|
837
1085
|
const s = asNum(shape);
|
|
838
1086
|
// GOTCHA:buildTopologyFromMesh 会对面产物调 subShapeHashes(face,'face');
|
|
839
|
-
// getSolidFaces 是 solid-only
|
|
840
|
-
|
|
1087
|
+
// getSolidFaces 是 solid-only,对面句柄崩溃。输入本身是面时,哈希即其自身指纹。
|
|
1088
|
+
const kind = resolveKind(shape, s);
|
|
1089
|
+
if (kind === KIND_FACE)
|
|
841
1090
|
return [faceFingerprint(kernel, s, hashUpperBound)];
|
|
842
1091
|
// wire/edge 无面;compound(sectionByPlane 面组)的子句柄即面。
|
|
843
|
-
if (
|
|
1092
|
+
if (kind === KIND_WIRE || kind === KIND_EDGE)
|
|
844
1093
|
return [];
|
|
845
1094
|
const compKids = knownCompounds.get(s);
|
|
846
1095
|
if (compKids) {
|
|
@@ -856,9 +1105,25 @@ export async function createBrepkitPrimitives() {
|
|
|
856
1105
|
return hashes;
|
|
857
1106
|
},
|
|
858
1107
|
hashCode(shape, upperBound) {
|
|
859
|
-
|
|
1108
|
+
// 类型由句柄标签决定(见文件头句柄桥接 GOTCHA):brepkit 无法反查句柄类型,
|
|
1109
|
+
// 而面指纹与边指纹必须落在**互不相交**的取值域,否则 edgeGroups 的 hash 会
|
|
1110
|
+
// 命中面的指纹(实测:box 的 edge 0..5 句柄号与 face 0..5 相同)。
|
|
1111
|
+
// 生产端(faceMesh/solidMesh/compoundMesh → faceFingerprint;wireframe →
|
|
1112
|
+
// edgeFingerprint)与消费端(本函数)用同一组函数、同一个上界,查表才命中。
|
|
1113
|
+
const raw = asNum(shape);
|
|
1114
|
+
return kindOf(shape) === KIND_EDGE
|
|
1115
|
+
? edgeFingerprint(kernel, raw, upperBound)
|
|
1116
|
+
: faceFingerprint(kernel, raw, upperBound);
|
|
1117
|
+
},
|
|
1118
|
+
isSame(a, b) {
|
|
1119
|
+
// 裸句柄号相同还不够:brepkit 的 face 3 与 edge 3 是**两个不同的形**。
|
|
1120
|
+
// 两侧都带标签时必须同类型;任一侧无标签(历史调用方)时退回纯数字比较,
|
|
1121
|
+
// 保证加标签不改变既有行为。
|
|
1122
|
+
if (asNum(a) !== asNum(b))
|
|
1123
|
+
return false;
|
|
1124
|
+
const ka = kindOf(a), kb = kindOf(b);
|
|
1125
|
+
return ka === kb || ka === KIND_SOLID || kb === KIND_SOLID;
|
|
860
1126
|
},
|
|
861
|
-
isSame(a, b) { return asNum(a) === asNum(b); },
|
|
862
1127
|
isSolid(shape) {
|
|
863
1128
|
try {
|
|
864
1129
|
return arr(kernel.getSolidFaces(asNum(shape))).length > 0;
|
|
@@ -890,10 +1155,10 @@ export async function createBrepkitPrimitives() {
|
|
|
890
1155
|
return kernel.edgeToFaceMap(asNum(shape));
|
|
891
1156
|
},
|
|
892
1157
|
adjacentFaces(shape, face) {
|
|
893
|
-
return arr(kernel.adjacentFaces(asNum(shape), asNum(face))).map(
|
|
1158
|
+
return arr(kernel.adjacentFaces(asNum(shape), asNum(face))).map(asFace);
|
|
894
1159
|
},
|
|
895
1160
|
sharedEdges(a, b) {
|
|
896
|
-
return arr(kernel.sharedEdges(asNum(a), asNum(b))).map(
|
|
1161
|
+
return arr(kernel.sharedEdges(asNum(a), asNum(b))).map(asEdge);
|
|
897
1162
|
},
|
|
898
1163
|
// ── 几何求值 ──
|
|
899
1164
|
curveType(edge) { return String(kernel.getEdgeCurveType(asNum(edge))); },
|
|
@@ -966,21 +1231,42 @@ export async function createBrepkitPrimitives() {
|
|
|
966
1231
|
getNurbsCurveData(edge) {
|
|
967
1232
|
try {
|
|
968
1233
|
const p = JSON.parse(kernel.getNurbsCurveData(asNum(edge)));
|
|
969
|
-
if (p && typeof p.degree === 'number')
|
|
970
|
-
return {
|
|
1234
|
+
if (p && typeof p.degree === 'number') {
|
|
1235
|
+
return {
|
|
1236
|
+
degree: p.degree,
|
|
1237
|
+
periodic: !!p.periodic,
|
|
1238
|
+
rational: !!p.rational,
|
|
1239
|
+
knots: (p.knots ?? []).map(Number),
|
|
1240
|
+
multiplicities: (p.multiplicities ?? []).map(Number),
|
|
1241
|
+
poles: (p.poles ?? []).map(Number),
|
|
1242
|
+
weights: (p.weights ?? []).map(Number),
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
971
1245
|
}
|
|
972
1246
|
catch { /* 非 Nurbs 边 */ }
|
|
973
1247
|
return null;
|
|
974
1248
|
},
|
|
1249
|
+
curveSplit(edge, param) {
|
|
1250
|
+
// brepkit 原生返回 Uint32Array 两元素(occt 返回 [ShapeHandle, ShapeHandle])——
|
|
1251
|
+
// 适配器统一为二元组。两个碎片都必须登记进 knownEdges,否则下游 meshShape 分发不到。
|
|
1252
|
+
const parts = kernel.curveSplit(asNum(edge), param);
|
|
1253
|
+
if (parts.length !== 2)
|
|
1254
|
+
fail(`curveSplit: expected 2 edges, got ${parts.length}`);
|
|
1255
|
+
const a = parts[0];
|
|
1256
|
+
const b = parts[1];
|
|
1257
|
+
knownEdges.add(a);
|
|
1258
|
+
knownEdges.add(b);
|
|
1259
|
+
return [asEdge(a), asEdge(b)];
|
|
1260
|
+
},
|
|
975
1261
|
interpolatePoints(points, degree) {
|
|
976
1262
|
// GOTCHA:interpolatePoints 返回 **edge** 句柄(不是 wire)——wire.ts smooth 路径把它
|
|
977
1263
|
// 直接当 wire 送 solidToShape。登记进 knownEdges,meshShape 才能走 tessellateEdge 路径。
|
|
978
1264
|
const e = kernel.interpolatePoints(flattenPoints(points), degree);
|
|
979
1265
|
knownEdges.add(e);
|
|
980
|
-
return
|
|
1266
|
+
return asEdge(e);
|
|
981
1267
|
},
|
|
982
1268
|
defeature(shape, faces) {
|
|
983
|
-
return asHandle(kernel.defeature(asNum(shape), Uint32Array.from(faces.map(asNum))));
|
|
1269
|
+
return asHandle(markSolid(kernel.defeature(asNum(shape), Uint32Array.from(faces.map(asNum)))));
|
|
984
1270
|
},
|
|
985
1271
|
draft(shape, faces, pull, neutral, angleDeg) {
|
|
986
1272
|
return asHandle(kernel.draft(asNum(shape), Uint32Array.from(faces.map(asNum)), pull.x, pull.y, pull.z, neutral.x, neutral.y, neutral.z, angleDeg));
|
|
@@ -989,10 +1275,10 @@ export async function createBrepkitPrimitives() {
|
|
|
989
1275
|
// removeHolesFromFace 返回**新 face 句柄**(去掉内孔的同曲面 face),必须登记进 knownFaces。
|
|
990
1276
|
const f = kernel.removeHolesFromFace(asNum(face));
|
|
991
1277
|
knownFaces.add(f);
|
|
992
|
-
return
|
|
1278
|
+
return asFace(f);
|
|
993
1279
|
},
|
|
994
1280
|
reverseShape(shape) {
|
|
995
|
-
return
|
|
1281
|
+
return withKind(kindOf(shape), kernel.reverseShape(asNum(shape)));
|
|
996
1282
|
},
|
|
997
1283
|
projectEdges(shape, origin, direction, xAxis, hiddenLines, deflection) {
|
|
998
1284
|
// brepkit 返回 JSON 字符串 {"visible":[[x,y,…]],"hidden":[[…]]};L1 契约是 unknown。
|
|
@@ -1052,11 +1338,12 @@ export async function createBrepkitPrimitives() {
|
|
|
1052
1338
|
}
|
|
1053
1339
|
// GOTCHA:kernel.boundingBox 是 solid-only。face/wire/edge 句柄必须走 tessellation 采样,
|
|
1054
1340
|
// 否则 measure() 对 wire/profile 调 getBoundingBox 即崩 "invalid solid handle"。
|
|
1055
|
-
|
|
1341
|
+
const kind = resolveKind(shape, s);
|
|
1342
|
+
if (kind === KIND_FACE)
|
|
1056
1343
|
return bboxFromPoints(arr(kernel.tessellateFace(s, 0.1, 1).positions));
|
|
1057
|
-
if (
|
|
1344
|
+
if (kind === KIND_WIRE)
|
|
1058
1345
|
return bboxFromPoints(arr(kernel.getWireEdges(s)).flatMap((e) => arr(kernel.tessellateEdge(e, 16))));
|
|
1059
|
-
if (
|
|
1346
|
+
if (kind === KIND_EDGE)
|
|
1060
1347
|
return bboxFromPoints(arr(kernel.tessellateEdge(s, 16)));
|
|
1061
1348
|
return solidBbox(s);
|
|
1062
1349
|
},
|
|
@@ -1070,17 +1357,15 @@ export async function createBrepkitPrimitives() {
|
|
|
1070
1357
|
return Number(kernel.surfaceArea(asNum(shape), 0.05));
|
|
1071
1358
|
},
|
|
1072
1359
|
getLength(shape) {
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1075
|
-
// 对 wire
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
return Number(kernel.wireLength(s));
|
|
1083
|
-
}
|
|
1360
|
+
// 唯一 edge 弧长之和(与 occt 适配器同口径,D5)。
|
|
1361
|
+
// 旧实现用 `try { getEdgeCurveType } catch { wireLength }` 判别入参差异,但
|
|
1362
|
+
// getEdgeCurveType 对 solid / face / wire **也不抛错**,于是统一走 edgeLength,
|
|
1363
|
+
// 返回「首条边」长度——值随构建历史漂移(盒 20 vs 10;两边的 wire 真长 15 却给 20),
|
|
1364
|
+
// 且与 occt 的 Σ 面周长(280)不同口径。改为按 topo 去重枚举边后求和。
|
|
1365
|
+
let total = 0;
|
|
1366
|
+
for (const e of api.getSubShapes(shape, 'edge'))
|
|
1367
|
+
total += api.curveLength(e);
|
|
1368
|
+
return total;
|
|
1084
1369
|
},
|
|
1085
1370
|
// ── 校验与修复 ──
|
|
1086
1371
|
// ⚠️ brepkit 的修复类内核函数全部是「**原地修改入参实体 + 返回修复计数**」,不是返回新句柄:
|
|
@@ -1111,12 +1396,12 @@ export async function createBrepkitPrimitives() {
|
|
|
1111
1396
|
return asHandle(c);
|
|
1112
1397
|
},
|
|
1113
1398
|
fixFaceOrientations(shape) {
|
|
1114
|
-
const c = kernel.copySolid(asNum(shape));
|
|
1399
|
+
const c = markSolid(kernel.copySolid(asNum(shape)));
|
|
1115
1400
|
kernel.fixFaceOrientations(c);
|
|
1116
1401
|
return asHandle(c);
|
|
1117
1402
|
},
|
|
1118
1403
|
removeDegenerateEdges(shape, tolerance) {
|
|
1119
|
-
const c = kernel.copySolid(asNum(shape));
|
|
1404
|
+
const c = markSolid(kernel.copySolid(asNum(shape)));
|
|
1120
1405
|
kernel.removeDegenerateEdges(c, tolerance ?? 1e-6);
|
|
1121
1406
|
return asHandle(c);
|
|
1122
1407
|
},
|
|
@@ -1128,7 +1413,10 @@ export async function createBrepkitPrimitives() {
|
|
|
1128
1413
|
const solids = arr(kernel.importStep(bytes));
|
|
1129
1414
|
if (solids.length === 0)
|
|
1130
1415
|
fail('importStep: kernel returned no solid');
|
|
1131
|
-
|
|
1416
|
+
const c = solids.length === 1 ? solids[0] : kernel.makeCompound(Uint32Array.from(solids));
|
|
1417
|
+
if (solids.length > 1)
|
|
1418
|
+
knownCompounds.set(c, solids);
|
|
1419
|
+
return asHandle(markSolid(c));
|
|
1132
1420
|
},
|
|
1133
1421
|
exportStep(shape) {
|
|
1134
1422
|
// brepkit exportStep 返回 UTF-8 字节(Uint8Array),需解码为 STEP 文本(2026-09-19 实测)
|
|
@@ -1137,14 +1425,39 @@ export async function createBrepkitPrimitives() {
|
|
|
1137
1425
|
},
|
|
1138
1426
|
importStl(data) {
|
|
1139
1427
|
const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data);
|
|
1140
|
-
return asHandle(kernel.importStl(bytes));
|
|
1428
|
+
return asHandle(markSolid(kernel.importStl(bytes)));
|
|
1141
1429
|
},
|
|
1142
1430
|
fromBREP(data) {
|
|
1143
1431
|
// ⚠️ brepkit fromBREP 吃字符串(STEP 文本或 toBREP/toBrepJson 输出,内核自动判别),
|
|
1144
1432
|
// 与 serializeSolid/deserializeSolid 的**二进制 arena** 是两套机制。
|
|
1145
1433
|
// 旧实现误用 `deserializeSolid(atob(data))`:base64 解码破坏了 STEP 文本 → 往返必失败
|
|
1146
1434
|
// (2026-09-25 实证:fromBREP(STEP)、fromBREP(toBREP)、fromBREP(toBrepJson) 均成功)。
|
|
1147
|
-
return asHandle(kernel.fromBREP(data));
|
|
1435
|
+
return asHandle(markSolid(kernel.fromBREP(data)));
|
|
1436
|
+
},
|
|
1437
|
+
// ── 网格实体原语(方案 2026-10-01 §3.3;内核私有,不在 L1 契约面) ──
|
|
1438
|
+
// 规范构造顺序**不可交换**:importMesh → weld → unify。
|
|
1439
|
+
// 实测(brepkit-kernel/mesh-solid-topology.test.ts):先 unify 后 weld 会把实体做坏
|
|
1440
|
+
// (体积归零、validate 非 0)。本对象只暴露原语,顺序由 `normalizeMeshSolid` 驱动。
|
|
1441
|
+
meshSolid: {
|
|
1442
|
+
importMesh(positions, indices) {
|
|
1443
|
+
// 方言:importIndexedMesh 吃 **Float64Array**(坐标)+ **Uint32Array**(索引),
|
|
1444
|
+
// 返回裸 solid 号。逐三角形建面、顶点按坐标焊接、边不共享(不是真流形)。
|
|
1445
|
+
const coords = new Float64Array(positions.length);
|
|
1446
|
+
for (let i = 0; i < positions.length; i++)
|
|
1447
|
+
coords[i] = positions[i];
|
|
1448
|
+
return asHandle(markSolid(kernel.importIndexedMesh(coords, indices)));
|
|
1449
|
+
},
|
|
1450
|
+
weld(faces, tolerance) {
|
|
1451
|
+
// weldShellsAndFaces 吃**裸面号数组**(Uint32Array),返回新 solid 号;
|
|
1452
|
+
// 把重复边缝成共享边 → 真流形(实测 10mm 立方体 36 边 → 18 边、validate 0)。
|
|
1453
|
+
return asHandle(markSolid(kernel.weldShellsAndFaces(Uint32Array.from(faces.map((f) => asNum(f))), tolerance)));
|
|
1454
|
+
},
|
|
1455
|
+
unify(solid) {
|
|
1456
|
+
// GOTCHA:unifyFaces 是**原地修改**入参实体,返回值是**被合并掉的面数**
|
|
1457
|
+
// (不是新句柄)。写成 `const s = unify(...)` 会拿到一个落在合法句柄区间的
|
|
1458
|
+
// 数字,后续全部查询打在一个无关实体上且不报错。
|
|
1459
|
+
return Number(kernel.unifyFaces(asNum(solid)));
|
|
1460
|
+
},
|
|
1148
1461
|
},
|
|
1149
1462
|
// ── 面演化(L1 三员 + filletWithHistory,双方都有对齐实现) ──
|
|
1150
1463
|
cutWithHistory(a, b, inputFaceHashes, hashUpperBound) {
|
|
@@ -1160,6 +1473,8 @@ export async function createBrepkitPrimitives() {
|
|
|
1160
1473
|
return mapEvolution(kernel, raw, JSON.parse(raw).solid, inputFaceHashes, hashUpperBound);
|
|
1161
1474
|
},
|
|
1162
1475
|
};
|
|
1476
|
+
memoizedKernel = kernel;
|
|
1477
|
+
memoizedPrimitives = api;
|
|
1163
1478
|
return api;
|
|
1164
1479
|
}
|
|
1165
1480
|
// ── 工具 ──
|
|
@@ -1204,6 +1519,9 @@ function vec3Of(p) {
|
|
|
1204
1519
|
}
|
|
1205
1520
|
/** 已初始化的 brepkit 内核单例(createBrepkitPrimitives 时赋值)。 */
|
|
1206
1521
|
let liveKernel = null;
|
|
1522
|
+
/** 已构建的 L1 契约面对象(按内核实例 memo;见 createBrepkitPrimitives 的 GOTCHA)。 */
|
|
1523
|
+
let memoizedPrimitives = null;
|
|
1524
|
+
let memoizedKernel = null;
|
|
1207
1525
|
/**
|
|
1208
1526
|
* 原生 brepkit 内核面(D3):平台特定代码访问 brepkit 独有能力的唯一入口
|
|
1209
1527
|
* (chamfer2d/chamferV2/filletV2/sketch* 族、serializeSolid、meshBoolean 等)。
|
|
@@ -1219,7 +1537,14 @@ export function getBrepkitKernel() {
|
|
|
1219
1537
|
}
|
|
1220
1538
|
return liveKernel;
|
|
1221
1539
|
}
|
|
1222
|
-
/**
|
|
1540
|
+
/**
|
|
1541
|
+
* 释放内核单例(测试收尾用;宿主常驻不需调用)。
|
|
1542
|
+
*
|
|
1543
|
+
* GOTCHA(2026-10-01 修复):旧实现只 `free()` 内核、**不重置** brepkitWasm.ts 里
|
|
1544
|
+
* 缓存的 `initPromise`,也不丢 memo 化的原语对象 → 第二次 `createBrepkitPrimitives()`
|
|
1545
|
+
* 拿到**已释放**的内核,随后一切内核调用报 `null pointer passed to rust`
|
|
1546
|
+
* (实测:`BrepKernel.makeBox`)。现在三样一起清:内核、initPromise、memo 原语。
|
|
1547
|
+
*/
|
|
1223
1548
|
export function disposeBrepkit() {
|
|
1224
1549
|
try {
|
|
1225
1550
|
if (liveKernel?.free)
|
|
@@ -1227,5 +1552,8 @@ export function disposeBrepkit() {
|
|
|
1227
1552
|
}
|
|
1228
1553
|
catch { /* 已释放 */ }
|
|
1229
1554
|
liveKernel = null;
|
|
1555
|
+
memoizedPrimitives = null;
|
|
1556
|
+
memoizedKernel = null;
|
|
1557
|
+
resetBrepkitWasm();
|
|
1230
1558
|
}
|
|
1231
1559
|
//# sourceMappingURL=brepkitKernel.js.map
|