diff --git a/packages/mesh-io/typescript/cypress/e2e/common.ts b/packages/mesh-io/typescript/cypress/e2e/common.ts index b1418d399..ed4107fc0 100644 --- a/packages/mesh-io/typescript/cypress/e2e/common.ts +++ b/packages/mesh-io/typescript/cypress/e2e/common.ts @@ -11,3 +11,10 @@ export function verifyMesh (mesh) { cy.expect(mesh.numberOfPoints).to.equal(2903) cy.expect(mesh.numberOfCells).to.equal(3263) } + +export function verifyPointSet (pointSet) { + cy.expect(pointSet.pointSetType.dimension).to.equal(3) + cy.expect(pointSet.pointSetType.pointComponentType).to.equal(FloatTypes.Float32) + cy.expect(pointSet.pointSetType.pointPixelType).to.equal(PixelTypes.Vector) + cy.expect(pointSet.numberOfPoints).to.equal(8) +} diff --git a/packages/mesh-io/typescript/cypress/e2e/read-point-set.cy.ts b/packages/mesh-io/typescript/cypress/e2e/read-point-set.cy.ts new file mode 100644 index 000000000..b26a5b338 --- /dev/null +++ b/packages/mesh-io/typescript/cypress/e2e/read-point-set.cy.ts @@ -0,0 +1,90 @@ +import { demoServer, verifyPointSet } from "./common.ts"; + +describe("read-point-set", () => { + beforeEach(function () { + cy.visit(demoServer); + + const testPathPrefix = "../test/data/input/"; + + const testImageFiles = ["box-points.obj"]; + testImageFiles.forEach((fileName) => { + cy.readFile(`${testPathPrefix}${fileName}`, null).as(fileName); + }); + }); + + it("Reads an point set File in the demo", function () { + cy.get('sl-tab[panel="readPointSet-panel"]').click(); + + const testFile = { + contents: new Uint8Array(this["box-points.obj"]), + fileName: "box-points.obj", + }; + cy.get( + '#readPointSetInputs input[name="serialized-point-set-file"]', + ).selectFile([testFile], { force: true }); + cy.get("#readPointSet-serialized-point-set-details").should( + "contain", + "35,32", + ); + + cy.get('#readPointSetInputs sl-button[name="run"]').click(); + + cy.get("#readPointSet-point-set-details").should("contain", "pointSetType"); + }); + + it("Reads an pointSet BinaryFile", function () { + cy.window().then(async (win) => { + const arrayBuffer = new Uint8Array(this["box-points.obj"]).buffer; + const { pointSet, webWorker } = await win.meshIo.readPointSet({ + data: new Uint8Array(arrayBuffer), + path: "box-points.obj", + }); + webWorker.terminate(); + verifyPointSet(pointSet); + }); + }); + + it("Reads an pointSet File", function () { + cy.window().then(async (win) => { + const arrayBuffer = new Uint8Array(this["box-points.obj"]).buffer; + const cowFile = new win.File([arrayBuffer], "box-points.obj"); + const { pointSet, webWorker } = await win.meshIo.readPointSet(cowFile); + webWorker.terminate(); + verifyPointSet(pointSet); + }); + }); + + it("Reads re-uses a WebWorker", function () { + cy.window().then(async (win) => { + const arrayBuffer = new Uint8Array(this["box-points.obj"]).buffer; + const cowFile = new win.File([arrayBuffer], "box-points.obj"); + const { webWorker } = await win.meshIo.readPointSet(cowFile); + const { pointSet } = await win.meshIo.readPointSet(cowFile, { + webWorker, + }); + webWorker.terminate(); + verifyPointSet(pointSet); + }); + }); + + it( + "Throws a catchable error for an invalid file", + { defaultCommandTimeout: 120000 }, + function () { + cy.window().then(async (win) => { + const invalidArray = new Uint8Array([21, 4, 4, 4, 4, 9, 5, 0, 82, 42]); + const invalidBlob = new win.Blob([invalidArray]); + const invalidFile = new win.File([invalidBlob], "invalid.file"); + try { + const { webWorker, pointSet } = + await win.meshIo.readPointSet(invalidFile); + webWorker.terminate(); + } catch (error) { + cy.expect(error.message).to.equal( + "Could not find IO for: invalid.file", + ); + } + }); + }, + ); +}); diff --git a/packages/mesh-io/typescript/test/browser/demo-app/index.html b/packages/mesh-io/typescript/test/browser/demo-app/index.html index 5b18eef0f..39a6d6c53 100644 --- a/packages/mesh-io/typescript/test/browser/demo-app/index.html +++ b/packages/mesh-io/typescript/test/browser/demo-app/index.html @@ -1,946 +1,1477 @@ + - - - - + + + + - + - @itk-wasm/mesh-io<img src="./javascript-logo.svg" alt="JavaScript logo" class="language-logo"/><img src="./typescript-logo.svg" alt="TypeScript logo" class="language-logo"/> + @itk-wasm/mesh-io<img src="./javascript-logo.svg" alt="JavaScript logo" class="language-logo" /><img + src="./typescript-logo.svg" alt="TypeScript logo" class="language-logo" /> + - - - -
- - - - -

