diff --git a/packages/cornerstone-render/src/RenderingEngine/Viewport.ts b/packages/cornerstone-render/src/RenderingEngine/Viewport.ts
index 69f22d11ee..802e07c4c4 100644
--- a/packages/cornerstone-render/src/RenderingEngine/Viewport.ts
+++ b/packages/cornerstone-render/src/RenderingEngine/Viewport.ts
@@ -346,7 +346,7 @@ class Viewport {
     this._suppressCameraModifiedEvents = false
   }
 
-  protected setCameraNoEvent(camera: ICamera) {
+  protected setCameraNoEvent(camera: ICamera): void {
     this._suppressCameraModifiedEvents = true
     this.setCamera(camera)
     this._suppressCameraModifiedEvents = false
@@ -621,7 +621,7 @@ class Viewport {
       //
       // Compensating for the flipped viewport. Since our method for flipping is
       // flipping the actor matrix itself, the focal point won't change; therefore,
-      // we need to accomodate for this required change elsewhere
+      // we need to accommodate for this required change elsewhere
       // vec3.sub(dir, viewport.applyFlipTx(focalPoint), point)
       position: <Point3>this.applyFlipTx(vtkCamera.getPosition() as Point3),
       focalPoint: <Point3>this.applyFlipTx(vtkCamera.getFocalPoint() as Point3),
diff --git a/packages/cornerstone-render/src/types/Plane.ts b/packages/cornerstone-render/src/types/Plane.ts
new file mode 100644
index 0000000000..2ab94696c2
--- /dev/null
+++ b/packages/cornerstone-render/src/types/Plane.ts
@@ -0,0 +1,4 @@
+// Plane equation Ax+By+Cz=D, plane is defined by [A, B, C, D]
+type Plane = [number, number, number, number]
+
+export default Plane
diff --git a/packages/cornerstone-render/src/types/index.ts b/packages/cornerstone-render/src/types/index.ts
index 2c261854cb..2279980d5f 100644
--- a/packages/cornerstone-render/src/types/index.ts
+++ b/packages/cornerstone-render/src/types/index.ts
@@ -24,6 +24,7 @@ import type Orientation from './Orientation'
 import type Point2 from './Point2'
 import type Point3 from './Point3'
 import type Point4 from './Point4'
+import type Plane from './Plane'
 import type IStreamingImageVolume from './IStreamingImageVolume'
 import type ViewportInputOptions from './ViewportInputOptions'
 import type IImageData from './IImageData'
@@ -85,6 +86,7 @@ export type {
   Point2,
   Point3,
   Point4,
+  Plane,
   ViewportInputOptions,
   VOIRange,
   VOI,
diff --git a/packages/cornerstone-render/src/utilities/planar.ts b/packages/cornerstone-render/src/utilities/planar.ts
index f3994b1e58..fd2f7cf373 100644
--- a/packages/cornerstone-render/src/utilities/planar.ts
+++ b/packages/cornerstone-render/src/utilities/planar.ts
@@ -1,18 +1,15 @@
-import { Point3 } from '../types'
+import { Point3, Plane } from '../types'
+import { vec3, mat3 } from 'gl-matrix'
 
 /**
  * It calculates the intersection of a line and a plane.
  * Plane equation is Ax+By+Cz=D
  * @param p0 [x,y,z] of the first point of the line
  * @param p1 [x,y,z] of the second point of the line
- * @param plane [A, B, C, D] Plane parameter
+ * @param plane [A, B, C, D] Plane parameter: Ax+By+Cz=D
  * @returns [X,Y,Z] coordinates of the intersection
  */
-function linePlaneIntersection(
-  p0: Point3,
-  p1: Point3,
-  plane: [number, number, number, number]
-): Point3 {
+function linePlaneIntersection(p0: Point3, p1: Point3, plane: Plane): Point3 {
   const [x0, y0, z0] = p0
   const [x1, y1, z1] = p1
   const [A, B, C, D] = plane
@@ -27,8 +24,49 @@ function linePlaneIntersection(
   return [X, Y, Z]
 }
 
+/**
+ *
+ * @param normal normal vector
+ * @param point a point on the plane
+ * @returns [A, B,C, D] of plane equation A*X + B*Y + C*Z = D
+ */
+function planeEquation(normal: Point3, point: Point3 | vec3): Plane {
+  const [A, B, C] = normal
+  const D = A * point[0] + B * point[1] + C * point[2]
+  return [A, B, C, D]
+}
+
+/**
+ * Computes the intersection of three planes in 3D space with equations:
+ * A1*X + B1*Y + C1*Z = D1
+ * A2*X + B2*Y + C2*Z = D2
+ * A3*X + B3*Y + C3*Z = D3
+ * @returns {x, y, z} the intersection in the world coordinate
+ */
+function threePlaneIntersection(
+  firstPlane: Plane,
+  secondPlane: Plane,
+  thirdPlane: Plane
+): Point3 {
+  const [A1, B1, C1, D1] = firstPlane
+  const [A2, B2, C2, D2] = secondPlane
+  const [A3, B3, C3, D3] = thirdPlane
+  const m0 = mat3.fromValues(A1, A2, A3, B1, B2, B3, C1, C2, C3)
+  const m1 = mat3.fromValues(D1, D2, D3, B1, B2, B3, C1, C2, C3)
+  const m2 = mat3.fromValues(A1, A2, A3, D1, D2, D3, C1, C2, C3)
+  const m3 = mat3.fromValues(A1, A2, A3, B1, B2, B3, D1, D2, D3)
+
+  // TODO: handle no intersection scenario
+  const x = mat3.determinant(m1) / mat3.determinant(m0)
+  const y = mat3.determinant(m2) / mat3.determinant(m0)
+  const z = mat3.determinant(m3) / mat3.determinant(m0)
+  return [x, y, z]
+}
+
 const planar = {
   linePlaneIntersection,
+  planeEquation,
+  threePlaneIntersection,
 }
 
 export default planar
diff --git a/packages/cornerstone-tools/src/eventDispatchers/cameraModifiedEventDispatcher.ts b/packages/cornerstone-tools/src/eventDispatchers/cameraModifiedEventDispatcher.ts
index 34735e1b2c..00bbc6e1c4 100644
--- a/packages/cornerstone-tools/src/eventDispatchers/cameraModifiedEventDispatcher.ts
+++ b/packages/cornerstone-tools/src/eventDispatchers/cameraModifiedEventDispatcher.ts
@@ -19,8 +19,6 @@ const onCameraModified = function (evt) {
     Enabled,
   ])
 
-  // todo: this will trigger crosshair tool onCameraModified in cases
-  // where crosshair is not active, shall we only filter active?
   enabledTools.forEach((tool) => {
     if (tool.onCameraModified) {
       tool.onCameraModified(evt)
diff --git a/packages/cornerstone-tools/src/store/ToolGroupManager/createToolGroup.ts b/packages/cornerstone-tools/src/store/ToolGroupManager/createToolGroup.ts
index 88d6990df5..9a9438b6dc 100644
--- a/packages/cornerstone-tools/src/store/ToolGroupManager/createToolGroup.ts
+++ b/packages/cornerstone-tools/src/store/ToolGroupManager/createToolGroup.ts
@@ -1,10 +1,10 @@
-import { ToolBindings } from '../../enums'
+import { ToolBindings, ToolModes } from '../../enums'
 import { getRenderingEngine } from '@ohif/cornerstone-render'
 import { state } from '../index'
 import IToolGroup from './IToolGroup'
 import ISetToolModeOptions from '../../types/ISetToolModeOptions'
-import ToolModes from '../../enums/ToolModes'
 import deepmerge from '../../util/deepMerge'
+
 import { MouseCursor, SVGMouseCursor } from '../../cursors'
 import { initElementCursor } from '../../cursors/elementCursor'
 
@@ -154,6 +154,10 @@ function createToolGroup(toolGroupId: string): IToolGroup | undefined {
       if (this.isPrimaryButtonBinding(toolModeOptions)) {
         this.resetViewportsCursor(this._toolInstances[toolName])
       }
+
+      if (typeof this._toolInstances[toolName].init === 'function') {
+        this._toolInstances[toolName].init(this.viewports)
+      }
       this.refreshViewports()
     },
     setToolPassive: function (
diff --git a/packages/cornerstone-tools/src/tools/CrosshairsTool.ts b/packages/cornerstone-tools/src/tools/CrosshairsTool.ts
index f34ef43ca2..2fd03143f4 100644
--- a/packages/cornerstone-tools/src/tools/CrosshairsTool.ts
+++ b/packages/cornerstone-tools/src/tools/CrosshairsTool.ts
@@ -1,7 +1,16 @@
 import { BaseAnnotationTool } from './base'
 // ~~ VTK Viewport
-import { getEnabledElement, RenderingEngine } from '@ohif/cornerstone-render'
-import { addToolState, getToolState } from '../stateManagement/toolState'
+import {
+  getEnabledElement,
+  RenderingEngine,
+  getRenderingEngine,
+  Utilities as csUtils,
+} from '@ohif/cornerstone-render'
+import {
+  addToolState,
+  getToolState,
+  removeToolStateByToolDataUID,
+} from '../stateManagement/toolState'
 import {
   drawCircle as drawCircleSvg,
   drawHandles as drawHandlesSvg,
@@ -22,7 +31,6 @@ import {
   Point2,
   Point3,
 } from '../types'
-import { ToolGroupManager } from '../store'
 import { isToolDataLocked } from '../stateManagement/toolDataLocking'
 import triggerAnnotationRenderForViewportUIDs from '../util/triggerAnnotationRenderForViewportUIDs'
 
@@ -40,6 +48,12 @@ interface ToolConfiguration {
   }
 }
 
+type ViewportInput = {
+  renderingEngineUID: string
+  viewportUID: string
+}
+type ViewportInputs = Array<ViewportInput>
+
 interface CrosshairsSpecificToolData extends ToolSpecificToolData {
   data: {
     handles: {
@@ -128,65 +142,189 @@ export default class CrosshairsTool extends BaseAnnotationTool {
     this._mouseDragCallback = this._mouseDragCallback.bind(this)
   }
 
-  addNewMeasurement(
-    evt: CustomEvent,
-    interactionType: string
-  ): CrosshairsSpecificToolData {
-    // not used, but is necessary if BaseAnnotationTool.
-    // NOTE: this is a BaseAnnotationTool and not a BaseTool, because in future
-    // we will likely pre-filter all tools using typeof / instanceof
-    // in the mouse down dispatchers where we check for methods like pointNearTool.
-    const toolSpecificToolData = {
+  /**
+   * Gets the camera from the viewport, and adds crosshairs toolData for the viewport
+   * to the toolStateManager. If any toolData is found in the toolStateManager, it
+   * overwrites it.
+   * @param {renderingEngineUID, viewportUID}
+   * @returns {normal, point} viewPlaneNormal and center of viewport canvas in world space
+   */
+  initializeViewport = ({
+    renderingEngineUID,
+    viewportUID,
+  }: ViewportInput): {
+    normal: Point3
+    point: Point3
+  } => {
+    const renderingEngine = getRenderingEngine(renderingEngineUID)
+    const viewport = renderingEngine.getViewport(viewportUID)
+    const { element } = viewport
+    const enabledElement = getEnabledElement(element)
+    const { FrameOfReferenceUID, sceneUID } = enabledElement
+    const { position, focalPoint, viewPlaneNormal } = viewport.getCamera()
+
+    // Check if there is already toolData for this viewport
+    let toolState = getToolState(enabledElement, this.name)
+    toolState = this.filterInteractableToolStateForElement(element, toolState)
+
+    if (toolState.length) {
+      // If found, it will override it by removing the toolData and adding it later
+      removeToolStateByToolDataUID(element, toolState[0].metadata.toolDataUID)
+    }
+
+    const toolData = {
       metadata: {
-        viewPlaneNormal: <Point3>[0, 0, 0],
-        viewUp: <Point3>[0, 0, 0],
-        toolDataUID: '1',
-        FrameOfReferenceUID: '1',
-        referencedImageId: '1',
+        cameraPosition: <Point3>[...position],
+        cameraFocalPoint: <Point3>[...focalPoint],
+        FrameOfReferenceUID,
         toolName: this.name,
       },
       data: {
         handles: {
           rotationPoints: [], // rotation handles, used for rotation interactions
           slabThicknessPoints: [], // slab thickness handles, used for setting the slab thickness
-          activeOperation: null, // 0 translation, 1 rotation handles, 2 slab thickness handles
-          toolCenter: <Point3>[0, 0, 0], // Used in testings
+          toolCenter: this.toolCenter,
         },
         active: false,
+        // Todo: add enum for active Operations
+        activeOperation: null, // 0 translation, 1 rotation handles, 2 slab thickness handles
         activeViewportUIDs: [], // a list of the viewport uids connected to the reference lines being translated
-        viewportUID: '1',
-        sceneUID: '1',
+        viewportUID,
+        sceneUID,
       },
     }
 
-    return toolSpecificToolData
+    resetElementCursor(element)
+
+    addToolState(element, toolData)
+
+    return {
+      normal: viewPlaneNormal,
+      point: viewport.canvasToWorld([
+        viewport.sWidth / 2,
+        viewport.sHeight / 2,
+      ]),
+    }
   }
 
-  cancel = () => {
-    console.log('Not implemented yet')
+  /**
+   * When activated, it initializes the crosshairs. It begins by computing
+   * the intersection of viewports associated with the crosshairs instance.
+   * When all three views are accessible, the intersection (e.g., crosshairs tool centre)
+   * will be an exact point in space; however, with two viewports, because the
+   * intersection of two planes is a line, it assumes the last view is between the centre
+   * of the two rendering viewports.
+   * @param viewports Array of viewportInputs which each item containing {viewportUID, renderingEngineUID}
+   */
+  init = (viewports: ViewportInputs): void => {
+    if (!viewports.length || viewports.length === 1) {
+      throw new Error(
+        'For crosshairs to operate, at least two viewports must be given.'
+      )
+    }
+
+    // Todo: handle two same view viewport, or more than 3 viewports
+    const [firstViewport, secondViewport, thirdViewport] = viewports
+
+    // Initialize first viewport
+    const { normal: normal1, point: point1 } =
+      this.initializeViewport(firstViewport)
+
+    // Initialize second viewport
+    const { normal: normal2, point: point2 } =
+      this.initializeViewport(secondViewport)
+
+    let normal3 = <Point3>[0, 0, 0]
+    let point3 = vec3.create()
+
+    // If there are three viewports
+    if (thirdViewport) {
+      ;({ normal: normal3, point: point3 } =
+        this.initializeViewport(thirdViewport))
+    } else {
+      // If there are only two views (viewport) associated with the crosshairs:
+      // In this situation, we don't have a third information to find the
+      // exact intersection, and we "assume" the third view is looking at
+      // a location in between the first and second view centers
+      vec3.add(point3, point1, point2)
+      vec3.scale(point3, point3, 0.5)
+      vec3.cross(normal3, normal1, normal2)
+    }
+
+    // Planes of each viewport
+    const firstPlane = csUtils.planar.planeEquation(normal1, point1)
+    const secondPlane = csUtils.planar.planeEquation(normal2, point2)
+    const thirdPlane = csUtils.planar.planeEquation(normal3, point3)
+
+    // Calculating the intersection of 3 planes
+    // prettier-ignore
+    this.toolCenter = csUtils.planar.threePlaneIntersection(firstPlane, secondPlane, thirdPlane)
   }
 
-  getHandleNearImagePoint = (element, toolData, canvasCoords, proximity) => {
-    // We need a better way of surfacing this...
-    const {
-      viewportUid: viewportUID,
-      sceneUid: sceneUID,
-      renderingEngineUid: renderingEngineUID,
-    } = element.dataset
-    const toolGroups = ToolGroupManager.getToolGroups(
-      renderingEngineUID,
-      sceneUID,
-      viewportUID
+  /**
+   * For Crosshairs it handle the click event.
+   * @param evt
+   * @param interactionType
+   * @returns
+   */
+  addNewMeasurement(
+    evt: CustomEvent,
+    interactionType: string
+  ): CrosshairsSpecificToolData {
+    const eventData = evt.detail
+    const { element } = eventData
+
+    const { currentPoints } = eventData
+    const jumpWorld = currentPoints.world
+
+    const enabledElement = getEnabledElement(element)
+    const { viewport } = enabledElement
+    this._jump(enabledElement, jumpWorld)
+
+    const toolState = getToolState(enabledElement, this.name)
+    const filteredToolState = this.filterInteractableToolStateForElement(
+      viewport.element,
+      toolState
     )
-    const groupTools = toolGroups[0]?.toolOptions
-    const mode = groupTools[this.name]?.mode
 
-    // We don't want this annotation tool to render or be interactive unless its
-    // active
-    if (mode !== 'Active') {
-      return undefined
+    // viewport ToolData
+    const { data } = filteredToolState[0]
+
+    const { rotationPoints } = data.handles
+    const viewportUIDArray = []
+    // put all the draggable reference lines in the viewportUIDArray
+    for (let i = 0; i < rotationPoints.length - 1; ++i) {
+      const otherViewport = rotationPoints[i][1]
+      const viewportControllable = this._getReferenceLineControllable(
+        otherViewport.uid
+      )
+      const viewportDraggableRotatable =
+        this._getReferenceLineDraggableRotatable(otherViewport.uid)
+      if (!viewportControllable || !viewportDraggableRotatable) {
+        continue
+      }
+      viewportUIDArray.push(otherViewport.uid)
+      // rotation handles are two per viewport
+      i++
     }
 
+    data.activeViewportUIDs = [...viewportUIDArray]
+    // set translation operation
+    data.handles.activeOperation = OPERATION.DRAG
+
+    evt.preventDefault()
+
+    hideElementCursor(element)
+
+    this._activateModify(element)
+    return filteredToolState[0]
+  }
+
+  cancel = () => {
+    console.log('Not implemented yet')
+  }
+
+  getHandleNearImagePoint = (element, toolData, canvasCoords, proximity) => {
     const enabledElement = getEnabledElement(element)
     const { viewport } = enabledElement
 
@@ -247,74 +385,7 @@ export default class CrosshairsTool extends BaseAnnotationTool {
     proximity,
     interactionType
   ) => {
-    // We need a better way of surfacing this...
-    const {
-      viewportUid: viewportUID,
-      sceneUid: sceneUID,
-      renderingEngineUid: renderingEngineUID,
-    } = element.dataset
-    const toolGroups = ToolGroupManager.getToolGroups(
-      renderingEngineUID,
-      sceneUID,
-      viewportUID
-    )
-    const groupTools = toolGroups[0]?.toolOptions
-    const mode = groupTools[this.name]?.mode
-
-    // We don't want this annotation tool to render or be interactive unless its
-    // active
-    if (mode !== 'Active') {
-      return false
-    }
-
-    // This iterates all instances of Crosshairs across all toolGroups
-    // And updates `isCrosshairsActive` if ANY are active?
-    let isCrosshairsActive = false
-    for (let i = 0; i < toolGroups.length; ++i) {
-      const toolGroup = toolGroups[i]
-      const tool = toolGroup.toolOptions['Crosshairs']
-
-      if (tool.mode === 'Active') {
-        isCrosshairsActive = true
-        break
-      }
-    }
-
-    const { data } = toolData
     if (this._pointNearTool(element, toolData, canvasCoords, 6)) {
-      return true
-    } else if (data.activeViewportUIDs.length === 0) {
-      const enabledElement = getEnabledElement(element)
-      const { viewport } = enabledElement
-      const jumpWorld = viewport.canvasToWorld(canvasCoords)
-
-      this._jump(enabledElement, jumpWorld)
-
-      const { rotationPoints } = data.handles
-      const viewportUIDArray = []
-      // put all the draggable reference lines in the viewportUIDArray
-      for (let i = 0; i < rotationPoints.length - 1; ++i) {
-        const otherViewport = rotationPoints[i][1]
-        const viewportControllable = this._getReferenceLineControllable(
-          otherViewport.uid
-        )
-        const viewportDraggableRotatable =
-          this._getReferenceLineDraggableRotatable(otherViewport.uid)
-
-        if (!viewportControllable || !viewportDraggableRotatable) {
-          continue
-        }
-
-        viewportUIDArray.push(otherViewport.uid)
-
-        // rotation handles are two for viewport
-        i++
-      }
-
-      data.activeViewportUIDs = [...viewportUIDArray]
-      // set translation operation
-      data.handles.activeOperation = OPERATION.DRAG
-
       return true
     }
 
@@ -336,80 +407,11 @@ export default class CrosshairsTool extends BaseAnnotationTool {
     evt.preventDefault()
   }
 
-  _isCrosshairsActive({ renderingEngineUID, sceneUID, viewportUID }) {
-    const toolGroups = ToolGroupManager.getToolGroups(
-      renderingEngineUID,
-      sceneUID,
-      viewportUID
-    )
-
-    // This iterates all instances of Crosshairs across all toolGroups
-    // And updates `isCrosshairsActive` if ANY are active?
-    let isCrosshairsActive = false
-    for (let i = 0; i < toolGroups.length; ++i) {
-      const toolGroup = toolGroups[i]
-      const tool = toolGroup.toolOptions['Crosshairs']
-
-      if (tool.mode === 'Active') {
-        isCrosshairsActive = true
-        break
-      }
-    }
-
-    // So if none are active, we have nothing to render, and we peace out
-    return isCrosshairsActive
-  }
-
-  _initCrosshairs = (evt, toolState) => {
-    const eventData = evt.detail
-    const { element } = eventData
-    const enabledElement = getEnabledElement(element)
-    const { viewport, FrameOfReferenceUID, viewportUID, sceneUID } =
-      enabledElement
-    const { sHeight, sWidth, canvasToWorld } = viewport
-    const centerCanvas: Point2 = [sWidth * 0.5, sHeight * 0.5]
-
-    // Calculate the crosshair center
-    // NOTE: it is assumed that all the active/linked viewports share the same crosshair center.
-    // This because the rotation operations rotates also all the other active/intersecting reference lines of the same angle
-    this.toolCenter = canvasToWorld(centerCanvas)
-
-    const camera = viewport.getCamera()
-    const { position, focalPoint } = camera
-
-    const toolData = {
-      metadata: {
-        cameraPosition: <Point3>[...position],
-        cameraFocalPoint: <Point3>[...focalPoint],
-        FrameOfReferenceUID,
-        toolName: this.name,
-      },
-      data: {
-        handles: {
-          rotationPoints: [], // rotation handles, used for rotation interactions
-          slabThicknessPoints: [], // slab thickness handles, used for setting the slab thickness
-          toolCenter: this.toolCenter,
-        },
-        active: false,
-        activeOperation: null, // 0 translation, 1 rotation handles, 2 slab thickness handles
-        activeViewportUIDs: [], // a list of the viewport uids connected to the reference lines being translated
-        viewportUID,
-        sceneUID,
-      },
-    }
-
-    // NOTE: rotation handles are initialized in renderTool when drawing.
-
-    addToolState(element, toolData)
-
-    resetElementCursor(element)
-  }
-
   onCameraModified = (evt) => {
     const eventData = evt.detail
     const { element } = eventData
     const enabledElement = getEnabledElement(element)
-    const { FrameOfReferenceUID, renderingEngine, viewport } = enabledElement
+    const { renderingEngine, viewport } = enabledElement
 
     const requireSameOrientation = false
     const viewportUIDsToRender = getViewportUIDsWithToolToRender(
@@ -418,23 +420,12 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       requireSameOrientation
     )
 
-    let toolState = getToolState(enabledElement, this.name)
-    let filteredToolState = this.filterInteractableToolStateForElement(
+    const toolState = getToolState(enabledElement, this.name)
+    const filteredToolState = this.filterInteractableToolStateForElement(
       element,
       toolState
     )
 
-    if (!filteredToolState.length && FrameOfReferenceUID) {
-      this._initCrosshairs(evt, toolState)
-
-      toolState = getToolState(enabledElement, this.name)
-
-      filteredToolState = this.filterInteractableToolStateForElement(
-        element,
-        toolState
-      )
-    }
-
     // viewport ToolData
     const viewportToolData = filteredToolState[0] as CrosshairsSpecificToolData
 
@@ -442,12 +433,6 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       return
     }
 
-    // if (
-    //   !this._isCrosshairsActive({ renderingEngineUID, sceneUID, viewportUID })
-    // ) {
-    //   return
-    // }
-
     // -- Update the camera of other linked viewports in the same scene that
     //    have the same camera in case of translation
     // -- Update the crosshair center in world coordinates in toolData.
@@ -507,34 +492,34 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       ) {
         // update linked view in the same scene that have the same camera
         // this goes here, because the parent viewport translation may happen in another tool
-        const otherLinkedViewportsToolDataWithSameCameraDirection =
-          this._filterLinkedViewportWithSameOrientationAndScene(
-            enabledElement,
-            toolState
-          )
-
-        for (
-          let i = 0;
-          i < otherLinkedViewportsToolDataWithSameCameraDirection.length;
-          ++i
-        ) {
-          const toolData =
-            otherLinkedViewportsToolDataWithSameCameraDirection[i]
-          const { data } = toolData
-          const scene = renderingEngine.getScene(data.sceneUID)
-          const otherViewport = scene.getViewport(data.viewportUID)
-          const camera = otherViewport.getCamera()
-
-          const newFocalPoint = [0, 0, 0]
-          const newPosition = [0, 0, 0]
-
-          vtkMath.add(camera.focalPoint, deltaCameraPosition, newFocalPoint)
-          vtkMath.add(camera.position, deltaCameraPosition, newPosition)
-
-          // updated cached "previous" camera position and focal point
-          toolData.metadata.cameraPosition = [...currentCamera.position]
-          toolData.metadata.cameraFocalPoint = [...currentCamera.focalPoint]
-        }
+        // const otherLinkedViewportsToolDataWithSameCameraDirection =
+        //   this._filterLinkedViewportWithSameOrientationAndScene(
+        //     enabledElement,
+        //     toolState
+        //   )
+
+        // for (
+        //   let i = 0;
+        //   i < otherLinkedViewportsToolDataWithSameCameraDirection.length;
+        //   ++i
+        // ) {
+        //   const toolData =
+        //     otherLinkedViewportsToolDataWithSameCameraDirection[i]
+        //   const { data } = toolData
+        //   const scene = renderingEngine.getScene(data.sceneUID)
+        //   const otherViewport = scene.getViewport(data.viewportUID)
+        //   const camera = otherViewport.getCamera()
+
+        //   const newFocalPoint = [0, 0, 0]
+        //   const newPosition = [0, 0, 0]
+
+        //   vtkMath.add(camera.focalPoint, deltaCameraPosition, newFocalPoint)
+        //   vtkMath.add(camera.position, deltaCameraPosition, newPosition)
+
+        //   // updated cached "previous" camera position and focal point
+        //   toolData.metadata.cameraPosition = [...currentCamera.position]
+        //   toolData.metadata.cameraFocalPoint = [...currentCamera.focalPoint]
+        // }
 
         // update center of the crosshair
         this.toolCenter[0] += deltaCameraPosition[0]
@@ -628,17 +613,6 @@ export default class CrosshairsTool extends BaseAnnotationTool {
   }
 
   renderToolData(evt: CustomEvent, svgDrawingHelper: any): void {
-    const { renderingEngineUID, sceneUID, viewportUID } = evt.detail
-
-    // This iterates all instances of Crosshairs across all toolGroups
-    // And updates `isCrosshairsActive` if ANY are active?
-    // So if none are active, we have nothing to render, and we peace out
-    if (
-      !this._isCrosshairsActive({ renderingEngineUID, sceneUID, viewportUID })
-    ) {
-      return
-    }
-
     const eventData = evt.detail
     const { element } = eventData
     const toolState = getToolState(svgDrawingHelper.enabledElement, this.name)
@@ -724,6 +698,7 @@ export default class CrosshairsTool extends BaseAnnotationTool {
 
       const { focalPoint } = camera
       const focalPointCanvas = viewport.worldToCanvas(focalPoint)
+      // Todo: focalpointCanvas is a lot, how is it doing arithmetics on it??
       const canvasBox = [
         focalPointCanvas - sWidth * 0.5,
         focalPointCanvas + sWidth * 0.5,
@@ -743,7 +718,37 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       )
       vec2.normalize(canvasUnitVectorFromCenter, canvasUnitVectorFromCenter)
 
+      // Graphic:
+      // Mid -> SlabThickness handle
+      // Short -> Rotation handle
+      //                           Long
+      //                            |
+      //                            |
+      //                            |
+      //                           Mid
+      //                            |
+      //                            |
+      //                            |
+      //                          Short
+      //                            |
+      //                            |
+      //                            |
+      // Long --- Mid--- Short--- Center --- Short --- Mid --- Long
+      //                            |
+      //                            |
+      //                            |
+      //                          Short
+      //                            |
+      //                            |
+      //                            |
+      //                           Mid
+      //                            |
+      //                            |
+      //                            |
+      //                           Long
       const canvasVectorFromCenterLong = vec2.create()
+
+      // Todo: configuration should provide constants below (100, 0.25, 0.15, 0.04)
       vec2.scale(
         canvasVectorFromCenterLong,
         canvasUnitVectorFromCenter,
@@ -765,10 +770,11 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       vec2.scale(
         canvasVectorFromCenterStart,
         canvasUnitVectorFromCenter,
-        canvasDiagonalLength * 0.05
+        // Don't put a gap if the the third view is missing
+        otherViewportToolData.length === 2 ? canvasDiagonalLength * 0.04 : 0
       )
 
-      // points for reference lines
+      // Computing Reference start and end (4 lines per viewport in case of 3 view MPR)
       const refLinePointOne = vec2.create()
       const refLinePointTwo = vec2.create()
       const refLinePointThree = vec2.create()
@@ -792,10 +798,12 @@ export default class CrosshairsTool extends BaseAnnotationTool {
         canvasVectorFromCenterLong
       )
 
+      // Clipping lines to be only included in a box (canvas), we don't want
+      // the lines goes beyond canvas
       liangBarksyClip(refLinePointOne, refLinePointTwo, canvasBox)
       liangBarksyClip(refLinePointThree, refLinePointFour, canvasBox)
 
-      // points for rotation handles
+      // Computing rotation handle positions
       const rotHandleOne = vec2.create()
       vec2.subtract(
         rotHandleOne,
@@ -806,21 +814,24 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       const rotHandleTwo = vec2.create()
       vec2.add(rotHandleTwo, crosshairCenterCanvas, canvasVectorFromCenterMid)
 
-      // get world information for lines and points (vertical world distances)
-      let stHanlesCenterCanvas = vec2.clone(crosshairCenterCanvas)
+      // Computing SlabThickness (st below) position
+
+      // SlabThickness center in canvas
+      let stHandlesCenterCanvas = vec2.clone(crosshairCenterCanvas)
       if (
         !otherViewportDraggableRotatable &&
         otherViewportSlabThicknessControlsOn
       ) {
-        stHanlesCenterCanvas = vec2.clone(otherViewportCenterCanvas)
+        stHandlesCenterCanvas = vec2.clone(otherViewportCenterCanvas)
       }
 
-      let stHanlesCenterWorld = [...this.toolCenter]
+      // SlabThickness center in world
+      let stHandlesCenterWorld = [...this.toolCenter]
       if (
         !otherViewportDraggableRotatable &&
         otherViewportSlabThicknessControlsOn
       ) {
-        stHanlesCenterWorld = [...otherViewportCenterWorld]
+        stHandlesCenterWorld = [...otherViewportCenterWorld]
       }
 
       const worldUnitVectorFromCenter: Point3 = [0, 0, 0]
@@ -848,7 +859,7 @@ export default class CrosshairsTool extends BaseAnnotationTool {
 
       const worldVerticalRefPoint: Point3 = [0, 0, 0]
       vtkMath.add(
-        stHanlesCenterWorld,
+        stHandlesCenterWorld,
         worldOrthoVectorFromCenter,
         worldVerticalRefPoint
       )
@@ -862,20 +873,24 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       const canvasOrthoVectorFromCenter = vec2.create()
       vec2.subtract(
         canvasOrthoVectorFromCenter,
-        stHanlesCenterCanvas,
+        stHandlesCenterCanvas,
         canvasVerticalRefPoint
       )
 
       const stLinePointOne = vec2.create()
       vec2.subtract(
         stLinePointOne,
-        stHanlesCenterCanvas,
+        stHandlesCenterCanvas,
         canvasVectorFromCenterLong
       )
       vec2.add(stLinePointOne, stLinePointOne, canvasOrthoVectorFromCenter)
 
       const stLinePointTwo = vec2.create()
-      vec2.add(stLinePointTwo, stHanlesCenterCanvas, canvasVectorFromCenterLong)
+      vec2.add(
+        stLinePointTwo,
+        stHandlesCenterCanvas,
+        canvasVectorFromCenterLong
+      )
       vec2.add(stLinePointTwo, stLinePointTwo, canvasOrthoVectorFromCenter)
 
       liangBarksyClip(stLinePointOne, stLinePointTwo, canvasBox)
@@ -883,7 +898,7 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       const stLinePointThree = vec2.create()
       vec2.add(
         stLinePointThree,
-        stHanlesCenterCanvas,
+        stHandlesCenterCanvas,
         canvasVectorFromCenterLong
       )
       vec2.subtract(
@@ -895,7 +910,7 @@ export default class CrosshairsTool extends BaseAnnotationTool {
       const stLinePointFour = vec2.create()
       vec2.subtract(
         stLinePointFour,
-        stHanlesCenterCanvas,
+        stHandlesCenterCanvas,
         canvasVectorFromCenterLong
       )
       vec2.subtract(
@@ -914,19 +929,19 @@ export default class CrosshairsTool extends BaseAnnotationTool {
 
       vec2.subtract(
         stHandleOne,
-        stHanlesCenterCanvas,
+        stHandlesCenterCanvas,
         canvasVectorFromCenterShort
       )
       vec2.add(stHandleOne, stHandleOne, canvasOrthoVectorFromCenter)
-      vec2.add(stHandleTwo, stHanlesCenterCanvas, canvasVectorFromCenterShort)
+      vec2.add(stHandleTwo, stHandlesCenterCanvas, canvasVectorFromCenterShort)
       vec2.add(stHandleTwo, stHandleTwo, canvasOrthoVectorFromCenter)
       vec2.subtract(
         stHandleThree,
-        stHanlesCenterCanvas,
+        stHandlesCenterCanvas,
         canvasVectorFromCenterShort
       )
       vec2.subtract(stHandleThree, stHandleThree, canvasOrthoVectorFromCenter)
-      vec2.add(stHandleFour, stHanlesCenterCanvas, canvasVectorFromCenterShort)
+      vec2.add(stHandleFour, stHandlesCenterCanvas, canvasVectorFromCenterShort)
       vec2.subtract(stHandleFour, stHandleFour, canvasOrthoVectorFromCenter)
 
       referenceLines.push([
@@ -1794,6 +1809,12 @@ export default class CrosshairsTool extends BaseAnnotationTool {
         angle *= -1
       }
 
+      // Rounding the angle to allow rotated handles to be undone
+      // If we don't round and rotate handles clockwise by 0.0131233 radians,
+      // there's no assurance that the counter-clockwise rotation occurs at
+      // precisely -0.0131233, resulting in the drawn annotations being lost.
+      angle = Math.round(angle * 100) / 100
+
       const rotationAxis = viewport.getCamera().viewPlaneNormal
       // @ts-ignore : vtkjs incorrect typing
       const { matrix } = vtkMatrixBuilder
@@ -1950,8 +1971,8 @@ export default class CrosshairsTool extends BaseAnnotationTool {
               otherViewport.setSlabThickness(null)
             } else {
               otherViewport.setSlabThickness(slabThicknessValue)
-              otherViewport.render()
             }
+            otherViewport.render()
           }
         }
       )
diff --git a/packages/cornerstone-tools/test/CrosshairsTool_test.js b/packages/cornerstone-tools/test/CrosshairsTool_test.js
index b44fd28572..2c0077c686 100644
--- a/packages/cornerstone-tools/test/CrosshairsTool_test.js
+++ b/packages/cornerstone-tools/test/CrosshairsTool_test.js
@@ -109,9 +109,6 @@ describe('Cornerstone Tools: ', () => {
     this.testToolGroup.addTool('Crosshairs', {
       configuration: {},
     })
-    this.testToolGroup.setToolActive('Crosshairs', {
-      bindings: [{ mouseButton: 1 }],
-    })
 
     this.renderingEngine = new RenderingEngine(renderingEngineUID)
     registerVolumeLoader('fakeVolumeLoader', fakeVolumeLoader)
@@ -206,6 +203,10 @@ describe('Cornerstone Tools: ', () => {
         CornerstoneTools3DEvents.ANNOTATION_RENDERED,
         crosshairsEventHandler
       )
+
+      this.testToolGroup.setToolActive('Crosshairs', {
+        bindings: [{ mouseButton: 1 }],
+      })
     }
 
     element1.addEventListener(EVENTS.IMAGE_RENDERED, renderEventHandler)
@@ -299,6 +300,10 @@ describe('Cornerstone Tools: ', () => {
         return
       }
 
+      this.testToolGroup.setToolActive('Crosshairs', {
+        bindings: [{ mouseButton: 1 }],
+      })
+
       const vp1 = this.renderingEngine.getViewport(viewportUID1)
       const { imageData } = vp1.getImageData()
 
@@ -395,6 +400,10 @@ describe('Cornerstone Tools: ', () => {
         return
       }
 
+      this.testToolGroup.setToolActive('Crosshairs', {
+        bindings: [{ mouseButton: 1 }],
+      })
+
       const vp1 = this.renderingEngine.getViewport(viewportUID1)
       const { imageData } = vp1.getImageData()
 
diff --git a/packages/demo/src/App.tsx b/packages/demo/src/App.tsx
index 91971b968c..c83ae381db 100644
--- a/packages/demo/src/App.tsx
+++ b/packages/demo/src/App.tsx
@@ -24,6 +24,7 @@ import { resetCPURenderingOnlyForDebugOrTests } from '@ohif/cornerstone-render'
 import SegmentationRender from './ExampleSegmentationRender'
 import RenderToCanvasExample from './ExampleRenderToCanvas'
 
+import CrosshairsExample from './ExampleCrosshairs'
 
 function LinkOut({ href, text }) {
   return (
@@ -91,6 +92,11 @@ function Index() {
       url: '/segmentationRender',
       text: 'Example for demonstrating the rendering of Segmentation',
     },
+    {
+      title: 'Crosshairs',
+      url: '/crosshairs',
+      text: 'Example for Crosshairs',
+    },
     {
       title: 'Canvas Resize',
       url: '/canvasResize',
@@ -279,6 +285,11 @@ function AppRouter() {
       children: <VTKSetVolumesExample />,
     })
 
+  const crosshairs = () =>
+    Example({
+      children: <CrosshairsExample />,
+    })
+
   const cacheDecache = () =>
     Example({
       children: <CacheDecacheExample />,
@@ -359,6 +370,7 @@ function AppRouter() {
         <Route exact path="/testUtilsVolume/" render={TestVolume} />
         <Route exact path="/calibratedImages/" render={calibratedImages} />
         <Route exact path="/segmentationRender/" render={segmentationRender} />
+        <Route exact path="/crosshairs/" render={crosshairs} />
         <Route
           exact
           path="/toolDisplayConfiguration/"
diff --git a/packages/demo/src/ExampleCrosshairs.tsx b/packages/demo/src/ExampleCrosshairs.tsx
new file mode 100644
index 0000000000..7aa88de4ed
--- /dev/null
+++ b/packages/demo/src/ExampleCrosshairs.tsx
@@ -0,0 +1,407 @@
+import React, { Component } from 'react'
+import {
+  cache,
+  RenderingEngine,
+  createAndCacheVolume,
+  ORIENTATION,
+  VIEWPORT_TYPE,
+} from '@ohif/cornerstone-render'
+import { ToolBindings, ToolModes } from '@ohif/cornerstone-tools'
+import * as csTools3d from '@ohif/cornerstone-tools'
+
+import vtkConstants from 'vtk.js/Sources/Rendering/Core/VolumeMapper/Constants'
+
+import {
+  setCTWWWC,
+  setPetTransferFunction,
+} from './helpers/transferFunctionHelpers'
+
+import getImageIds from './helpers/getImageIds'
+import ViewportGrid from './components/ViewportGrid'
+import { initToolGroups, addToolsToToolGroups } from './initToolGroups'
+import './ExampleVTKMPR.css'
+import {
+  renderingEngineUID,
+  ctVolumeUID,
+  ptVolumeUID,
+  SCENE_IDS,
+  VIEWPORT_IDS,
+  ANNOTATION_TOOLS,
+  prostateVolumeUID,
+} from './constants'
+
+const VOLUME = 'volume'
+
+window.cache = cache
+
+let ctSceneToolGroup, prostateSceneToolGroup
+
+const { BlendMode } = vtkConstants
+
+const toolsToUse = ['WindowLevel', 'Pan', 'Zoom', ...ANNOTATION_TOOLS]
+
+class CrosshairsExample extends Component {
+  state = {
+    progressText: 'fetching metadata...',
+    metadataLoaded: false,
+    petColorMapIndex: 0,
+    layoutIndex: 0,
+    destroyed: false,
+    //
+    viewportGrid: {
+      numCols: 3,
+      numRows: 2,
+      viewports: [{}, {}, {}, {}, {}],
+    },
+    leftClickTool: 'WindowLevel',
+    toolGroupName: 'FirstRow',
+    toolGroups: {},
+    ctWindowLevelDisplay: { ww: 0, wc: 0 },
+    ptThresholdDisplay: 5,
+  }
+
+  constructor(props) {
+    super(props)
+
+    csTools3d.init()
+    this._elementNodes = new Map()
+    this._offScreenRef = React.createRef()
+
+    this._viewportGridRef = React.createRef()
+
+    this.ctImageIds = getImageIds('ct1', VOLUME)
+    this.prostateImageIds = getImageIds('prostateX', VOLUME)
+
+    Promise.all([this.ctImageIds, this.prostateImageIds]).then(() =>
+      this.setState({ progressText: 'Loading data...' })
+    )
+
+    this.viewportGridResizeObserver = new ResizeObserver((entries) => {
+      // ThrottleFn? May not be needed. This is lightning fast.
+      // Set in mount
+      if (this.renderingEngine) {
+        this.renderingEngine.resize()
+        this.renderingEngine.render()
+      }
+    })
+  }
+
+  /**
+   * LIFECYCLE
+   */
+  async componentDidMount() {
+    ;({ ctSceneToolGroup, prostateSceneToolGroup } = initToolGroups())
+
+    const ctImageIds = await this.ctImageIds
+    const prostateImageIds = await this.prostateImageIds
+
+    const renderingEngine = new RenderingEngine(renderingEngineUID)
+
+    this.renderingEngine = renderingEngine
+    window.renderingEngine = renderingEngine
+
+    const viewportInput = [
+      // CT volume axial
+      {
+        sceneUID: SCENE_IDS.CT,
+        viewportUID: VIEWPORT_IDS.CT.AXIAL,
+        type: VIEWPORT_TYPE.ORTHOGRAPHIC,
+        element: this._elementNodes.get(0),
+        defaultOptions: {
+          orientation: ORIENTATION.AXIAL,
+          background: [0, 0, 0],
+        },
+      },
+      {
+        sceneUID: SCENE_IDS.CT,
+        viewportUID: VIEWPORT_IDS.CT.SAGITTAL,
+        type: VIEWPORT_TYPE.ORTHOGRAPHIC,
+        element: this._elementNodes.get(1),
+        defaultOptions: {
+          orientation: ORIENTATION.SAGITTAL,
+          background: [0, 0, 0],
+        },
+      },
+      {
+        sceneUID: SCENE_IDS.CT,
+        viewportUID: VIEWPORT_IDS.CT.CORONAL,
+        type: VIEWPORT_TYPE.ORTHOGRAPHIC,
+        element: this._elementNodes.get(2),
+        defaultOptions: {
+          orientation: ORIENTATION.CORONAL,
+          background: [0, 0, 0],
+        },
+      },
+      {
+        sceneUID: SCENE_IDS.PROSTATE,
+        viewportUID: VIEWPORT_IDS.PROSTATE.AXIAL,
+        type: VIEWPORT_TYPE.ORTHOGRAPHIC,
+        element: this._elementNodes.get(3),
+        defaultOptions: {
+          orientation: ORIENTATION.AXIAL,
+          background: [0, 0, 0],
+        },
+      },
+      {
+        sceneUID: SCENE_IDS.PROSTATE,
+        viewportUID: VIEWPORT_IDS.PROSTATE.SAGITTAL,
+        type: VIEWPORT_TYPE.ORTHOGRAPHIC,
+        element: this._elementNodes.get(4),
+        defaultOptions: {
+          orientation: ORIENTATION.SAGITTAL,
+          background: [0, 0, 0],
+        },
+      },
+    ]
+
+    renderingEngine.setViewports(viewportInput)
+
+    // volume ct
+    ctSceneToolGroup.addViewports(
+      renderingEngineUID,
+      SCENE_IDS.CT,
+      VIEWPORT_IDS.CT.AXIAL
+    )
+    ctSceneToolGroup.addViewports(
+      renderingEngineUID,
+      SCENE_IDS.CT,
+      VIEWPORT_IDS.CT.SAGITTAL
+    )
+    ctSceneToolGroup.addViewports(
+      renderingEngineUID,
+      SCENE_IDS.CT,
+      VIEWPORT_IDS.CT.CORONAL
+    )
+    prostateSceneToolGroup.addViewports(
+      renderingEngineUID,
+      SCENE_IDS.PROSTATE,
+      VIEWPORT_IDS.PROSTATE.AXIAL
+    )
+    prostateSceneToolGroup.addViewports(
+      renderingEngineUID,
+      SCENE_IDS.PROSTATE,
+      VIEWPORT_IDS.PROSTATE.SAGITTAL
+    )
+
+    addToolsToToolGroups({
+      ctSceneToolGroup,
+      prostateSceneToolGroup,
+    })
+
+    window.ctSceneToolGroup = ctSceneToolGroup
+    this.setState({
+      toolGroups: {
+        FirstRow: ctSceneToolGroup,
+        SecondRow: prostateSceneToolGroup,
+      },
+    })
+
+    renderingEngine.render()
+
+    // This only creates the volumes, it does not actually load all
+    // of the pixel data (yet)
+    const ctVolume = await createAndCacheVolume(ctVolumeUID, {
+      imageIds: ctImageIds,
+    })
+    const prostateVolume = await createAndCacheVolume(prostateVolumeUID, {
+      imageIds: prostateImageIds,
+    })
+
+    ctVolume.load()
+    prostateVolume.load()
+
+    const ctScene = renderingEngine.getScene(SCENE_IDS.CT)
+    const prostateScene = renderingEngine.getScene(SCENE_IDS.PROSTATE)
+    await ctScene.setVolumes([
+      {
+        volumeUID: ctVolumeUID,
+        callback: setCTWWWC,
+        blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND,
+      },
+    ])
+    await prostateScene.setVolumes([
+      {
+        volumeUID: prostateVolumeUID,
+        blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND,
+      },
+    ])
+
+    // This will initialise volumes in GPU memory
+    renderingEngine.render()
+
+    // Start listening for resize
+    this.viewportGridResizeObserver.observe(this._viewportGridRef.current)
+  }
+
+  componentDidUpdate(prevProps, prevState) {
+    const { layoutIndex } = this.state
+    const { renderingEngine } = this
+    const onLoad = () => this.setState({ progressText: 'Loaded.' })
+  }
+
+  componentWillUnmount() {
+    // Stop listening for resize
+    if (this.viewportGridResizeObserver) {
+      this.viewportGridResizeObserver.disconnect()
+    }
+
+    cache.purgeCache()
+    csTools3d.destroy()
+
+    this.renderingEngine.destroy()
+  }
+
+  setToolMode = (toolMode) => {
+    const toolGroup = this.state.toolGroups[this.state.toolGroupName]
+    if (toolMode === ToolModes.Active) {
+      const activeTool = toolGroup.getActivePrimaryButtonTools()
+      if (activeTool) {
+        toolGroup.setToolPassive(activeTool)
+      }
+
+      toolGroup.setToolActive(this.state.leftClickTool, {
+        bindings: [{ mouseButton: ToolBindings.Mouse.Primary }],
+      })
+    } else if (toolMode === ToolModes.Passive) {
+      toolGroup.setToolPassive(this.state.leftClickTool)
+    } else if (toolMode === ToolModes.Enabled) {
+      toolGroup.setToolEnabled(this.state.leftClickTool)
+    } else if (toolMode === ToolModes.Disabled) {
+      toolGroup.setToolDisabled(this.state.leftClickTool)
+    }
+  }
+
+  showOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+    const uri = this.renderingEngine._debugRender()
+    const image = document.createElement('img')
+    image.src = uri
+    image.setAttribute('width', '100%')
+
+    this._offScreenRef.current.appendChild(image)
+  }
+
+  hideOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+  }
+
+  render() {
+    return (
+      <div style={{ paddingBottom: '55px' }}>
+        <div className="row">
+          <div className="col-xs-12" style={{ margin: '8px 0' }}>
+            <h2>Crosshairs example ({this.state.progressText})</h2>
+            <p>
+              This demo demonstrates the use of crosshairs on two studies that
+              don't share the same frameOfReference.
+            </p>
+            <p>
+              Top row: CT scene from patient 1 and Bottom row: PET scene from
+              patient2
+            </p>
+          </div>
+          <div
+            className="col-xs-12"
+            style={{ margin: '8px 0', marginLeft: '-4px' }}
+          >
+            {/* Hide until we update react in a better way  {fusionWLDisplay} */}
+          </div>
+        </div>
+        <span>Set this tool </span>
+        <select
+          value={this.state.leftClickTool}
+          onChange={(evt) => {
+            this.setState({ leftClickTool: evt.target.value })
+          }}
+        >
+          {toolsToUse.map((toolName) => (
+            <option key={toolName} value={toolName}>
+              {toolName}
+            </option>
+          ))}
+        </select>
+        <span style={{ marginLeft: '4px' }}>for this toolGroup </span>
+        <select
+          value={this.state.toolGroupName}
+          onChange={(evt) => {
+            this.setState({ toolGroupName: evt.target.value })
+          }}
+        >
+          {Object.keys(this.state.toolGroups).map((toolGroupName) => (
+            <option key={toolGroupName} value={toolGroupName}>
+              {toolGroupName}
+            </option>
+          ))}
+        </select>
+        <button
+          style={{ marginLeft: '4px' }}
+          onClick={() => this.setToolMode(ToolModes.Active)}
+        >
+          Active
+        </button>
+        <button
+          style={{ marginLeft: '4px' }}
+          onClick={() => this.setToolMode(ToolModes.Passive)}
+        >
+          Passive
+        </button>
+        <button
+          style={{ marginLeft: '4px' }}
+          onClick={() => this.setToolMode(ToolModes.Enabled)}
+        >
+          Enabled
+        </button>
+        <button
+          style={{ marginLeft: '4px' }}
+          onClick={() => this.setToolMode(ToolModes.Disabled)}
+        >
+          Disabled
+        </button>
+
+        <ViewportGrid
+          numCols={this.state.viewportGrid.numCols}
+          numRows={this.state.viewportGrid.numRows}
+          renderingEngine={this.renderingEngine}
+          style={{ minHeight: '650px', marginTop: '35px' }}
+          ref={this._viewportGridRef}
+        >
+          {this.state.viewportGrid.viewports.map((vp, i) => (
+            <div
+              style={{
+                width: '100%',
+                height: '100%',
+                border: '2px solid grey',
+                background: 'black',
+              }}
+              ref={(c) => this._elementNodes.set(i, c)}
+              onContextMenu={(e) => e.preventDefault()}
+              key={i}
+            />
+          ))}
+        </ViewportGrid>
+        <div>
+          <h1>OffScreen Canvas Render</h1>
+          <button
+            onClick={this.showOffScreenCanvas}
+            className="btn btn-primary"
+            style={{ margin: '2px 4px' }}
+          >
+            Show OffScreenCanvas
+          </button>
+          <button
+            onClick={this.hideOffScreenCanvas}
+            className="btn btn-primary"
+            style={{ margin: '2px 4px' }}
+          >
+            Hide OffScreenCanvas
+          </button>
+          <div ref={this._offScreenRef}></div>
+        </div>
+      </div>
+    )
+  }
+}
+
+export default CrosshairsExample
diff --git a/packages/demo/src/ExampleEnableDisableAPI.tsx b/packages/demo/src/ExampleEnableDisableAPI.tsx
index adadd92278..c06e6f5e17 100644
--- a/packages/demo/src/ExampleEnableDisableAPI.tsx
+++ b/packages/demo/src/ExampleEnableDisableAPI.tsx
@@ -445,7 +445,7 @@ class EnableDisableViewportExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
-  hidOffScreenCanvas = () => {
+  hideOffScreenCanvas = () => {
     // remove all children
     this._offScreenRef.current.innerHTML = ''
   }
@@ -552,7 +552,7 @@ class EnableDisableViewportExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleFlipViewport.tsx b/packages/demo/src/ExampleFlipViewport.tsx
index 1f45d33919..784e28bb4f 100644
--- a/packages/demo/src/ExampleFlipViewport.tsx
+++ b/packages/demo/src/ExampleFlipViewport.tsx
@@ -40,10 +40,7 @@ const { BlendMode } = vtkConstants
 window.cache = cache
 
 let ctSceneToolGroup,
-  stackCTViewportToolGroup,
-  stackPTViewportToolGroup,
-  stackDXViewportToolGroup,
-  ptSceneToolGroup
+  stackCTViewportToolGroup
 
 const toolsToUse = ANNOTATION_TOOLS
 const ctLayoutTools = ['Levels'].concat(toolsToUse)
@@ -112,9 +109,6 @@ class FlipViewportExample extends Component {
     ;({
       ctSceneToolGroup,
       stackCTViewportToolGroup,
-      stackPTViewportToolGroup,
-      stackDXViewportToolGroup,
-      ptSceneToolGroup,
     } = initToolGroups({
       configuration: { preventHandleOutsideImage: true },
     }))
@@ -196,9 +190,6 @@ class FlipViewportExample extends Component {
     addToolsToToolGroups({
       ctSceneToolGroup,
       stackCTViewportToolGroup,
-      stackPTViewportToolGroup,
-      stackDXViewportToolGroup,
-      ptSceneToolGroup,
     })
 
     this.axialSync.add({
@@ -303,7 +294,7 @@ class FlipViewportExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
-  hidOffScreenCanvas = () => {
+  hideOffScreenCanvas = () => {
     // remove children
     this._offScreenRef.current.innerHTML = ''
   }
@@ -452,7 +443,7 @@ class FlipViewportExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleModifierKeys.tsx b/packages/demo/src/ExampleModifierKeys.tsx
index 5bf2869e85..797f45e294 100644
--- a/packages/demo/src/ExampleModifierKeys.tsx
+++ b/packages/demo/src/ExampleModifierKeys.tsx
@@ -289,6 +289,11 @@ class ModifierKeysExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
+  hideOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+  }
+
   rotateViewport = (rotateDeg) => {
     // remove all children
     const vp = this.renderingEngine.getViewport(VIEWPORT_IDS.STACK.CT)
@@ -452,7 +457,7 @@ class ModifierKeysExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleNineStackViewport.tsx b/packages/demo/src/ExampleNineStackViewport.tsx
index 2923eda1e3..cbfe12218d 100644
--- a/packages/demo/src/ExampleNineStackViewport.tsx
+++ b/packages/demo/src/ExampleNineStackViewport.tsx
@@ -222,7 +222,7 @@ class NineStackViewportExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
-  hidOffScreenCanvas = () => {
+  hideOffScreenCanvas = () => {
     // remove all children
     this._offScreenRef.current.innerHTML = ''
   }
@@ -271,7 +271,7 @@ class NineStackViewportExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleOneStack.tsx b/packages/demo/src/ExampleOneStack.tsx
index 6c6f944808..bd11ce190c 100644
--- a/packages/demo/src/ExampleOneStack.tsx
+++ b/packages/demo/src/ExampleOneStack.tsx
@@ -251,6 +251,11 @@ class OneStackExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
+  hideOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+  }
+
   rotateViewport = (rotateDeg) => {
     // remove all children
     const vp = this.renderingEngine.getViewport(VIEWPORT_IDS.STACK.CT)
@@ -399,7 +404,7 @@ class OneStackExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleOneVolume.tsx b/packages/demo/src/ExampleOneVolume.tsx
index 2b66dddedc..3958aff38c 100644
--- a/packages/demo/src/ExampleOneVolume.tsx
+++ b/packages/demo/src/ExampleOneVolume.tsx
@@ -278,6 +278,11 @@ class OneVolumeExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
+  hideOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+  }
+
   render() {
     return (
       <div style={{ paddingBottom: '55px' }}>
@@ -337,7 +342,7 @@ class OneVolumeExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleStackViewport.tsx b/packages/demo/src/ExampleStackViewport.tsx
index 3dc40d67c6..1de879ca48 100644
--- a/packages/demo/src/ExampleStackViewport.tsx
+++ b/packages/demo/src/ExampleStackViewport.tsx
@@ -480,7 +480,7 @@ class StackViewportExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
-  hidOffScreenCanvas = () => {
+  hideOffScreenCanvas = () => {
     // remove all children
     this._offScreenRef.current.innerHTML = ''
   }
@@ -780,7 +780,7 @@ class StackViewportExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleTestUtils.tsx b/packages/demo/src/ExampleTestUtils.tsx
index ac29f942f8..f7a4045dd2 100644
--- a/packages/demo/src/ExampleTestUtils.tsx
+++ b/packages/demo/src/ExampleTestUtils.tsx
@@ -194,6 +194,11 @@ class testUtil extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
+  hideOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+  }
+
   rotateViewport = (rotateDeg) => {
     // remove all childs
     const vp = this.renderingEngine.getViewport(VIEWPORT_IDS.STACK.CT)
@@ -285,7 +290,7 @@ class testUtil extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleTestUtilsVolume.tsx b/packages/demo/src/ExampleTestUtilsVolume.tsx
index 3ae1586b4e..c11159e3a8 100644
--- a/packages/demo/src/ExampleTestUtilsVolume.tsx
+++ b/packages/demo/src/ExampleTestUtilsVolume.tsx
@@ -263,6 +263,11 @@ class testUtilVolume extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
+  hideOffScreenCanvas = () => {
+    // remove all children
+    this._offScreenRef.current.innerHTML = ''
+  }
+
   rotateViewport = (rotateDeg) => {
     // remove all childs
     const vp = this.renderingEngine.getViewport(VIEWPORT_IDS.STACK.CT)
@@ -327,7 +332,7 @@ class testUtilVolume extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleToolDisplayConfiguration.tsx b/packages/demo/src/ExampleToolDisplayConfiguration.tsx
index ecca9af17f..65386edded 100644
--- a/packages/demo/src/ExampleToolDisplayConfiguration.tsx
+++ b/packages/demo/src/ExampleToolDisplayConfiguration.tsx
@@ -328,7 +328,7 @@ class ToolDisplayConfigurationExample extends Component {
     this._offScreenRef.current.appendChild(image)
   }
 
-  hidOffScreenCanvas = () => {
+  hideOffScreenCanvas = () => {
     // remove all children
     this._offScreenRef.current.innerHTML = ''
   }
@@ -422,7 +422,7 @@ class ToolDisplayConfigurationExample extends Component {
             Show OffScreenCanvas
           </button>
           <button
-            onClick={this.hidOffScreenCanvas}
+            onClick={this.hideOffScreenCanvas}
             className="btn btn-primary"
             style={{ margin: '2px 4px' }}
           >
diff --git a/packages/demo/src/ExampleVTKMPR.tsx b/packages/demo/src/ExampleVTKMPR.tsx
index 4e4a09d857..12da742342 100644
--- a/packages/demo/src/ExampleVTKMPR.tsx
+++ b/packages/demo/src/ExampleVTKMPR.tsx
@@ -134,9 +134,6 @@ class MPRExample extends Component {
       ptSceneToolGroup,
       fusionSceneToolGroup,
       ptMipSceneToolGroup,
-      ctVRSceneToolGroup,
-      ctObliqueToolGroup,
-      ptTypesSceneToolGroup,
     } = initToolGroups())
 
     this.ctVolumeUID = ctVolumeUID
@@ -171,8 +168,6 @@ class MPRExample extends Component {
       ptSceneToolGroup,
       fusionSceneToolGroup,
       ptMipSceneToolGroup,
-      ctVRSceneToolGroup,
-      ctObliqueToolGroup,
       ptTypesSceneToolGroup,
     })
 
@@ -402,7 +397,6 @@ class MPRExample extends Component {
       toolName
     )
 
-    this.renderingEngine.render()
     this.setState({ ptCtLeftClickTool: toolName })
   }
 
@@ -490,7 +484,7 @@ class MPRExample extends Component {
             style={{ margin: '8px 0', marginLeft: '-4px' }}
           >
             {/* LAYOUT BUTTONS */}
-            {filteredLayoutButtons.map((layout) => (
+            {/* {filteredLayoutButtons.map((layout) => (
               <button
                 key={layout.id}
                 onClick={() => this.swapLayout(layout.id)}
@@ -499,7 +493,7 @@ class MPRExample extends Component {
               >
                 {layout.text}
               </button>
-            ))}
+            ))} */}
             {/* TOGGLES */}
             {fusionButtons}
             {/* Hide until we update react in a better way  {fusionWLDisplay} */}
diff --git a/packages/demo/src/config/default.js b/packages/demo/src/config/default.js
index 6f298900d1..b1d0367709 100644
--- a/packages/demo/src/config/default.js
+++ b/packages/demo/src/config/default.js
@@ -62,8 +62,9 @@ export default {
     SeriesInstanceUID:
       '1.2.826.0.1.3680043.8.498.95761650623702141948748826678788764509',
   },
+  // ProstateX-0000 T2-tra
   prostateX: {
-    wadoRsRoot: 'http://localhost:8080/dcm4chee-arc/aets/DCM4CHEE/rs',
+    wadoRsRoot: 'https://d1jjp7d53qmguz.cloudfront.net/dicomweb',
     StudyInstanceUID:
       '1.3.6.1.4.1.14519.5.2.1.7311.5101.158323547117540061132729905711',
     SeriesInstanceUID:
diff --git a/packages/demo/src/constants/index.js b/packages/demo/src/constants/index.js
index aca9241eef..077407780c 100644
--- a/packages/demo/src/constants/index.js
+++ b/packages/demo/src/constants/index.js
@@ -1,6 +1,7 @@
 const renderingEngineUID = 'PETCTRenderingEngine'
 const ptVolumeUID = 'cornerstoneStreamingImageVolume:PET_VOLUME'
 const ctVolumeUID = 'cornerstoneStreamingImageVolume:CT_VOLUME'
+const prostateVolumeUID = 'cornerstoneStreamingImageVolume:PROSTATE_VOLUME'
 const ctVolumeTestUID = 'fakeVolumeLoader:volumeURI_100_100_10_1_1_1_0'
 const ptVolumeTestUID = 'fakeVolumeLoader:volumeURI_100_100_4_1_1_1_0'
 const ctStackUID = 'CT_Stack'
@@ -15,6 +16,7 @@ const SCENE_IDS = {
   STACK: 'stackScene',
   CT: 'ctScene',
   PT: 'ptScene',
+  PROSTATE: 'prostateScene',
   FUSION: 'fusionScene',
   PTMIP: 'ptMipScene',
   CTVR: 'ctVRScene',
@@ -36,6 +38,11 @@ const VIEWPORT_IDS = {
     SAGITTAL: 'ctSagittal',
     CORONAL: 'ctCoronal',
   },
+  PROSTATE: {
+    AXIAL: 'prostateAxial',
+    SAGITTAL: 'prostateSagittal',
+    CORONAL: 'prostateCoronal',
+  },
   PT: {
     AXIAL: 'ptAxial',
     SAGITTAL: 'ptSagittal',
@@ -74,6 +81,7 @@ const TOOL_GROUP_UIDS = {
   STACK_DX: 'stackDXToolGroup',
   CT: 'ctSceneToolGroup',
   PT: 'ptSceneToolGroup',
+  PROSTATE: 'prostateSceneToolGroup',
   FUSION: 'fusionSceneToolGroup',
   PTMIP: 'ptMipSceneToolGroup',
   CTVR: 'ctVRSceneToolGroup',
@@ -108,6 +116,7 @@ export {
   renderingEngineUID,
   ptVolumeUID,
   ctVolumeUID,
+  prostateVolumeUID,
   ctStackUID,
   ctVolumeTestUID,
   ptVolumeTestUID,
diff --git a/packages/demo/src/initToolGroups.js b/packages/demo/src/initToolGroups.js
index 05282c281f..4108200994 100644
--- a/packages/demo/src/initToolGroups.js
+++ b/packages/demo/src/initToolGroups.js
@@ -7,6 +7,7 @@ import {
   ctVolumeTestUID,
   ptVolumeTestUID,
   VIEWPORT_IDS,
+  prostateVolumeUID,
 } from './constants'
 const {
   PanTool,
@@ -54,6 +55,9 @@ let viewportReferenceLineControllable = [
   VIEWPORT_IDS.PT.AXIAL,
   VIEWPORT_IDS.PT.SAGITTAL,
   VIEWPORT_IDS.PT.CORONAL,
+  VIEWPORT_IDS.PROSTATE.AXIAL,
+  VIEWPORT_IDS.PROSTATE.SAGITTAL,
+  VIEWPORT_IDS.PROSTATE.CORONAL,
   VIEWPORT_IDS.FUSION.AXIAL,
   VIEWPORT_IDS.FUSION.SAGITTAL,
   VIEWPORT_IDS.FUSION.CORONAL,
@@ -94,6 +98,9 @@ let viewportReferenceLineDraggableRotatable = [
   VIEWPORT_IDS.PT.AXIAL,
   VIEWPORT_IDS.PT.SAGITTAL,
   VIEWPORT_IDS.PT.CORONAL,
+  VIEWPORT_IDS.PROSTATE.AXIAL,
+  VIEWPORT_IDS.PROSTATE.SAGITTAL,
+  VIEWPORT_IDS.PROSTATE.CORONAL,
   VIEWPORT_IDS.FUSION.AXIAL,
   VIEWPORT_IDS.FUSION.SAGITTAL,
   VIEWPORT_IDS.FUSION.CORONAL,
@@ -131,6 +138,9 @@ let viewportReferenceLineSlabThicknessControlsOn = [
   VIEWPORT_IDS.CT.AXIAL,
   VIEWPORT_IDS.CT.SAGITTAL,
   VIEWPORT_IDS.CT.CORONAL,
+  VIEWPORT_IDS.PROSTATE.AXIAL,
+  VIEWPORT_IDS.PROSTATE.SAGITTAL,
+  VIEWPORT_IDS.PROSTATE.CORONAL,
   /*VIEWPORT_IDS.PT.AXIAL,
   VIEWPORT_IDS.PT.SAGITTAL,
   VIEWPORT_IDS.PT.CORONAL,*/
@@ -180,6 +190,10 @@ viewportColors[VIEWPORT_IDS.PT.AXIAL] = 'rgb(200, 0, 0)'
 viewportColors[VIEWPORT_IDS.PT.SAGITTAL] = 'rgb(200, 200, 0)'
 viewportColors[VIEWPORT_IDS.PT.CORONAL] = 'rgb(0, 200, 0)'
 
+viewportColors[VIEWPORT_IDS.PROSTATE.AXIAL] = 'rgb(200, 0, 0)'
+viewportColors[VIEWPORT_IDS.PROSTATE.SAGITTAL] = 'rgb(200, 200, 0)'
+viewportColors[VIEWPORT_IDS.PROSTATE.CORONAL] = 'rgb(0, 200, 0)'
+
 viewportColors[VIEWPORT_IDS.FUSION.AXIAL] = 'rgb(200, 0, 0)'
 viewportColors[VIEWPORT_IDS.FUSION.SAGITTAL] = 'rgb(200, 200, 0)'
 viewportColors[VIEWPORT_IDS.FUSION.CORONAL] = 'rgb(0, 200, 0)'
@@ -245,6 +259,7 @@ function initToolGroups(toolConfiguration = {}) {
   const colorSceneToolGroup = ToolGroupManager.createToolGroup(
     TOOL_GROUP_UIDS.COLOR
   )
+  const prostateSceneToolGroup = ToolGroupManager.createToolGroup(TOOL_GROUP_UIDS.PROSTATE)
   const fusionSceneToolGroup = ToolGroupManager.createToolGroup(
     TOOL_GROUP_UIDS.FUSION
   )
@@ -271,6 +286,7 @@ function initToolGroups(toolConfiguration = {}) {
     stackPTViewportToolGroup,
     stackDXViewportToolGroup,
     ctSceneToolGroup,
+    prostateSceneToolGroup,
     ptSceneToolGroup,
     fusionSceneToolGroup,
     ptMipSceneToolGroup,
@@ -287,6 +303,7 @@ function addToolsToToolGroups({
   stackCTViewportToolGroup,
   stackPTViewportToolGroup,
   stackDXViewportToolGroup,
+  prostateSceneToolGroup,
   ctSceneToolGroup,
   ptSceneToolGroup,
   fusionSceneToolGroup,
@@ -335,7 +352,7 @@ function addToolsToToolGroups({
     stackPTViewportToolGroup.setToolPassive('Probe')
     stackPTViewportToolGroup.setToolPassive('RectangleRoi')
     stackPTViewportToolGroup.setToolPassive('EllipticalRoi')
-    stackPTViewportToolGroup.setToolPassive('Crosshairs')
+    stackPTViewportToolGroup.setToolDisabled('Crosshairs')
 
     stackPTViewportToolGroup.setToolActive('StackScrollMouseWheel')
     stackPTViewportToolGroup.setToolActive('WindowLevel', {
@@ -396,7 +413,7 @@ function addToolsToToolGroups({
     stackCTViewportToolGroup.setToolPassive('Probe')
     stackCTViewportToolGroup.setToolPassive('RectangleRoi')
     stackCTViewportToolGroup.setToolPassive('EllipticalRoi')
-    stackCTViewportToolGroup.setToolPassive('Crosshairs')
+    stackCTViewportToolGroup.setToolDisabled('Crosshairs')
 
     stackCTViewportToolGroup.setToolPassive('Length')
     stackCTViewportToolGroup.setToolActive('StackScrollMouseWheel')
@@ -459,7 +476,7 @@ function addToolsToToolGroups({
     stackDXViewportToolGroup.setToolPassive('Probe')
     stackDXViewportToolGroup.setToolPassive('RectangleRoi')
     stackDXViewportToolGroup.setToolPassive('EllipticalRoi')
-    stackDXViewportToolGroup.setToolPassive('Crosshairs')
+    stackDXViewportToolGroup.setToolDisabled('Crosshairs')
 
     stackDXViewportToolGroup.setToolActive('StackScrollMouseWheel')
     stackDXViewportToolGroup.setToolActive('WindowLevel', {
@@ -538,7 +555,7 @@ function addToolsToToolGroups({
     ctSceneToolGroup.setToolPassive('Probe')
     ctSceneToolGroup.setToolPassive('RectangleRoi')
     ctSceneToolGroup.setToolPassive('EllipticalRoi')
-    ctSceneToolGroup.setToolPassive('Crosshairs')
+    ctSceneToolGroup.setToolDisabled('Crosshairs')
 
     ctSceneToolGroup.setToolActive('StackScrollMouseWheel')
     ctSceneToolGroup.setToolActive('WindowLevel', {
@@ -564,6 +581,72 @@ function addToolsToToolGroups({
     })
   }
 
+  if (prostateSceneToolGroup) {
+    // Set up CT Scene tools
+
+    // @TODO: This kills the volumeUID and tool configuration
+    prostateSceneToolGroup.addTool('WindowLevel', {
+      configuration: { volumeUID: prostateVolumeUID },
+    })
+    prostateSceneToolGroup.addTool('Length', {})
+    prostateSceneToolGroup.addTool('Pan', {})
+    prostateSceneToolGroup.addTool('Zoom', {})
+    prostateSceneToolGroup.addTool('StackScrollMouseWheel', {})
+    prostateSceneToolGroup.addTool('Bidirectional', {
+      configuration: { volumeUID: prostateVolumeUID },
+    })
+    prostateSceneToolGroup.addTool('Length', {
+      configuration: { volumeUID: prostateVolumeUID },
+    })
+    prostateSceneToolGroup.addTool('Probe', {
+      configuration: { volumeUID: prostateVolumeUID },
+    })
+    prostateSceneToolGroup.addTool('RectangleRoi', {
+      configuration: { volumeUID: prostateVolumeUID },
+    })
+    prostateSceneToolGroup.addTool('EllipticalRoi', {
+      configuration: { volumeUID: ctVolumeUID },
+    })
+    prostateSceneToolGroup.addTool('Crosshairs', {
+      configuration: {
+        getReferenceLineColor,
+        getReferenceLineControllable,
+        getReferenceLineDraggableRotatable,
+        getReferenceLineSlabThicknessControlsOn,
+      },
+    })
+
+    prostateSceneToolGroup.setToolPassive('Bidirectional')
+    prostateSceneToolGroup.setToolPassive('Length')
+    prostateSceneToolGroup.setToolPassive('Probe')
+    prostateSceneToolGroup.setToolPassive('RectangleRoi')
+    prostateSceneToolGroup.setToolPassive('EllipticalRoi')
+    prostateSceneToolGroup.setToolDisabled('Crosshairs')
+
+    prostateSceneToolGroup.setToolActive('StackScrollMouseWheel')
+    prostateSceneToolGroup.setToolActive('WindowLevel', {
+      bindings: [
+        {
+          mouseButton: ToolBindings.Mouse.Primary,
+        },
+      ],
+    })
+    prostateSceneToolGroup.setToolActive('Pan', {
+      bindings: [
+        {
+          mouseButton: ToolBindings.Mouse.Auxiliary,
+        },
+      ],
+    })
+    prostateSceneToolGroup.setToolActive('Zoom', {
+      bindings: [
+        {
+          mouseButton: ToolBindings.Mouse.Secondary,
+        },
+      ],
+    })
+  }
+
   if (ptSceneToolGroup) {
     // Set up PT Scene tools
     ptSceneToolGroup.addTool('RectangleScissors', {
@@ -616,7 +699,7 @@ function addToolsToToolGroups({
     ptSceneToolGroup.setToolPassive('RectangleRoi')
     ptSceneToolGroup.setToolPassive('EllipticalRoi')
     ptSceneToolGroup.setToolPassive('Bidirectional')
-    ptSceneToolGroup.setToolPassive('Crosshairs')
+    ptSceneToolGroup.setToolDisabled('Crosshairs')
 
     ptSceneToolGroup.setToolActive('StackScrollMouseWheel')
     ptSceneToolGroup.setToolActive('PetThreshold', {
@@ -680,7 +763,7 @@ function addToolsToToolGroups({
     fusionSceneToolGroup.setToolPassive('Probe')
     fusionSceneToolGroup.setToolPassive('RectangleRoi')
     fusionSceneToolGroup.setToolPassive('EllipticalRoi')
-    fusionSceneToolGroup.setToolPassive('Crosshairs')
+    fusionSceneToolGroup.setToolDisabled('Crosshairs')
 
     fusionSceneToolGroup.setToolActive('StackScrollMouseWheel')
     fusionSceneToolGroup.setToolActive('PetThreshold', {
diff --git a/packages/docs/docs/concepts/tools.md b/packages/docs/docs/concepts/tools.md
index 511a06d207..98f17eee65 100644
--- a/packages/docs/docs/concepts/tools.md
+++ b/packages/docs/docs/concepts/tools.md
@@ -129,6 +129,29 @@ ctSceneToolGroup.addTool('Zoom', {})
 ctSceneToolGroup.addTool('Probe', {})
 ```
 
+### Annotation sharing
+The annotations in StackViewport and VolumeViewport are immediately shared.
+You can activate both a Stack and a Volume viewport and draw annotations on
+one while editing (modifying or moving) the other. This is accomplished by
+providing the toolGroup of the VolumeViewports with the `VolumeUID`.
+
+When drawing a measurement:
+-The tool gets the volume using volumeUID
+- It checks which imageId of the volume the tool has been drawn on
+- If in a stack viewport, we are at the same imageId, we render the tool
+
+```js
+ctSceneToolGroup.addTool('Length', {
+  configuration: { volumeUID: ctVolumeUID },
+})
+ctStackToolGroup.addTool('Length')
+```
+
+<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
+    <iframe src="https://player.vimeo.com/video/601943316?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479&amp;h=a6f3ee6e3d" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
+</div>
+
+
 #### Dynamic tool statistics
 Cornerstone3D-Tools is capable of calculating dynamic statistics based on the modality of the volume being rendered. For instance, for CT volumes a `ProbeTool` will give Hounsfield Units and for PET it will calculate SUV stats.
 
diff --git a/packages/docs/docs/tools-usage.md b/packages/docs/docs/tools-usage.md
index d15114dfdf..c937265276 100644
--- a/packages/docs/docs/tools-usage.md
+++ b/packages/docs/docs/tools-usage.md
@@ -58,3 +58,58 @@ stackToolGroup.setToolActive('Probe', {
   bindings: [{ mouseButton:  ToolBindings.Mouse.Primary }],
 })
 ```
+
+
+## Crosshairs
+Crosshairs enables cross-locating a point in 2 or 3 viewports. They can be
+Active, Passive, Enabled, Disabled similar to other tools.
+
+```js
+ctSceneToolGroup.addTool('Crosshairs', {
+  configuration: {
+    getReferenceLineColor,
+    getReferenceLineControllable,
+    getReferenceLineDraggableRotatable,
+    getReferenceLineSlabThicknessControlsOn,
+  },
+})
+```
+
+
+### Rotation
+By clicking and dragging a rotation handle, you may change the view of the other viewports in the scene.
+
+### Slab Thickness
+You can reformat a thick slab through the data. This feature computes a 2D thick view along the direction of the view from a 3D image.
+
+
+In order to use the slab thickness you need to set the `blendMode` on the `Scene` to be `BlendMode.MAXIMUM_INTENSITY_BLEND`.
+
+
+```js
+await ctScene.setVolumes([
+  {
+    volumeUID: ctVolumeUID,
+    blendMode: BlendMode.MAXIMUM_INTENSITY_BLEND,
+  },
+])
+```
+### Configuration
+Customization options include changing the colour of the crosshairs and determining whether or not to display the slabThickness and rotation handles.
+
+To familiarize yourself with these options, go to `initiToolGroups` in the demo folder.
+
+```js
+ctSceneToolGroup.addTool('Crosshairs', {
+  configuration: {
+    getReferenceLineColor,
+    getReferenceLineControllable,
+    getReferenceLineDraggableRotatable,
+    getReferenceLineSlabThicknessControlsOn,
+  },
+})
+```
+
+<div style={{padding:"56.25% 0 0 0", position:"relative"}}>
+    <iframe src="https://player.vimeo.com/video/601952835?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479&amp;h=abc1591622" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture" allowFullScreen style= {{ position:"absolute",top:0,left:0,width:"100%",height:"100%"}} title="measurement-report"></iframe>
+</div>
diff --git a/yarn.lock b/yarn.lock
index be789190b9..1d7ac5ff8d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3937,7 +3937,7 @@ array-unique@^0.3.2:
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
   integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
 
-array.prototype.flat@^1.2.4:
+array.prototype.flat@^1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13"
   integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==