fix: Jump to measurement from measurement panel after rotating viewport (#5090)

Requested issues were resolved.  Approved this and am merging.

* sort the viewports based on the closest orientation as that of measurement

* fix: Separate out function for finding viewport alignment

---------

Co-authored-by: Arul Mozhi J <arul.mozhi@trenser.com>
Co-authored-by: Bill Wallace <wayfarer3130@gmail.com>
This commit is contained in:
nithin-trenser 2025-12-18 03:22:45 +05:30 committed by GitHub
parent df40ffbf12
commit ef98516b4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,3 +1,4 @@
import { vec3 } from 'gl-matrix';
import { PubSubService } from '@ohif/core';
import { Types as OhifTypes } from '@ohif/core';
import {
@ -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.
@ -562,7 +562,7 @@ 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;
}
@ -570,25 +570,19 @@ class CornerstoneViewportService extends PubSubService implements IViewportServi
// 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;
}
}
@ -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