@itk-wasm/mesh-io

- Input and output for scientific and medical image file formats. -

👨‍💻 Live API Demo ✨

-

- - - - readMesh - writeMesh - - - byuReadMesh - byuWriteMesh - freeSurferAsciiReadMesh - freeSurferAsciiWriteMesh - freeSurferBinaryReadMesh - freeSurferBinaryWriteMesh - objReadMesh - objWriteMesh - offReadMesh - offWriteMesh - stlReadMesh - stlWriteMesh - swcReadMesh - swcWriteMesh - vtkPolyDataReadMesh - vtkPolyDataWriteMesh - wasmReadMesh - wasmWriteMesh - wasmZstdReadMesh - wasmZstdWriteMesh - wasmZtdReadMesh - wasmZtdWriteMesh - - - - - - Read a mesh file

- -
- - -

- informationOnly - Only read mesh metadata -- do not read points and point and cell data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - - - - Read a mesh file format and convert it to the itk-wasm file format

- -
- - -

- informationOnly - Only read image metadata -- do not read pixel data. -

- -
Load sample inputs - Run

- -
- - -
- - Download -

- - - vtk - byu - fsa - fsb - obj - off - stl - swc - - Download -

-
- -
- - - - - Write an itk-wasm file format converted to an mesh file format

- -
- - -

- informationOnly - Only write image metadata -- do not write pixel data. -

- useCompression - Use compression in the written file, if supported -

- binaryFileType - Use a binary file type in the written file, if supported -

- - -
Load sample inputs - Run

- -
- - -
- - Download -

- - Download -

-
- -
- - -
-
- - + + + +
+ + + + +

@itk-wasm/mesh-io

+ Input and output for scientific and medical image file formats. +

👨‍💻 Live API Demo ✨

+

+ + + + readMesh + writeMesh + readPointSet + writePointSet + + + byuReadMesh + byuWriteMesh + freeSurferAsciiReadMesh + freeSurferAsciiWriteMesh + freeSurferBinaryReadMesh + freeSurferBinaryWriteMesh + objReadMesh + objWriteMesh + offReadMesh + offWriteMesh + stlReadMesh + stlWriteMesh + swcReadMesh + swcWriteMesh + vtkPolyDataReadMesh + vtkPolyDataWriteMesh + wasmReadMesh + wasmWriteMesh + wasmZstdReadMesh + wasmZstdWriteMesh + wasmZtdReadMesh + wasmZtdWriteMesh + + + + + + Read a mesh file

+ +
+
+ + +

+ informationOnly - Only read mesh metadata -- + do not read points and point and cell data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + Read a point-set file

+ +
+
+ + +

+ informationOnly - Only read point-set + metadata -- do not read points and point and cell + data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an point-set file + format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + + + + Read a mesh file format and convert it to the itk-wasm file + format

+ +
+
+ + +

+ informationOnly - Only read image metadata + -- do not read pixel data. +

+ +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + + vtk + byu + fsa + fsb + obj + off + stl + swc + + Download +

+
+ +
+ + + + + Write an itk-wasm file format converted to an mesh file format

+ +
+
+ + +

+ informationOnly - Only write image metadata + -- do not write pixel data. +

+ useCompression - Use compression in the + written file, if supported +

+ binaryFileType - Use a binary file type in + the written file, if supported +

+ + +
Load + sample inputs + Run

+ +
+
+ + +
+ + Download +

+ + Download +

