Skip to content

Commit

Permalink
feat(volume3d): add orientation to volume viewport 3d (#482)
Browse files Browse the repository at this point in the history
* feat(volume3d): add orientation to volume viewport 3d

* fix tests

* apply review comments

* fix api
  • Loading branch information
sedghi authored Mar 16, 2023
1 parent 8dde2c4 commit 55d7f44
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 82 deletions.
4 changes: 4 additions & 0 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export abstract class BaseVolumeViewport extends Viewport implements IVolumeView
// (undocumented)
addVolumes(volumeInputArray: Array<IVolumeInput>, immediate?: boolean, suppressEvents?: boolean): Promise<void>;
// (undocumented)
protected applyViewOrientation(orientation: OrientationAxis | OrientationVectors): void;
// (undocumented)
canvasToWorld: (canvasPos: Point2) => Point3;
// (undocumented)
flip(flipDirection: FlipDirection): void;
Expand All @@ -70,6 +72,8 @@ export abstract class BaseVolumeViewport extends Viewport implements IVolumeView
// (undocumented)
getIntensityFromWorld(point: Point3): number;
// (undocumented)
protected _getOrientationVectors(orientation: OrientationAxis | OrientationVectors): OrientationVectors;
// (undocumented)
getProperties: () => VolumeViewportProperties;
// (undocumented)
getSlabThickness(): number;
Expand Down
20 changes: 8 additions & 12 deletions packages/core/examples/volumeViewport3D/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import {
RenderingEngine,
Types,
CONSTANTS,
Enums,
RenderingEngine,
setVolumesForViewports,
volumeLoader,
Types,
utilities,
CONSTANTS,
volumeLoader,
} from '@cornerstonejs/core';
import * as cornerstoneTools from '@cornerstonejs/tools';
import {
initDemo,
addDropdownToToolbar,
createImageIdsAndCacheMetaData,
initDemo,
setTitleAndDescription,
addDropdownToToolbar,
} from '../../../../utils/demo/helpers';
import * as cornerstoneTools from '@cornerstonejs/tools';

// This is for debugging purposes
console.warn(
Expand Down Expand Up @@ -138,7 +138,7 @@ async function run() {
type: ViewportType.VOLUME_3D,
element: element1,
defaultOptions: {
orientation: Enums.OrientationAxis.SAGITTAL,
orientation: Enums.OrientationAxis.CORONAL,
background: <Types.Point3>[0.2, 0, 0.2],
},
},
Expand Down Expand Up @@ -168,10 +168,6 @@ async function run() {
CONSTANTS.VIEWPORT_PRESETS.find((preset) => preset.name === 'CT-Bone')
);

const renderer = viewport.getRenderer();
renderer.getActiveCamera().elevation(-70);
viewport.setCamera({ parallelScale: 600 });

viewport.render();
}
);
Expand Down
88 changes: 65 additions & 23 deletions packages/core/src/RenderingEngine/BaseVolumeViewport.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,45 @@
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';

import cache from '../cache';
import { MPR_CAMERA_VALUES, RENDERING_DEFAULTS } from '../constants';
import {
BlendModes,
Events,
OrientationAxis,
VOILUTFunctionType,
} from '../enums';
import ViewportType from '../enums/ViewportType';
import Viewport from './Viewport';
import { createVolumeActor } from './helpers';
import volumeNewImageEventDispatcher, {
resetVolumeNewImageState,
} from './helpers/volumeNewImageEventDispatcher';
import { loadVolume } from '../loaders/volumeLoader';
import vtkSlabCamera from './vtkClasses/vtkSlabCamera';
import eventTarget from '../eventTarget';
import { getShouldUseCPURendering } from '../init';
import { loadVolume } from '../loaders/volumeLoader';
import type {
Point2,
Point3,
IImageData,
IVolumeInput,
ActorEntry,
FlipDirection,
VolumeViewportProperties,
IImageData,
IVolumeInput,
OrientationVectors,
Point2,
Point3,
VOIRange,
VolumeViewportProperties,
} from '../types';
import { VoiModifiedEventDetail } from '../types/EventTypes';
import type { ViewportInput } from '../types/IViewport';
import type IVolumeViewport from '../types/IVolumeViewport';
import {
Events,
BlendModes,
OrientationAxis,
VOILUTFunctionType,
} from '../enums';
import eventTarget from '../eventTarget';
import {
actorIsA,
imageIdToURI,
triggerEvent,
createSigmoidRGBTransferFunction,
getVoiFromSigmoidRGBTransferFunction,
imageIdToURI,
triggerEvent,
} from '../utilities';
import { createVolumeActor } from './helpers';
import volumeNewImageEventDispatcher, {
resetVolumeNewImageState,
} from './helpers/volumeNewImageEventDispatcher';
import Viewport from './Viewport';
import type { vtkSlabCamera as vtkSlabCameraType } from './vtkClasses/vtkSlabCamera';
import { VoiModifiedEventDetail } from '../types/EventTypes';
import { RENDERING_DEFAULTS } from '../constants';
import vtkSlabCamera from './vtkClasses/vtkSlabCamera';

