Skip to content

Commit

Permalink
feat: camera sync canvas relative (#167)
Browse files Browse the repository at this point in the history
* feat(cameraSync):Sync on raw camera or just pan/zoom

* feat(zoomPanSync):Add a separate zoom/pan synchronizer

* fix(synchronizers):Some cleanup on the synchronizers

* fix(cameraSync):PR review changes

* fix(sync):Move the options into a per-viewport store instead of info

* small edits

* update api
  • Loading branch information
wayfarer3130 authored Aug 23, 2022
1 parent 5fb1562 commit 2fd6c98
Show file tree
Hide file tree
Showing 14 changed files with 456 additions and 40 deletions.
26 changes: 23 additions & 3 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1246,10 +1246,14 @@ interface IViewport {
// (undocumented)
getFrameOfReferenceUID: () => string;
// (undocumented)
getPan(): Point2;
// (undocumented)
getRenderer(): void;
// (undocumented)
getRenderingEngine(): any;
// (undocumented)
getZoom(): number;
// (undocumented)
id: string;
// (undocumented)
options: ViewportInputOptions;
Expand All @@ -1264,10 +1268,14 @@ interface IViewport {
// (undocumented)
setActors(actors: Array<ActorEntry>): void;
// (undocumented)
setCamera(cameraInterface: ICamera): void;
setCamera(cameraInterface: ICamera, storeAsInitialCamera?: boolean): void;
// (undocumented)
setOptions(options: ViewportInputOptions, immediate: boolean): void;
// (undocumented)
setPan(pan: Point2, storeAsInitialCamera?: boolean): any;
// (undocumented)
setZoom(zoom: number, storeAsInitialCamera?: boolean): any;
// (undocumented)
sHeight: number;
// (undocumented)
suppressEvents: boolean;
Expand Down Expand Up @@ -1951,6 +1959,8 @@ export class Viewport implements IViewport {
// (undocumented)
getFrameOfReferenceUID: () => string;
// (undocumented)
getPan(): Point2;
// (undocumented)
getProperties: () => void;
// (undocumented)
getRenderer(): any;
Expand All @@ -1959,10 +1969,14 @@ export class Viewport implements IViewport {
// (undocumented)
protected getVtkActiveCamera(): vtkCamera | vtkSlabCamera;
// (undocumented)
getZoom(): number;
// (undocumented)
protected hasPixelSpacing: boolean;
// (undocumented)
readonly id: string;
// (undocumented)
protected initialCamera: ICamera;
// (undocumented)
_isInBounds(point: Point3, bounds: number[]): boolean;
// (undocumented)
options: ViewportInputOptions;
Expand All @@ -1979,7 +1993,7 @@ export class Viewport implements IViewport {
// (undocumented)
reset(immediate?: boolean): void;
// (undocumented)
protected resetCamera(resetPan?: boolean, resetZoom?: boolean): boolean;
protected resetCamera(resetPan?: boolean, resetZoom?: boolean, storeAsInitialCamera?: boolean): boolean;
// (undocumented)
protected resetCameraNoEvent(): void;
// (undocumented)
Expand All @@ -1989,14 +2003,20 @@ export class Viewport implements IViewport {
// (undocumented)
setActors(actors: Array<ActorEntry>): void;
// (undocumented)
setCamera(cameraInterface: ICamera): void;
setCamera(cameraInterface: ICamera, storeAsInitialCamera?: boolean): void;
// (undocumented)
protected setCameraNoEvent(camera: ICamera): void;
// (undocumented)
protected setInitialCamera(camera: ICamera): void;
// (undocumented)
setOptions(options: ViewportInputOptions, immediate?: boolean): void;
// (undocumented)
setOrientationOfClippingPlanes(vtkPlanes: Array<vtkPlane>, slabThickness: number, viewPlaneNormal: Point3, focalPoint: Point3): void;
// (undocumented)
setPan(pan: Point2, storeAsInitialCamera?: boolean): void;
// (undocumented)
setZoom(value: number, storeAsInitialCamera?: boolean): void;
// (undocumented)
sHeight: number;
// (undocumented)
readonly suppressEvents: boolean;
Expand Down
6 changes: 5 additions & 1 deletion common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -893,17 +893,21 @@ interface IViewport {
_getCorners(bounds: Array<number>): Array<number>[];
getDefaultActor(): ActorEntry;
getFrameOfReferenceUID: () => string;
getPan(): Point2;
getRenderer(): void;
getRenderingEngine(): any;
getZoom(): number;
id: string;
options: ViewportInputOptions;
removeAllActors(): void;
render(): void;
renderingEngineId: string;
reset(immediate: boolean): void;
setActors(actors: Array<ActorEntry>): void;
setCamera(cameraInterface: ICamera): void;
setCamera(cameraInterface: ICamera, storeAsInitialCamera?: boolean): void;
setOptions(options: ViewportInputOptions, immediate: boolean): void;
setPan(pan: Point2, storeAsInitialCamera?: boolean);
setZoom(zoom: number, storeAsInitialCamera?: boolean);
sHeight: number;
suppressEvents: boolean;
sWidth: number;
Expand Down
16 changes: 14 additions & 2 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,9 @@ function createToolGroup(toolGroupId: string): IToolGroup | undefined;
// @public (undocumented)
function createVOISynchronizer(synchronizerName: string): Synchronizer;

// @public (undocumented)
function createZoomPanSynchronizer(synchronizerName: string): Synchronizer;

// @public (undocumented)
export class CrosshairsTool extends AnnotationTool {
constructor(toolProps?: PublicToolProps, defaultToolProps?: ToolProps);
Expand Down Expand Up @@ -2369,17 +2372,21 @@ interface IViewport {
_getCorners(bounds: Array<number>): Array<number>[];
getDefaultActor(): ActorEntry;
getFrameOfReferenceUID: () => string;
getPan(): Point2;
getRenderer(): void;
getRenderingEngine(): any;
getZoom(): number;
id: string;
options: ViewportInputOptions;
removeAllActors(): void;
render(): void;
renderingEngineId: string;
reset(immediate: boolean): void;
setActors(actors: Array<ActorEntry>): void;
setCamera(cameraInterface: ICamera): void;
setCamera(cameraInterface: ICamera, storeAsInitialCamera?: boolean): void;
setOptions(options: ViewportInputOptions, immediate: boolean): void;
setPan(pan: Point2, storeAsInitialCamera?: boolean);
setZoom(zoom: number, storeAsInitialCamera?: boolean);
sHeight: number;
suppressEvents: boolean;
sWidth: number;
Expand Down Expand Up @@ -3988,6 +3995,8 @@ export class Synchronizer {
// (undocumented)
destroy(): void;
// (undocumented)
getOptions(viewportId: string): Record<string, unknown> | undefined;
// (undocumented)
getSourceViewports(): Array<Types_2.IViewportId>;
// (undocumented)
getTargetViewports(): Array<Types_2.IViewportId>;
Expand All @@ -4005,6 +4014,8 @@ export class Synchronizer {
removeSource(viewportInfo: Types_2.IViewportId): void;
// (undocumented)
removeTarget(viewportInfo: Types_2.IViewportId): void;
// (undocumented)
setOptions(viewportId: string, options?: Record<string, unknown>): void;
}

declare namespace SynchronizerManager {
Expand All @@ -4022,7 +4033,8 @@ export { SynchronizerManager }
declare namespace synchronizers {
export {
createCameraPositionSynchronizer,
createVOISynchronizer
createVOISynchronizer,
createZoomPanSynchronizer
}
}
export { synchronizers }
Expand Down
162 changes: 162 additions & 0 deletions packages/core/examples/programaticPanZoom/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import {
getRenderingEngine,
RenderingEngine,
Types,
Enums,
} from '@cornerstonejs/core';
import {
initDemo,
createImageIdsAndCacheMetaData,
setTitleAndDescription,
ctVoiRange,
addButtonToToolbar,
} from '../../../../utils/demo/helpers';

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

const { ViewportType } = Enums;
const renderingEngineId = 'myRenderingEngine';
const viewportId = 'CT_STACK';

// ======== Set up page ======== //
setTitleAndDescription(
'Programmatic Pan and Zoom with initial pan and zoom',
'Displays an image at the top of the viewport, half off the screen, and has pan/zoom buttons.'
);

const content = document.getElementById('content');
const element = document.createElement('div');
element.id = 'cornerstone-element';
element.style.width = '500px';
element.style.height = '500px';

content.appendChild(element);
// ============================= //
addButtonToToolbar({
title: 'Set Pan (+5,0)',
onClick: () => {
// Get the rendering engine
const renderingEngine = getRenderingEngine(renderingEngineId);

// Get the stack viewport
const viewport = <Types.IVolumeViewport>(
renderingEngine.getViewport(viewportId)
);

const pan = viewport.getPan();
console.log('Current pan', JSON.stringify(pan));
viewport.setPan([pan[0] + 5, pan[1]]);
viewport.render();
},
});

addButtonToToolbar({
title: 'Set zoom * 1.05 ',
onClick: () => {
// Get the rendering engine
const renderingEngine = getRenderingEngine(renderingEngineId);

// Get the stack viewport
const viewport = <Types.IVolumeViewport>(
renderingEngine.getViewport(viewportId)
);

const zoom = viewport.getZoom();
console.log('Current zoom', zoom);
viewport.setZoom(zoom * 1.05);
viewport.render();
},
});

addButtonToToolbar({
title: 'Reset Original',
onClick: () => {
// Get the rendering engine
const renderingEngine = getRenderingEngine(renderingEngineId);

// Get the stack viewport
const viewport = <Types.IVolumeViewport>(
renderingEngine.getViewport(viewportId)
);
//viewport.resetCamera();
viewport.setZoom(1);
viewport.setPan([0, 0]);
viewport.render();
},
});

// This can be used to see how the reset works
// Compare a reset before and after having done this
addButtonToToolbar({
title: 'Set current offset/size as pan 0,0/zoom 1',
onClick: () => {
// Get the rendering engine
const renderingEngine = getRenderingEngine(renderingEngineId);

// Get the stack viewport
const viewport = <Types.IVolumeViewport>(
renderingEngine.getViewport(viewportId)
);
viewport.setZoom(viewport.getZoom(), true);
},
});

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

// 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.334240657131972136850343327463',
SeriesInstanceUID:
'1.3.6.1.4.1.14519.5.2.1.7009.2403.226151125820845824875394858561',
wadoRsRoot: 'https://d1qmxk7r72ysft.cloudfront.net/dicomweb',
type: 'STACK',
});

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

// Create a stack viewport
const viewportInput = {
viewportId,
type: ViewportType.STACK,
element,
defaultOptions: {
background: <Types.Point3>[0.2, 0, 0.2],
},
};

renderingEngine.enableElement(viewportInput);

// Get the stack viewport that was created
const viewport = <Types.IStackViewport>(
renderingEngine.getViewport(viewportId)
);

// Define a stack containing a single image
const stack = [imageIds[0]];

// Set the stack on the viewport
await viewport.setStack(stack);

// Set the VOI of the stack
viewport.setProperties({ voiRange: ctVoiRange });

// Render the image
viewport.render();

viewport.setZoom(0.8);
viewport.setPan([-128, 0]);
// Second one should have no affect
viewport.setPan([-128, 0]);
}

run();
Loading

0 comments on commit 2fd6c98

Please sign in to comment.