@cornerstonejs/core 1.71.3 → 1.71.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.d.ts +7 -6
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +87 -12
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/RenderingEngine.js +6 -1
- package/dist/cjs/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/cjs/RenderingEngine/StackViewport.d.ts +5 -5
- package/dist/cjs/RenderingEngine/StackViewport.js +71 -50
- package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/Viewport.d.ts +2 -1
- package/dist/cjs/RenderingEngine/Viewport.js +21 -16
- package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/VolumeViewport.d.ts +5 -3
- package/dist/cjs/RenderingEngine/VolumeViewport.js +39 -15
- package/dist/cjs/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/cjs/RenderingEngine/VolumeViewport3D.d.ts +1 -0
- package/dist/cjs/RenderingEngine/VolumeViewport3D.js +3 -0
- package/dist/cjs/RenderingEngine/VolumeViewport3D.js.map +1 -1
- package/dist/cjs/types/EventTypes.d.ts +8 -1
- package/dist/cjs/types/IViewport.d.ts +5 -1
- package/dist/cjs/types/IVolumeViewport.d.ts +2 -1
- package/dist/cjs/utilities/index.d.ts +3 -2
- package/dist/cjs/utilities/index.js +8 -4
- package/dist/cjs/utilities/index.js.map +1 -1
- package/dist/cjs/utilities/isEqual.d.ts +3 -0
- package/dist/cjs/utilities/isEqual.js +8 -0
- package/dist/cjs/utilities/isEqual.js.map +1 -1
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js +87 -15
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/RenderingEngine.js +6 -1
- package/dist/esm/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/esm/RenderingEngine/StackViewport.js +53 -34
- package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/Viewport.js +20 -16
- package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
- package/dist/esm/RenderingEngine/VolumeViewport.js +39 -15
- package/dist/esm/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/esm/RenderingEngine/VolumeViewport3D.js +3 -0
- package/dist/esm/RenderingEngine/VolumeViewport3D.js.map +1 -1
- package/dist/esm/utilities/index.js +3 -2
- package/dist/esm/utilities/index.js.map +1 -1
- package/dist/esm/utilities/isEqual.js +5 -0
- package/dist/esm/utilities/isEqual.js.map +1 -1
- package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts +7 -6
- package/dist/types/RenderingEngine/BaseVolumeViewport.d.ts.map +1 -1
- package/dist/types/RenderingEngine/RenderingEngine.d.ts.map +1 -1
- package/dist/types/RenderingEngine/StackViewport.d.ts +5 -5
- package/dist/types/RenderingEngine/StackViewport.d.ts.map +1 -1
- package/dist/types/RenderingEngine/Viewport.d.ts +2 -1
- package/dist/types/RenderingEngine/Viewport.d.ts.map +1 -1
- package/dist/types/RenderingEngine/VolumeViewport.d.ts +5 -3
- package/dist/types/RenderingEngine/VolumeViewport.d.ts.map +1 -1
- package/dist/types/RenderingEngine/VolumeViewport3D.d.ts +1 -0
- package/dist/types/RenderingEngine/VolumeViewport3D.d.ts.map +1 -1
- package/dist/types/types/EventTypes.d.ts +8 -1
- package/dist/types/types/EventTypes.d.ts.map +1 -1
- package/dist/types/types/IViewport.d.ts +5 -1
- package/dist/types/types/IViewport.d.ts.map +1 -1
- package/dist/types/types/IVolumeViewport.d.ts +2 -1
- package/dist/types/types/IVolumeViewport.d.ts.map +1 -1
- package/dist/types/types/displayArea.d.ts.map +1 -1
- package/dist/types/utilities/index.d.ts +3 -2
- package/dist/types/utilities/index.d.ts.map +1 -1
- package/dist/types/utilities/isEqual.d.ts +3 -0
- package/dist/types/utilities/isEqual.d.ts.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +2 -2
- package/src/RenderingEngine/BaseVolumeViewport.ts +189 -21
- package/src/RenderingEngine/RenderingEngine.ts +12 -1
- package/src/RenderingEngine/StackViewport.ts +81 -50
- package/src/RenderingEngine/Viewport.ts +37 -24
- package/src/RenderingEngine/VolumeViewport.ts +73 -24
- package/src/RenderingEngine/VolumeViewport3D.ts +4 -0
- package/src/types/EventTypes.ts +19 -0
- package/src/types/IViewport.ts +64 -18
- package/src/types/IVolumeViewport.ts +6 -1
- package/src/types/displayArea.ts +27 -0
- package/src/utilities/index.ts +6 -2
- package/src/utilities/isEqual.ts +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "1.71.
|
|
3
|
+
"version": "1.71.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"type": "individual",
|
|
48
48
|
"url": "https://ohif.org/donate"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "589239e007a87fa5316efa222054c518e6f00098"
|
|
51
51
|
}
|
|
@@ -37,11 +37,12 @@ import type {
|
|
|
37
37
|
VolumeViewportProperties,
|
|
38
38
|
ViewReferenceSpecifier,
|
|
39
39
|
ReferenceCompatibleOptions,
|
|
40
|
+
ViewPresentation,
|
|
41
|
+
ViewReference,
|
|
42
|
+
IVolumeViewport,
|
|
40
43
|
} from '../types';
|
|
41
44
|
import { VoiModifiedEventDetail } from '../types/EventTypes';
|
|
42
45
|
import type { ViewportInput } from '../types/IViewport';
|
|
43
|
-
import type IVolumeViewport from '../types/IVolumeViewport';
|
|
44
|
-
import type { ViewReference } from '../types/IViewport';
|
|
45
46
|
import {
|
|
46
47
|
actorIsA,
|
|
47
48
|
applyPreset,
|
|
@@ -51,6 +52,10 @@ import {
|
|
|
51
52
|
invertRgbTransferFunction,
|
|
52
53
|
triggerEvent,
|
|
53
54
|
colormap as colormapUtils,
|
|
55
|
+
isEqualNegative,
|
|
56
|
+
getVolumeViewportScrollInfo,
|
|
57
|
+
snapFocalPointToSlice,
|
|
58
|
+
isEqual,
|
|
54
59
|
} from '../utilities';
|
|
55
60
|
import { createVolumeActor } from './helpers';
|
|
56
61
|
import volumeNewImageEventDispatcher, {
|
|
@@ -126,7 +131,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
protected applyViewOrientation(
|
|
129
|
-
orientation: OrientationAxis | OrientationVectors
|
|
134
|
+
orientation: OrientationAxis | OrientationVectors,
|
|
135
|
+
resetCamera = true
|
|
130
136
|
) {
|
|
131
137
|
const { viewPlaneNormal, viewUp } =
|
|
132
138
|
this._getOrientationVectors(orientation);
|
|
@@ -139,7 +145,9 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
139
145
|
camera.setViewUpFrom(viewUp);
|
|
140
146
|
this.initialViewUp = viewUp;
|
|
141
147
|
|
|
142
|
-
|
|
148
|
+
if (resetCamera) {
|
|
149
|
+
this.resetCamera();
|
|
150
|
+
}
|
|
143
151
|
}
|
|
144
152
|
|
|
145
153
|
private initializeVolumeNewImageEventDispatcher(): void {
|
|
@@ -597,15 +605,36 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
597
605
|
viewRefSpecifier: ViewReferenceSpecifier = {}
|
|
598
606
|
): ViewReference {
|
|
599
607
|
const target = super.getViewReference(viewRefSpecifier);
|
|
608
|
+
const volumeId = this.getVolumeId(viewRefSpecifier);
|
|
600
609
|
if (viewRefSpecifier?.forFrameOfReference !== false) {
|
|
601
|
-
target.volumeId =
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
610
|
+
target.volumeId = volumeId;
|
|
611
|
+
}
|
|
612
|
+
if (typeof viewRefSpecifier?.sliceIndex !== 'number') {
|
|
613
|
+
return target;
|
|
614
|
+
}
|
|
615
|
+
const { viewPlaneNormal } = target;
|
|
616
|
+
const delta =
|
|
617
|
+
(viewRefSpecifier.sliceIndex as number) - this.getCurrentImageIdIndex();
|
|
618
|
+
// Calculate a camera focal point and position
|
|
619
|
+
const { sliceRangeInfo } = getVolumeViewportScrollInfo(
|
|
620
|
+
this,
|
|
621
|
+
volumeId,
|
|
622
|
+
true
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
const { sliceRange, spacingInNormalDirection, camera } = sliceRangeInfo;
|
|
626
|
+
const { focalPoint, position } = camera;
|
|
627
|
+
const { newFocalPoint } = snapFocalPointToSlice(
|
|
628
|
+
focalPoint,
|
|
629
|
+
position,
|
|
630
|
+
sliceRange,
|
|
631
|
+
viewPlaneNormal,
|
|
632
|
+
spacingInNormalDirection,
|
|
633
|
+
delta
|
|
634
|
+
);
|
|
635
|
+
target.cameraFocalPoint = newFocalPoint;
|
|
636
|
+
|
|
637
|
+
return target;
|
|
609
638
|
}
|
|
610
639
|
|
|
611
640
|
/**
|
|
@@ -619,6 +648,9 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
619
648
|
viewRef: ViewReference,
|
|
620
649
|
options?: ReferenceCompatibleOptions
|
|
621
650
|
): boolean {
|
|
651
|
+
if (!viewRef.FrameOfReferenceUID) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
622
654
|
if (!super.isReferenceViewable(viewRef, options)) {
|
|
623
655
|
return false;
|
|
624
656
|
}
|
|
@@ -635,6 +667,117 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
635
667
|
return sliceIndex === undefined || sliceIndex === currentSliceIndex;
|
|
636
668
|
}
|
|
637
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Scrolls the viewport in the given direction/amount
|
|
672
|
+
*/
|
|
673
|
+
public scroll(delta = 1) {
|
|
674
|
+
const volumeId = this.getVolumeId();
|
|
675
|
+
const { sliceRangeInfo } = getVolumeViewportScrollInfo(
|
|
676
|
+
this,
|
|
677
|
+
volumeId,
|
|
678
|
+
true
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
if (!sliceRangeInfo) {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
const { sliceRange, spacingInNormalDirection, camera } = sliceRangeInfo;
|
|
686
|
+
const { focalPoint, viewPlaneNormal, position } = camera;
|
|
687
|
+
|
|
688
|
+
const { newFocalPoint, newPosition } = snapFocalPointToSlice(
|
|
689
|
+
focalPoint,
|
|
690
|
+
position,
|
|
691
|
+
sliceRange,
|
|
692
|
+
viewPlaneNormal,
|
|
693
|
+
spacingInNormalDirection,
|
|
694
|
+
delta
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
this.setCamera({
|
|
698
|
+
focalPoint: newFocalPoint,
|
|
699
|
+
position: newPosition,
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Navigates to the specified view reference.
|
|
705
|
+
*/
|
|
706
|
+
public setViewReference(viewRef: ViewReference): void {
|
|
707
|
+
if (!viewRef) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
const volumeId = this.getVolumeId();
|
|
711
|
+
const {
|
|
712
|
+
viewPlaneNormal: refViewPlaneNormal,
|
|
713
|
+
FrameOfReferenceUID: refFrameOfReference,
|
|
714
|
+
cameraFocalPoint,
|
|
715
|
+
viewUp,
|
|
716
|
+
} = viewRef;
|
|
717
|
+
let { sliceIndex } = viewRef;
|
|
718
|
+
const { focalPoint, viewPlaneNormal, position } = this.getCamera();
|
|
719
|
+
const isNegativeNormal = isEqualNegative(
|
|
720
|
+
viewPlaneNormal,
|
|
721
|
+
refViewPlaneNormal
|
|
722
|
+
);
|
|
723
|
+
const isSameNormal = isEqual(viewPlaneNormal, refViewPlaneNormal);
|
|
724
|
+
|
|
725
|
+
// Handle slices
|
|
726
|
+
if (
|
|
727
|
+
typeof sliceIndex === 'number' &&
|
|
728
|
+
viewRef.volumeId === volumeId &&
|
|
729
|
+
(isNegativeNormal || isSameNormal)
|
|
730
|
+
) {
|
|
731
|
+
const { currentStepIndex, sliceRangeInfo, numScrollSteps } =
|
|
732
|
+
getVolumeViewportScrollInfo(this, volumeId, true);
|
|
733
|
+
|
|
734
|
+
const { sliceRange, spacingInNormalDirection } = sliceRangeInfo;
|
|
735
|
+
if (isNegativeNormal) {
|
|
736
|
+
// Convert opposite orientation view refs to normal orientation
|
|
737
|
+
sliceIndex = numScrollSteps - sliceIndex - 1;
|
|
738
|
+
}
|
|
739
|
+
const delta = sliceIndex - currentStepIndex;
|
|
740
|
+
const { newFocalPoint, newPosition } = snapFocalPointToSlice(
|
|
741
|
+
focalPoint,
|
|
742
|
+
position,
|
|
743
|
+
sliceRange,
|
|
744
|
+
viewPlaneNormal,
|
|
745
|
+
spacingInNormalDirection,
|
|
746
|
+
delta
|
|
747
|
+
);
|
|
748
|
+
this.setCamera({ focalPoint: newFocalPoint, position: newPosition });
|
|
749
|
+
} else if (refFrameOfReference === this.getFrameOfReferenceUID()) {
|
|
750
|
+
// Handle same frame of reference navigation
|
|
751
|
+
|
|
752
|
+
if (refViewPlaneNormal && !isNegativeNormal && !isSameNormal) {
|
|
753
|
+
// Need to update the orientation vectors correctly for this case
|
|
754
|
+
// this.setCameraNoEvent({ viewPlaneNormal: refViewPlaneNormal, viewUp });
|
|
755
|
+
this.setOrientation({ viewPlaneNormal: refViewPlaneNormal, viewUp });
|
|
756
|
+
return this.setViewReference(viewRef);
|
|
757
|
+
}
|
|
758
|
+
if (cameraFocalPoint) {
|
|
759
|
+
const focalDelta = vec3.subtract(
|
|
760
|
+
[0, 0, 0],
|
|
761
|
+
cameraFocalPoint,
|
|
762
|
+
focalPoint
|
|
763
|
+
);
|
|
764
|
+
const useNormal = refViewPlaneNormal ?? viewPlaneNormal;
|
|
765
|
+
const normalDot = vec3.dot(focalDelta, useNormal);
|
|
766
|
+
if (!isEqual(normalDot, 0)) {
|
|
767
|
+
// Gets the portion of the focal point in the normal direction
|
|
768
|
+
vec3.scale(focalDelta, useNormal, normalDot);
|
|
769
|
+
}
|
|
770
|
+
const newFocal = <Point3>vec3.add([0, 0, 0], focalPoint, focalDelta);
|
|
771
|
+
const newPosition = <Point3>vec3.add([0, 0, 0], position, focalDelta);
|
|
772
|
+
this.setCamera({ focalPoint: newFocal, position: newPosition });
|
|
773
|
+
}
|
|
774
|
+
} else {
|
|
775
|
+
throw new Error(
|
|
776
|
+
`Incompatible view refs: ${refFrameOfReference}!==${this.getFrameOfReferenceUID()}`
|
|
777
|
+
);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
638
781
|
/**
|
|
639
782
|
* Sets the properties for the volume viewport on the volume
|
|
640
783
|
* and if setProperties is called for the first time, the properties will also become the default one.
|
|
@@ -1084,7 +1227,10 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1084
1227
|
* @param orientation - The orientation to set the camera to.
|
|
1085
1228
|
* @param immediate - Whether the `Viewport` should be rendered as soon as the camera is set.
|
|
1086
1229
|
*/
|
|
1087
|
-
public setOrientation(
|
|
1230
|
+
public setOrientation(
|
|
1231
|
+
_orientation: OrientationAxis | OrientationVectors,
|
|
1232
|
+
_immediate = true
|
|
1233
|
+
): void {
|
|
1088
1234
|
console.warn('Method "setOrientation" needs implementation');
|
|
1089
1235
|
}
|
|
1090
1236
|
|
|
@@ -1564,21 +1710,40 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1564
1710
|
|
|
1565
1711
|
abstract getCurrentImageId(): string;
|
|
1566
1712
|
|
|
1567
|
-
/**
|
|
1568
|
-
|
|
1713
|
+
/**
|
|
1714
|
+
* Gets the volumeId to use for references.
|
|
1715
|
+
* Returns undefined if the specified volume is NOT in this viewport.
|
|
1716
|
+
*/
|
|
1717
|
+
protected getVolumeId(specifier?: ViewReferenceSpecifier) {
|
|
1718
|
+
const actorEntries = this.getActors();
|
|
1719
|
+
if (!actorEntries) {
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1569
1722
|
if (!specifier?.volumeId) {
|
|
1570
|
-
const actorEntries = this.getActors();
|
|
1571
|
-
if (!actorEntries) {
|
|
1572
|
-
return;
|
|
1573
|
-
}
|
|
1574
1723
|
// find the first image actor of instance type vtkVolume
|
|
1575
1724
|
return actorEntries.find(
|
|
1576
1725
|
(actorEntry) => actorEntry.actor.getClassName() === 'vtkVolume'
|
|
1577
1726
|
)?.uid;
|
|
1578
1727
|
}
|
|
1579
|
-
|
|
1728
|
+
|
|
1729
|
+
// See if this volumeId can be found in one of the actors for this
|
|
1730
|
+
// viewport. This check will cause undefined to be returned when the
|
|
1731
|
+
// volumeId isn't currently shown in this viewport.
|
|
1732
|
+
return actorEntries.find(
|
|
1733
|
+
(actorEntry) =>
|
|
1734
|
+
actorEntry.actor.getClassName() === 'vtkVolume' &&
|
|
1735
|
+
actorEntry.uid === specifier.volumeId
|
|
1736
|
+
)?.uid;
|
|
1580
1737
|
}
|
|
1581
1738
|
|
|
1739
|
+
/**
|
|
1740
|
+
* For a volume viewport, the reference id will be a URN starting with
|
|
1741
|
+
* `volumeId:<volumeId>`, followed by additional arguments to specify
|
|
1742
|
+
* the view orientation. This will end up being a unique string that
|
|
1743
|
+
* identifies the view reference being shown. It is different from the
|
|
1744
|
+
* view reference in that the values are all incorporated into a string to
|
|
1745
|
+
* allow using it as a parameter key.
|
|
1746
|
+
*/
|
|
1582
1747
|
public getReferenceId(specifier: ViewReferenceSpecifier = {}): string {
|
|
1583
1748
|
let { volumeId, sliceIndex: sliceIndex } = specifier;
|
|
1584
1749
|
if (!volumeId) {
|
|
@@ -1592,7 +1757,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1592
1757
|
)?.uid;
|
|
1593
1758
|
}
|
|
1594
1759
|
|
|
1595
|
-
|
|
1760
|
+
const currentIndex = this.getCurrentImageIdIndex();
|
|
1761
|
+
sliceIndex ??= currentIndex;
|
|
1596
1762
|
const { viewPlaneNormal, focalPoint } = this.getCamera();
|
|
1597
1763
|
const querySeparator = volumeId.indexOf('?') > -1 ? '&' : '?';
|
|
1598
1764
|
return `volumeId:${volumeId}${querySeparator}sliceIndex=${sliceIndex}&viewPlaneNormal=${viewPlaneNormal.join(
|
|
@@ -1611,6 +1777,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1611
1777
|
filterActorUIDs?: Array<string>
|
|
1612
1778
|
): void;
|
|
1613
1779
|
|
|
1780
|
+
abstract resetSlabThickness(): void;
|
|
1781
|
+
|
|
1614
1782
|
abstract resetProperties(volumeId?: string): void;
|
|
1615
1783
|
}
|
|
1616
1784
|
|
|
@@ -626,7 +626,18 @@ class RenderingEngine implements IRenderingEngine {
|
|
|
626
626
|
const prevCamera = vp.getCamera();
|
|
627
627
|
const rotation = vp.getRotation();
|
|
628
628
|
const { flipHorizontal } = prevCamera;
|
|
629
|
-
|
|
629
|
+
const resetPan = true;
|
|
630
|
+
const resetZoom = true;
|
|
631
|
+
const resetToCenter = true;
|
|
632
|
+
const resetRotation = false;
|
|
633
|
+
const supressEvents = true;
|
|
634
|
+
vp.resetCamera(
|
|
635
|
+
resetPan,
|
|
636
|
+
resetZoom,
|
|
637
|
+
resetToCenter,
|
|
638
|
+
resetRotation,
|
|
639
|
+
supressEvents
|
|
640
|
+
);
|
|
630
641
|
|
|
631
642
|
const displayArea = vp.getDisplayArea();
|
|
632
643
|
|
|
@@ -511,34 +511,13 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
|
|
|
511
511
|
* metadata, it returns undefined, otherwise, frameOfReferenceUID is returned.
|
|
512
512
|
* @returns frameOfReferenceUID : string representing frame of reference id
|
|
513
513
|
*/
|
|
514
|
-
public getFrameOfReferenceUID = (): string
|
|
515
|
-
|
|
516
|
-
const imageId = this.getCurrentImageId();
|
|
517
|
-
|
|
518
|
-
if (!imageId) {
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// Use the metadata provider to grab its imagePlaneModule metadata
|
|
523
|
-
const imagePlaneModule = metaData.get('imagePlaneModule', imageId);
|
|
524
|
-
|
|
525
|
-
// If nothing exists, return undefined
|
|
526
|
-
if (!imagePlaneModule) {
|
|
527
|
-
return;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// Otherwise, provide the FrameOfReferenceUID so we can map
|
|
531
|
-
// annotations made on VolumeViewports back to StackViewports
|
|
532
|
-
// and vice versa
|
|
533
|
-
return imagePlaneModule.frameOfReferenceUID;
|
|
534
|
-
};
|
|
514
|
+
public getFrameOfReferenceUID = (sliceIndex?: number): string =>
|
|
515
|
+
this.getImagePlaneReferenceData(sliceIndex)?.FrameOfReferenceUID;
|
|
535
516
|
|
|
536
517
|
/**
|
|
537
518
|
* Returns the raw/loaded image being shown inside the stack viewport.
|
|
538
519
|
*/
|
|
539
|
-
public getCornerstoneImage = (): IImage =>
|
|
540
|
-
return this.csImage;
|
|
541
|
-
};
|
|
520
|
+
public getCornerstoneImage = (): IImage => this.csImage;
|
|
542
521
|
|
|
543
522
|
/**
|
|
544
523
|
* Creates imageMapper based on the provided vtkImageData and also creates
|
|
@@ -1609,6 +1588,37 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
|
|
|
1609
1588
|
};
|
|
1610
1589
|
}
|
|
1611
1590
|
|
|
1591
|
+
/**
|
|
1592
|
+
* Gets the view reference data for a given image slice. This uses the
|
|
1593
|
+
* image plane module to read a default focal point/normal, and also returns
|
|
1594
|
+
* the referenced image id and the frame of reference uid.
|
|
1595
|
+
*/
|
|
1596
|
+
public getImagePlaneReferenceData(
|
|
1597
|
+
sliceIndex = this.getCurrentImageIdIndex()
|
|
1598
|
+
): ViewReference {
|
|
1599
|
+
const imageId = this.imageIds[sliceIndex];
|
|
1600
|
+
if (!imageId) {
|
|
1601
|
+
return;
|
|
1602
|
+
}
|
|
1603
|
+
const imagePlaneModule = metaData.get(MetadataModules.IMAGE_PLANE, imageId);
|
|
1604
|
+
const { imagePositionPatient, frameOfReferenceUID: FrameOfReferenceUID } =
|
|
1605
|
+
imagePlaneModule;
|
|
1606
|
+
let { rowCosines, columnCosines } = imagePlaneModule;
|
|
1607
|
+
// Values are null, not undefined, so need to assign instead of defaulting
|
|
1608
|
+
rowCosines ||= [1, 0, 0];
|
|
1609
|
+
columnCosines ||= [0, 1, 0];
|
|
1610
|
+
const viewPlaneNormal = <Point3>(
|
|
1611
|
+
vec3.cross([0, 0, 0], columnCosines, rowCosines)
|
|
1612
|
+
);
|
|
1613
|
+
return {
|
|
1614
|
+
FrameOfReferenceUID,
|
|
1615
|
+
viewPlaneNormal,
|
|
1616
|
+
cameraFocalPoint: <Point3>imagePositionPatient,
|
|
1617
|
+
referencedImageId: imageId,
|
|
1618
|
+
sliceIndex,
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1612
1622
|
/**
|
|
1613
1623
|
* Converts the image direction to camera viewUp and viewplaneNormal
|
|
1614
1624
|
*
|
|
@@ -2215,7 +2225,7 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
|
|
|
2215
2225
|
*
|
|
2216
2226
|
* @param stackInputs - An array of stack inputs, each containing an image ID and an actor UID.
|
|
2217
2227
|
*/
|
|
2218
|
-
public
|
|
2228
|
+
public addImages(stackInputs: Array<IStackInput>) {
|
|
2219
2229
|
const actors = this.getActors();
|
|
2220
2230
|
stackInputs.forEach((stackInput) => {
|
|
2221
2231
|
const image = cache.getImage(stackInput.imageId);
|
|
@@ -2870,10 +2880,6 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
|
|
|
2870
2880
|
return this.currentImageIdIndex;
|
|
2871
2881
|
};
|
|
2872
2882
|
|
|
2873
|
-
public getSliceIndex = (): number => {
|
|
2874
|
-
return this.currentImageIdIndex;
|
|
2875
|
-
};
|
|
2876
|
-
|
|
2877
2883
|
/**
|
|
2878
2884
|
* Checks to see if this target is or could be shown in this viewport
|
|
2879
2885
|
*/
|
|
@@ -2910,40 +2916,65 @@ class StackViewport extends Viewport implements IStackViewport, IImagesLoader {
|
|
|
2910
2916
|
|
|
2911
2917
|
/**
|
|
2912
2918
|
* Gets a standard target to show this image instance.
|
|
2919
|
+
* Returns undefined if the requested slice index is not available.
|
|
2920
|
+
*
|
|
2921
|
+
* <b>Warning<b>If using sliceIndex for requeseting a specific reference, the slice index MUST come
|
|
2922
|
+
* from the stack of image ids. Using slice index from a volume or from a different
|
|
2923
|
+
* stack of images ids, EVEN if they contain the same set of images will result in
|
|
2924
|
+
* random images being chosen.
|
|
2913
2925
|
*/
|
|
2914
2926
|
public getViewReference(
|
|
2915
2927
|
viewRefSpecifier: ViewReferenceSpecifier = {}
|
|
2916
2928
|
): ViewReference {
|
|
2917
|
-
const { sliceIndex
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2929
|
+
const { sliceIndex = this.getCurrentImageIdIndex() } = viewRefSpecifier;
|
|
2930
|
+
const reference = super.getViewReference(viewRefSpecifier);
|
|
2931
|
+
const referencedImageId = this.imageIds[sliceIndex as number];
|
|
2932
|
+
if (!referencedImageId) {
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
reference.referencedImageId = referencedImageId;
|
|
2936
|
+
if (this.getCurrentImageIdIndex() !== sliceIndex) {
|
|
2937
|
+
const referenceData = this.getImagePlaneReferenceData(
|
|
2938
|
+
sliceIndex as number
|
|
2939
|
+
);
|
|
2940
|
+
if (!referenceData) {
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
Object.assign(reference, referenceData);
|
|
2944
|
+
}
|
|
2945
|
+
return reference;
|
|
2924
2946
|
}
|
|
2925
2947
|
|
|
2926
2948
|
/**
|
|
2927
2949
|
* Applies the view reference, which may navigate the slice index and apply
|
|
2928
|
-
* other camera modifications
|
|
2950
|
+
* other camera modifications.
|
|
2951
|
+
* Assumes that the slice index is correct for this viewport
|
|
2929
2952
|
*/
|
|
2930
|
-
public
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2953
|
+
public setViewReference(viewRef: ViewReference): void {
|
|
2954
|
+
if (!viewRef) {
|
|
2955
|
+
return;
|
|
2956
|
+
}
|
|
2957
|
+
const { referencedImageId, sliceIndex, volumeId } = viewRef;
|
|
2958
|
+
if (
|
|
2959
|
+
typeof sliceIndex === 'number' &&
|
|
2960
|
+
referencedImageId &&
|
|
2961
|
+
referencedImageId === this.imageIds[sliceIndex]
|
|
2962
|
+
) {
|
|
2963
|
+
this.setImageIdIndex(sliceIndex);
|
|
2964
|
+
} else {
|
|
2965
|
+
const foundIndex = this.imageIds.indexOf(referencedImageId);
|
|
2966
|
+
if (foundIndex !== -1) {
|
|
2967
|
+
this.setImageIdIndex(foundIndex);
|
|
2968
|
+
} else {
|
|
2969
|
+
throw new Error('Unsupported - referenced image id not found');
|
|
2943
2970
|
}
|
|
2944
2971
|
}
|
|
2945
2972
|
}
|
|
2946
2973
|
|
|
2974
|
+
/**
|
|
2975
|
+
* Returns the imageId string for the specified view, using the
|
|
2976
|
+
* `imageId:<imageId>` URN format.
|
|
2977
|
+
*/
|
|
2947
2978
|
public getReferenceId(specifier: ViewReferenceSpecifier = {}): string {
|
|
2948
2979
|
const { sliceIndex: sliceIndex = this.currentImageIdIndex } = specifier;
|
|
2949
2980
|
if (Array.isArray(sliceIndex)) {
|
|
@@ -695,7 +695,7 @@ class Viewport implements IViewport {
|
|
|
695
695
|
this.setDisplayAreaScale(displayArea);
|
|
696
696
|
} else {
|
|
697
697
|
this.setInterpolationType(
|
|
698
|
-
this.getProperties()
|
|
698
|
+
this.getProperties()?.interpolationType || InterpolationType.LINEAR
|
|
699
699
|
);
|
|
700
700
|
this.setDisplayAreaFit(displayArea);
|
|
701
701
|
}
|
|
@@ -1097,6 +1097,11 @@ class Viewport implements IViewport {
|
|
|
1097
1097
|
throw new Error('Not implemented');
|
|
1098
1098
|
}
|
|
1099
1099
|
|
|
1100
|
+
/**
|
|
1101
|
+
* Gets a referenced image url of some sort - could be a real image id, or
|
|
1102
|
+
* could be a URL with parameters. Regardless it refers to the currently displaying
|
|
1103
|
+
* image as a string value.
|
|
1104
|
+
*/
|
|
1100
1105
|
public getReferenceId(_specifier?: ViewReferenceSpecifier): string {
|
|
1101
1106
|
return null;
|
|
1102
1107
|
}
|
|
@@ -1592,11 +1597,16 @@ class Viewport implements IViewport {
|
|
|
1592
1597
|
public getViewReference(
|
|
1593
1598
|
viewRefSpecifier: ViewReferenceSpecifier = {}
|
|
1594
1599
|
): ViewReference {
|
|
1595
|
-
const {
|
|
1600
|
+
const {
|
|
1601
|
+
focalPoint: cameraFocalPoint,
|
|
1602
|
+
viewPlaneNormal,
|
|
1603
|
+
viewUp,
|
|
1604
|
+
} = this.getCamera();
|
|
1596
1605
|
const target: ViewReference = {
|
|
1597
1606
|
FrameOfReferenceUID: this.getFrameOfReferenceUID(),
|
|
1598
1607
|
cameraFocalPoint,
|
|
1599
1608
|
viewPlaneNormal,
|
|
1609
|
+
viewUp,
|
|
1600
1610
|
sliceIndex: viewRefSpecifier.sliceIndex ?? this.getCurrentImageIdIndex(),
|
|
1601
1611
|
};
|
|
1602
1612
|
return target;
|
|
@@ -1630,8 +1640,8 @@ class Viewport implements IViewport {
|
|
|
1630
1640
|
viewPlaneNormal
|
|
1631
1641
|
)
|
|
1632
1642
|
) {
|
|
1633
|
-
// Could navigate as a volume to the reference
|
|
1634
|
-
return options?.
|
|
1643
|
+
// Could navigate as a volume to the reference with an orientation change
|
|
1644
|
+
return options?.withOrientation === true;
|
|
1635
1645
|
}
|
|
1636
1646
|
return true;
|
|
1637
1647
|
}
|
|
@@ -1689,27 +1699,30 @@ class Viewport implements IViewport {
|
|
|
1689
1699
|
}
|
|
1690
1700
|
|
|
1691
1701
|
/**
|
|
1692
|
-
*
|
|
1693
|
-
* without getting multiple event notifications on shared values like camera updates or
|
|
1694
|
-
* flickers as multiple changes are applied.
|
|
1695
|
-
*
|
|
1696
|
-
* @param viewRef - the basic positioning in terms of what image id/slice index/orientation to display
|
|
1697
|
-
* * The viewRef must be applicable to the current stack or volume, otherwise an exception will be thrown
|
|
1698
|
-
* @param viewPres - the presentation information to apply to the current image (as chosen above)
|
|
1702
|
+
* Navigates to the image specified by the viewRef.
|
|
1699
1703
|
*/
|
|
1700
|
-
public
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1704
|
+
public setViewReference(viewRef: ViewReference) {
|
|
1705
|
+
// No-op
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
/**
|
|
1709
|
+
* Applies the display area, zoom, pan and rotation from the view presentation.
|
|
1710
|
+
* No-op is viewPres isn't defined.
|
|
1711
|
+
*/
|
|
1712
|
+
public setViewPresentation(viewPres: ViewPresentation) {
|
|
1713
|
+
if (!viewPres) {
|
|
1714
|
+
return;
|
|
1715
|
+
}
|
|
1716
|
+
const { displayArea, zoom = this.getZoom(), pan, rotation } = viewPres;
|
|
1717
|
+
if (displayArea !== this.getDisplayArea()) {
|
|
1718
|
+
this.setDisplayArea(displayArea);
|
|
1719
|
+
}
|
|
1720
|
+
this.setZoom(zoom);
|
|
1721
|
+
if (pan) {
|
|
1722
|
+
this.setPan(vec2.scale([0, 0], pan, zoom) as Point2);
|
|
1723
|
+
}
|
|
1724
|
+
if (rotation >= 0) {
|
|
1725
|
+
this.setRotation(rotation);
|
|
1713
1726
|
}
|
|
1714
1727
|
}
|
|
1715
1728
|
|