+
+ +
+ + +
+
+ + - + + \ No newline at end of file diff --git a/packages/mesh-io/typescript/test/browser/demo-app/index.ts b/packages/mesh-io/typescript/test/browser/demo-app/index.ts index aa74aaa2d..0a96cab70 100644 --- a/packages/mesh-io/typescript/test/browser/demo-app/index.ts +++ b/packages/mesh-io/typescript/test/browser/demo-app/index.ts @@ -19,6 +19,8 @@ if (!params.has('functionName')) { import './read-mesh-controller.js' import './write-mesh-controller.js' +import './read-point-set-controller.js' +import './write-point-set-controller.js' // End added content import './byu-read-mesh-controller.js' import './byu-write-mesh-controller.js' diff --git a/packages/mesh-io/typescript/test/browser/demo-app/read-mesh-load-sample-inputs.ts b/packages/mesh-io/typescript/test/browser/demo-app/read-mesh-load-sample-inputs.ts index 2636527fd..193f785c8 100644 --- a/packages/mesh-io/typescript/test/browser/demo-app/read-mesh-load-sample-inputs.ts +++ b/packages/mesh-io/typescript/test/browser/demo-app/read-mesh-load-sample-inputs.ts @@ -1,4 +1,4 @@ -export default async function readImageLoadSampleInputs (model, preRun=false) { +export default async function readMeshLoadSampleInputs (model, preRun=false) { const inputButton = document.querySelector('#readMeshInputs sl-button[name=serialized-mesh-file-button]') if (!preRun) { inputButton.loading = true diff --git a/packages/mesh-io/typescript/test/browser/demo-app/read-point-set-controller.ts b/packages/mesh-io/typescript/test/browser/demo-app/read-point-set-controller.ts new file mode 100644 index 000000000..4704e65d0 --- /dev/null +++ b/packages/mesh-io/typescript/test/browser/demo-app/read-point-set-controller.ts @@ -0,0 +1,206 @@ +import * as meshIo from "../../../dist/index.js"; +import readPointSetLoadSampleInputs, { + usePreRun, +} from "./read-point-set-load-sample-inputs.js"; + +class ReadPointSetModel { + inputs: Map; + options: Map; + outputs: Map; + + constructor() { + this.inputs = new Map(); + this.options = new Map(); + this.outputs = new Map(); + } +} + +class ReadPointSetController { + constructor(loadSampleInputs) { + this.loadSampleInputs = loadSampleInputs; + + this.model = new ReadPointSetModel(); + const model = this.model; + + this.webWorker = null; + + if (loadSampleInputs) { + const loadSampleInputsButton = document.querySelector( + "#readPointSetInputs [name=loadSampleInputs]", + ); + loadSampleInputsButton.setAttribute("style", "display: block-inline;"); + loadSampleInputsButton.addEventListener("click", async (event) => { + loadSampleInputsButton.loading = true; + await loadSampleInputs(model); + loadSampleInputsButton.loading = false; + }); + } + + // ---------------------------------------------- + // Inputs + const serializedPointSetElement = document.querySelector( + "#readPointSetInputs input[name=serialized-point-set-file]", + ); + serializedPointSetElement.addEventListener("change", async (event) => { + const dataTransfer = event.dataTransfer; + const files = event.target.files || dataTransfer.files; + + const arrayBuffer = await files[0].arrayBuffer(); + model.inputs.set("serializedPointSet", { + data: new Uint8Array(arrayBuffer), + path: files[0].name, + }); + const details = document.getElementById( + "readPointSet-serialized-pointSet-details", + ); + details.innerHTML = `
${globalThis.escapeHtml(model.inputs.get("serializedPointSet").data.subarray(0, 50).toString() + " ...")}
`; + details.disabled = false; + }); + + // ---------------------------------------------- + // Options + const informationOnlyElement = document.querySelector( + "#readPointSetInputs sl-checkbox[name=information-only]", + ); + informationOnlyElement.addEventListener("sl-change", (event) => { + model.options.set("informationOnly", informationOnlyElement.checked); + }); + + // ---------------------------------------------- + // Outputs + const pointSetOutputDownload = document.querySelector( + "#readPointSetOutputs sl-button[name=point-set-download]", + ); + pointSetOutputDownload.addEventListener("click", async (event) => { + event.preventDefault(); + event.stopPropagation(); + if (model.outputs.has("pointSet")) { + const pointSetDownloadFormat = document.getElementById( + "point-set-output-format", + ); + const downloadFormat = pointSetDownloadFormat.value || "nrrd"; + const fileName = `pointSet.${downloadFormat}`; + const { webWorker, serializedPointSet } = await meshIo.writePointSet( + model.outputs.get("pointSet"), + fileName, + ); + + webWorker.terminate(); + globalThis.downloadFile(serializedPointSet, fileName); + } + }); + + const preRun = async () => { + if (!this.webWorker && loadSampleInputs && usePreRun) { + await loadSampleInputs(model, true); + await this.run(); + } + }; + + const onSelectTab = async (event) => { + if (event.detail.name === "readPointSet-panel") { + const params = new URLSearchParams(window.location.search); + if ( + !params.has("functionName") || + params.get("functionName") !== "readPointSet" + ) { + params.set("functionName", "readPointSet"); + const url = new URL(document.location); + url.search = params; + window.history.replaceState( + { functionName: "readPointSet" }, + "", + url, + ); + await preRun(); + } + } + }; + + const tabGroup = document.querySelector("sl-tab-group"); + tabGroup.addEventListener("sl-tab-show", onSelectTab); + function onInit() { + const params = new URLSearchParams(window.location.search); + if ( + params.has("functionName") && + params.get("functionName") === "readPointSet" + ) { + tabGroup.show("readPointSet-panel"); + preRun(); + } + } + onInit(); + + const runButton = document.querySelector( + '#readPointSetInputs sl-button[name="run"]', + ); + runButton.addEventListener("click", async (event) => { + event.preventDefault(); + + if (!model.inputs.has("serializedPointSet")) { + globalThis.notify( + "Required input not provided", + "serializedPointSet", + "danger", + "exclamation-octagon", + ); + return; + } + + try { + runButton.loading = true; + + const t0 = performance.now(); + const { couldRead, pointSet } = await this.run(); + const t1 = performance.now(); + globalThis.notify( + "readPointSet successfully completed", + `in ${t1 - t0} milliseconds.`, + "success", + "rocket-fill", + ); + + model.outputs.set("pointSet", pointSet); + pointSetOutputDownload.variant = "success"; + pointSetOutputDownload.disabled = false; + const pointSetDetails = document.getElementById( + "readPointSet-point-set-details", + ); + pointSetDetails.innerHTML = `
${globalThis.escapeHtml(JSON.stringify(pointSet, globalThis.interfaceTypeJsonReplacer, 2))}
`; + pointSetDetails.disabled = false; + const pointSetOutput = document.getElementById( + "readPointSet-point-set-details", + ); + } catch (error) { + globalThis.notify( + "Error while running pipeline", + error.toString(), + "danger", + "exclamation-octagon", + ); + throw error; + } finally { + runButton.loading = false; + } + }); + } + + async run() { + const options = Object.fromEntries(this.model.options.entries()); + options.webWorker = this.webWorker; + const { webWorker, pointSet } = await meshIo.readPointSet( + { + data: this.model.inputs.get("serializedPointSet").data.slice(), + path: this.model.inputs.get("serializedPointSet").path, + }, + options, + ); + this.webWorker = webWorker; + + return { pointSet }; + } +} + +const readPointSetController = new ReadPointSetController( + readPointSetLoadSampleInputs, +); diff --git a/packages/mesh-io/typescript/test/browser/demo-app/read-point-set-load-sample-inputs.ts b/packages/mesh-io/typescript/test/browser/demo-app/read-point-set-load-sample-inputs.ts new file mode 100644 index 000000000..09ba08a48 --- /dev/null +++ b/packages/mesh-io/typescript/test/browser/demo-app/read-point-set-load-sample-inputs.ts @@ -0,0 +1,20 @@ +export default async function readPointSetLoadSampleInputs (model, preRun=false) { + const inputButton = document.querySelector('#readPointSetInputs sl-button[name=serialized-point-set-file-button]') + if (!preRun) { + inputButton.loading = true + } + const fileName = 'box-points.obj' + const inputResponse = await fetch(`https://bafybeigniwg5zquxmw5izw22absoqvxwrrezr6wv3hc3gbrvgs6ywv4mdq.ipfs.w3s.link/ipfs/bafybeigniwg5zquxmw5izw22absoqvxwrrezr6wv3hc3gbrvgs6ywv4mdq/input/${fileName}`) + const inputData = new Uint8Array(await inputResponse.arrayBuffer()) + model.inputs.set('serializedPointSet', { data: inputData, path: fileName }) + if (!preRun) { + const inputElement = document.getElementById('readPointSet-serialized-point-set-details') + inputElement.innerHTML = `
${globalThis.escapeHtml(inputData.subarray(0, 50).toString())}
` + inputElement.disabled = false + inputButton.loading = false + } + + return model +} + +export const usePreRun = true diff --git a/packages/mesh-io/typescript/test/browser/demo-app/write-point-set-controller.ts b/packages/mesh-io/typescript/test/browser/demo-app/write-point-set-controller.ts new file mode 100644 index 000000000..07a71a485 --- /dev/null +++ b/packages/mesh-io/typescript/test/browser/demo-app/write-point-set-controller.ts @@ -0,0 +1,243 @@ +import { readPointSet } from "../../../dist/index.js"; +import * as meshIo from "../../../dist/index.js"; +import writePointSetLoadSampleInputs, { + usePreRun, +} from "./write-point-set-load-sample-inputs.js"; + +class WritePointSetModel { + inputs: Map; + options: Map; + outputs: Map; + + constructor() { + this.inputs = new Map(); + this.options = new Map(); + this.outputs = new Map(); + } +} + +class WritePointSetController { + constructor(loadSampleInputs) { + this.loadSampleInputs = loadSampleInputs; + + this.model = new WritePointSetModel(); + const model = this.model; + + this.webWorker = null; + + if (loadSampleInputs) { + const loadSampleInputsButton = document.querySelector( + "#writePointSetInputs [name=loadSampleInputs]", + ); + loadSampleInputsButton.setAttribute("style", "display: block-inline;"); + loadSampleInputsButton.addEventListener("click", async (event) => { + loadSampleInputsButton.loading = true; + await loadSampleInputs(model); + loadSampleInputsButton.loading = false; + }); + } + + // ---------------------------------------------- + // Inputs + const pointSetElement = document.querySelector( + "#writePointSetInputs input[name=point-set-file]", + ); + pointSetElement.addEventListener("change", async (event) => { + const dataTransfer = event.dataTransfer; + const files = event.target.files || dataTransfer.files; + + const { pointSet, webWorker } = await readPointSet(files[0]); + webWorker.terminate(); + model.inputs.set("pointSet", pointSet); + const details = document.getElementById( + "writePointSet-point-set-details", + ); + details.innerHTML = `
${globalThis.escapeHtml(JSON.stringify(pointSet, globalThis.interfaceTypeJsonReplacer, 2))}
`; + details.disabled = false; + }); + + const serializedPointSetElement = document.querySelector( + "#writePointSetInputs sl-input[name=serialized-point-set]", + ); + serializedPointSetElement.addEventListener("sl-change", (event) => { + model.inputs.set("serializedPointSet", serializedPointSetElement.value); + }); + + // ---------------------------------------------- + // Options + const informationOnlyElement = document.querySelector( + "#writePointSetInputs sl-checkbox[name=information-only]", + ); + informationOnlyElement.addEventListener("sl-change", (event) => { + model.options.set("informationOnly", informationOnlyElement.checked); + }); + + const useCompressionElement = document.querySelector( + "#writePointSetInputs sl-checkbox[name=use-compression]", + ); + useCompressionElement.addEventListener("sl-change", (event) => { + model.options.set("useCompression", useCompressionElement.checked); + }); + + const binaryFileTypeElement = document.querySelector( + "#writePointSetInputs sl-checkbox[name=binary-file-type]", + ); + binaryFileTypeElement.addEventListener("sl-change", (event) => { + model.options.set("binaryFileType", binaryFileTypeElement.checked); + }); + + // ---------------------------------------------- + // Outputs + const couldWriteOutputDownload = document.querySelector( + "#writePointSetOutputs sl-button[name=could-write-download]", + ); + couldWriteOutputDownload.addEventListener("click", async (event) => { + event.preventDefault(); + event.stopPropagation(); + if (model.outputs.has("couldWrite")) { + const fileName = `couldWrite.json`; + globalThis.downloadFile( + new TextEncoder().encode( + JSON.stringify(model.outputs.get("couldWrite")), + ), + fileName, + ); + } + }); + + const serializedPointSetOutputDownload = document.querySelector( + "#writePointSetOutputs sl-button[name=serialized-point-set-download]", + ); + serializedPointSetOutputDownload.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + if (model.outputs.has("serializedPointSet")) { + globalThis.downloadFile( + model.outputs.get("serializedPointSet").data, + model.outputs.get("serializedPointSet").path, + ); + } + }); + + const preRun = async () => { + if (!this.webWorker && loadSampleInputs && usePreRun) { + await loadSampleInputs(model, true); + await this.run(); + } + }; + + const onSelectTab = async (event) => { + if (event.detail.name === "writePointSet-panel") { + const params = new URLSearchParams(window.location.search); + if ( + !params.has("functionName") || + params.get("functionName") !== "writePointSet" + ) { + params.set("functionName", "writePointSet"); + const url = new URL(document.location); + url.search = params; + window.history.replaceState( + { functionName: "writePointSet" }, + "", + url, + ); + await preRun(); + } + } + }; + + const tabGroup = document.querySelector("sl-tab-group"); + tabGroup.addEventListener("sl-tab-show", onSelectTab); + function onInit() { + const params = new URLSearchParams(window.location.search); + if ( + params.has("functionName") && + params.get("functionName") === "writePointSet" + ) { + tabGroup.show("writePointSet-panel"); + preRun(); + } + } + onInit(); + + const runButton = document.querySelector( + '#writePointSetInputs sl-button[name="run"]', + ); + runButton.addEventListener("click", async (event) => { + event.preventDefault(); + + if (!model.inputs.has("pointSet")) { + globalThis.notify( + "Required input not provided", + "pointSet", + "danger", + "exclamation-octagon", + ); + return; + } + + try { + runButton.loading = true; + + const t0 = performance.now(); + const { couldWrite, serializedPointSet } = await this.run(); + const t1 = performance.now(); + globalThis.notify( + "writePointSet successfully completed", + `in ${t1 - t0} milliseconds.`, + "success", + "rocket-fill", + ); + + model.outputs.set("couldWrite", couldWrite); + couldWriteOutputDownload.variant = "success"; + couldWriteOutputDownload.disabled = false; + const couldWriteDetails = document.getElementById( + "writePointSet-could-write-details", + ); + couldWriteDetails.innerHTML = `
${globalThis.escapeHtml(JSON.stringify(couldWrite, globalThis.interfaceTypeJsonReplacer, 2))}
`; + couldWriteDetails.disabled = false; + const couldWriteOutput = document.getElementById( + "writePointSet-could-write-details", + ); + + model.outputs.set("serializedPointSet", serializedPointSet); + serializedPointSetOutputDownload.variant = "success"; + serializedPointSetOutputDownload.disabled = false; + const serializedPointSetOutput = document.getElementById( + "writePointSet-serialized-point-set-details", + ); + serializedPointSetOutput.innerHTML = `
${globalThis.escapeHtml(serializedPointSet.data.subarray(0, 1024).toString() + " ...")}
`; + serializedPointSetOutput.disabled = false; + } catch (error) { + globalThis.notify( + "Error while running pipeline", + error.toString(), + "danger", + "exclamation-octagon", + ); + throw error; + } finally { + runButton.loading = false; + } + }); + } + + async run() { + const options = Object.fromEntries(this.model.options.entries()); + options.webWorker = this.webWorker; + const { webWorker, couldWrite, serializedPointSet } = + await meshIo.writePointSet( + this.model.inputs.get("pointSet"), + this.model.inputs.get("serializedPointSet"), + options, + ); + this.webWorker = webWorker; + + return { couldWrite, serializedPointSet }; + } +} + +const writePointSetController = new WritePointSetController( + writePointSetLoadSampleInputs, +); diff --git a/packages/mesh-io/typescript/test/browser/demo-app/write-point-set-load-sample-inputs.ts b/packages/mesh-io/typescript/test/browser/demo-app/write-point-set-load-sample-inputs.ts new file mode 100644 index 000000000..def67e051 --- /dev/null +++ b/packages/mesh-io/typescript/test/browser/demo-app/write-point-set-load-sample-inputs.ts @@ -0,0 +1,28 @@ +// Generated file. To retain edits, remove this comment. + +export default null +// export default async function writeMeshLoadSampleInputs (model, preRun=false) { + + // Load sample inputs for the writeMesh function. + // + // This function should load sample inputs: + // + // 1) In the provided model map. + // 2) Into the corresponding HTML input elements if preRun is not true. + // + // Example for an input named `exampleInput`: + + // const exampleInput = 5 + // model.inputs.set("exampleInput", exampleInput) + // if (!preRun) { + // const exampleElement = document.querySelector("#writeMeshInputs [name=example-input]") + // exampleElement.value = 5 + // } + + // return model +// } + +// Use this function to run the pipeline when this tab group is select. +// This will load the web worker if it is not already loaded, download the wasm module, and allocate memory in the wasm model. +// Set this to `false` if sample inputs are very large or sample pipeline computation is long. +export const usePreRun = true