[vtk.js] show same plane for images with different spacing, origin and orientation.

Using vtk.js

I’m trying to display (in two separate viewports) two nfiti images (reading using cornerstone-nifti-image-loader) that are coregistered, but have different voxel spacings and dimensions (256x256x256 vs 160x512x512).

I’m using vtkInteractorStyleMPRSlice to interact with the volumes and do the mpr.

I want to sync the two viewports such that the two viewports always display the same plane in world space. To begin with, I like to display the same planes upon the first render.

The two images have the following properties (truncated to 2 decimal places for readability):

image1 = {
  imageOrientationPatient: [-0.99, 0.00, 0.00, 0.021, 0.99, -0.09],
  imagePositionPatient: [-75.78, -78.51, -125.54],
  columnPixelSpacing: 1.00,
  rowPixelSpacing: 0.48,
  sliceThickness: 0.48,
}

image2 = {
  imageOrientationPatient: [-1, 0, -0, -0, 1, -0],
  imagePositionPatient: [67.23, -105.20, 77.69],
  rowPixelSpacing: 0.69,
  columnPixelSpacing: 0.52,
  sliceThickness: 0.53
}

Following this link I created an affine matrix that I apply to the volumeActor as follows:

const [F11, F21, F31] = imageOrientationPatient.slice(3, 6);
const [F12, F22, F32] = imageOrientationPatient.slice(0, 3);

const n = [];
vec3.cross(n, [F12, F22, F32], [F11, F21, F31]);

const dRow = rowPixelSpacing;
const dCol = columnPixelSpacing;
const dSlice = sliceThickness
const S = imagePositionPatient;
          
actor.setUserMatrix(new Float64Array([
  F11 * dRow, F12* dCol, n[0] * dSlice, S[0],
  F21 * dRow, F22 * dCol, n[1] * dSlice, S[1],
  F31 * dRow, F32 * dCol, n[2] * dSlice, S[2],
  0, 0, 0, 1
]))

After doing so, I don’t see anything in my viewports anymore, so clearly this is not the way. I’m wondering though if someone here could identify my mistake (I’m guessing I am not rotating around the correct origin), or point me in the right direction.

vtkInteractorStyleMPRSlice does slicing using the camera (using the camera clipping range to generate the visible slab), so you would want to synchronize the camera parameters in order to view the same plane in world space.