Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { vec3 } from 'gl-matrix';
import { PubSubService } from '@ohif/core';
import { Types as OhifTypes } from '@ohif/core';
import {
Expand Down Expand Up @@ -538,8 +539,7 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
* viewport to display the image in where it matches, in order:
* * Active viewport that can be navigated to the given image without orientation change
* * Other viewport that can be navigated to the given image without orientation change
* * Active viewport that can change orientation to display the image
* * Other viewport that can change orientation to display the image
* * Best-aligned viewport that can display the image with an orientation change
*
* It returns `null` otherwise, indicating that a viewport needs display set/type
* changes in order to display the image.
Expand All @@ -562,33 +562,27 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
if (!activeViewport) {
console.warn('No active viewport found for', activeViewportId);
}
if (activeViewport?.isReferenceViewable(metadata, { withNavigation: true })) {
if (activeViewport?.isReferenceViewable(metadata, WITH_NAVIGATION)) {
return activeViewportId;
}

// Next, see if any viewport could be navigated to show the given item,
// without considering orientation changes.
for (const id of this.viewportsById.keys()) {
const viewport = this.getCornerstoneViewport(id);
if (viewport?.isReferenceViewable(metadata, { withNavigation: true })) {
if (viewport?.isReferenceViewable(metadata, WITH_NAVIGATION)) {
return id;
}
}

// No viewport is in the right display set/orientation to show this, so see if
// the active viewport could change orientations to show this
if (
activeViewport?.isReferenceViewable(metadata, { withNavigation: true, withOrientation: true })
) {
return activeViewportId;
}
// Compute view-plane alignment scores for all viewports to prefer the one
// requiring the least orientation change when navigation-only is not possible.
const viewportAlignmentData = this.getViewportAlignmentData(metadata);

// See if any viewport could show this with an orientation change
for (const id of this.viewportsById.keys()) {
for (const { viewportId: id } of viewportAlignmentData) {
const viewport = this.getCornerstoneViewport(id);
if (
viewport?.isReferenceViewable(metadata, { withNavigation: true, withOrientation: true })
) {
if (viewport?.isReferenceViewable(metadata, WITH_ORIENTATION)) {
return id;
}
}
Expand All @@ -597,6 +591,47 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
return null;
}

/**
* Given a metadata instance containing a planeRestriction, returns the
* ordered list of best orientation match viewport ids.
*
* This uses the planeRestriction preferentially as that one is more reliably
* filled than the viewport normal since it is created from data points on
* rehydration.
*/
public getViewportAlignmentData(metadata) {
const viewportAlignmentData = [];
const { viewPlaneNormal: refViewPlaneNormal, planeRestriction } = metadata;
const inPlaneVector1 = planeRestriction?.inPlaneVector1;
const inPlaneVector2 = planeRestriction?.inPlaneVector2;

for (const id of this.viewportsById.keys()) {
const viewport = this.getCornerstoneViewport(id);
const { viewPlaneNormal } = viewport.getCamera();

if (!viewPlaneNormal) {
continue;
}
let alignmentScore = 0;
if (inPlaneVector1 || inPlaneVector2) {
const inPlane1Score = inPlaneVector1
? -Math.abs(vec3.dot(viewPlaneNormal, inPlaneVector1))
: 0;
const inPlane2Score = inPlaneVector2
? -Math.abs(vec3.dot(viewPlaneNormal, inPlaneVector2))
: 0;
alignmentScore = inPlane1Score + inPlane2Score;
} else if (refViewPlaneNormal) {
alignmentScore = Math.abs(vec3.dot(viewPlaneNormal, refViewPlaneNormal));
}
viewportAlignmentData.push({ viewportId: id, alignmentScore });
}

// Try best-aligned viewports first
viewportAlignmentData.sort((a, b) => b.alignmentScore - a.alignmentScore);
return viewportAlignmentData;
}

/**
* Figures out which viewport to update when the viewport type needs to change.
* This may not be the active viewport if there is already a viewport showing
Expand Down