Skip to content

Instantly share code, notes, and snippets.

@agirault
Last active February 5, 2021 15:32
Show Gist options
  • Save agirault/1779e12ad36ae8bca7da526fbbd772a8 to your computer and use it in GitHub Desktop.
Save agirault/1779e12ad36ae8bca7da526fbbd772a8 to your computer and use it in GitHub Desktop.
import vtkImageMapper from 'vtk.js/Sources/Rendering/Core/ImageMapper';
import * as vtkMath from 'vtk.js/Sources/Common/Core/Math';
const { SlicingMode } = vtkImageMapper;
const ScreenSide = {
top: Symbol('top'),
bottom: Symbol('bottom'),
left: Symbol('left'),
right: Symbol('right'),
close: Symbol('close'),
far: Symbol('far'),
};
function LPSCoordinatesOfScreenSide(screenSide) {
switch (screenSide) {
case ScreenSide.top: return [0, -1, 0];
case ScreenSide.bottom: return [0, 1, 0];
case ScreenSide.left: return [-1, 0, 0];
case ScreenSide.right: return [1, 0, 0];
case ScreenSide.close: return [0, 0, -1];
case ScreenSide.far: return [0, 0, 1];
default: return [];
}
}
const Label = {
left: Symbol('Left'),
right: Symbol('Right'),
posterior: Symbol('Posterior'),
anterior: Symbol('Anterior'),
superior: Symbol('Superior'),
inferior: Symbol('Inferior'),
};
function LPSCoordinatesOfLabel(label) {
switch (label) {
case Label.left: return [1, 0, 0];
case Label.right: return [-1, 0, 0];
case Label.posterior: return [0, 1, 0];
case Label.anterior: return [0, -1, 0];
case Label.superior: return [0, 0, 1];
case Label.inferior: return [0, 0, -1];
default: return [];
}
}
function labelFor(screenSide, mapper) {
// Method for image space slicing (I, J, K)
function labelForImageSpaceSlicing(mat3x3) {
// Create a 3x3 matrix transformation from the image space
// (IJK, JKI or KIJ) to world space (LPS)
const dir9 = mapper.getInputData().getDirection();
const dir3x3 = [
[dir9[0], dir9[3], dir9[6]],
[dir9[1], dir9[4], dir9[7]],
[dir9[2], dir9[5], dir9[8]],
];
vtkMath.multiply3x3_mat3(dir3x3, mat3x3, mat3x3);
// Apply the transformation to the coordinate of the side
let outVec = [0, 0, 0];
const inVec = LPSCoordinatesOfScreenSide(screenSide);
vtkMath.multiply3x3_vect3(mat3x3, inVec, outVec);
// Restrict to the unit vectors
outVec = outVec.map((val) => {
const threshold = Math.sqrt(0.5);
if (val < -threshold) {
return -1;
}
if (val > threshold) {
return 1;
}
return 0;
});
// Find matching label
const labels = Object.values(Label);
return labels.find((label) => vtkMath.areMatricesEqual(outVec, LPSCoordinatesOfLabel(label)));
}
switch (mapper.getSlicingMode()) {
case SlicingMode.I: {
// JKI -> IJK
const mat3x3 = [[0, 1, 0], [0, 0, -1], [-1, 0, 0]];
return labelForImageSpaceSlicing(mat3x3);
}
case SlicingMode.J: {
// KIJ -> IJK
const mat3x3 = [[1, 0, 0], [0, 0, -1], [0, 1, 0]];
return labelForImageSpaceSlicing(mat3x3);
}
case SlicingMode.K: {
// IJK -> IJK
const mat3x3 = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
return labelForImageSpaceSlicing(mat3x3);
}
case SlicingMode.X:
switch (screenSide) {
case ScreenSide.top: return Label.superior;
case ScreenSide.bottom: return Label.inferior;
case ScreenSide.left: return Label.anterior;
case ScreenSide.right: return Label.posterior;
case ScreenSide.close: return Label.left;
case ScreenSide.far: return Label.right;
default: return null;
}
case SlicingMode.Y:
switch (side) {
case ScreenSide.top: return Label.superior;
case ScreenSide.bottom: return Label.inferior;
case ScreenSide.left: return Label.right;
case ScreenSide.right: return Label.left;
case ScreenSide.close: return Label.anterior;
case ScreenSide.far: return Label.posterior;
default: return null;
}
case SlicingMode.Z:
switch (screenSide) {
case ScreenSide.top: return Label.anterior;
case ScreenSide.bottom: return Label.posterior;
case ScreenSide.left: return Label.right;
case ScreenSide.right: return Label.left;
case ScreenSide.close: return Label.inferior;
case ScreenSide.far: return Label.superior;
default: return null;
}
default: return null;
}
}
export default {
ScreenSide,
labelFor,
};
@finetjul
Copy link

finetjul commented Feb 3, 2021

Not sure to fully understand, but it seems that you know what you are doing :-)

As a side note, I did not realize that Side was for screen positions, maybe ScreenSide would be more meaningful...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment