From 3094306518611afd2313ecb3da03f4e7bb30b0ea Mon Sep 17 00:00:00 2001 From: bionoone <22618425+bionoone@users.noreply.github.com> Date: Mon, 24 Oct 2022 14:35:16 +0200 Subject: [PATCH 1/4] fix logic for flip, remove useless member variable ( panCache ) --- .../core/src/RenderingEngine/StackViewport.ts | 31 ++++++++++-------- packages/core/src/RenderingEngine/Viewport.ts | 32 +++++++++++++++---- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/packages/core/src/RenderingEngine/StackViewport.ts b/packages/core/src/RenderingEngine/StackViewport.ts index dac1b43f01..f43eb19d31 100644 --- a/packages/core/src/RenderingEngine/StackViewport.ts +++ b/packages/core/src/RenderingEngine/StackViewport.ts @@ -140,7 +140,6 @@ class StackViewport extends Viewport implements IStackViewport { private _imageData: vtkImageDataType; private cameraPosOnRender: Point3; private stackInvalidated = false; // if true -> new actor is forced to be created for the stack - private panCache: Point3; private voiApplied = false; private rotationCache = 0; private _publishCalibratedEvent = false; @@ -196,7 +195,6 @@ class StackViewport extends Viewport implements IStackViewport { this.imageIds = []; this.currentImageIdIndex = 0; this.targetImageIdIndex = 0; - this.panCache = [0, 0, 0]; this.cameraPosOnRender = [0, 0, 0]; this.resetCamera(); @@ -1667,9 +1665,11 @@ class StackViewport extends Viewport implements IStackViewport { // it in the space 3) restore the pan, zoom props. const cameraProps = this.getCamera(); - this.panCache[0] = this.cameraPosOnRender[0] - cameraProps.position[0]; - this.panCache[1] = this.cameraPosOnRender[1] - cameraProps.position[1]; - this.panCache[2] = this.cameraPosOnRender[2] - cameraProps.position[2]; + const panCache: [number, number, number] = [ + this.cameraPosOnRender[0] - cameraProps.position[0], + this.cameraPosOnRender[1] - cameraProps.position[1], + this.cameraPosOnRender[2] - cameraProps.position[2], + ]; // store rotation cache since reset camera will reset it const rotationCache = this.rotationCache; @@ -1691,7 +1691,7 @@ class StackViewport extends Viewport implements IStackViewport { // We shouldn't restore the focalPoint, position and parallelScale after reset // if it is the first render or we have completely re-created the vtkImageData - this._restoreCameraProps(cameraProps, previousCameraProps); + this._restoreCameraProps(cameraProps, previousCameraProps, panCache); // Restore rotation for the new slice of the image this.rotationCache = 0; @@ -1976,7 +1976,8 @@ class StackViewport extends Viewport implements IStackViewport { */ private _restoreCameraProps( { parallelScale: prevScale }: ICamera, - previousCamera: ICamera + previousCamera: ICamera, + panCache: [number, number, number] ): void { const renderer = this.getRenderer(); @@ -1984,15 +1985,15 @@ class StackViewport extends Viewport implements IStackViewport { const { position, focalPoint } = this.getCamera(); const newPosition = [ - position[0] - this.panCache[0], - position[1] - this.panCache[1], - position[2] - this.panCache[2], + position[0] - panCache[0], + position[1] - panCache[1], + position[2] - panCache[2], ]; const newFocal = [ - focalPoint[0] - this.panCache[0], - focalPoint[1] - this.panCache[1], - focalPoint[2] - this.panCache[2], + focalPoint[0] - panCache[0], + focalPoint[1] - panCache[1], + focalPoint[2] - panCache[2], ]; // Restoring previous state x,y and scale, keeping the new z @@ -2001,6 +2002,10 @@ class StackViewport extends Viewport implements IStackViewport { position: newPosition, focalPoint: newFocal, }); + this.flip({ + flipHorizontal: previousCamera.flipHorizontal, + flipVertical: previousCamera.flipVertical, + }); const camera = this.getCamera(); diff --git a/packages/core/src/RenderingEngine/Viewport.ts b/packages/core/src/RenderingEngine/Viewport.ts index 2ec362cb3d..aab422c64c 100644 --- a/packages/core/src/RenderingEngine/Viewport.ts +++ b/packages/core/src/RenderingEngine/Viewport.ts @@ -252,20 +252,38 @@ class Viewport implements IViewport { vec3.scaleAndAdd(center, center, jVector, (size[1] / 2.0) * spacing[1]); vec3.scaleAndAdd(center, center, kVector, (size[2] / 2.0) * spacing[2]); + const imageToWorld: mat4 = [ + direction[0], + direction[1], + direction[2], + 0, // + direction[3], + direction[4], + direction[5], + 0, // + direction[6], + direction[7], + direction[8], + 0, // + 0, + 0, + 0, + 1, // + ]; + const worldToImage: mat4 = mat4.transpose( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], + imageToWorld + ); + let flipHTx, flipVTx; const transformToOriginTx = vtkMatrixBuilder .buildFromRadian() - .identity() .translate(center[0], center[1], center[2]) - .rotateFromDirections(jVector, [0, 1, 0]) - .rotateFromDirections(iVector, [1, 0, 0]); - + .multiply(imageToWorld); const transformBackFromOriginTx = vtkMatrixBuilder .buildFromRadian() - .identity() - .rotateFromDirections([1, 0, 0], iVector) - .rotateFromDirections([0, 1, 0], jVector) + .multiply(worldToImage) .translate(-center[0], -center[1], -center[2]); if (flipH) { From 06476cb92dd8aad2a12f3f37e634863e188f1d2a Mon Sep 17 00:00:00 2001 From: bionoone <22618425+bionoone@users.noreply.github.com> Date: Wed, 26 Oct 2022 10:54:47 +0200 Subject: [PATCH 2/4] simplify code by using vtk transform matrix --- packages/core/src/RenderingEngine/Viewport.ts | 46 ++----------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/packages/core/src/RenderingEngine/Viewport.ts b/packages/core/src/RenderingEngine/Viewport.ts index aab422c64c..9237706e71 100644 --- a/packages/core/src/RenderingEngine/Viewport.ts +++ b/packages/core/src/RenderingEngine/Viewport.ts @@ -237,55 +237,19 @@ class Viewport implements IViewport { // proper scaling (flipping), they should be transformed to the origin and // then flipped. The following code does this transformation. - const origin = imageData.getOrigin(); - const direction = imageData.getDirection(); - const spacing = imageData.getSpacing(); const size = imageData.getDimensions(); - const iVector = direction.slice(0, 3); - const jVector = direction.slice(3, 6); - const kVector = direction.slice(6, 9); - - // finding the center of the image - const center = vec3.create(); - vec3.scaleAndAdd(center, origin, iVector, (size[0] / 2.0) * spacing[0]); - vec3.scaleAndAdd(center, center, jVector, (size[1] / 2.0) * spacing[1]); - vec3.scaleAndAdd(center, center, kVector, (size[2] / 2.0) * spacing[2]); - - const imageToWorld: mat4 = [ - direction[0], - direction[1], - direction[2], - 0, // - direction[3], - direction[4], - direction[5], - 0, // - direction[6], - direction[7], - direction[8], - 0, // - 0, - 0, - 0, - 1, // - ]; - const worldToImage: mat4 = mat4.transpose( - [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6], - imageToWorld - ); - let flipHTx, flipVTx; const transformToOriginTx = vtkMatrixBuilder .buildFromRadian() - .translate(center[0], center[1], center[2]) - .multiply(imageToWorld); + .multiply(imageData.getIndexToWorld()) + .translate(size[0] / 2, size[1] / 2, 0); + const transformBackFromOriginTx = vtkMatrixBuilder .buildFromRadian() - .multiply(worldToImage) - .translate(-center[0], -center[1], -center[2]); - + .translate(-size[0] / 2, -size[1] / 2, 0) + .multiply(imageData.getWorldToIndex()); if (flipH) { this.flipHorizontal = flipHorizontal; flipHTx = vtkMatrixBuilder From 397cb862e6cc7941651d34b589d19cc442f97768 Mon Sep 17 00:00:00 2001 From: bionoone <22618425+bionoone@users.noreply.github.com> Date: Wed, 26 Oct 2022 11:26:47 +0200 Subject: [PATCH 3/4] fix half voxel shift ( DICOM ) --- packages/core/src/RenderingEngine/Viewport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/RenderingEngine/Viewport.ts b/packages/core/src/RenderingEngine/Viewport.ts index 9237706e71..1f8f8eb60f 100644 --- a/packages/core/src/RenderingEngine/Viewport.ts +++ b/packages/core/src/RenderingEngine/Viewport.ts @@ -244,11 +244,11 @@ class Viewport implements IViewport { const transformToOriginTx = vtkMatrixBuilder .buildFromRadian() .multiply(imageData.getIndexToWorld()) - .translate(size[0] / 2, size[1] / 2, 0); + .translate((size[0] - 1) / 2.0, (size[1] - 1) / 2.0, 0); const transformBackFromOriginTx = vtkMatrixBuilder .buildFromRadian() - .translate(-size[0] / 2, -size[1] / 2, 0) + .translate(-(size[0] - 1) / 2.0, -(size[1] - 1) / 2.0, 0) .multiply(imageData.getWorldToIndex()); if (flipH) { this.flipHorizontal = flipHorizontal; From cb8997d4aefa71b4640098bbad2952587b8746e5 Mon Sep 17 00:00:00 2001 From: bionoone <22618425+bionoone@users.noreply.github.com> Date: Wed, 26 Oct 2022 18:05:36 +0200 Subject: [PATCH 4/4] revert half voxel. there is probably some bug in rendering pipeline --- packages/core/src/RenderingEngine/Viewport.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core/src/RenderingEngine/Viewport.ts b/packages/core/src/RenderingEngine/Viewport.ts index 1f8f8eb60f..68842033b9 100644 --- a/packages/core/src/RenderingEngine/Viewport.ts +++ b/packages/core/src/RenderingEngine/Viewport.ts @@ -244,12 +244,13 @@ class Viewport implements IViewport { const transformToOriginTx = vtkMatrixBuilder .buildFromRadian() .multiply(imageData.getIndexToWorld()) - .translate((size[0] - 1) / 2.0, (size[1] - 1) / 2.0, 0); + .translate(size[0] / 2.0, size[1] / 2.0, 0); const transformBackFromOriginTx = vtkMatrixBuilder .buildFromRadian() - .translate(-(size[0] - 1) / 2.0, -(size[1] - 1) / 2.0, 0) + .translate(-size[0] / 2.0, -size[1] / 2.0, 0) .multiply(imageData.getWorldToIndex()); + if (flipH) { this.flipHorizontal = flipHorizontal; flipHTx = vtkMatrixBuilder