WIP reorganization
This commit is contained in:
1 parent
6706dfe634
commit
054e37dfb7
266 files changed
+98
-620
No files matched your search
+22
@@ -0,0 +1,22 @@
|
||||
import { cornerstoneTools } from 'meteor/ohif:cornerstone';
|
||||
|
||||
// Add a proxy to cornerstoneTools.drawHandles function to change the handles' active state base on
|
||||
// the hover, moving and selected states
|
||||
export default function(context, eventData, handles, color, options) {
|
||||
Object.keys(handles).forEach(handleKey => {
|
||||
if (handleKey === 'textBox') return;
|
||||
const handle = handles[handleKey];
|
||||
handle.drawnIndependently = handle.moving;
|
||||
if (handle.selected) {
|
||||
handle.active = handle.hover;
|
||||
} else {
|
||||
if (handle.hover) {
|
||||
handle.active = true;
|
||||
} else {
|
||||
handle.active = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cornerstoneTools.drawHandles(context, eventData, handles, color, options);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import { cornerstone } from 'meteor/ohif:cornerstone';
|
||||
|
||||
// draw perpendicular line
|
||||
export default function(context, element, data, color, lineWidth) {
|
||||
// Draw perpendicular line
|
||||
const { perpendicularStart, perpendicularEnd } = data.handles;
|
||||
const perpendicularStartCanvas = cornerstone.pixelToCanvas(element, perpendicularStart);
|
||||
const perpendicularEndCanvas = cornerstone.pixelToCanvas(element, perpendicularEnd);
|
||||
|
||||
context.beginPath();
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = lineWidth;
|
||||
context.moveTo(perpendicularStartCanvas.x, perpendicularStartCanvas.y);
|
||||
context.lineTo(perpendicularEndCanvas.x, perpendicularEndCanvas.y);
|
||||
context.stroke();
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone';
|
||||
|
||||
// Draw a line marker over the selected arm
|
||||
export default function(eventData, handles, color) {
|
||||
const lib = OHIF.lesiontracker.bidirectional;
|
||||
const { canvasContext, element } = eventData;
|
||||
|
||||
const handleKey = lib.getSelectedHandleKey(handles);
|
||||
if (!handleKey) return;
|
||||
const handle = handles[handleKey];
|
||||
|
||||
// Used a big distance (1km) to fill the entire line
|
||||
const mmStep = -1000000;
|
||||
|
||||
// Get the line's start and end points
|
||||
const fakeImage = {
|
||||
columnPixelSpacing: eventData.viewport.scale,
|
||||
rowPixelSpacing: eventData.viewport.scale
|
||||
};
|
||||
const pointA = lib.repositionBidirectionalArmHandle(fakeImage, handles, handleKey, mmStep, 0);
|
||||
const pointB = _.pick(handle, ['x', 'y']);
|
||||
|
||||
// Stop here if pointA is not present
|
||||
if (!pointA) return;
|
||||
|
||||
// Get the canvas coordinates for the line var perpendicularStartCanvas = cornerstone.pixelToCanvas(element, data.handles.perpendicularStart);
|
||||
const canvasPointA = cornerstone.pixelToCanvas(element, pointA);
|
||||
const canvasPointB = cornerstone.pixelToCanvas(element, pointB);
|
||||
|
||||
// Draw the line marker
|
||||
canvasContext.beginPath();
|
||||
canvasContext.strokeStyle = color;
|
||||
canvasContext.lineWidth = cornerstoneTools.toolStyle.getToolWidth();
|
||||
canvasContext.moveTo(canvasPointA.x, canvasPointA.y);
|
||||
canvasContext.lineTo(canvasPointB.x, canvasPointB.y);
|
||||
canvasContext.stroke();
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import onImageRendered from './onImageRendered';
|
||||
export default onImageRendered;
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
import { cornerstone, cornerstoneMath, cornerstoneTools } from 'meteor/ohif:cornerstone';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { toolType } from '../definitions';
|
||||
import drawHandles from './drawHandles';
|
||||
import calculateLongestAndShortestDiameters from '../calculateLongestAndShortestDiameters';
|
||||
import updatePerpendicularLineHandles from '../updatePerpendicularLineHandles';
|
||||
import drawPerpendicularLine from './drawPerpendicularLine';
|
||||
import drawSelectedMarker from './drawSelectedMarker';
|
||||
|
||||
export default function onImageRendered(event) {
|
||||
const eventData = event.detail;
|
||||
const { element, canvasContext } = eventData;
|
||||
|
||||
// if we have no toolData for this element, return immediately as there is nothing to do
|
||||
const toolData = cornerstoneTools.getToolState(element, toolType);
|
||||
if (!toolData) return;
|
||||
|
||||
const imagePlane = cornerstone.metaData.get('imagePlaneModule', eventData.image.imageId);
|
||||
let rowPixelSpacing;
|
||||
let colPixelSpacing;
|
||||
|
||||
if (imagePlane) {
|
||||
rowPixelSpacing = imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing;
|
||||
colPixelSpacing = imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing;
|
||||
} else {
|
||||
rowPixelSpacing = eventData.image.rowPixelSpacing;
|
||||
colPixelSpacing = eventData.image.columnPixelSpacing;
|
||||
}
|
||||
|
||||
// LT-29 Disable Target Measurements when pixel spacing is not available
|
||||
if (!rowPixelSpacing || !colPixelSpacing) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we have tool data for this element - iterate over each one and draw it
|
||||
const context = canvasContext.canvas.getContext('2d');
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
|
||||
let color;
|
||||
const lineWidth = cornerstoneTools.toolStyle.getToolWidth();
|
||||
const config = cornerstoneTools[toolType].getConfiguration();
|
||||
|
||||
for (let i = 0; i < toolData.data.length; i++) {
|
||||
const data = toolData.data[i];
|
||||
if (data.visible === false) continue;
|
||||
|
||||
const { start, end, perpendicularStart, perpendicularEnd, textBox } = data.handles;
|
||||
const strokeWidth = lineWidth;
|
||||
|
||||
context.save();
|
||||
|
||||
// configurable shadow from CornerstoneTools
|
||||
const { shadow } = config;
|
||||
if (shadow && shadow.shadow) {
|
||||
context.shadowColor = shadow.shadowColor || '#000000';
|
||||
context.shadowOffsetX = shadow.shadowOffsetX || 1;
|
||||
context.shadowOffsetY = shadow.shadowOffsetY || 1;
|
||||
}
|
||||
|
||||
const activeColor = cornerstoneTools.toolColors.getActiveColor();
|
||||
if (data.active) {
|
||||
color = activeColor;
|
||||
} else {
|
||||
color = cornerstoneTools.toolColors.getToolColor();
|
||||
}
|
||||
|
||||
// Update the perpendicular handles to draw it correctly
|
||||
updatePerpendicularLineHandles(eventData, data);
|
||||
|
||||
// Draw the line
|
||||
const { pixelToCanvas } = cornerstone;
|
||||
const handleStartCanvas = pixelToCanvas(element, start);
|
||||
const handleEndCanvas = pixelToCanvas(element, end);
|
||||
const handlePerpendicularStartCanvas = pixelToCanvas(element, perpendicularStart);
|
||||
const handlePerpendicularEndCanvas = pixelToCanvas(element, perpendicularEnd);
|
||||
const canvasTextLocation = pixelToCanvas(element, textBox);
|
||||
|
||||
context.beginPath();
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = strokeWidth;
|
||||
context.moveTo(handleStartCanvas.x, handleStartCanvas.y);
|
||||
context.lineTo(handleEndCanvas.x, handleEndCanvas.y);
|
||||
context.stroke();
|
||||
|
||||
// Draw perpendicular line
|
||||
drawPerpendicularLine(context, element, data, color, strokeWidth);
|
||||
|
||||
// Draw the handles
|
||||
const handlesColor = color;
|
||||
drawHandles(context, eventData, data.handles, handlesColor, { drawHandlesIfActive: true });
|
||||
|
||||
// Draw the selected marker
|
||||
drawSelectedMarker(eventData, data.handles, '#FF9999');
|
||||
|
||||
// Calculate the longest and shortest diameters, storing it in the respective attributes
|
||||
calculateLongestAndShortestDiameters(eventData, data);
|
||||
|
||||
if (data.measurementNumber) {
|
||||
// Draw the textbox
|
||||
let suffix = ' mm';
|
||||
if (!rowPixelSpacing || !colPixelSpacing) {
|
||||
suffix = ' pixels';
|
||||
}
|
||||
|
||||
const lengthText = ' L ' + data.longestDiameter + suffix;
|
||||
const widthText = ' W ' + data.shortestDiameter + suffix;
|
||||
let textLines = [`Target ${data.measurementNumber}`, lengthText, widthText];
|
||||
|
||||
// Append extra text lines when applies
|
||||
if (data.additionalData && Array.isArray(data.additionalData.extraTextLines)) {
|
||||
textLines = textLines.concat(data.additionalData.extraTextLines);
|
||||
}
|
||||
|
||||
const boundingBox = cornerstoneTools.drawTextBox(
|
||||
context,
|
||||
textLines,
|
||||
canvasTextLocation.x,
|
||||
canvasTextLocation.y,
|
||||
color,
|
||||
config.textBox
|
||||
);
|
||||
|
||||
textBox.boundingBox = boundingBox;
|
||||
|
||||
OHIF.cornerstone.repositionTextBox(eventData, data, config.textBox);
|
||||
|
||||
// Draw linked line as dashed
|
||||
const link = {
|
||||
start: {},
|
||||
end: {}
|
||||
};
|
||||
|
||||
const longLine = {
|
||||
start: handleStartCanvas,
|
||||
end: handleEndCanvas
|
||||
};
|
||||
|
||||
const perpendicularLine = {
|
||||
start: handlePerpendicularStartCanvas,
|
||||
end: handlePerpendicularEndCanvas
|
||||
};
|
||||
|
||||
// Check if the perpendicular line has some length (start and end are not equal)
|
||||
// Note: this check is needed to prevent NaN value on the intersection result
|
||||
const { distance } = cornerstoneMath.point;
|
||||
const lineHasLength = distance(perpendicularLine.start, perpendicularLine.end) > 0;
|
||||
|
||||
// Define the lines intersection point
|
||||
let linesIntersection;
|
||||
if (lineHasLength) {
|
||||
// As the line has length, define it as the intersection between the lines
|
||||
const { intersectLine } = cornerstoneMath.lineSegment;
|
||||
linesIntersection = intersectLine(longLine, perpendicularLine);
|
||||
} else {
|
||||
// As the line has no length, the tool is in its start position
|
||||
linesIntersection = longLine.start;
|
||||
}
|
||||
|
||||
const points = [
|
||||
handleStartCanvas,
|
||||
handleEndCanvas,
|
||||
handlePerpendicularStartCanvas,
|
||||
handlePerpendicularEndCanvas,
|
||||
linesIntersection
|
||||
];
|
||||
|
||||
link.end.x = canvasTextLocation.x;
|
||||
link.end.y = canvasTextLocation.y;
|
||||
|
||||
link.start = cornerstoneMath.point.findClosestPoint(points, link.end);
|
||||
|
||||
const boundingBoxPoints = [ {
|
||||
// Top middle point of bounding box
|
||||
x: boundingBox.left + boundingBox.width / 2,
|
||||
y: boundingBox.top
|
||||
}, {
|
||||
// Left middle point of bounding box
|
||||
x: boundingBox.left,
|
||||
y: boundingBox.top + boundingBox.height / 2
|
||||
}, {
|
||||
// Bottom middle point of bounding box
|
||||
x: boundingBox.left + boundingBox.width / 2,
|
||||
y: boundingBox.top + boundingBox.height
|
||||
}, {
|
||||
// Right middle point of bounding box
|
||||
x: boundingBox.left + boundingBox.width,
|
||||
y: boundingBox.top + boundingBox.height / 2
|
||||
},
|
||||
];
|
||||
|
||||
link.end = cornerstoneMath.point.findClosestPoint(boundingBoxPoints, link.start);
|
||||
context.beginPath();
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = lineWidth;
|
||||
context.setLineDash([ 2, 3 ]);
|
||||
|
||||
context.moveTo(link.start.x, link.start.y);
|
||||
context.lineTo(link.end.x, link.end.y);
|
||||
context.stroke();
|
||||
}
|
||||
|
||||
context.restore();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user