/**
* Abstract base class for volume viewports. VolumeViewports are used to render
Expand Down Expand Up @@ -94,6 +95,22 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
return false;
}

protected applyViewOrientation(
orientation: OrientationAxis | OrientationVectors
) {
const { viewPlaneNormal, viewUp } =
this._getOrientationVectors(orientation);
const camera = this.getVtkActiveCamera();
camera.setDirectionOfProjection(
-viewPlaneNormal[0],
-viewPlaneNormal[1],
-viewPlaneNormal[2]
);
camera.setViewUpFrom(viewUp);

this.resetCamera();
}

private initializeVolumeNewImageEventDispatcher(): void {
const volumeNewImageHandlerBound = volumeNewImageHandler.bind(this);
const volumeNewImageCleanUpBound = volumeNewImageCleanUp.bind(this);
Expand Down Expand Up @@ -758,6 +775,31 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
});
};

protected _getOrientationVectors(
orientation: OrientationAxis | OrientationVectors
): OrientationVectors {
if (typeof orientation === 'object') {
if (orientation.viewPlaneNormal && orientation.viewUp) {
return orientation;
} else {
throw new Error(
'Invalid orientation object. It must contain viewPlaneNormal and viewUp'
);
}
} else if (
typeof orientation === 'string' &&
MPR_CAMERA_VALUES[orientation]
) {
return MPR_CAMERA_VALUES[orientation];
} else {
throw new Error(
`Invalid orientation: ${orientation}. Valid orientations are: ${Object.keys(
MPR_CAMERA_VALUES
).join(', ')}`
);
}
}

/**
* Reset the camera for the volume viewport
*/
Expand Down
51 changes: 8 additions & 43 deletions packages/core/src/RenderingEngine/VolumeViewport.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { vec3 } from 'gl-matrix';
import vtkPlane from '@kitware/vtk.js/Common/DataModel/Plane';
import { vec3 } from 'gl-matrix';

import cache from '../cache';
import transformWorldToIndex from '../utilities/transformWorldToIndex';
import { EPSILON, MPR_CAMERA_VALUES, RENDERING_DEFAULTS } from '../constants';
import { BlendModes, OrientationAxis } from '../enums';
import type {
Point3,
IVolumeInput,
ActorEntry,
IImageVolume,
IVolumeInput,
OrientationVectors,
Point3,
} from '../types';
import type { ViewportInput } from '../types/IViewport';
import { RENDERING_DEFAULTS, MPR_CAMERA_VALUES, EPSILON } from '../constants';
import { BlendModes, OrientationAxis } from '../enums';
import BaseVolumeViewport from './BaseVolumeViewport';
import { actorIsA } from '../utilities';
import transformWorldToIndex from '../utilities/transformWorldToIndex';
import BaseVolumeViewport from './BaseVolumeViewport';

/**
* An object representing a VolumeViewport. VolumeViewports are used to render
Expand All @@ -35,17 +35,7 @@ class VolumeViewport extends BaseVolumeViewport {
// if the camera is set to be acquisition axis then we need to skip
// it for now until the volume is set
if (orientation && orientation !== OrientationAxis.ACQUISITION) {
const { viewPlaneNormal, viewUp } =
this._getOrientationVectors(orientation);
const camera = this.getVtkActiveCamera();
camera.setDirectionOfProjection(
-viewPlaneNormal[0],
-viewPlaneNormal[1],
-viewPlaneNormal[2]
);
camera.setViewUpFrom(viewUp);

this.resetCamera();
this.applyViewOrientation(orientation);
return;
}

Expand Down Expand Up @@ -144,31 +134,6 @@ class VolumeViewport extends BaseVolumeViewport {
}
}

private _getOrientationVectors(
orientation: OrientationAxis | OrientationVectors
): OrientationVectors {
if (typeof orientation === 'object') {
if (orientation.viewPlaneNormal && orientation.viewUp) {
return orientation;
} else {
throw new Error(
'Invalid orientation object. It must contain viewPlaneNormal and viewUp'
);
}
} else if (
typeof orientation === 'string' &&
MPR_CAMERA_VALUES[orientation]
) {
return MPR_CAMERA_VALUES[orientation];
} else {
throw new Error(
`Invalid orientation: ${orientation}. Valid orientations are: ${Object.keys(
MPR_CAMERA_VALUES
).join(', ')}`
);
}
}

private _getAcquisitionPlaneOrientation(): OrientationVectors {
const actorEntry = this.getDefaultActor();

Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/RenderingEngine/VolumeViewport3D.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { OrientationAxis } from '../enums';
import type { ViewportInput } from '../types/IViewport';
import BaseVolumeViewport from './BaseVolumeViewport';
import { RENDERING_DEFAULTS } from '../constants';

/**
* An object representing a 3-dimensional volume viewport. VolumeViewport3Ds are used to render
Expand All @@ -13,13 +13,17 @@ class VolumeViewport3D extends BaseVolumeViewport {
constructor(props: ViewportInput) {
super(props);

const { parallelProjection } = this.options;
const { parallelProjection, orientation } = this.options;

const activeCamera = this.getVtkActiveCamera();

if (parallelProjection != null) {
activeCamera.setParallelProjection(parallelProjection);
}

if (orientation && orientation !== OrientationAxis.ACQUISITION) {
this.applyViewOrientation(orientation);
}
}

public resetCamera(
Expand Down
Binary file modified packages/core/test/groundTruth/sphere_default_sagittal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions packages/core/test/volumeViewport_gpu_render_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ describe('Volume Viewport GPU -- ', () => {
const element = createViewport(
this.renderingEngine,
Enums.OrientationAxis.SAGITTAL,
1000,
1000,
300,
300,
ViewportType.VOLUME_3D
);
this.DOMElements.push(element);
Expand Down

0 comments on commit 55d7f44

Please sign in to comment.