Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new 3D volume viewport #281

Merged
merged 7 commits into from
Dec 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4,658 changes: 2,359 additions & 2,299 deletions common/reviews/api/core.api.md

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1250,11 +1250,37 @@ type ViewportInputOptions = {
suppressEvents?: boolean;
};

// @public (undocumented)
interface ViewportPreset {
// (undocumented)
ambient: string;
// (undocumented)
colorTransfer: string;
// (undocumented)
diffuse: string;
// (undocumented)
gradientOpacity: string;
// (undocumented)
interpolation: string;
// (undocumented)
name: string;
// (undocumented)
scalarOpacity: string;
// (undocumented)
shade: string;
// (undocumented)
specular: string;
// (undocumented)
specularPower: string;
}

// @public
enum ViewportType {
ORTHOGRAPHIC = 'orthographic',
PERSPECTIVE = 'perspective',
STACK = 'stack',
// (undocumented)
VOLUME_3D = 'volume3d',
}

// @public (undocumented)
Expand Down
24 changes: 24 additions & 0 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4606,6 +4606,30 @@ type ViewportInputOptions = {
suppressEvents?: boolean;
};

// @public (undocumented)
interface ViewportPreset {
// (undocumented)
ambient: string;
// (undocumented)
colorTransfer: string;
// (undocumented)
diffuse: string;
// (undocumented)
gradientOpacity: string;
// (undocumented)
interpolation: string;
// (undocumented)
name: string;
// (undocumented)
scalarOpacity: string;
// (undocumented)
shade: string;
// (undocumented)
specular: string;
// (undocumented)
specularPower: string;
}

declare namespace visibility {
export {
setAnnotationVisibility,
Expand Down
185 changes: 185 additions & 0 deletions packages/core/examples/volumeViewport3D/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import {
RenderingEngine,
Types,
Enums,
setVolumesForViewports,
volumeLoader,
utilities,
CONSTANTS,
} from '@cornerstonejs/core';
import {
initDemo,
createImageIdsAndCacheMetaData,
setTitleAndDescription,
addDropdownToToolbar,
} from '../../../../utils/demo/helpers';
import * as cornerstoneTools from '@cornerstonejs/tools';
import { VolumeActor } from 'core/src/types';

// This is for debugging purposes
console.warn(
'Click on index.ts to open source code for this example --------->'
);

const {
ToolGroupManager,
TrackballRotateTool,
Enums: csToolsEnums,
} = cornerstoneTools;

const { ViewportType } = Enums;
const { MouseBindings } = csToolsEnums;

// Define a unique id for the volume
let renderingEngine;
const volumeName = 'CT_VOLUME_ID'; // Id of the volume less loader prefix
const volumeLoaderScheme = 'cornerstoneStreamingImageVolume'; // Loader id which defines which volume loader to use
const volumeId = `${volumeLoaderScheme}:${volumeName}`; // VolumeId with loader id + volume id
const renderingEngineId = 'myRenderingEngine';
const viewportId = '3D_VIEWPORT';

// ======== Set up page ======== //
setTitleAndDescription(
'3D Volume Rendering',
'Here we demonstrate how to 3D render a volume.'
);

const size = '500px';
const content = document.getElementById('content');
const viewportGrid = document.createElement('div');

viewportGrid.style.display = 'flex';
viewportGrid.style.display = 'flex';
viewportGrid.style.flexDirection = 'row';

const element1 = document.createElement('div');
element1.oncontextmenu = () => false;

element1.style.width = size;
element1.style.height = size;

viewportGrid.appendChild(element1);

content.appendChild(viewportGrid);

const instructions = document.createElement('p');
instructions.innerText = 'Click the image to rotate it.';

content.append(instructions);

addDropdownToToolbar({
options: {
values: CONSTANTS.VIEWPORT_PRESETS.map((preset) => preset.name),
defaultValue: 'CT-Bone',
},
onSelectedValueChange: (presetName) => {
const volumeActor = renderingEngine
.getViewport(viewportId)
.getDefaultActor().actor as VolumeActor;

utilities.applyPreset(
volumeActor,
CONSTANTS.VIEWPORT_PRESETS.find((preset) => preset.name === presetName)
);

renderingEngine.render();
},
});

// ============================= //

/**
* Runs the demo
*/
async function run() {
// Init Cornerstone and related libraries
await initDemo();

const toolGroupId = 'TOOL_GROUP_ID';

// Add tools to Cornerstone3D
cornerstoneTools.addTool(TrackballRotateTool);

// Define a tool group, which defines how mouse events map to tool commands for
// Any viewport using the group
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId);

// Add the tools to the tool group and specify which volume they are pointing at
toolGroup.addTool(TrackballRotateTool.toolName, {
configuration: { volumeId },
});

// Set the initial state of the tools, here we set one tool active on left click.
// This means left click will draw that tool.
toolGroup.setToolActive(TrackballRotateTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Primary, // Left Click
},
],
});

// Get Cornerstone imageIds and fetch metadata into RAM
const imageIds = await createImageIdsAndCacheMetaData({
StudyInstanceUID:
'1.3.6.1.4.1.14519.5.2.1.7009.2403.871108593056125491804754960339',
SeriesInstanceUID:
'1.3.6.1.4.1.14519.5.2.1.7009.2403.367700692008930469189923116409',
wadoRsRoot: 'https://domvja9iplmyu.cloudfront.net/dicomweb',
type: 'VOLUME',
});

// Instantiate a rendering engine
renderingEngine = new RenderingEngine(renderingEngineId);

// Create the viewports

const viewportInputArray = [
{
viewportId: viewportId,
type: ViewportType.VOLUME_3D,
element: element1,
defaultOptions: {
orientation: Enums.OrientationAxis.SAGITTAL,
background: <Types.Point3>[0.2, 0, 0.2],
},
},
];

renderingEngine.setViewports(viewportInputArray);

// Set the tool group on the viewports
toolGroup.addViewport(viewportId, renderingEngineId);

// Define a volume in memory
const volume = await volumeLoader.createAndCacheVolume(volumeId, {
imageIds,
});

// Set the volume to load
volume.load();

setVolumesForViewports(renderingEngine, [{ volumeId }], [viewportId]).then(
() => {
const volumeActor = renderingEngine
.getViewport(viewportId)
.getDefaultActor().actor as VolumeActor;

utilities.applyPreset(
volumeActor,
CONSTANTS.VIEWPORT_PRESETS.find((preset) => preset.name === 'CT-Bone')
);

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

viewport.render();
}
);

const viewport = renderingEngine.getViewport(viewportId);
renderingEngine.render();
}

run();
Loading