@cornerstonejs/core
Version:
Cornerstone3D Core
115 lines (114 loc) • 4.93 kB
JavaScript
import { vec3 } from 'gl-matrix';
import cache from '../../../cache/cache.js';
import { OrientationAxis } from '../../../enums/index.js';
import { getEffectiveRenderBackend } from '../../../init.js';
import * as metaData from '../../../metaData.js';
import { getRenderModeForBackend } from '../../helpers/renderBackendRegistry.js';
import { isValidVolume } from '../../../utilities/isValidVolume.js';
import { getOrientationFromScanAxisNormal } from '../../helpers/getCameraVectors.js';
export class PlanarRenderPathDecisionService {
select(dataSet, options = {}) {
if (!dataSet.imageIds.length) {
throw new Error('[PlanarViewport] Cannot add an empty planar dataset');
}
const orientation = options.orientation || OrientationAxis.ACQUISITION;
const acquisitionOrientation = getPlanarAcquisitionOrientation(dataSet.imageIds);
const volumeId = getVolumeId(dataSet);
const isAcquisitionPath = orientation === OrientationAxis.ACQUISITION ||
(acquisitionOrientation !== undefined &&
orientation === acquisitionOrientation);
const useVolumePath = isVolumeBackedDataSet(dataSet, isAcquisitionPath);
if (!isAcquisitionPath &&
!useVolumePath &&
!dataSet.useWorldCoordinateImageData) {
throw new Error('[PlanarViewport] Non-acquisition rendering requires a valid volume dataset');
}
if (useVolumePath && !supportsVolumeRendering(dataSet)) {
throw new Error('[PlanarViewport] Volume rendering requires a valid volume dataset');
}
return {
acquisitionOrientation,
renderMode: useVolumePath
? this.selectVolumeRenderMode(options)
: this.selectImageRenderMode(options),
volumeId,
};
}
canRender(dataSet, options = {}) {
if (!dataSet.imageIds.length) {
return false;
}
const orientation = options.orientation || OrientationAxis.ACQUISITION;
const acquisitionOrientation = getPlanarAcquisitionOrientation(dataSet.imageIds);
const isAcquisitionPath = orientation === OrientationAxis.ACQUISITION ||
(acquisitionOrientation !== undefined &&
orientation === acquisitionOrientation);
const useVolumePath = isVolumeBackedDataSet(dataSet, isAcquisitionPath);
if (!isAcquisitionPath &&
!useVolumePath &&
!dataSet.useWorldCoordinateImageData) {
return false;
}
if (useVolumePath && !supportsVolumeRendering(dataSet)) {
return false;
}
return true;
}
selectImageRenderMode(options) {
return getRenderModeForBackend(this.resolveBackend(options), 'image');
}
selectVolumeRenderMode(options) {
return getRenderModeForBackend(this.resolveBackend(options), 'volume');
}
resolveBackend(options) {
return getEffectiveRenderBackend(options.renderBackend);
}
}
export const defaultPlanarRenderPathDecisionService = new PlanarRenderPathDecisionService();
export function selectPlanarRenderPath(dataSet, options = {}) {
return defaultPlanarRenderPathDecisionService.select(dataSet, options);
}
export function getPlanarAcquisitionOrientation(imageIds) {
const imageId = imageIds[0];
if (!imageId) {
return;
}
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
const imageOrientationPatient = imagePlaneModule?.imageOrientationPatient;
if (!imageOrientationPatient || imageOrientationPatient.length !== 6) {
return;
}
const rowVec = vec3.fromValues(imageOrientationPatient[0], imageOrientationPatient[1], imageOrientationPatient[2]);
const colVec = vec3.fromValues(imageOrientationPatient[3], imageOrientationPatient[4], imageOrientationPatient[5]);
const scanAxisNormal = vec3.create();
vec3.cross(scanAxisNormal, rowVec, colVec);
const orientation = getOrientationFromScanAxisNormal([
scanAxisNormal[0],
scanAxisNormal[1],
scanAxisNormal[2],
]);
if (orientation !== OrientationAxis.AXIAL &&
orientation !== OrientationAxis.CORONAL &&
orientation !== OrientationAxis.SAGITTAL) {
return;
}
return orientation;
}
function getVolumeId(dataSet) {
return dataSet.volumeId || cache.generateVolumeId(dataSet.imageIds);
}
function hasExplicitCachedVolume(dataSet) {
return !!(dataSet.volumeId && cache.getVolume(dataSet.volumeId));
}
function supportsVolumeRendering(dataSet) {
return hasExplicitCachedVolume(dataSet) || isValidVolume(dataSet.imageIds);
}
function isVolumeBackedDataSet(dataSet, isAcquisitionPath) {
if (dataSet.useWorldCoordinateImageData) {
return false;
}
if (dataSet.volumeId) {
return true;
}
return !isAcquisitionPath && supportsVolumeRendering(dataSet);
}