Fixing issues with bidirectional tool and measure flow

This commit is contained in:
Bruno Alves de Faria 2018-02-20 06:53:25 -03:00
parent 797b2f5588
commit 00a76a6ca5
10 changed files with 85 additions and 75 deletions

View File

@ -19,7 +19,7 @@ Meteor.startup(() => {
OHIF.viewer.stackImagePositionOffsetSynchronizer = new OHIF.viewerbase.StackImagePositionOffsetSynchronizer();
// Create the synchronizer used to update reference lines
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.updateImageSynchronizer);
OHIF.viewer.metadataProvider = OHIF.cornerstone.metadataProvider;
@ -373,7 +373,7 @@ Template.viewer.events({
instance.measurementModifiedHandler(originalEvent, instance);
},
'cornerstonetoolsmeasurementremoved .imageViewerViewport'(event, instance) {
'cornerstonemeasurementremoved .imageViewerViewport'(event, instance) {
const originalEvent = event.originalEvent;
OHIF.measurements.MeasurementHandlers.onRemoved(originalEvent, instance);
}

View File

@ -67,7 +67,7 @@ Meteor.startup(() => {
OHIF.viewer.stackImagePositionOffsetSynchronizer = new OHIF.viewerbase.StackImagePositionOffsetSynchronizer();
// Create the synchronizer used to update reference lines
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.updateImageSynchronizer);
OHIF.viewer.metadataProvider = OHIF.cornerstone.metadataProvider;

View File

@ -21,7 +21,7 @@ const unselectAllHandles = handles => {
// Clear the bidirectional tool's selection for all tool handles
const clearBidirectionalSelection = event => {
let imageNeedsUpdate = false;
const toolData = cornerstoneTools.getToolState(event.currentTarget, 'bidirectional');
const toolData = cornerstoneTools.getToolState(event.target, 'bidirectional');
if (!toolData) return;
toolData.data.forEach(data => {
const unselectResult = unselectAllHandles(data.handles);
@ -37,7 +37,7 @@ const setHandlesMovingState = (handles, state) => {
});
};
// mouseDowCallback is used to restrict behaviour of perpendicular-line
// mouseDownCallback is used to restrict behaviour of perpendicular-line
export default function(event) {
const eventData = event.detail;
let data;
@ -45,6 +45,8 @@ export default function(event) {
const $element = $(element);
const options = cornerstoneTools.getToolOptions(toolType, element);
if (!cornerstoneTools.isMouseButtonEnabled(eventData.which, options.mouseButtonMask)) return;
// Add an event listener to clear the selected state when a measurement is activated
const activateEventKey = 'ViewerMeasurementsActivated';
$element.off(activateEventKey).on(activateEventKey, () => clearBidirectionalSelection(event));
@ -74,72 +76,71 @@ export default function(event) {
}
cornerstone.updateImage(element);
element.removeEventListener('cornerstonetoolsmousemove', mouseMoveCallback);
element.addEventListener('cornerstonetoolsmousemove', mouseMoveCallback);
}
if (cornerstoneTools.isMouseButtonEnabled(eventData.which, options.mouseButtonMask)) {
const coords = eventData.startPoints.canvas;
const toolData = cornerstoneTools.getToolState(event.currentTarget, toolType);
const coords = eventData.startPoints.canvas;
const toolData = cornerstoneTools.getToolState(event.currentTarget, toolType);
// now check to see if there is a handle we can move
if (toolData) {
for (let i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
const handle = cornerstoneTools.getHandleNearImagePoint(
element,
data.handles,
coords,
distanceThreshold
);
if (!toolData) return;
if (handle) {
// Hide the cursor to improve precision while resizing the line or set to move
// if dragging text box
$element.css('cursor', handle.hasBoundingBox ? 'move' : 'none');
// now check to see if there is a handle we can move
for (let i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
const handleParams = [element, data.handles, coords, distanceThreshold];
const handle = cornerstoneTools.getHandleNearImagePoint(...handleParams);
element.removeEventListener('cornerstonetoolsmousemove', mouseMoveCallback);
data.active = true;
if (handle) {
// Hide the cursor to improve precision while resizing the line or set to move
// if dragging text box
$element.css('cursor', handle.hasBoundingBox ? 'move' : 'none');
unselectAllHandles(data.handles);
handle.moving = true;
moveHandle(eventData, toolType, data, handle, () => handleDoneMove(handle));
event.stopImmediatePropagation();
return false;
}
}
element.removeEventListener('cornerstonetoolsmousemove', mouseMoveCallback);
data.active = true;
unselectAllHandles(data.handles);
handle.moving = true;
moveHandle(eventData, toolType, data, handle, () => handleDoneMove(handle));
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
return;
}
}
// Now check to see if there is a line we can move
// Now check to see if we have a tool that we can move
if (toolData) {
const options = {
deleteIfHandleOutsideImage: true,
preventHandleOutsideImage: false
};
// Now check to see if there is a line we can move
// Now check to see if we have a tool that we can move
const opt = {
deleteIfHandleOutsideImage: true,
preventHandleOutsideImage: false
};
const getDoneMovingCallback = handles => () => {
setHandlesMovingState(handles, false);
handleDoneMove();
};
const getDoneMovingCallback = handles => () => {
setHandlesMovingState(handles, false);
handleDoneMove();
};
for (let i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
if (pointNearTool(element, data, coords)) {
// Set the cursor to move
$element.css('cursor', 'move');
for (let i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
if (pointNearTool(element, data, coords)) {
// Set the cursor to move
$element.css('cursor', 'move');
element.removeEventListener('cornerstonetoolsmousemove', mouseMoveCallback);
data.active = true;
element.removeEventListener('cornerstonetoolsmousemove', mouseMoveCallback);
data.active = true;
unselectAllHandles(data.handles);
setHandlesMovingState(data.handles, true);
unselectAllHandles(data.handles);
setHandlesMovingState(data.handles, true);
const doneMovingCallback = getDoneMovingCallback(data.handles);
cornerstoneTools.moveAllHandles(event, data, toolData, toolType, options, doneMovingCallback);
event.stopImmediatePropagation();
return false;
}
}
const doneMovingCallback = getDoneMovingCallback(data.handles);
const allHandlesParams = [event, data, toolData, toolType, opt, doneMovingCallback];
cornerstoneTools.moveAllHandles(...allHandlesParams);
event.stopImmediatePropagation();
event.stopPropagation();
event.preventDefault();
return;
}
}
}

View File

@ -6,7 +6,8 @@ import pointNearTool from './pointNearTool';
// Replaces the cornerstoneTools.handleActivator function by skiping the active handle comparison
const handleActivator = (element, handles, canvasPoint, distanceThreshold=6) => {
const nearbyHandle = cornerstoneTools.getHandleNearImagePoint(element, handles, canvasPoint, distanceThreshold);
const getHandle = cornerstoneTools.getHandleNearImagePoint;
const nearbyHandle = getHandle(element, handles, canvasPoint, distanceThreshold);
let handleActivatorChanged = false;
Object.keys(handles).forEach(handleKey => {
@ -26,6 +27,7 @@ const handleActivator = (element, handles, canvasPoint, distanceThreshold=6) =>
// mouseMoveCallback is used to hide handles when mouse is away
export default function (event) {
const eventData = event.detail;
const { element } = eventData;
cornerstoneTools.toolCoordinates.setCoords(eventData);
// if a mouse button is down, do nothing
if (eventData.which !== 0) {
@ -33,7 +35,7 @@ export default function (event) {
}
// if we have no tool data for this element, do nothing
const toolData = cornerstoneTools.getToolState(eventData.element, toolType);
const toolData = cornerstoneTools.getToolState(element, toolType);
if (!toolData) return;
// We have tool data, search through all data and see if we can activate a handle
@ -43,7 +45,7 @@ export default function (event) {
const coords = eventData.currentPoints.canvas;
const data = toolData.data[i];
const handleActivatorChanged = handleActivator(eventData.element, data.handles, coords);
const handleActivatorChanged = handleActivator(element, data.handles, coords);
Object.keys(data.handles).forEach(handleKey => {
if (handleKey === 'textBox') return;
const handle = data.handles[handleKey];
@ -54,7 +56,9 @@ export default function (event) {
imageNeedsUpdate = true;
}
if ((pointNearTool(eventData.element, data, coords) && !data.active) || (!pointNearTool(eventData.element, data, coords) && data.active)) {
const nearToolAndInactive = pointNearTool(element, data, coords) && !data.active;
const notNearToolAndActive = !pointNearTool(element, data, coords) && data.active;
if (nearToolAndInactive || notNearToolAndActive) {
data.active = !data.active;
imageNeedsUpdate = true;
}
@ -62,6 +66,6 @@ export default function (event) {
// Handle activation status changed, redraw the image
if (imageNeedsUpdate === true) {
cornerstone.updateImage(eventData.element);
cornerstone.updateImage(element);
}
}

View File

@ -3,7 +3,6 @@ import setHandlesPosition from './setHandlesPosition';
export default function (mouseEventData, toolType, data, handle, doneMovingCallback, preventHandleOutsideImage) {
const element = mouseEventData.element;
const $element = $(element);
const distanceFromTool = {
x: handle.x - mouseEventData.currentPoints.image.x,
y: handle.y - mouseEventData.currentPoints.image.y
@ -32,11 +31,12 @@ export default function (mouseEventData, toolType, data, handle, doneMovingCallb
const eventType = 'cornerstonetoolsmeasurementmodified';
const modifiedEventData = {
toolType: toolType,
element: element,
toolType,
element,
measurementData: data
};
$element.trigger(eventType, modifiedEventData);
cornerstone.triggerEvent(element, eventType, modifiedEventData);
};
element.addEventListener('cornerstonetoolsmousedrag', mouseDragCallback);

View File

@ -106,8 +106,9 @@ export class MeasurementsLengthCriterion extends BaseCriterion {
let { longestDiameter, shortestDiameter } = measurement;
if (measurement.childToolsCount) {
longestDiameter = measurement.bidirectional.longestDiameter;
shortestDiameter = measurement.bidirectional.shortestDiameter;
const child = measurement.bidirectional;
longestDiameter = (child && child.longestDiameter) || 0;
shortestDiameter = (child && child.shortestDiameter) || 0;
}
const { sliceThickness } = metadata;

View File

@ -8,7 +8,7 @@ export class StackImagePositionOffsetSynchronizer {
constructor() {
this.active = false;
this.syncedViewports = [];
this.synchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.stackImagePositionOffsetSynchronizer);
this.synchronizer = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.stackImagePositionOffsetSynchronizer);
}
static get ELEMENT_DISABLED_EVENT() {

View File

@ -3,6 +3,7 @@ import { Session } from 'meteor/session';
import { Random } from 'meteor/random';
import { $ } from 'meteor/jquery';
import { OHIF } from 'meteor/ohif:core';
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { getFrameOfReferenceUID } from './getFrameOfReferenceUID';
import { updateCrosshairsSynchronizer } from './updateCrosshairsSynchronizer';
import { crosshairsSynchronizers } from './crosshairsSynchronizers';
@ -344,18 +345,21 @@ export const toolManager = {
if (button === 'left') {
newToolIdLeft = toolId;
}
const newCornerstoneToolLeft = tools[newToolIdLeft]; // left mouse tool is used for touch as well
let newToolIdMiddle = activeTool.middle;
if (button === 'middle') {
newToolIdMiddle = toolId;
}
const newCornerstoneToolMiddle = cornerstoneTools[newToolIdMiddle];
let newToolIdRight = activeTool.right;
if (button === 'right') {
newToolIdRight = toolId;
}
const newCornerstoneToolRight = cornerstoneTools[newToolIdRight];
// Deactivate scroll wheel tools

View File

@ -4,12 +4,12 @@ import { crosshairsSynchronizers } from './crosshairsSynchronizers';
/**
* This function is used to maintain the updateImageSynchronizers
* that are using in the Crosshair tool. The function creates
* that are using in the Crosshair tool. The function creates
* (and destroys any currently existing) a new synchronizer for the given
* frame of reference. It then searches for other viewports that share the same
* frame of reference, and adds those to the synchronizer. These viewports
* will now function together when the Crosshair tool is used.
*
*
* @param currentFrameOfReferenceUID
*/
export function updateCrosshairsSynchronizer(currentFrameOfReferenceUID) {
@ -21,10 +21,10 @@ import { crosshairsSynchronizers } from './crosshairsSynchronizers';
synchronizer.destroy();
} else {
// Create a new synchronizer
crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID] = new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.updateImageSynchronizer);
crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID] = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.updateImageSynchronizer);
synchronizer = crosshairsSynchronizers.synchronizers[currentFrameOfReferenceUID];
}
// Add all elements that stem from the same frame of reference
$('.imageViewerViewport').each((index, element) => {
const frameOfReferenceUID = getFrameOfReferenceUID(element);

View File

@ -12,7 +12,7 @@ Template.standaloneViewerMain.onCreated(() => {
window.addEventListener('resize', window.ResizeViewportManager.getResizeHandler());
// Create the synchronizer used to update reference lines
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('cornerstonenewimage', cornerstoneTools.updateImageSynchronizer);
OHIF.viewer.metadataProvider = OHIF.cornerstone.metadataProvider;
// Metadata configuration