Skip to content

Commit

Permalink
feat: Add cleaning for tools after viewport disabling (#139)
Browse files Browse the repository at this point in the history
* feat: Added cleaning for tools after viewport disabling

* Added CSWIL flag to not force floatToInt conversion

* Cleaning svg layer after viewport disable

* Removing viewport from synchronizer manager
  • Loading branch information
sedghi authored Jun 17, 2021
1 parent 27bfea7 commit a138fd0
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 120 deletions.
68 changes: 27 additions & 41 deletions packages/cornerstone-render/src/RenderingEngine/RenderingEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ class RenderingEngine implements IRenderingEngine {
this.uid = uid ? uid : uuidv4()
renderingEngineCache.set(this)

this.offscreenMultiRenderWindow = vtkOffscreenMultiRenderWindow.newInstance()
this.offscreenMultiRenderWindow =
vtkOffscreenMultiRenderWindow.newInstance()
this.offScreenCanvasContainer = document.createElement('div')
this.offscreenMultiRenderWindow.setContainer(this.offScreenCanvasContainer)
this._scenes = new Map()
Expand Down Expand Up @@ -133,10 +134,8 @@ class RenderingEngine implements IRenderingEngine {
canvases.push(viewportInputEntry.canvas)

// 2.a Calculating the new size for offScreen Canvas
const {
offScreenCanvasWidth,
offScreenCanvasHeight,
} = this._resizeOffScreenCanvas(canvases)
const { offScreenCanvasWidth, offScreenCanvasHeight } =
this._resizeOffScreenCanvas(canvases)

// 2.b Re-position previous viewports on the offScreen Canvas based on the new
// offScreen canvas size
Expand Down Expand Up @@ -190,22 +189,22 @@ class RenderingEngine implements IRenderingEngine {
// 1. Getting the viewport to remove it
const viewport = this.getViewport(viewportUID)

// 1.a To throw if there is no viewport stored in rendering engine
// 2 To throw if there is no viewport stored in rendering engine
if (!viewport) {
console.warn(`viewport ${viewportUID} does not exist`)
return
}

// 1.b Remove the requested viewport from the rendering engine
this._removeViewport(viewportUID)
// 3. Reset the viewport to remove attributes, and reset the canvas
this._resetViewport(viewport)

// 2. Remove the related renderer from the offScreenMultiRenderWindow
// 4. Remove the related renderer from the offScreenMultiRenderWindow
this.offscreenMultiRenderWindow.removeRenderer(viewportUID)

// 3. Reset the viewport to remove attributes, and reset the canvas
this._resetViewport(viewport)
// 5. Remove the requested viewport from the rendering engine
this._removeViewport(viewportUID)

// 4. Resize the offScreen canvas to accommodate for the new size (after removal)
// 6. Resize the offScreen canvas to accommodate for the new size (after removal)
this.resize()
}

Expand Down Expand Up @@ -263,13 +262,8 @@ class RenderingEngine implements IRenderingEngine {
offScreenCanvasHeight: number,
_xOffset: number
): void {
const {
canvas,
sceneUID,
viewportUID,
type,
defaultOptions,
} = viewportInputEntry
const { canvas, sceneUID, viewportUID, type, defaultOptions } =
viewportInputEntry

// 1. Calculate the size of location of the viewport on the offScreen canvas
const {
Expand Down Expand Up @@ -375,10 +369,8 @@ class RenderingEngine implements IRenderingEngine {
const canvases = viewportInputEntries.map((vp) => vp.canvas)

// 2. Set canvas size based on height and sum of widths
const {
offScreenCanvasWidth,
offScreenCanvasHeight,
} = this._resizeOffScreenCanvas(canvases)
const { offScreenCanvasWidth, offScreenCanvasHeight } =
this._resizeOffScreenCanvas(canvases)

/*
TODO: Commenting this out until we can mock the Canvas usage in the tests (or use jsdom?)
Expand Down Expand Up @@ -505,10 +497,8 @@ class RenderingEngine implements IRenderingEngine {
const canvases = viewports.map((vp) => vp.canvas)

// 2. Recalculate and resize the offscreen canvas size
const {
offScreenCanvasWidth,
offScreenCanvasHeight,
} = this._resizeOffScreenCanvas(canvases)
const { offScreenCanvasWidth, offScreenCanvasHeight } =
this._resizeOffScreenCanvas(canvases)

// 3. Recalculate the viewports location on the off screen canvas
this._resize(viewports, offScreenCanvasWidth, offScreenCanvasHeight)
Expand Down Expand Up @@ -715,7 +705,8 @@ class RenderingEngine implements IRenderingEngine {

renderWindow.render()

const openGLRenderWindow = offscreenMultiRenderWindow.getOpenGLRenderWindow()
const openGLRenderWindow =
offscreenMultiRenderWindow.getOpenGLRenderWindow()
const context = openGLRenderWindow.get3DContext()

const offScreenCanvas = context.canvas
Expand Down Expand Up @@ -821,15 +812,8 @@ class RenderingEngine implements IRenderingEngine {
viewport: StackViewport | VolumeViewport,
offScreenCanvas
) {
const {
sx,
sy,
sWidth,
sHeight,
uid,
sceneUID,
renderingEngineUID,
} = viewport
const { sx, sy, sWidth, sHeight, uid, sceneUID, renderingEngineUID } =
viewport

const canvas = <HTMLCanvasElement>viewport.canvas
const { width: dWidth, height: dHeight } = canvas
Expand Down Expand Up @@ -877,16 +861,17 @@ class RenderingEngine implements IRenderingEngine {
renderingEngineUID,
}

// Trigger first before removing the data attributes, as we need the enabled
// element to remove tools associated with the viewport
triggerEvent(eventTarget, EVENTS.ELEMENT_DISABLED, eventData)

canvas.removeAttribute('data-viewport-uid')
canvas.removeAttribute('data-scene-uid')
canvas.removeAttribute('data-rendering-engine-uid')
// todo: remove svg layer

// clear drawing
const context = canvas.getContext('2d')
context.clearRect(0, 0, canvas.width, canvas.height)

triggerEvent(eventTarget, EVENTS.ELEMENT_DISABLED, eventData)
}

/**
Expand Down Expand Up @@ -961,7 +946,8 @@ class RenderingEngine implements IRenderingEngine {
}

renderWindow.render()
const openGLRenderWindow = offscreenMultiRenderWindow.getOpenGLRenderWindow()
const openGLRenderWindow =
offscreenMultiRenderWindow.getOpenGLRenderWindow()
const context = openGLRenderWindow.get3DContext()

const offScreenCanvas = context.canvas
Expand Down
52 changes: 33 additions & 19 deletions packages/cornerstone-render/src/RenderingEngine/StackViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,42 @@ const EPSILON = 1e-4
interface ImageDataMetaData {
bitsAllocated: number
numComps: number
origin: [number, number, number]
origin: Point3
direction: Float32Array
dimensions: [number, number, number]
spacing: [number, number, number]
dimensions: Point3
spacing: Point3
numVoxels: number
}

type PetScaling = {
suvbwToSuvlbm?: number
suvbwToSuvbsa?: number
}

type Scaling = {
PET?: PetScaling
}

type PublicImageData = {
dimensions: Point3
direction: Float32Array
scalarData: Float32Array
vtkImageData: vtkImageData
metadata: { Modality: string }
scaling?: Scaling
}
/**
* An object representing a single viewport, which is a camera
* looking into a scene, and an associated target output `canvas`.
*/
class StackViewport extends Viewport {
private imageIds: Array<string>
private currentImageIdIndex: number
// private _stackActors: Map<string, any>
private _imageData: any // vtk image data
private _imageData: vtkImageData // vtk image data
private stackActorVOI: VOIRange
public modality: string // this is needed for tools
public scaling: any
loadCallbacks: any
public scaling: Scaling
loadCallbacks: (({ volumeActor: vtkVolume }) => void)[]
panCache: Point3
cameraPosOnRender: Point3

Expand All @@ -67,8 +79,8 @@ class StackViewport extends Viewport {
sliceNormal,
viewUp,
}: {
sliceNormal: [number, number, number]
viewUp: [number, number, number]
sliceNormal: Point3
viewUp: Point3
} = this.defaultOptions.orientation

camera.setDirectionOfProjection(
Expand All @@ -88,7 +100,7 @@ class StackViewport extends Viewport {
this.resetCamera()
}

public getImageData(): any {
public getImageData(): PublicImageData {
const { volumeActor } = this.getDefaultActor()
const vtkImageData = volumeActor.getMapper().getInputData()
return {
Expand Down Expand Up @@ -199,7 +211,7 @@ class StackViewport extends Viewport {
this._addScalingToViewport(imageIdScalingFactor)
}

// todo: some tools rely on the modality, i'm passing modality like this for now
// todo: some tools rely on the modality
this.modality = modality
// Compute the image size and spacing given the meta data we already have available.
// const metaDataMap = new Map()
Expand Down Expand Up @@ -269,8 +281,8 @@ class StackViewport extends Viewport {
rowCosines,
columnCosines,
}: {
rowCosines: [number, number, number]
columnCosines: [number, number, number]
rowCosines: Point3
columnCosines: Point3
} = imagePlaneModule

const rowCosineVec = vec3.fromValues(...rowCosines)
Expand Down Expand Up @@ -313,7 +325,7 @@ class StackViewport extends Viewport {
}
}

private _getCameraOrientation(imageDataDirection: Array<number>): {
private _getCameraOrientation(imageDataDirection: Float32Array): {
viewPlaneNormal: Point3
viewUp: Point3
} {
Expand Down Expand Up @@ -378,7 +390,7 @@ class StackViewport extends Viewport {
imageIds: Array<string>,
currentImageIdIndex = 0,
callbacks = []
): any {
): void {
this.imageIds = imageIds
this.currentImageIdIndex = currentImageIdIndex

Expand Down Expand Up @@ -431,7 +443,7 @@ class StackViewport extends Viewport {
const imagePlaneModule = metaData.get('imagePlaneModule', image.imageId)
const origin = imagePlaneModule.imagePositionPatient

this._imageData.setOrigin(...origin)
this._imageData.setOrigin(origin)
// 1. Update the pixel data in the vtkImageData object with the pixelData
// from the loaded Cornerstone image
const pixelData = image.getPixelData()
Expand Down Expand Up @@ -473,9 +485,11 @@ class StackViewport extends Viewport {
const eventData = {
image,
imageId,
viewportUID: this.uid,
renderingEngineUID: this.renderingEngineUID,
}

triggerEvent(eventTarget, EVENTS.STACK_NEW_IMAGE, eventData)
triggerEvent(this.canvas, EVENTS.STACK_NEW_IMAGE, eventData)

this._updateActorToDisplayImageId(image)

Expand Down Expand Up @@ -577,7 +591,7 @@ class StackViewport extends Viewport {

// Adjusting the camera based on slice axis. this is required if stack
// contains various image orientations (axial ct, sagittal xray)
const direction = this._imageData.getDirection()
const direction = this._imageData.getDirection() as Float32Array
const { viewPlaneNormal, viewUp } = this._getCameraOrientation(direction)

this.setCamera({ viewUp, viewPlaneNormal })
Expand Down Expand Up @@ -631,7 +645,7 @@ class StackViewport extends Viewport {
this.setActors([{ uid: this.uid, volumeActor: stackActor }])
// Adjusting the camera based on slice axis. this is required if stack
// contains various image orientations (axial ct, sagittal xray)
const direction = this._imageData.getDirection()
const direction = this._imageData.getDirection() as Float32Array
const { viewPlaneNormal, viewUp } = this._getCameraOrientation(direction)

this.setCamera({ viewUp, viewPlaneNormal })
Expand Down
2 changes: 2 additions & 0 deletions packages/cornerstone-render/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ import type IStreamingImageVolume from './IStreamingImageVolume'
import type ViewportInputOptions from './ViewportInputOptions'
import type IImage from './IImage'
import type ScalingParameters from './ScalingParameters'
import type IViewportUID from './IViewportUID'

export type {
ICamera,
IEnabledElement,
ICache,
IVolume,
IViewportUID,
IImageVolume,
ScalingParameters,
IStreamingImageVolume,
Expand Down
Loading

0 comments on commit a138fd0

Please sign in to comment.