diff --git a/src/tools/annotation/AngleTool.js b/src/tools/annotation/AngleTool.js index ab2cb7178..f8545732c 100644 --- a/src/tools/annotation/AngleTool.js +++ b/src/tools/annotation/AngleTool.js @@ -112,22 +112,9 @@ export default class AngleTool extends BaseAnnotationTool { } updateCachedStats(image, element, data) { - const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image); - - const sideA = { - x: (data.handles.middle.x - data.handles.start.x) * colPixelSpacing, - y: (data.handles.middle.y - data.handles.start.y) * rowPixelSpacing, - }; - - const sideB = { - x: (data.handles.end.x - data.handles.middle.x) * colPixelSpacing, - y: (data.handles.end.y - data.handles.middle.y) * rowPixelSpacing, - }; - - const sideC = { - x: (data.handles.end.x - data.handles.start.x) * colPixelSpacing, - y: (data.handles.end.y - data.handles.start.y) * rowPixelSpacing, - }; + const sideA = getSide(image, data.handles.middle, data.handles.start); + const sideB = getSide(image, data.handles.end, data.handles.middle); + const sideC = getSide(image, data.handles.end, data.handles.middle); const sideALength = length(sideA); const sideBLength = length(sideB); @@ -360,3 +347,12 @@ export default class AngleTool extends BaseAnnotationTool { function length(vector) { return Math.sqrt(Math.pow(vector.x, 2) + Math.pow(vector.y, 2)); } + +function getSide(image, handleEnd, handleStart) { + const { rowPixelSpacing, colPixelSpacing } = getPixelSpacing(image); + + return { + x: (handleEnd.x - handleStart.x) * (colPixelSpacing || 1), + y: (handleEnd.y - handleStart.y) * (rowPixelSpacing || 1), + }; +} diff --git a/src/tools/annotation/AngleTool.test.js b/src/tools/annotation/AngleTool.test.js new file mode 100644 index 000000000..fa0f1576e --- /dev/null +++ b/src/tools/annotation/AngleTool.test.js @@ -0,0 +1,173 @@ +import AngleTool from './AngleTool.js'; +import { getToolState } from './../../stateManagement/toolState.js'; + +jest.mock('./../../stateManagement/toolState.js', () => ({ + getToolState: jest.fn(), +})); + +jest.mock('./../../importInternal.js', () => ({ + default: jest.fn(), +})); + +jest.mock('./../../externalModules.js', () => ({ + cornerstone: { + metaData: { + get: jest.fn(), + }, + }, +})); + +const goodMouseEventData = { + currentPoints: { + image: { + x: 0, + y: 0, + }, + }, +}; + +const image = { + rowPixelSpacing: 0.8984375, + columnPixelSpacing: 0.8984375, +}; + +describe('AngleTool.js', () => { + describe('default values', () => { + it('has a default name of "Angle"', () => { + const defaultName = 'Angle'; + const instantiatedTool = new AngleTool(); + + expect(instantiatedTool.name).toEqual(defaultName); + }); + + it('can be created with a custom tool name', () => { + const customToolName = { name: 'customToolName' }; + const instantiatedTool = new AngleTool(customToolName); + + expect(instantiatedTool.name).toEqual(customToolName.name); + }); + }); + + describe('createNewMeasurement', () => { + it('returns an angle tool object', () => { + const instantiatedTool = new AngleTool('Angle'); + + const toolMeasurement = instantiatedTool.createNewMeasurement( + goodMouseEventData + ); + + expect(typeof toolMeasurement).toBe(typeof {}); + }); + + it("returns a measurement with a start, middle and end handle at the eventData's x and y", () => { + const instantiatedTool = new AngleTool('toolName'); + + const toolMeasurement = instantiatedTool.createNewMeasurement( + goodMouseEventData + ); + const startHandle = { + x: toolMeasurement.handles.start.x, + y: toolMeasurement.handles.start.y, + }; + const middleHandle = { + x: toolMeasurement.handles.middle.x, + y: toolMeasurement.handles.middle.y, + }; + const endHandle = { + x: toolMeasurement.handles.end.x, + y: toolMeasurement.handles.end.y, + }; + + expect(startHandle.x).toBe(goodMouseEventData.currentPoints.image.x); + expect(startHandle.y).toBe(goodMouseEventData.currentPoints.image.y); + expect(middleHandle.x).toBe(goodMouseEventData.currentPoints.image.x); + expect(middleHandle.y).toBe(goodMouseEventData.currentPoints.image.y); + expect(endHandle.x).toBe(goodMouseEventData.currentPoints.image.x); + expect(endHandle.y).toBe(goodMouseEventData.currentPoints.image.y); + }); + + it('returns a measurement with a textBox handle', () => { + const instantiatedTool = new AngleTool('toolName'); + + const toolMeasurement = instantiatedTool.createNewMeasurement( + goodMouseEventData + ); + + expect(typeof toolMeasurement.handles.textBox).toBe(typeof {}); + }); + }); + + describe('pointNearTool', () => { + let element, coords; + + beforeEach(() => { + element = jest.fn(); + coords = jest.fn(); + }); + + it('returns false when measurement data is not visible', () => { + const instantiatedTool = new AngleTool('AngleTool'); + const notVisibleMeasurementData = { + visible: false, + }; + + const isPointNearTool = instantiatedTool.pointNearTool( + element, + notVisibleMeasurementData, + coords + ); + + expect(isPointNearTool).toBe(false); + }); + }); + + describe('updateCachedStats', () => { + let element; + + beforeEach(() => { + element = jest.fn(); + }); + + it('should calculate and update annotation value', () => { + const instantiatedTool = new AngleTool('AngleTool'); + + const data = { + handles: { + start: { + x: 166, + y: 90, + }, + middle: { + x: 120, + y: 113, + }, + end: { + x: 145, + y: 143, + }, + }, + }; + + instantiatedTool.updateCachedStats(image, element, data); + expect(data.rAngle).toBe(48.82); + expect(data.invalidated).toBe(false); + }); + }); + + describe('renderToolData', () => { + it('returns undefined when no toolData exists for the tool', () => { + const instantiatedTool = new AngleTool('AngleTool'); + const mockEvent = { + detail: { + enabledElement: undefined, + }, + }; + + getToolState.mockReturnValueOnce(undefined); + + const renderResult = instantiatedTool.renderToolData(mockEvent); + + expect(renderResult).toBe(undefined); + }); + }); +}); diff --git a/src/tools/annotation/CobbAngleTool.js b/src/tools/annotation/CobbAngleTool.js index e2a2db44f..3394e3a30 100644 --- a/src/tools/annotation/CobbAngleTool.js +++ b/src/tools/annotation/CobbAngleTool.js @@ -133,16 +133,16 @@ export default class CobbAngleTool extends BaseAnnotationTool { const dx1 = (Math.ceil(data.handles.start.x) - Math.ceil(data.handles.end.x)) * - colPixelSpacing; + (colPixelSpacing || 1); const dy1 = (Math.ceil(data.handles.start.y) - Math.ceil(data.handles.end.y)) * - rowPixelSpacing; + (rowPixelSpacing || 1); const dx2 = (Math.ceil(data.handles.start2.x) - Math.ceil(data.handles.end2.x)) * - colPixelSpacing; + (colPixelSpacing || 1); const dy2 = (Math.ceil(data.handles.start2.y) - Math.ceil(data.handles.end2.y)) * - rowPixelSpacing; + (rowPixelSpacing || 1); let angle = Math.acos( Math.abs(