From 0e87ab37c29fcf9af74bbcefca854c6e6b8707bc Mon Sep 17 00:00:00 2001 From: James Petts Date: Mon, 10 Aug 2020 13:16:19 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20Add=20support=20for=20PO?= =?UTF-8?q?INT=20and=20OPEN=5FPLANAR=20for=20RT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 🎸 Add support for POINT and OPEN_PLANAR for RT --- extensions/dicom-rt/src/loadRTStruct.js | 66 +++++++++++-------- .../dicom-rt/src/tools/RTStructDisplayTool.js | 57 ++++++++++++---- 2 files changed, 82 insertions(+), 41 deletions(-) diff --git a/extensions/dicom-rt/src/loadRTStruct.js b/extensions/dicom-rt/src/loadRTStruct.js index 005944de3..5fc1edb27 100644 --- a/extensions/dicom-rt/src/loadRTStruct.js +++ b/extensions/dicom-rt/src/loadRTStruct.js @@ -76,21 +76,15 @@ export default async function loadRTStruct( const isSupported = false; - for (let c = 0; c < ContourSequence.length; c++) { + const ContourSequenceArray = _toArray(ContourSequence); + + for (let c = 0; c < ContourSequenceArray.length; c++) { const { ContourImageSequence, ContourData, NumberOfContourPoints, ContourGeometricType, - } = ContourSequence[c]; - - if (ContourGeometricType !== 'CLOSED_PLANAR') { - // TODO: Do we want to visualise types other than closed planar? - // We could easily do open planar and point. - continue; - } - - isSupported = true; + } = ContourSequenceArray[c]; const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID; const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID); @@ -102,26 +96,38 @@ export default async function loadRTStruct( const imagePlane = cornerstone.metaData.get('imagePlaneModule', imageId); const points = []; + let measurementData; - for (let p = 0; p < NumberOfContourPoints * 3; p += 3) { - points.push({ - x: ContourData[p], - y: ContourData[p + 1], - z: ContourData[p + 2], - }); + switch (ContourGeometricType) { + case 'CLOSED_PLANAR': + case 'OPEN_PLANAR': + case 'POINT': + isSupported = true; + + for (let p = 0; p < NumberOfContourPoints * 3; p += 3) { + points.push({ + x: ContourData[p], + y: ContourData[p + 1], + z: ContourData[p + 2], + }); + } + + transformPointsToImagePlane(points, imagePlane); + + measurementData = { + handles: { + points, + }, + type: ContourGeometricType, + structureSetSeriesInstanceUid: rtStructDataset.SeriesInstanceUID, + ROINumber: ReferencedROINumber, + }; + + imageIdSpecificToolData.push(measurementData); + break; + default: + continue; } - - transformPointsToImagePlane(points, imagePlane); - - const measurementData = { - handles: { - points, - }, - structureSetSeriesInstanceUid: rtStructDataset.SeriesInstanceUID, - ROINumber: ReferencedROINumber, - }; - - imageIdSpecificToolData.push(measurementData); } _setROIContourMetadata( @@ -314,3 +320,7 @@ function _getImageIdSopInstanceUidPairsForDisplaySet( }; }); } + +function _toArray(objOrArray) { + return Array.isArray(objOrArray) ? objOrArray : [objOrArray]; +} diff --git a/extensions/dicom-rt/src/tools/RTStructDisplayTool.js b/extensions/dicom-rt/src/tools/RTStructDisplayTool.js index 85da79f76..e60b8ce91 100644 --- a/extensions/dicom-rt/src/tools/RTStructDisplayTool.js +++ b/extensions/dicom-rt/src/tools/RTStructDisplayTool.js @@ -4,6 +4,7 @@ import TOOL_NAMES from '../utils/toolNames'; // Cornerstone 3rd party dev kit imports const draw = importInternal('drawing/draw'); +const drawCircle = importInternal('drawing/drawCircle'); const drawJoinedLines = importInternal('drawing/drawJoinedLines'); const getNewContext = importInternal('drawing/getNewContext'); const BaseTool = importInternal('base/BaseTool'); @@ -72,22 +73,52 @@ export default class RTStructDisplayTool extends BaseTool { const colorArray = ROIContourData.colorArray; const color = `rgba(${colorArray[0]},${colorArray[1]},${ colorArray[2] - },${opacity})`; + },${opacity})`; - lineWidth; - - draw(context, context => { - drawJoinedLines( - context, - eventData.element, - points[points.length - 1], - points, - { + switch (data.type) { + case 'CLOSED_PLANAR': + this._renderClosedPlanar(context, eventData.element, points, { color, lineWidth, - } - ); - }); + }); + break; + case 'POINT': + this._renderPoint(context, eventData.element, points, { + color, + lineWidth, + }); + break; + case 'OPEN_PLANAR': + this._renderOpenPlanar(context, eventData.element, points, { + color, + lineWidth, + }); + break; + } } } + + _renderClosedPlanar(context, element, points, options) { + draw(context, context => { + drawJoinedLines( + context, + element, + points[points.length - 1], + points, + options + ); + }); + } + + _renderPoint(context, element, points, options) { + draw(context, context => { + drawCircle(context, element, points[0], 3, options); + }); + } + + _renderOpenPlanar(context, element, points, options) { + draw(context, context => { + drawJoinedLines(context, element, points[0], points, options); + }); + } }