LT-40: Recalculating text call-outs position when creating measurments without dragging
This commit is contained in:
parent
8df077f046
commit
888c337f84
@ -28,7 +28,12 @@ OHIF.cornerstone.pixelToPage = (element, position) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
OHIF.cornerstone.repositionTextBoxWhileDragging = (eventData, measurementData) => {
|
OHIF.cornerstone.repositionTextBox = (eventData, measurementData) => {
|
||||||
|
// Stop here if it's not a measurement creating
|
||||||
|
if (!measurementData.isCreating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const element = eventData.element;
|
const element = eventData.element;
|
||||||
const enabledElement = cornerstone.getEnabledElement(element);
|
const enabledElement = cornerstone.getEnabledElement(element);
|
||||||
const $element = $(element);
|
const $element = $(element);
|
||||||
@ -96,124 +101,111 @@ OHIF.cornerstone.repositionTextBoxWhileDragging = (eventData, measurementData) =
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const modifiedCallback = () => {
|
const handles = measurementData.handles;
|
||||||
const handles = measurementData.handles;
|
const textBox = handles.textBox;
|
||||||
const textBox = handles.textBox;
|
|
||||||
|
|
||||||
const $canvas = $(enabledElement.canvas);
|
const $canvas = $(enabledElement.canvas);
|
||||||
const canvasWidth = $canvas.outerWidth();
|
const canvasWidth = $canvas.outerWidth();
|
||||||
const canvasHeight = $canvas.outerHeight();
|
const canvasHeight = $canvas.outerHeight();
|
||||||
const offset = $canvas.offset();
|
const offset = $canvas.offset();
|
||||||
const canvasDimensions = {
|
const canvasDimensions = {
|
||||||
x: canvasWidth,
|
x: canvasWidth,
|
||||||
y: canvasHeight
|
y: canvasHeight
|
||||||
};
|
|
||||||
|
|
||||||
const bounds = {};
|
|
||||||
bounds.x = textBox.boundingBox.width;
|
|
||||||
bounds.y = textBox.boundingBox.height;
|
|
||||||
|
|
||||||
const getHandlePosition = key => _.pick(handles[key], ['x', 'y']);
|
|
||||||
const start = getHandlePosition('start');
|
|
||||||
const end = getHandlePosition('end');
|
|
||||||
|
|
||||||
const tool = {};
|
|
||||||
tool.x = calculateAxisCenter('x', start, end);
|
|
||||||
tool.y = calculateAxisCenter('y', start, end);
|
|
||||||
|
|
||||||
let limits = {};
|
|
||||||
limits.x = image.width;
|
|
||||||
limits.y = image.height;
|
|
||||||
|
|
||||||
let { directions, cornerAxis } = getRenderingInformation(limits, tool);
|
|
||||||
|
|
||||||
const availableAreas = getAvailableBlankAreas(enabledElement, bounds.x, bounds.y);
|
|
||||||
const tempDirections = _.clone(directions);
|
|
||||||
let tempCornerAxis = cornerAxis;
|
|
||||||
let foundPlace = false;
|
|
||||||
let current = 0;
|
|
||||||
while (current < 4) {
|
|
||||||
if (availableAreas[tempCornerAxis + tempDirections[tempCornerAxis]]) {
|
|
||||||
foundPlace = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invert the direction for the next iteration
|
|
||||||
tempDirections[tempCornerAxis] *= -1;
|
|
||||||
|
|
||||||
// Invert the tempCornerAxis
|
|
||||||
tempCornerAxis = tempCornerAxis === 'x' ? 'y' : 'x';
|
|
||||||
|
|
||||||
current++;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cornerAxisPosition;
|
|
||||||
if (foundPlace) {
|
|
||||||
_.extend(directions, tempDirections);
|
|
||||||
cornerAxis = tempCornerAxis;
|
|
||||||
cornerAxisPosition = directions[cornerAxis] < 0 ? 0 : limits[cornerAxis];
|
|
||||||
} else {
|
|
||||||
_.extend(limits, canvasDimensions);
|
|
||||||
|
|
||||||
const toolPositionOnCanvas = cornerstone.pixelToCanvas(element, tool);
|
|
||||||
const renderingInformation = getRenderingInformation(limits, toolPositionOnCanvas);
|
|
||||||
directions = renderingInformation.directions;
|
|
||||||
cornerAxis = renderingInformation.cornerAxis;
|
|
||||||
|
|
||||||
const position = {
|
|
||||||
x: directions.x < 0 ? offset.left : offset.left + canvasWidth,
|
|
||||||
y: directions.y < 0 ? offset.top : offset.top + canvasHeight
|
|
||||||
};
|
|
||||||
|
|
||||||
const pixelPosition = cornerstone.pageToPixel(element, position.x, position.y);
|
|
||||||
cornerAxisPosition = pixelPosition[cornerAxis];
|
|
||||||
}
|
|
||||||
|
|
||||||
const toolAxis = cornerAxis === 'x' ? 'y' : 'x';
|
|
||||||
const boxSize = getTextBoxSizeInPixels(element, bounds);
|
|
||||||
|
|
||||||
textBox[cornerAxis] = cornerAxisPosition;
|
|
||||||
textBox[toolAxis] = tool[toolAxis] - (boxSize[toolAxis] / 2);
|
|
||||||
|
|
||||||
// Adjust the text box position reducing its size from the corner axis
|
|
||||||
const isDirectionPositive = directions[cornerAxis] > 0;
|
|
||||||
if ((foundPlace && !isDirectionPositive) || (!foundPlace && isDirectionPositive)) {
|
|
||||||
textBox[cornerAxis] -= boxSize[cornerAxis];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preventing the text box from partially going outside the canvas area
|
|
||||||
const topLeft = cornerstone.pixelToCanvas(element, textBox);
|
|
||||||
const bottomRight = {
|
|
||||||
x: topLeft.x + bounds.x,
|
|
||||||
y: topLeft.y + bounds.y
|
|
||||||
};
|
|
||||||
const canvasBorders = {
|
|
||||||
x0: offset.left,
|
|
||||||
y0: offset.top,
|
|
||||||
x1: offset.left + canvasWidth,
|
|
||||||
y1: offset.top + canvasHeight
|
|
||||||
};
|
|
||||||
if (topLeft[toolAxis] < 0) {
|
|
||||||
const x = canvasBorders.x0;
|
|
||||||
const y = canvasBorders.y0;
|
|
||||||
const pixelPosition = cornerstone.pageToPixel(element, x, y);
|
|
||||||
textBox[toolAxis] = pixelPosition[toolAxis];
|
|
||||||
} else if (bottomRight[toolAxis] > canvasDimensions[toolAxis]) {
|
|
||||||
const x = canvasBorders.x1 - bounds.x;
|
|
||||||
const y = canvasBorders.y1 - bounds.y;
|
|
||||||
const pixelPosition = cornerstone.pageToPixel(element, x, y);
|
|
||||||
textBox[toolAxis] = pixelPosition[toolAxis];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const mouseUpCallback = () => {
|
const bounds = {};
|
||||||
$element.off('CornerstoneToolsMeasurementModified', modifiedCallback);
|
bounds.x = textBox.boundingBox.width;
|
||||||
|
bounds.y = textBox.boundingBox.height;
|
||||||
|
|
||||||
|
const getHandlePosition = key => _.pick(handles[key], ['x', 'y']);
|
||||||
|
const start = getHandlePosition('start');
|
||||||
|
const end = getHandlePosition('end');
|
||||||
|
|
||||||
|
const tool = {};
|
||||||
|
tool.x = calculateAxisCenter('x', start, end);
|
||||||
|
tool.y = calculateAxisCenter('y', start, end);
|
||||||
|
|
||||||
|
let limits = {};
|
||||||
|
limits.x = image.width;
|
||||||
|
limits.y = image.height;
|
||||||
|
|
||||||
|
let { directions, cornerAxis } = getRenderingInformation(limits, tool);
|
||||||
|
|
||||||
|
const availableAreas = getAvailableBlankAreas(enabledElement, bounds.x, bounds.y);
|
||||||
|
const tempDirections = _.clone(directions);
|
||||||
|
let tempCornerAxis = cornerAxis;
|
||||||
|
let foundPlace = false;
|
||||||
|
let current = 0;
|
||||||
|
while (current < 4) {
|
||||||
|
if (availableAreas[tempCornerAxis + tempDirections[tempCornerAxis]]) {
|
||||||
|
foundPlace = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert the direction for the next iteration
|
||||||
|
tempDirections[tempCornerAxis] *= -1;
|
||||||
|
|
||||||
|
// Invert the tempCornerAxis
|
||||||
|
tempCornerAxis = tempCornerAxis === 'x' ? 'y' : 'x';
|
||||||
|
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cornerAxisPosition;
|
||||||
|
if (foundPlace) {
|
||||||
|
_.extend(directions, tempDirections);
|
||||||
|
cornerAxis = tempCornerAxis;
|
||||||
|
cornerAxisPosition = directions[cornerAxis] < 0 ? 0 : limits[cornerAxis];
|
||||||
|
} else {
|
||||||
|
_.extend(limits, canvasDimensions);
|
||||||
|
|
||||||
|
const toolPositionOnCanvas = cornerstone.pixelToCanvas(element, tool);
|
||||||
|
const renderingInformation = getRenderingInformation(limits, toolPositionOnCanvas);
|
||||||
|
directions = renderingInformation.directions;
|
||||||
|
cornerAxis = renderingInformation.cornerAxis;
|
||||||
|
|
||||||
|
const position = {
|
||||||
|
x: directions.x < 0 ? offset.left : offset.left + canvasWidth,
|
||||||
|
y: directions.y < 0 ? offset.top : offset.top + canvasHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
const pixelPosition = cornerstone.pageToPixel(element, position.x, position.y);
|
||||||
|
cornerAxisPosition = pixelPosition[cornerAxis];
|
||||||
|
}
|
||||||
|
|
||||||
|
const toolAxis = cornerAxis === 'x' ? 'y' : 'x';
|
||||||
|
const boxSize = getTextBoxSizeInPixels(element, bounds);
|
||||||
|
|
||||||
|
textBox[cornerAxis] = cornerAxisPosition;
|
||||||
|
textBox[toolAxis] = tool[toolAxis] - (boxSize[toolAxis] / 2);
|
||||||
|
|
||||||
|
// Adjust the text box position reducing its size from the corner axis
|
||||||
|
const isDirectionPositive = directions[cornerAxis] > 0;
|
||||||
|
if ((foundPlace && !isDirectionPositive) || (!foundPlace && isDirectionPositive)) {
|
||||||
|
textBox[cornerAxis] -= boxSize[cornerAxis];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preventing the text box from partially going outside the canvas area
|
||||||
|
const topLeft = cornerstone.pixelToCanvas(element, textBox);
|
||||||
|
const bottomRight = {
|
||||||
|
x: topLeft.x + bounds.x,
|
||||||
|
y: topLeft.y + bounds.y
|
||||||
};
|
};
|
||||||
|
const canvasBorders = {
|
||||||
$element.one('CornerstoneToolsMouseDrag', () => {
|
x0: offset.left,
|
||||||
$element.on('CornerstoneToolsMeasurementModified', modifiedCallback);
|
y0: offset.top,
|
||||||
});
|
x1: offset.left + canvasWidth,
|
||||||
|
y1: offset.top + canvasHeight
|
||||||
// Using mouseup because sometimes the CornerstoneToolsMouseUp event is not triggered
|
};
|
||||||
$element.one('mouseup', mouseUpCallback);
|
if (topLeft[toolAxis] < 0) {
|
||||||
|
const x = canvasBorders.x0;
|
||||||
|
const y = canvasBorders.y0;
|
||||||
|
const pixelPosition = cornerstone.pageToPixel(element, x, y);
|
||||||
|
textBox[toolAxis] = pixelPosition[toolAxis];
|
||||||
|
} else if (bottomRight[toolAxis] > canvasDimensions[toolAxis]) {
|
||||||
|
const x = canvasBorders.x1 - bounds.x;
|
||||||
|
const y = canvasBorders.y1 - bounds.y;
|
||||||
|
const pixelPosition = cornerstone.pageToPixel(element, x, y);
|
||||||
|
textBox[toolAxis] = pixelPosition[toolAxis];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -44,6 +44,7 @@ import { OHIF } from 'meteor/ohif:core';
|
|||||||
function createNewMeasurement(mouseEventData) {
|
function createNewMeasurement(mouseEventData) {
|
||||||
// Create the measurement data for this tool with the end handle activated
|
// Create the measurement data for this tool with the end handle activated
|
||||||
const measurementData = {
|
const measurementData = {
|
||||||
|
isCreating: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
active: true,
|
active: true,
|
||||||
handles: {
|
handles: {
|
||||||
@ -99,8 +100,6 @@ import { OHIF } from 'meteor/ohif:core';
|
|||||||
toolType: 'bidirectional'
|
toolType: 'bidirectional'
|
||||||
};
|
};
|
||||||
|
|
||||||
OHIF.cornerstone.repositionTextBoxWhileDragging(mouseEventData, measurementData);
|
|
||||||
|
|
||||||
return measurementData;
|
return measurementData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,6 +1039,8 @@ import { OHIF } from 'meteor/ohif:core';
|
|||||||
|
|
||||||
data.handles.textBox.boundingBox = boundingBox;
|
data.handles.textBox.boundingBox = boundingBox;
|
||||||
|
|
||||||
|
OHIF.cornerstone.repositionTextBox(eventData, data);
|
||||||
|
|
||||||
// Draw linked line as dashed
|
// Draw linked line as dashed
|
||||||
var link = {
|
var link = {
|
||||||
start: {},
|
start: {},
|
||||||
|
|||||||
@ -38,6 +38,8 @@ import { toolManager } from 'meteor/ohif:viewerbase';
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete measurementData.isCreating;
|
||||||
|
|
||||||
OHIF.ui.showFormDialog('dialogNonTargetMeasurement', {
|
OHIF.ui.showFormDialog('dialogNonTargetMeasurement', {
|
||||||
position: getPosition(eventData),
|
position: getPosition(eventData),
|
||||||
title: 'Select Lesion Location',
|
title: 'Select Lesion Location',
|
||||||
@ -142,6 +144,7 @@ import { toolManager } from 'meteor/ohif:viewerbase';
|
|||||||
|
|
||||||
// create the measurement data for this tool with the end handle activated
|
// create the measurement data for this tool with the end handle activated
|
||||||
var measurementData = {
|
var measurementData = {
|
||||||
|
isCreating: true,
|
||||||
visible: true,
|
visible: true,
|
||||||
active: true,
|
active: true,
|
||||||
handles: {
|
handles: {
|
||||||
@ -178,8 +181,6 @@ import { toolManager } from 'meteor/ohif:viewerbase';
|
|||||||
toolType: 'nonTarget'
|
toolType: 'nonTarget'
|
||||||
};
|
};
|
||||||
|
|
||||||
OHIF.cornerstone.repositionTextBoxWhileDragging(mouseEventData, measurementData);
|
|
||||||
|
|
||||||
return measurementData;
|
return measurementData;
|
||||||
}
|
}
|
||||||
///////// END ACTIVE TOOL ///////
|
///////// END ACTIVE TOOL ///////
|
||||||
@ -255,6 +256,8 @@ import { toolManager } from 'meteor/ohif:viewerbase';
|
|||||||
var boundingBox = cornerstoneTools.drawTextBox(context, 'Non-Target ' + data.measurementNumber, canvasTextLocation.x, canvasTextLocation.y, color);
|
var boundingBox = cornerstoneTools.drawTextBox(context, 'Non-Target ' + data.measurementNumber, canvasTextLocation.x, canvasTextLocation.y, color);
|
||||||
data.handles.textBox.boundingBox = boundingBox;
|
data.handles.textBox.boundingBox = boundingBox;
|
||||||
|
|
||||||
|
OHIF.cornerstone.repositionTextBox(eventData, data);
|
||||||
|
|
||||||
// Draw linked line as dashed
|
// Draw linked line as dashed
|
||||||
var link = {
|
var link = {
|
||||||
start: {},
|
start: {},
|
||||||
|
|||||||
@ -40,6 +40,8 @@ Template.measurementLocationDialog.onCreated(() => {
|
|||||||
const timepointApi = instance.data.timepointApi;
|
const timepointApi = instance.data.timepointApi;
|
||||||
|
|
||||||
const toggleLabel = (measurementData, eventData, doneCallback) => {
|
const toggleLabel = (measurementData, eventData, doneCallback) => {
|
||||||
|
delete measurementData.isCreating;
|
||||||
|
|
||||||
if (OHIF.lesiontracker.removeMeasurementIfInvalid(measurementData, eventData)) {
|
if (OHIF.lesiontracker.removeMeasurementIfInvalid(measurementData, eventData)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user