Fixing issues with bidirectional tool

This commit is contained in:
Bruno Alves de Faria 2017-11-17 14:08:35 -02:00
parent 0acdff0bc5
commit 475580b2f9
10 changed files with 147 additions and 1443 deletions

View File

@ -1,11 +1,13 @@
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { cornerstone, cornerstoneTools, cornerstoneMath } from 'meteor/ohif:cornerstone';
import { toolType } from './definitions';
import createNewMeasurement from './createNewMeasurement';
import mouseMoveCallback from './mouseMoveCallback';
import mouseDownCallback from './mouseDownCallback';
import doubleClickCallback from './doubleClickCallback';
import updatePerpendicularLineHandles from './updatePerpendicularLineHandles';
export default function(mouseEventData) {
const element = mouseEventData.element;
const { element } = mouseEventData;
const $element = $(element);
// LT-29 Disable Target Measurements when pixel spacing is not available
@ -21,9 +23,7 @@ export default function(mouseEventData) {
const measurementData = createNewMeasurement(mouseEventData);
measurementData.viewport = cornerstone.getViewport(element);
const eventData = {
mouseButtonMask: mouseEventData.which
};
const eventData = { mouseButtonMask: mouseEventData.which };
const tool = cornerstoneTools[toolType];
const config = tool.getConfiguration();
@ -32,11 +32,21 @@ export default function(mouseEventData) {
// associate this data with this imageId so we can render it and manipulate it
cornerstoneTools.addToolState(element, toolType, measurementData);
// since we are dragging to another place to drop the end point, we can just activate
// the end point and let the moveHandle move it for us.
$element.off('CornerstoneToolsMouseMove', mouseMoveCallback);
$element.off('CornerstoneToolsMouseDown', mouseDownCallback);
$element.off('CornerstoneToolsMouseDownActivate', mouseDownActivateCallback);
const disableDefaultHandlers = () => {
// since we are dragging to another place to drop the end point, we can just activate
// the end point and let the moveHandle move it for us.
$element.off('CornerstoneToolsMouseMove', mouseMoveCallback);
$element.off('CornerstoneToolsMouseDown', mouseDownCallback);
$element.off('CornerstoneToolsMouseDownActivate', mouseDownActivateCallback);
$element.off('CornerstoneToolsMouseDoubleClick', doubleClickCallback);
};
disableDefaultHandlers();
// Update the perpendicular line handles position
const updateHandler = (event, eventData) => updatePerpendicularLineHandles(eventData, measurementData);
$element.on('CornerstoneToolsMouseDrag', updateHandler);
$element.on('CornerstoneToolsMouseUp', updateHandler);
let cancelled = false;
const cancelAction = () => {
@ -59,6 +69,17 @@ export default function(mouseEventData) {
// Bind a one-time event listener for the Esc key
$element.one('keydown', keyDownHandler);
// Bind a mousedown handler to cancel the measurement if it's zero-sized
const mousedownHandler = () => {
const { start, end } = measurementData.handles;
if (!cornerstoneMath.point.distance(start, end)) {
cancelAction();
}
};
// Bind a one-time event listener for mouse down
$element.one('mousedown', mousedownHandler);
// Keep the current image and create a handler for new rendered images
const currentImage = cornerstone.getImage(element);
const currentViewport = cornerstone.getViewport(element);
@ -103,6 +124,9 @@ export default function(mouseEventData) {
// Unbind the Esc keydown hook
$element.off('keydown', keyDownHandler);
// Unbind the mouse down hook
$element.off('mousedown', mousedownHandler);
// Unbind the event listener for image rendering
$element.off('CornerstoneImageRendered', imageRenderedHandler);
@ -113,9 +137,17 @@ export default function(mouseEventData) {
// perpendicular line is not connected to long-line
perpendicularStart.locked = false;
// Unbind the handlers to update perpendicular line
$element.off('CornerstoneToolsMouseDrag', updateHandler);
$element.off('CornerstoneToolsMouseUp', updateHandler);
// Disable the default handlers and re-enable again
disableDefaultHandlers();
$element.on('CornerstoneToolsMouseMove', eventData, mouseMoveCallback);
$element.on('CornerstoneToolsMouseDown', eventData, mouseDownCallback);
$element.on('CornerstoneToolsMouseDownActivate', eventData, mouseDownActivateCallback);
$element.on('CornerstoneToolsMouseDoubleClick', eventData, doubleClickCallback);
cornerstone.updateImage(element);
});
}

View File

@ -1,6 +1,7 @@
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { toolType } from './definitions';
import createNewMeasurement from './createNewMeasurement';
import updatePerpendicularLineHandles from './updatePerpendicularLineHandles';
export default function(touchEventData) {
const element = { touchEventData };
@ -28,6 +29,11 @@ export default function(touchEventData) {
$element.off('CornerstoneToolsTap', tapCallback);
$element.off('CornerstoneToolsDragStartActive', touchDownActivateCallback);
// Update the perpendicular line handles position
const updateHandler = (event, eventData) => updatePerpendicularLineHandles(eventData, measurementData);
$element.on('CornerstoneToolsTouchDrag', updateHandler);
$element.on('CornerstoneToolsTouchEnd', updateHandler);
cornerstone.updateImage(element);
const { end, perpendicularStart } = handles;
cornerstoneTools.moveNewHandleTouch(touchEventData, toolType, measurementData, end, () => {
@ -42,6 +48,10 @@ export default function(touchEventData) {
// perpendicular line is not connected to long-line
perpendicularStart.locked = false;
// Unbind the handlers to update perpendicular line
$element.off('CornerstoneToolsTouchDrag', updateHandler);
$element.off('CornerstoneToolsTouchEnd', updateHandler);
$element.on('CornerstoneToolsTouchDrag', touchMoveHandle);
$element.on('CornerstoneToolsTap', tapCallback);
$element.on('CornerstoneToolsDragStartActive', touchDownActivateCallback);

View File

@ -25,7 +25,8 @@ export default function(mouseEventData) {
end: getHandle(x, y, 1, { active: true }),
perpendicularStart: getHandle(x, y, 2, { locked: true }),
perpendicularEnd: getHandle(x, y, 3),
textBox: getHandle(x - 50, y - 70, 4, {
textBox: getHandle(x - 50, y - 70, null, {
highlight: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,

View File

@ -0,0 +1,41 @@
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { toolType } from './definitions';
import pointNearTool from './pointNearTool';
export default function (event, eventData) {
const { element } = eventData.element;
function doneCallback(data, deleteTool) {
if (deleteTool === true) {
cornerstoneTools.removeToolState(element, toolType, data);
cornerstone.updateImage(element);
}
}
const buttonMask = event.data && event.data.mouseButtonMask;
if (buttonMask && !cornerstoneTools.isMouseButtonEnabled(eventData.which, buttonMask)) {
return false;
}
const config = cornerstoneTools.bidirectional.getConfiguration();
const coords = eventData.currentPoints.canvas;
const toolData = cornerstoneTools.getToolState(element, toolType);
// now check to see if there is a handle we can move
if (!toolData) return;
let data;
for (let i = 0; i < toolData.data.length; i++) {
data = toolData.data[i];
if (pointNearTool(element, data, coords)) {
data.active = true;
cornerstone.updateImage(element);
// Allow relabelling via a callback
config.changeMeasurementLocationCallback(data, eventData, doneCallback);
event.stopImmediatePropagation();
return false;
}
}
}

View File

@ -1,3 +1,5 @@
/* jshint -W083 */
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { toolType, distanceThreshold } from './definitions';
import mouseMoveCallback from './mouseMoveCallback';
@ -98,7 +100,7 @@ export default function(event, eventData) {
unselectAllHandles(data.handles);
handle.moving = true;
moveHandle(eventData, toolType, data, handle, handleDoneMove);
moveHandle(eventData, toolType, data, handle, () => handleDoneMove(handle));
event.stopImmediatePropagation();
return false;
}

View File

@ -1,3 +1,5 @@
/* jshint -W083 */
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
import { toolType } from './definitions';
import pointNearTool from './pointNearTool';

View File

@ -1,48 +1,11 @@
import { cornerstone } from 'meteor/ohif:cornerstone';
// draw perpendicular line
export default function(context, eventData, element, data, color, lineWidth) {
let startX, startY, endX, endY;
if (data.handles.start.x === data.handles.end.x &&
data.handles.start.y === data.handles.end.y) {
startX = data.handles.start.x;
startY = data.handles.start.y;
endX = data.handles.end.x;
endY = data.handles.end.y;
} else {
// mid point of long-axis line
const mid = {
x: (data.handles.start.x + data.handles.end.x) / 2,
y: (data.handles.start.y + data.handles.end.y) / 2
};
// Length of long-axis
const dx = (data.handles.start.x - data.handles.end.x) * (eventData.image.columnPixelSpacing || 1);
const dy = (data.handles.start.y - data.handles.end.y) * (eventData.image.rowPixelSpacing || 1);
const length = Math.sqrt(dx * dx + dy * dy);
const vectorX = (data.handles.start.x - data.handles.end.x) / length;
const vectorY = (data.handles.start.y - data.handles.end.y) / length;
const perpendicularLineLength = length / 2;
startX = mid.x + (perpendicularLineLength / 2) * vectorY;
startY = mid.y - (perpendicularLineLength / 2) * vectorX;
endX = mid.x - (perpendicularLineLength / 2) * vectorY;
endY = mid.y + (perpendicularLineLength / 2) * vectorX;
}
if (data.handles.perpendicularStart.locked) {
data.handles.perpendicularStart.x = startX;
data.handles.perpendicularStart.y = startY;
data.handles.perpendicularEnd.x = endX;
data.handles.perpendicularEnd.y = endY;
}
export default function(context, element, data, color, lineWidth) {
// Draw perpendicular line
const perpendicularStartCanvas = cornerstone.pixelToCanvas(element, data.handles.perpendicularStart);
const perpendicularEndCanvas = cornerstone.pixelToCanvas(element, data.handles.perpendicularEnd);
const { perpendicularStart, perpendicularEnd } = data.handles;
const perpendicularStartCanvas = cornerstone.pixelToCanvas(element, perpendicularStart);
const perpendicularEndCanvas = cornerstone.pixelToCanvas(element, perpendicularEnd);
context.beginPath();
context.strokeStyle = color;
@ -50,5 +13,4 @@ export default function(context, eventData, element, data, color, lineWidth) {
context.moveTo(perpendicularStartCanvas.x, perpendicularStartCanvas.y);
context.lineTo(perpendicularEndCanvas.x, perpendicularEndCanvas.y);
context.stroke();
}

View File

@ -2,6 +2,7 @@ import { cornerstone, cornerstoneMath, cornerstoneTools } from 'meteor/ohif:corn
import { OHIF } from 'meteor/ohif:core';
import { toolType } from '../definitions';
import drawHandles from './drawHandles';
import updatePerpendicularLineHandles from '../updatePerpendicularLineHandles';
import drawPerpendicularLine from './drawPerpendicularLine';
import drawSelectedMarker from './drawSelectedMarker';
@ -59,7 +60,8 @@ export default function(event, eventData) {
context.stroke();
// Draw perpendicular line
drawPerpendicularLine(context, eventData, element, data, color, strokeWidth);
updatePerpendicularLineHandles(eventData, data);
drawPerpendicularLine(context, element, data, color, strokeWidth);
// Draw the handles
const handlesColor = color;

View File

@ -0,0 +1,40 @@
// Update the perpendicular line handles
export default function(eventData, data) {
if (!data.handles.perpendicularStart.locked) return;
let startX, startY, endX, endY;
const { start, end } = data.handles;
if (start.x === end.x && start.y === end.y) {
startX = start.x;
startY = start.y;
endX = end.x;
endY = end.y;
} else {
// mid point of long-axis line
const mid = {
x: (start.x + end.x) / 2,
y: (start.y + end.y) / 2
};
// Length of long-axis
const dx = (start.x - end.x) * (eventData.image.columnPixelSpacing || 1);
const dy = (start.y - end.y) * (eventData.image.rowPixelSpacing || 1);
const length = Math.sqrt(dx * dx + dy * dy);
const vectorX = (start.x - end.x) / length;
const vectorY = (start.y - end.y) / length;
const perpendicularLineLength = length / 2;
startX = mid.x + (perpendicularLineLength / 2) * vectorY;
startY = mid.y - (perpendicularLineLength / 2) * vectorX;
endX = mid.x - (perpendicularLineLength / 2) * vectorY;
endY = mid.y + (perpendicularLineLength / 2) * vectorX;
}
data.handles.perpendicularStart.x = startX;
data.handles.perpendicularStart.y = startY;
data.handles.perpendicularEnd.x = endX;
data.handles.perpendicularEnd.y = endY;
}