[IDC-2063] Harden RTSTRUCT import (#2102)
* WIP * Fix RTSTRUCT import with missing ContourImageSequence
This commit is contained in:
parent
9448993cf0
commit
d6f79d9ddf
@ -32,6 +32,7 @@
|
|||||||
"cornerstone-core": "^2.2.8",
|
"cornerstone-core": "^2.2.8",
|
||||||
"cornerstone-tools": "^4.20.1",
|
"cornerstone-tools": "^4.20.1",
|
||||||
"dcmjs": "0.16.5",
|
"dcmjs": "0.16.5",
|
||||||
|
"gl-matrix": "^3.3.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.8.6",
|
"react": "^16.8.6",
|
||||||
"react-dom": "^16.8.6",
|
"react-dom": "^16.8.6",
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import cornerstone from 'cornerstone-core';
|
|||||||
import cornerstoneTools from 'cornerstone-tools';
|
import cornerstoneTools from 'cornerstone-tools';
|
||||||
import transformPointsToImagePlane from './utils/transformPointsToImagePlane';
|
import transformPointsToImagePlane from './utils/transformPointsToImagePlane';
|
||||||
import TOOL_NAMES from './utils/toolNames';
|
import TOOL_NAMES from './utils/toolNames';
|
||||||
|
import { vec3 } from 'gl-matrix';
|
||||||
|
|
||||||
const dicomlab2RGB = dcmjs.data.Colors.dicomlab2RGB;
|
const dicomlab2RGB = dcmjs.data.Colors.dicomlab2RGB;
|
||||||
const globalImageIdSpecificToolStateManager =
|
const globalImageIdSpecificToolStateManager =
|
||||||
@ -66,8 +67,6 @@ export default async function loadRTStruct(
|
|||||||
|
|
||||||
const rtStructDisplayToolName = TOOL_NAMES.RTSTRUCT_DISPLAY_TOOL;
|
const rtStructDisplayToolName = TOOL_NAMES.RTSTRUCT_DISPLAY_TOOL;
|
||||||
|
|
||||||
debugger;
|
|
||||||
|
|
||||||
for (let i = 0; i < ROIContourSequence.length; i++) {
|
for (let i = 0; i < ROIContourSequence.length; i++) {
|
||||||
const ROIContour = ROIContourSequence[i];
|
const ROIContour = ROIContourSequence[i];
|
||||||
const { ReferencedROINumber, ContourSequence } = ROIContour;
|
const { ReferencedROINumber, ContourSequence } = ROIContour;
|
||||||
@ -88,7 +87,14 @@ export default async function loadRTStruct(
|
|||||||
ContourGeometricType,
|
ContourGeometricType,
|
||||||
} = ContourSequenceArray[c];
|
} = ContourSequenceArray[c];
|
||||||
|
|
||||||
const sopInstanceUID = ContourImageSequence.ReferencedSOPInstanceUID;
|
const sopInstanceUID = ContourImageSequence
|
||||||
|
? ContourImageSequence.ReferencedSOPInstanceUID
|
||||||
|
: _getClosestSOPInstanceUID(
|
||||||
|
ContourData,
|
||||||
|
ContourGeometricType,
|
||||||
|
NumberOfContourPoints,
|
||||||
|
imageIdSopInstanceUidPairs
|
||||||
|
);
|
||||||
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
const imageId = _getImageId(imageIdSopInstanceUidPairs, sopInstanceUID);
|
||||||
const imageIdSpecificToolData = _getOrCreateImageIdSpecificToolData(
|
const imageIdSpecificToolData = _getOrCreateImageIdSpecificToolData(
|
||||||
toolState,
|
toolState,
|
||||||
@ -326,3 +332,78 @@ function _getImageIdSopInstanceUidPairsForDisplaySet(
|
|||||||
function _toArray(objOrArray) {
|
function _toArray(objOrArray) {
|
||||||
return Array.isArray(objOrArray) ? objOrArray : [objOrArray];
|
return Array.isArray(objOrArray) ? objOrArray : [objOrArray];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _getClosestSOPInstanceUID(
|
||||||
|
ContourData,
|
||||||
|
ContourGeometricType,
|
||||||
|
NumberOfContourPoints,
|
||||||
|
imageIdSopInstanceUidPairs
|
||||||
|
) {
|
||||||
|
const closest = {
|
||||||
|
distance: Infinity,
|
||||||
|
sopInstanceUID: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
let point;
|
||||||
|
|
||||||
|
switch (ContourGeometricType) {
|
||||||
|
case 'POINT':
|
||||||
|
point = ContourData;
|
||||||
|
break;
|
||||||
|
case 'CLOSED_PLANAR':
|
||||||
|
case 'OPEN_PLANAR':
|
||||||
|
// These are defined as planar, so get the of the region to get the
|
||||||
|
// Best mapping to a plane even if its potentially off center.
|
||||||
|
|
||||||
|
point = [0, 0, 0];
|
||||||
|
for (let p = 0; p < NumberOfContourPoints * 3; p += 3) {
|
||||||
|
point[0] += ContourData[p];
|
||||||
|
point[1] += ContourData[p + 1];
|
||||||
|
point[2] += ContourData[p + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
point[0] /= NumberOfContourPoints;
|
||||||
|
point[1] /= NumberOfContourPoints;
|
||||||
|
point[2] /= NumberOfContourPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageIdSopInstanceUidPairs.forEach(pair => {
|
||||||
|
const { imageId } = pair;
|
||||||
|
|
||||||
|
const imagePlaneModule = cornerstone.metaData.get(
|
||||||
|
'imagePlaneModule',
|
||||||
|
imageId
|
||||||
|
);
|
||||||
|
|
||||||
|
const distance = distanceFromPointToPlane(point, imagePlaneModule);
|
||||||
|
|
||||||
|
if (distance < closest.distance) {
|
||||||
|
closest.distance = distance;
|
||||||
|
closest.sopInstanceUID = pair.sopInstanceUID;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return closest.sopInstanceUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number[3]} P - The point
|
||||||
|
* @param {object} imagePlaneModule The cornerstone metadata object for the imagePlane
|
||||||
|
*/
|
||||||
|
function distanceFromPointToPlane(P, imagePlaneModule) {
|
||||||
|
const {
|
||||||
|
rowCosines,
|
||||||
|
columnCosines,
|
||||||
|
imagePositionPatient: Q,
|
||||||
|
} = imagePlaneModule;
|
||||||
|
|
||||||
|
let N = [];
|
||||||
|
vec3.cross(N, rowCosines, columnCosines);
|
||||||
|
|
||||||
|
const [A, B, C] = N;
|
||||||
|
|
||||||
|
const D = -A * Q[0] - B * Q[1] - C * Q[2];
|
||||||
|
|
||||||
|
return Math.abs(A * P[0] + B * P[1] + C * P[2] + D); // Denominator is sqrt(A**2 + B**2 + C**2) which is 1 as its a normal vector
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user