@faicad/faijs 0.22.2 → 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/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/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.js +2 -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 +1 -1
- package/dist/api/primitives.js +2 -2
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/profile.d.ts +39 -12
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +4 -4
- package/dist/api/profile.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 +7 -5
- package/dist/api/sketch-on-plane.d.ts.map +1 -1
- package/dist/api/sketch-on-plane.js +6 -7
- 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/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 +5 -1
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +62 -11
- 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/brep/brep-ops.d.ts +9 -7
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +23 -24
- 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 +6 -5
- 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.map +1 -1
- package/dist/brep/export/export-model.js +6 -5
- package/dist/brep/export/export-model.js.map +1 -1
- 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/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 +449 -123
- 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 +15 -3
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +33 -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 +42 -7
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +68 -5
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +15 -1
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +10 -1
- package/dist/define-op.js.map +1 -1
- package/dist/env-agnostic.d.ts +2 -2
- package/dist/env-agnostic.d.ts.map +1 -1
- package/dist/env-agnostic.js +1 -1
- 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 +65 -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/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 +1 -1
- package/dist/lang/code-to-args.js +1 -1
- package/dist/lang/code-to-args.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 +7 -0
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +14 -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 +42 -7
- package/dist/mesh/threemf-loader.d.ts.map +1 -1
- package/dist/mesh/threemf-loader.js +565 -100
- package/dist/mesh/threemf-loader.js.map +1 -1
- 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/node-host/cli.d.ts +44 -6
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +76 -26
- 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 +18 -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 +4 -5
- 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 +85 -9
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +72 -2
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdk.d.ts +3 -3
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +5 -5
- 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/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/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 +18 -2
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* threemf-loader — headless 3MF (ZIP/OPC) geometry loader.
|
|
3
3
|
*
|
|
4
4
|
* 3MF is a ZIP container whose geometry lives in `3D/3dmodel.model`, an XML
|
|
5
|
-
* document. Design
|
|
5
|
+
* document. Design requirements (unit-system §2.4/§5): the unit MUST be read
|
|
6
6
|
* from the real (inflated) XML, NOT from the raw bytes — `3D/3dmodel.model` is
|
|
7
7
|
* deflate-compressed inside the ZIP, so scanning the raw buffer cannot find
|
|
8
8
|
* `<model unit="…">` (the 3d_editor precedent returned 'millimeter' for real
|
|
@@ -17,11 +17,15 @@
|
|
|
17
17
|
* x' = a*x + d*y + g*z + p
|
|
18
18
|
* y' = b*x + e*y + h*z + q
|
|
19
19
|
* z' = c*x + f*y + i*z + r
|
|
20
|
-
* so object-local mesh coords bake into world-space positions
|
|
21
|
-
*
|
|
20
|
+
* so object-local mesh coords bake into world-space positions.
|
|
21
|
+
*
|
|
22
|
+
* Return: an `ThreemfArchive` — per-instance objects (one per `<build><item>`,
|
|
23
|
+
* transform baked, or per-`<resources>` object when `<build>` has no items at
|
|
24
|
+
* all), plus every non-model archive entry surfaced as `extraEntries` so the
|
|
25
|
+
* host can reach Bambu's private `model_settings.config` / thumbnails through
|
|
26
|
+
* the *same unzipped map* (single unzip, two consumer chains).
|
|
22
27
|
*/
|
|
23
|
-
import {
|
|
24
|
-
import { parseXmlDocument } from '../api/xml-dom.js';
|
|
28
|
+
import { readZipEntries } from '../io/zip.js';
|
|
25
29
|
import { UNIT_SCALE } from '../units.js';
|
|
26
30
|
/** Map a 3MF unit string to a faijs length unit name. */
|
|
27
31
|
function threemfUnitToFaijs(unit) {
|
|
@@ -35,129 +39,590 @@ function threemfUnitToFaijs(unit) {
|
|
|
35
39
|
default: return null;
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
|
-
/**
|
|
39
|
-
function
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
42
|
-
return
|
|
43
|
-
|
|
44
|
-
// Default per 3MF spec is millimeter.
|
|
45
|
-
return 'millimeter';
|
|
42
|
+
/** `#RRGGBB` → sRGB components in 0..1 (leading `#` required, alpha ignored). */
|
|
43
|
+
function hexToRgb(hex) {
|
|
44
|
+
const m = /^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})/.exec(hex);
|
|
45
|
+
if (!m)
|
|
46
|
+
return null;
|
|
47
|
+
return [parseInt(m[1], 16) / 255, parseInt(m[2], 16) / 255, parseInt(m[3], 16) / 255];
|
|
46
48
|
}
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
/** Bake a column-major ST_Matrix3D (translation = last three tokens) into positions. */
|
|
50
|
+
function bakeTransform(positions, m) {
|
|
51
|
+
const [a, b, c, d, e, f, g, h, iz, p, q, r] = m;
|
|
52
|
+
const out = new Float32Array(positions.length);
|
|
53
|
+
for (let v = 0; v < positions.length; v += 3) {
|
|
54
|
+
const x = positions[v];
|
|
55
|
+
const y = positions[v + 1];
|
|
56
|
+
const z = positions[v + 2];
|
|
57
|
+
out[v] = a * x + d * y + g * z + p;
|
|
58
|
+
out[v + 1] = b * x + e * y + h * z + q;
|
|
59
|
+
out[v + 2] = c * x + f * y + iz * z + r;
|
|
54
60
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
return out;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Compose two ST_Matrix3D column-major transforms (12 tokens each, same
|
|
65
|
+
* layout as `bakeTransform`: `[a b c, d e f, g h i, p q r]`, translation last).
|
|
66
|
+
*
|
|
67
|
+
* Semantics: the child transform is applied first, then the parent —
|
|
68
|
+
* `M = parent · child` (the child lives in the parent's space, exactly like
|
|
69
|
+
* three.js `clone.applyMatrix4(parent).applyMatrix4(child)`).
|
|
70
|
+
*/
|
|
71
|
+
function composeTransform(parent, child) {
|
|
72
|
+
const [a1, b1, c1, d1, e1, f1, g1, h1, i1, p1, q1, r1] = parent;
|
|
73
|
+
const [a2, b2, c2, d2, e2, f2, g2, h2, i2, p2, q2, r2] = child;
|
|
74
|
+
return [
|
|
75
|
+
a1 * a2 + d1 * b2 + g1 * c2,
|
|
76
|
+
b1 * a2 + e1 * b2 + h1 * c2,
|
|
77
|
+
c1 * a2 + f1 * b2 + i1 * c2,
|
|
78
|
+
a1 * d2 + d1 * e2 + g1 * f2,
|
|
79
|
+
b1 * d2 + e1 * e2 + h1 * f2,
|
|
80
|
+
c1 * d2 + f1 * e2 + i1 * f2,
|
|
81
|
+
a1 * g2 + d1 * h2 + g1 * i2,
|
|
82
|
+
b1 * g2 + e1 * h2 + h1 * i2,
|
|
83
|
+
c1 * g2 + f1 * h2 + i1 * i2,
|
|
84
|
+
a1 * p2 + d1 * q2 + g1 * r2 + p1,
|
|
85
|
+
b1 * p2 + e1 * q2 + h1 * r2 + q1,
|
|
86
|
+
c1 * p2 + f1 * q2 + i1 * r2 + r1,
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Parse an ST_Matrix3D attribute (12 or 16 tokens with trailing "0 0 0 1").
|
|
91
|
+
* Returns the first 12 tokens when valid, `null` when malformed (caller
|
|
92
|
+
* ignores the transform instead of baking NaN — mirrors the host tolerance
|
|
93
|
+
* contract).
|
|
94
|
+
*/
|
|
95
|
+
function parseTransformAttr(raw) {
|
|
96
|
+
if (!raw)
|
|
97
|
+
return null;
|
|
98
|
+
const t = raw.trim().split(/\s+/).map(Number);
|
|
99
|
+
const valid = t.length === 12 ||
|
|
100
|
+
(t.length === 16 && t[12] === 0 && t[13] === 0 && t[14] === 0 && t[15] === 1);
|
|
101
|
+
if (!valid || !t.every((n) => Number.isFinite(n)))
|
|
102
|
+
return null;
|
|
103
|
+
return t.length === 12 ? t : t.slice(0, 12);
|
|
104
|
+
}
|
|
105
|
+
/** Detect triangle-level material attributes (fast-3mf port). */
|
|
106
|
+
const TRI_MATERIAL_ATTR_RE = /(?:^|\s)(?:p1|p2|p3|pid)="/;
|
|
107
|
+
/**
|
|
108
|
+
* Loose vertex re-parse: extracts x/y/z independently, tolerating attribute
|
|
109
|
+
* reordering or newlines inside a vertex tag. Slow path — only used when the
|
|
110
|
+
* strict regex scan reports a count mismatch (fast-3mf port).
|
|
111
|
+
*/
|
|
112
|
+
function parseVerticesLoose(vertSec) {
|
|
113
|
+
const vRe = /<vertex\s+([^>]*?)\/?>/g;
|
|
114
|
+
const positions = [];
|
|
115
|
+
let vm;
|
|
116
|
+
while ((vm = vRe.exec(vertSec)) !== null) {
|
|
117
|
+
const a = vm[1];
|
|
118
|
+
const x = /(?:^|\s)x="(-?[\d.eE+-]+)"/.exec(a)?.[1];
|
|
119
|
+
const y = /(?:^|\s)y="(-?[\d.eE+-]+)"/.exec(a)?.[1];
|
|
120
|
+
const z = /(?:^|\s)z="(-?[\d.eE+-]+)"/.exec(a)?.[1];
|
|
121
|
+
if (x === undefined || y === undefined || z === undefined)
|
|
122
|
+
return null;
|
|
123
|
+
positions.push(+x, +y, +z);
|
|
124
|
+
}
|
|
125
|
+
return new Float32Array(positions);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Loose triangle re-parse: extracts v1/v2/v3 (and pid/p1/p2/p3 when needed)
|
|
129
|
+
* per attribute, tolerating attribute reordering (fast-3mf port). Slow path —
|
|
130
|
+
* only used when the strict regex scan reports a count mismatch.
|
|
131
|
+
*/
|
|
132
|
+
function parseTrianglesLoose(triSec, withProps) {
|
|
133
|
+
const tFullRe = /<triangle\s+([^>]*?)\/?>/g;
|
|
134
|
+
const idx = [];
|
|
135
|
+
const props = [];
|
|
136
|
+
let tm;
|
|
137
|
+
while ((tm = tFullRe.exec(triSec)) !== null) {
|
|
138
|
+
const a = tm[1];
|
|
139
|
+
const v1 = /(?:^|\s)v1="(\d+)"/.exec(a)?.[1];
|
|
140
|
+
const v2 = /(?:^|\s)v2="(\d+)"/.exec(a)?.[1];
|
|
141
|
+
const v3 = /(?:^|\s)v3="(\d+)"/.exec(a)?.[1];
|
|
142
|
+
if (v1 === undefined || v2 === undefined || v3 === undefined)
|
|
143
|
+
return null;
|
|
144
|
+
idx.push(+v1, +v2, +v3);
|
|
145
|
+
if (withProps) {
|
|
146
|
+
const p = {};
|
|
147
|
+
const pid = /(?:^|\s)pid="([^"]*)"/.exec(a)?.[1];
|
|
148
|
+
if (pid !== undefined)
|
|
149
|
+
p.pid = pid;
|
|
150
|
+
const p1 = /(?:^|\s)p1="([^"]*)"/.exec(a)?.[1];
|
|
151
|
+
if (p1 !== undefined)
|
|
152
|
+
p.p1 = +p1;
|
|
153
|
+
const p2 = /(?:^|\s)p2="([^"]*)"/.exec(a)?.[1];
|
|
154
|
+
if (p2 !== undefined)
|
|
155
|
+
p.p2 = +p2;
|
|
156
|
+
const p3 = /(?:^|\s)p3="([^"]*)"/.exec(a)?.[1];
|
|
157
|
+
if (p3 !== undefined)
|
|
158
|
+
p.p3 = +p3;
|
|
159
|
+
props.push(p);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { index: new Uint32Array(idx), props: withProps ? props : null };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Stream-scan one model XML document for `<resources>` material libraries and
|
|
166
|
+
* `<object>` entries, merging into the shared maps (caller keeps sub-models
|
|
167
|
+
* first / root last so the root wins id collisions).
|
|
168
|
+
*
|
|
169
|
+
* Text-scanner (no DOM) — ported from the host's retired fast-3mf parser, so
|
|
170
|
+
* very large model documents (Bambu exports reach ~140 MB of XML, where a full
|
|
171
|
+
* DOM parse exhausts the heap) stay linear in memory. Attribute extraction
|
|
172
|
+
* keeps fast-3mf's tolerance: attribute reordering / newline variance falls
|
|
173
|
+
* back to a loose re-parse; namespace-prefixed attributes (`p:objectid`,
|
|
174
|
+
* `p:transform`) match through substring.
|
|
175
|
+
*/
|
|
176
|
+
function scanResources(xml, scale, basematerialsById, colorgroupsById, byObjectId) {
|
|
177
|
+
const resourcesStart = xml.indexOf('<resources>');
|
|
178
|
+
if (resourcesStart < 0)
|
|
179
|
+
return;
|
|
180
|
+
const resourcesEnd = xml.indexOf('</resources>', resourcesStart);
|
|
181
|
+
const resBody = resourcesEnd >= 0
|
|
182
|
+
? xml.slice(resourcesStart, resourcesEnd)
|
|
183
|
+
: xml.slice(resourcesStart);
|
|
184
|
+
// basematerials: id + base list (name/displaycolor).
|
|
185
|
+
const bmRe = /<basematerials\s+([^>]*)>([\s\S]*?)<\/basematerials>/g;
|
|
186
|
+
let m;
|
|
187
|
+
while ((m = bmRe.exec(resBody)) !== null) {
|
|
188
|
+
const id = /(?:^|\s)id="([^"]+)"/.exec(m[1])?.[1];
|
|
189
|
+
if (id === undefined)
|
|
190
|
+
continue;
|
|
191
|
+
const bases = [];
|
|
192
|
+
const baseRe = /<base\s+([^>]*?)\/?>/g;
|
|
193
|
+
let bm2;
|
|
194
|
+
while ((bm2 = baseRe.exec(m[2])) !== null) {
|
|
195
|
+
bases.push({
|
|
196
|
+
name: /(?:^|\s)name="([^"]*)"/.exec(bm2[1])?.[1],
|
|
197
|
+
displaycolor: /(?:^|\s)displaycolor="([^"]*)"/.exec(bm2[1])?.[1],
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
basematerialsById.set(id, bases);
|
|
201
|
+
}
|
|
202
|
+
// colorgroup: id + color list (hex → sRGB components).
|
|
203
|
+
const cgRe = /<colorgroup\s+([^>]*)>([\s\S]*?)<\/colorgroup>/g;
|
|
204
|
+
while ((m = cgRe.exec(resBody)) !== null) {
|
|
205
|
+
const id = /(?:^|\s)id="([^"]+)"/.exec(m[1])?.[1];
|
|
206
|
+
if (id === undefined)
|
|
207
|
+
continue;
|
|
208
|
+
const colors = [];
|
|
209
|
+
const colorRe = /<color\s+([^>]*?)\/?>/g;
|
|
210
|
+
let cm;
|
|
211
|
+
while ((cm = colorRe.exec(m[2])) !== null) {
|
|
212
|
+
const hex = /(?:^|\s)color="([^"]*)"/.exec(cm[1])?.[1]?.slice(0, 7) ?? '#000000';
|
|
213
|
+
const rgb = hexToRgb(hex) ?? [0, 0, 0];
|
|
214
|
+
colors.push(rgb[0], rgb[1], rgb[2]);
|
|
215
|
+
}
|
|
216
|
+
colorgroupsById.set(id, new Float32Array(colors));
|
|
217
|
+
}
|
|
218
|
+
// objects — scanned across the whole document (not just `<resources>`) so
|
|
219
|
+
// out-of-resources `<object>` placements still load (external-data tolerance).
|
|
220
|
+
const objRe = /<object\s+([^>]*)>([\s\S]*?)<\/object>/g;
|
|
221
|
+
while ((m = objRe.exec(xml)) !== null) {
|
|
222
|
+
const attrs = m[1];
|
|
223
|
+
const body = m[2];
|
|
224
|
+
const idRaw = /(?:^|\s)id="([^"]+)"/.exec(attrs)?.[1];
|
|
225
|
+
if (idRaw === undefined)
|
|
64
226
|
continue;
|
|
65
|
-
const
|
|
66
|
-
if (!
|
|
227
|
+
const id = Number(idRaw);
|
|
228
|
+
if (!Number.isInteger(id))
|
|
67
229
|
continue;
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
230
|
+
const name = /(?:^|\s)name="([^"]*)"/.exec(attrs)?.[1];
|
|
231
|
+
const objPid = /(?:^|\s)pid="([^"]*)"/.exec(attrs)?.[1];
|
|
232
|
+
const objPindexRaw = /(?:^|\s)pindex="([^"]*)"/.exec(attrs)?.[1];
|
|
233
|
+
const objPindex = objPindexRaw !== undefined && objPindexRaw !== '' ? Number(objPindexRaw) : undefined;
|
|
234
|
+
let meta = { id, name, pid: objPid, pindex: objPindex };
|
|
235
|
+
// mesh: vertices + triangles (fast-3mf port — strict regex scan with a
|
|
236
|
+
// loose attribute-order fallback; missing sub-sections are tolerated and
|
|
237
|
+
// the object still registers, matching the retired host behavior).
|
|
238
|
+
const meshStart = body.indexOf('<mesh>');
|
|
239
|
+
const meshEnd = body.indexOf('</mesh>');
|
|
240
|
+
if (meshStart >= 0 && meshEnd > meshStart) {
|
|
241
|
+
const meshBody = body.slice(meshStart, meshEnd);
|
|
242
|
+
// vertices
|
|
243
|
+
const vertStart = meshBody.indexOf('<vertices>');
|
|
244
|
+
const vertEnd = meshBody.indexOf('</vertices>');
|
|
245
|
+
if (vertStart >= 0 && vertEnd > vertStart) {
|
|
246
|
+
const vertSec = meshBody.slice(vertStart, vertEnd);
|
|
247
|
+
let vc = 0;
|
|
248
|
+
let p = 0;
|
|
249
|
+
while ((p = vertSec.indexOf('<vertex ', p)) !== -1) {
|
|
250
|
+
vc++;
|
|
251
|
+
p += 8;
|
|
252
|
+
}
|
|
253
|
+
const vRe = /x="(-?[\d.eE+-]+)"\s+y="(-?[\d.eE+-]+)"\s+z="(-?[\d.eE+-]+)"/g;
|
|
254
|
+
let positions = new Float32Array(vc * 3);
|
|
255
|
+
let vm;
|
|
256
|
+
let vi = 0;
|
|
257
|
+
while ((vm = vRe.exec(vertSec)) !== null) {
|
|
258
|
+
positions[vi] = +vm[1] * scale;
|
|
259
|
+
positions[vi + 1] = +vm[2] * scale;
|
|
260
|
+
positions[vi + 2] = +vm[3] * scale;
|
|
261
|
+
vi += 3;
|
|
262
|
+
}
|
|
263
|
+
// XML attributes are unordered (spec XSD) — if any vertex failed to
|
|
264
|
+
// match (different attribute order / newline after tag), re-scan each
|
|
265
|
+
// attribute independently instead of giving up.
|
|
266
|
+
if (vc > 0 && vi !== vc * 3) {
|
|
267
|
+
const loose = parseVerticesLoose(vertSec);
|
|
268
|
+
if (!loose) {
|
|
269
|
+
throw new Error(`[mesh/threemf] cannot parse <vertices> in object ${id}`);
|
|
270
|
+
}
|
|
271
|
+
positions = new Float32Array(loose.length);
|
|
272
|
+
for (let i = 0; i < loose.length; i++)
|
|
273
|
+
positions[i] = loose[i] * scale;
|
|
274
|
+
}
|
|
275
|
+
meta = { ...meta, positions };
|
|
276
|
+
}
|
|
277
|
+
// triangles
|
|
278
|
+
const triStart = meshBody.indexOf('<triangles>');
|
|
279
|
+
const triEnd = meshBody.indexOf('</triangles>');
|
|
280
|
+
if (triStart >= 0 && triEnd > triStart) {
|
|
281
|
+
const triSec = meshBody.slice(triStart, triEnd);
|
|
282
|
+
let tc = 0;
|
|
283
|
+
let p = 0;
|
|
284
|
+
while ((p = triSec.indexOf('<triangle ', p)) !== -1) {
|
|
285
|
+
tc++;
|
|
286
|
+
p += 10;
|
|
287
|
+
}
|
|
288
|
+
const idx = new Uint32Array(tc * 3);
|
|
289
|
+
const hasMatAttrs = TRI_MATERIAL_ATTR_RE.test(triSec);
|
|
290
|
+
// Object-level pid without per-triangle material attrs: synthesize
|
|
291
|
+
// triangle properties so every triangle still routes through the
|
|
292
|
+
// resource (object pindex default) — fast-3mf semantics.
|
|
293
|
+
const needsProps = hasMatAttrs || objPid !== undefined;
|
|
294
|
+
const triProps = needsProps ? [] : undefined;
|
|
295
|
+
const tRe = /v1="(\d+)"\s+v2="(\d+)"\s+v3="(\d+)"/g;
|
|
296
|
+
let tm;
|
|
297
|
+
let ti = 0;
|
|
298
|
+
while ((tm = tRe.exec(triSec)) !== null) {
|
|
299
|
+
idx[ti] = +tm[1];
|
|
300
|
+
idx[ti + 1] = +tm[2];
|
|
301
|
+
idx[ti + 2] = +tm[3];
|
|
302
|
+
ti += 3;
|
|
303
|
+
}
|
|
304
|
+
if (tc > 0 && ti !== tc * 3) {
|
|
305
|
+
// Attribute order / newline variance → re-scan each attribute
|
|
306
|
+
// independently (slow path, rare).
|
|
307
|
+
const loose = parseTrianglesLoose(triSec, needsProps);
|
|
308
|
+
if (!loose) {
|
|
309
|
+
throw new Error(`[mesh/threemf] cannot parse <triangles> in object ${id}`);
|
|
310
|
+
}
|
|
311
|
+
idx.set(loose.index);
|
|
312
|
+
if (loose.props) {
|
|
313
|
+
triProps.length = 0;
|
|
314
|
+
triProps.push(...loose.props);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
else if (needsProps) {
|
|
318
|
+
if (hasMatAttrs) {
|
|
319
|
+
const tFullRe = /<triangle\s+([^>]*?)\/?>/g;
|
|
320
|
+
let tfm;
|
|
321
|
+
while ((tfm = tFullRe.exec(triSec)) !== null) {
|
|
322
|
+
const a = tfm[1];
|
|
323
|
+
const tv = /v1="(\d+)"\s+v2="(\d+)"\s+v3="(\d+)"/.exec(a);
|
|
324
|
+
if (!tv)
|
|
325
|
+
continue;
|
|
326
|
+
const prop = {};
|
|
327
|
+
const p1 = /\bp1="([^"]*)"/.exec(a)?.[1];
|
|
328
|
+
if (p1 !== undefined)
|
|
329
|
+
prop.p1 = +p1;
|
|
330
|
+
const p2 = /\bp2="([^"]*)"/.exec(a)?.[1];
|
|
331
|
+
if (p2 !== undefined)
|
|
332
|
+
prop.p2 = +p2;
|
|
333
|
+
const p3 = /\bp3="([^"]*)"/.exec(a)?.[1];
|
|
334
|
+
if (p3 !== undefined)
|
|
335
|
+
prop.p3 = +p3;
|
|
336
|
+
const pidm = /\bpid="([^"]*)"/.exec(a)?.[1];
|
|
337
|
+
if (pidm !== undefined)
|
|
338
|
+
prop.pid = pidm;
|
|
339
|
+
triProps.push(prop);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
// Object-level pid only → synthesized props (no per-triangle
|
|
344
|
+
// material attrs) so materializeMesh's per-triangle lookups fall
|
|
345
|
+
// through to the object-level defaults.
|
|
346
|
+
for (let i = 0; i < tc; i++)
|
|
347
|
+
triProps.push({});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
meta = { ...meta, indices: idx, triProps };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
// `<components>` children — Bambu builds plates/assemblies this way.
|
|
354
|
+
// A pure component container has no mesh; it still registers in byObjectId
|
|
355
|
+
// so build items referencing it expand recursively (component instances).
|
|
356
|
+
const compStart = body.indexOf('<components>');
|
|
357
|
+
if (compStart >= 0) {
|
|
358
|
+
const compEnd = body.indexOf('</components>', compStart);
|
|
359
|
+
const compSec = compEnd >= 0
|
|
360
|
+
? body.slice(compStart + '<components>'.length, compEnd)
|
|
361
|
+
: body.slice(compStart + '<components>'.length);
|
|
362
|
+
const comps = [];
|
|
363
|
+
const compRe = /<component\s+([^>]*?)\/?>/g;
|
|
364
|
+
let cpm;
|
|
365
|
+
while ((cpm = compRe.exec(compSec)) !== null) {
|
|
366
|
+
const oid = Number(/objectid="([^"]+)"/.exec(cpm[1])?.[1]);
|
|
367
|
+
if (!Number.isInteger(oid))
|
|
368
|
+
continue;
|
|
369
|
+
comps.push({
|
|
370
|
+
objectId: oid,
|
|
371
|
+
transform: parseTransformAttr(/\btransform="([^"]*)"/.exec(cpm[1])?.[1] ?? null),
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
if (comps.length > 0)
|
|
375
|
+
meta = { ...meta, components: comps };
|
|
376
|
+
}
|
|
377
|
+
if (!meta.positions && !meta.components)
|
|
71
378
|
continue;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
379
|
+
byObjectId.set(id, meta);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Parse the 3MF model XML documents (root + sub-models) into archive objects.
|
|
384
|
+
*
|
|
385
|
+
* Bambu exports are multi-file: `3D/3dmodel.model` holds only thin `<object>`
|
|
386
|
+
* skeletons (component containers) plus the `<build>`, while the actual mesh
|
|
387
|
+
* geometry lives in per-object files `3D/Objects/object_*.model` referenced
|
|
388
|
+
* through `p:path` (production extension) — which we ignore in favor of
|
|
389
|
+
* merging every model document's `<resources>` by object id (mirrors the
|
|
390
|
+
* host's fast-3mf collection order: sub-models first, root model last, root
|
|
391
|
+
* wins on id collisions).
|
|
392
|
+
*
|
|
393
|
+
* `unit` is read from the ROOT model document (the file the build items
|
|
394
|
+
* belong to); all documents share the same declared unit in practice.
|
|
395
|
+
*/
|
|
396
|
+
function parseModelXml(docTexts) {
|
|
397
|
+
// Last document = root model (caller appends it last).
|
|
398
|
+
const rootDoc = docTexts[docTexts.length - 1];
|
|
399
|
+
const unitMatch = /<model\b[^>]*\bunit="([^"]+)"/.exec(rootDoc);
|
|
400
|
+
const unit = unitMatch ? unitMatch[1] : 'millimeter';
|
|
401
|
+
const unitName = threemfUnitToFaijs(unit);
|
|
402
|
+
if (unitName === null) {
|
|
403
|
+
throw new Error(`[mesh/threemf] unsupported <model unit>: ${JSON.stringify(unit)}`);
|
|
404
|
+
}
|
|
405
|
+
const scale = UNIT_SCALE[unitName];
|
|
406
|
+
// resources → material libraries (basematerials / colorgroup) + objects,
|
|
407
|
+
// merged across every model document (sub-models first, root last).
|
|
408
|
+
const basematerialsById = new Map();
|
|
409
|
+
const colorgroupsById = new Map();
|
|
410
|
+
const byObjectId = new Map();
|
|
411
|
+
for (const text of docTexts) {
|
|
412
|
+
scanResources(text, scale, basematerialsById, colorgroupsById, byObjectId);
|
|
413
|
+
}
|
|
414
|
+
// (scanResources above handles basematerials / colorgroup / objects)
|
|
415
|
+
// (mesh/components + registration handled by scanResources)
|
|
416
|
+
/**
|
|
417
|
+
* Materialize object instances: a mesh object yields ONE ThreemfObject with
|
|
418
|
+
* the transform baked in and base/vertex colors resolved; a component
|
|
419
|
+
* container recursively expands each child (composing transforms, child
|
|
420
|
+
* applied first), one ThreemfObject per leaf mesh instance — mirroring the
|
|
421
|
+
* host's clone-and-apply semantics without shared geometry. `path` guards
|
|
422
|
+
* reference cycles (a self-referencing component chain terminates).
|
|
423
|
+
*/
|
|
424
|
+
function materialize(src, mat, path) {
|
|
425
|
+
if (src.positions && src.indices) {
|
|
426
|
+
return [materializeMesh(src, mat)];
|
|
79
427
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
428
|
+
if (src.components && src.components.length > 0) {
|
|
429
|
+
const out = [];
|
|
430
|
+
for (const comp of src.components) {
|
|
431
|
+
if (path.has(comp.objectId))
|
|
432
|
+
continue;
|
|
433
|
+
const ref = byObjectId.get(comp.objectId);
|
|
434
|
+
if (!ref)
|
|
435
|
+
continue;
|
|
436
|
+
const next = comp.transform
|
|
437
|
+
? (mat ? composeTransform(mat, comp.transform) : comp.transform)
|
|
438
|
+
: mat;
|
|
439
|
+
const nextPath = new Set(path);
|
|
440
|
+
nextPath.add(comp.objectId);
|
|
441
|
+
out.push(...materialize(ref, next, nextPath));
|
|
442
|
+
}
|
|
443
|
+
return out;
|
|
87
444
|
}
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
445
|
+
return [];
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Materialize a single mesh object instance: bake the optional build
|
|
449
|
+
* transform and resolve base/vertex colors. `vertexColors` expands the
|
|
450
|
+
* geometry (each triangle owns 3 independent vertices) so per-triangle
|
|
451
|
+
* p1/p2/p3 survive; `baseColor` keeps the compact form and applies only
|
|
452
|
+
* when every triangle references the same base index (multi-base objects
|
|
453
|
+
* fall back to the default material, matching the host contract).
|
|
454
|
+
*/
|
|
455
|
+
function materializeMesh(src, mat) {
|
|
456
|
+
const positions = src.positions;
|
|
457
|
+
const indices = src.indices;
|
|
458
|
+
let pid;
|
|
459
|
+
if (src.triProps) {
|
|
460
|
+
for (const p of src.triProps) {
|
|
461
|
+
const eff = p.pid ?? src.pid;
|
|
462
|
+
if (eff !== undefined) {
|
|
463
|
+
pid = eff;
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
pid = src.pid;
|
|
470
|
+
}
|
|
471
|
+
const cg = pid !== undefined ? colorgroupsById.get(pid) : undefined;
|
|
472
|
+
if (cg) {
|
|
473
|
+
const triCount = indices.length / 3;
|
|
474
|
+
const outPos = new Float32Array(triCount * 9);
|
|
475
|
+
const outCol = new Float32Array(triCount * 9);
|
|
476
|
+
const outIdx = new Uint32Array(triCount * 3);
|
|
477
|
+
const objectPindex = src.pindex;
|
|
478
|
+
for (let t = 0; t < triCount; t++) {
|
|
479
|
+
const v1 = indices[t * 3];
|
|
480
|
+
const v2 = indices[t * 3 + 1];
|
|
481
|
+
const v3 = indices[t * 3 + 2];
|
|
482
|
+
const tp = src.triProps ? src.triProps[t] : undefined;
|
|
483
|
+
const p1 = tp?.p1 ?? objectPindex ?? 0;
|
|
484
|
+
const p2 = tp?.p2 ?? p1;
|
|
485
|
+
const p3 = tp?.p3 ?? p1;
|
|
486
|
+
// vertex-contiguous layout (x1 y1 z1 x2 y2 z2 x3 y3 z3 / R1 G1 B1 …):
|
|
487
|
+
// each emitted vertex owns 3 consecutive components.
|
|
488
|
+
const vs = [v1, v2, v3];
|
|
489
|
+
const ps = [p1, p2, p3];
|
|
490
|
+
for (let k = 0; k < 3; k++) {
|
|
491
|
+
const sv = vs[k];
|
|
492
|
+
const sp = ps[k];
|
|
493
|
+
outPos[t * 9 + k * 3] = positions[sv * 3];
|
|
494
|
+
outPos[t * 9 + k * 3 + 1] = positions[sv * 3 + 1];
|
|
495
|
+
outPos[t * 9 + k * 3 + 2] = positions[sv * 3 + 2];
|
|
496
|
+
outCol[t * 9 + k * 3] = cg[sp * 3];
|
|
497
|
+
outCol[t * 9 + k * 3 + 1] = cg[sp * 3 + 1];
|
|
498
|
+
outCol[t * 9 + k * 3 + 2] = cg[sp * 3 + 2];
|
|
499
|
+
}
|
|
500
|
+
outIdx[t * 3] = t * 3;
|
|
501
|
+
outIdx[t * 3 + 1] = t * 3 + 1;
|
|
502
|
+
outIdx[t * 3 + 2] = t * 3 + 2;
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
id: src.id,
|
|
506
|
+
name: src.name,
|
|
507
|
+
positions: mat ? bakeTransform(outPos, mat) : outPos,
|
|
508
|
+
indices: outIdx,
|
|
509
|
+
vertexColors: outCol,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
const bases = pid !== undefined ? basematerialsById.get(pid) : undefined;
|
|
513
|
+
if (bases && bases.length > 0) {
|
|
514
|
+
const idx0 = src.triProps ? (src.triProps[0]?.p1 ?? src.pindex ?? 0) : (src.pindex ?? 0);
|
|
515
|
+
let same = true;
|
|
516
|
+
if (src.triProps) {
|
|
517
|
+
for (let t = 1; t < src.triProps.length; t++) {
|
|
518
|
+
if ((src.triProps[t]?.p1 ?? src.pindex ?? 0) !== idx0) {
|
|
519
|
+
same = false;
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const base = bases[idx0];
|
|
525
|
+
const baseColor = same && base?.displaycolor
|
|
526
|
+
? hexToRgb(base.displaycolor.slice(0, 7))
|
|
527
|
+
: undefined;
|
|
528
|
+
return {
|
|
529
|
+
id: src.id,
|
|
530
|
+
name: src.name,
|
|
531
|
+
positions: mat ? bakeTransform(positions, mat) : positions,
|
|
532
|
+
indices,
|
|
533
|
+
baseColor: baseColor ?? undefined,
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
return {
|
|
537
|
+
id: src.id,
|
|
538
|
+
name: src.name,
|
|
539
|
+
positions: mat ? bakeTransform(positions, mat) : positions,
|
|
540
|
+
indices,
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
// build → item → per-instance transforms baked to world space.
|
|
544
|
+
// `<build>` lives in the ROOT model document only.
|
|
545
|
+
const buildMatch = /<build\b[^>]*>/.exec(rootDoc);
|
|
546
|
+
let buildSec = '';
|
|
547
|
+
if (buildMatch) {
|
|
548
|
+
const buildStart = buildMatch.index;
|
|
549
|
+
const buildEnd = rootDoc.indexOf('</build>', buildStart);
|
|
550
|
+
buildSec = buildEnd >= 0 ? rootDoc.slice(buildStart, buildEnd) : rootDoc.slice(buildStart);
|
|
551
|
+
}
|
|
552
|
+
const itemRe = /<item\b[^>]*>/g;
|
|
553
|
+
const out = [];
|
|
554
|
+
let itemCount = 0;
|
|
555
|
+
let im;
|
|
556
|
+
while ((im = itemRe.exec(buildSec)) !== null) {
|
|
557
|
+
itemCount++;
|
|
558
|
+
const attrs = im[0];
|
|
559
|
+
const objId = Number(/(?:^|\s)objectid="([^"]+)"/.exec(attrs)?.[1]);
|
|
98
560
|
const src = byObjectId.get(objId);
|
|
99
561
|
if (!src)
|
|
100
562
|
continue;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
for (let v = 0; v < src.positions.length; v += 3) {
|
|
107
|
-
const x = src.positions[v];
|
|
108
|
-
const y = src.positions[v + 1];
|
|
109
|
-
const z = src.positions[v + 2];
|
|
110
|
-
allPos.push(a * x + d * y + g * z + p, b * x + e * y + h * z + q, c * x + f * y + iz * z + r);
|
|
111
|
-
}
|
|
112
|
-
for (let t = 0; t < src.indices.length; t++) {
|
|
113
|
-
allIdx.push(src.indices[t] + base);
|
|
114
|
-
}
|
|
563
|
+
// ST_Matrix3D: 4×3 (12) or 4×4 (16) whose trailing row is "0 0 0 1";
|
|
564
|
+
// malformed transforms are IGNORED (identity) — never bake NaN into
|
|
565
|
+
// geometry (mirrors the host's fast-3mf tolerance contract).
|
|
566
|
+
const tokens = parseTransformAttr(/\btransform="([^"]*)"/.exec(attrs)?.[1] ?? null);
|
|
567
|
+
out.push(...materialize(src, tokens ?? undefined, new Set([objId])));
|
|
115
568
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
for (const
|
|
120
|
-
|
|
121
|
-
for (let v = 0; v < src.positions.length; v++)
|
|
122
|
-
allPos.push(src.positions[v]);
|
|
123
|
-
for (let t = 0; t < src.indices.length; t++)
|
|
124
|
-
allIdx.push(src.indices[t] + base);
|
|
569
|
+
if (itemCount === 0) {
|
|
570
|
+
// No build items: emit every `<resources>` object directly (¶ the empty
|
|
571
|
+
// `<build>` contract — NOT a fallback; see plan §8 decision 8).
|
|
572
|
+
for (const src of byObjectId.values()) {
|
|
573
|
+
out.push(...materialize(src, undefined, new Set([src.id])));
|
|
125
574
|
}
|
|
126
575
|
}
|
|
127
|
-
if (
|
|
576
|
+
if (out.length === 0) {
|
|
128
577
|
throw new Error('[mesh/threemf] no buildable geometry found in 3dmodel.model');
|
|
129
578
|
}
|
|
130
|
-
return {
|
|
131
|
-
positions: new Float32Array(allPos),
|
|
132
|
-
indices: new Uint32Array(allIdx),
|
|
133
|
-
unit,
|
|
134
|
-
};
|
|
579
|
+
return { unitName, objects: out };
|
|
135
580
|
}
|
|
136
581
|
/**
|
|
137
|
-
* Parse 3MF bytes into a
|
|
582
|
+
* Parse 3MF bytes into a structured archive.
|
|
583
|
+
*
|
|
584
|
+
* Supports Bambu's multi-file layout: `3D/3dmodel.model` (root, holds the
|
|
585
|
+
* `<build>` and component-container skeletons) plus per-object sub-models
|
|
586
|
+
* `3D/Objects/*.model` whose `<resources>` are merged by object id
|
|
587
|
+
* (sub-models first, root last — root wins collisions).
|
|
588
|
+
*
|
|
138
589
|
* @param buffer - the raw .3mf (ZIP) bytes.
|
|
139
|
-
* @returns
|
|
590
|
+
* @returns an `ThreemfArchive` with mm-base per-instance objects, the declared
|
|
591
|
+
* source unit, and every non-model archive entry.
|
|
140
592
|
* @throws when the buffer is not a 3MF/ZIP archive or the unit is invalid.
|
|
141
593
|
*/
|
|
142
594
|
export async function parseThreemf(buffer) {
|
|
143
595
|
let entries;
|
|
144
596
|
try {
|
|
145
|
-
entries =
|
|
597
|
+
entries = readZipEntries(new Uint8Array(buffer));
|
|
146
598
|
}
|
|
147
599
|
catch {
|
|
148
600
|
throw new Error('[mesh/threemf] not a valid 3MF ZIP archive');
|
|
149
601
|
}
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
602
|
+
const rootKey = [...entries.keys()].find((k) => k.toLowerCase() === '3d/3dmodel.model');
|
|
603
|
+
if (!rootKey) {
|
|
152
604
|
throw new Error('[mesh/threemf] missing 3D/3dmodel.model entry');
|
|
153
605
|
}
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
606
|
+
// Sub-model documents first (fast-3mf collection order), root model last.
|
|
607
|
+
const docKeys = [];
|
|
608
|
+
for (const k of entries.keys()) {
|
|
609
|
+
if (k.toLowerCase() === rootKey.toLowerCase())
|
|
610
|
+
continue;
|
|
611
|
+
if (/^3d\/.+\/[^/]+\.model$/i.test(k))
|
|
612
|
+
docKeys.push(k);
|
|
613
|
+
}
|
|
614
|
+
docKeys.push(rootKey);
|
|
615
|
+
const docTexts = docKeys.map((k) => new TextDecoder().decode(entries.get(k)));
|
|
616
|
+
const parsed = parseModelXml(docTexts);
|
|
617
|
+
// `extraEntries` = everything that is NOT a model document — Bambu's
|
|
618
|
+
// `Metadata/model_settings.config`, `Metadata/project_settings.config`,
|
|
619
|
+
// `Metadata/thumbnail.png`, etc.
|
|
620
|
+
const extraEntries = new Map();
|
|
621
|
+
for (const [k, v] of entries) {
|
|
622
|
+
if (/\.model$/i.test(k))
|
|
623
|
+
continue;
|
|
624
|
+
extraEntries.set(k, v);
|
|
625
|
+
}
|
|
626
|
+
return { unit: parsed.unitName, objects: parsed.objects, extraEntries };
|
|
162
627
|
}
|
|
163
628
|
//# sourceMappingURL=threemf-loader.js.map
|