@cornerstonejs/core 1.71.4 → 1.71.6
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 +5 -5
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.js +83 -10
- package/dist/cjs/RenderingEngine/BaseVolumeViewport.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 +3 -2
- package/dist/cjs/RenderingEngine/VolumeViewport.js +13 -14
- package/dist/cjs/RenderingEngine/VolumeViewport.js.map +1 -1
- package/dist/cjs/types/IViewport.d.ts +5 -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 +83 -13
- package/dist/esm/RenderingEngine/BaseVolumeViewport.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 +13 -14
- package/dist/esm/RenderingEngine/VolumeViewport.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 +5 -5
- package/dist/types/RenderingEngine/BaseVolumeViewport.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 +3 -2
- package/dist/types/RenderingEngine/VolumeViewport.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/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 +182 -19
- package/src/RenderingEngine/StackViewport.ts +81 -50
- package/src/RenderingEngine/Viewport.ts +37 -24
- package/src/RenderingEngine/VolumeViewport.ts +40 -25
- package/src/types/IViewport.ts +64 -18
- 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.6",
|
|
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": "8abef807de438a043258b10395c516fa0cd0541d"
|
|
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, {
|
|
@@ -600,15 +605,36 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
600
605
|
viewRefSpecifier: ViewReferenceSpecifier = {}
|
|
601
606
|
): ViewReference {
|
|
602
607
|
const target = super.getViewReference(viewRefSpecifier);
|
|
608
|
+
const volumeId = this.getVolumeId(viewRefSpecifier);
|
|
603
609
|
if (viewRefSpecifier?.forFrameOfReference !== false) {
|
|
604
|
-
target.volumeId =
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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;
|
|
612
638
|
}
|
|
613
639
|
|
|
614
640
|
/**
|
|
@@ -622,6 +648,9 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
622
648
|
viewRef: ViewReference,
|
|
623
649
|
options?: ReferenceCompatibleOptions
|
|
624
650
|
): boolean {
|
|
651
|
+
if (!viewRef.FrameOfReferenceUID) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
625
654
|
if (!super.isReferenceViewable(viewRef, options)) {
|
|
626
655
|
return false;
|
|
627
656
|
}
|
|
@@ -638,6 +667,117 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
638
667
|
return sliceIndex === undefined || sliceIndex === currentSliceIndex;
|
|
639
668
|
}
|
|
640
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
|
+
|
|
641
781
|
/**
|
|
642
782
|
* Sets the properties for the volume viewport on the volume
|
|
643
783
|
* and if setProperties is called for the first time, the properties will also become the default one.
|
|
@@ -1087,7 +1227,10 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1087
1227
|
* @param orientation - The orientation to set the camera to.
|
|
1088
1228
|
* @param immediate - Whether the `Viewport` should be rendered as soon as the camera is set.
|
|
1089
1229
|
*/
|
|
1090
|
-
public setOrientation(
|
|
1230
|
+
public setOrientation(
|
|
1231
|
+
_orientation: OrientationAxis | OrientationVectors,
|
|
1232
|
+
_immediate = true
|
|
1233
|
+
): void {
|
|
1091
1234
|
console.warn('Method "setOrientation" needs implementation');
|
|
1092
1235
|
}
|
|
1093
1236
|
|
|
@@ -1567,21 +1710,40 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1567
1710
|
|
|
1568
1711
|
abstract getCurrentImageId(): string;
|
|
1569
1712
|
|
|
1570
|
-
/**
|
|
1571
|
-
|
|
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
|
+
}
|
|
1572
1722
|
if (!specifier?.volumeId) {
|
|
1573
|
-
const actorEntries = this.getActors();
|
|
1574
|
-
if (!actorEntries) {
|
|
1575
|
-
return;
|
|
1576
|
-
}
|
|
1577
1723
|
// find the first image actor of instance type vtkVolume
|
|
1578
1724
|
return actorEntries.find(
|
|
1579
1725
|
(actorEntry) => actorEntry.actor.getClassName() === 'vtkVolume'
|
|
1580
1726
|
)?.uid;
|
|
1581
1727
|
}
|
|
1582
|
-
|
|
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;
|
|
1583
1737
|
}
|
|
1584
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
|
+
*/
|
|
1585
1747
|
public getReferenceId(specifier: ViewReferenceSpecifier = {}): string {
|
|
1586
1748
|
let { volumeId, sliceIndex: sliceIndex } = specifier;
|
|
1587
1749
|
if (!volumeId) {
|
|
@@ -1595,7 +1757,8 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
|
|
|
1595
1757
|
)?.uid;
|
|
1596
1758
|
}
|
|
1597
1759
|
|
|
1598
|
-
|
|
1760
|
+
const currentIndex = this.getCurrentImageIdIndex();
|
|
1761
|
+
sliceIndex ??= currentIndex;
|
|
1599
1762
|
const { viewPlaneNormal, focalPoint } = this.getCamera();
|
|
1600
1763
|
const querySeparator = volumeId.indexOf('?') > -1 ? '&' : '?';
|
|
1601
1764
|
return `volumeId:${volumeId}${querySeparator}sliceIndex=${sliceIndex}&viewPlaneNormal=${viewPlaneNormal.join(
|
|
@@ -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
|
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import vtkPlane from '@kitware/vtk.js/Common/DataModel/Plane';
|
|
2
2
|
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
|
|
3
3
|
|
|
4
|
-
import { vec3 } from 'gl-matrix';
|
|
5
|
-
|
|
6
4
|
import cache from '../cache';
|
|
7
5
|
import { MPR_CAMERA_VALUES, RENDERING_DEFAULTS } from '../constants';
|
|
8
6
|
import { BlendModes, OrientationAxis, Events } from '../enums';
|
|
@@ -13,6 +11,8 @@ import type {
|
|
|
13
11
|
OrientationVectors,
|
|
14
12
|
Point3,
|
|
15
13
|
EventTypes,
|
|
14
|
+
ViewReference,
|
|
15
|
+
ViewReferenceSpecifier,
|
|
16
16
|
} from '../types';
|
|
17
17
|
import type { ViewportInput } from '../types/IViewport';
|
|
18
18
|
import {
|
|
@@ -29,6 +29,7 @@ import setDefaultVolumeVOI from './helpers/setDefaultVolumeVOI';
|
|
|
29
29
|
import { setTransferFunctionNodes } from '../utilities/transferFunctionUtils';
|
|
30
30
|
import { ImageActor } from '../types/IActor';
|
|
31
31
|
import getImageSliceDataForVolumeViewport from '../utilities/getImageSliceDataForVolumeViewport';
|
|
32
|
+
import getVolumeViewportScrollInfo from '../utilities/getVolumeViewportScrollInfo';
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* An object representing a VolumeViewport. VolumeViewports are used to render
|
|
@@ -267,7 +268,6 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
267
268
|
|
|
268
269
|
const activeCamera = this.getVtkActiveCamera();
|
|
269
270
|
const viewPlaneNormal = <Point3>activeCamera.getViewPlaneNormal();
|
|
270
|
-
const viewUp = <Point3>activeCamera.getViewUp();
|
|
271
271
|
const focalPoint = <Point3>activeCamera.getFocalPoint();
|
|
272
272
|
|
|
273
273
|
// always add clipping planes for the volume viewport. If a use case
|
|
@@ -365,6 +365,10 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
/**
|
|
368
|
+
* Uses the origin and focalPoint to calculate the slice index.
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
368
372
|
* Resets the slab thickness of the actors of the viewport to the default value.
|
|
369
373
|
*/
|
|
370
374
|
public resetSlabThickness(): void {
|
|
@@ -383,32 +387,23 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
383
387
|
}
|
|
384
388
|
|
|
385
389
|
/**
|
|
386
|
-
* Uses the
|
|
390
|
+
* Uses the slice range information to compute the current image id index.
|
|
391
|
+
* Note that this may be offset from the origin location, or opposite in
|
|
392
|
+
* direction to the distance from the origin location, as the index is a
|
|
393
|
+
* complete index from minimum to maximum.
|
|
387
394
|
*
|
|
388
395
|
* @returns The slice index in the direction of the view
|
|
389
396
|
*/
|
|
390
|
-
public getCurrentImageIdIndex = (
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const { origin, direction, spacing } = imageData;
|
|
400
|
-
|
|
401
|
-
const spacingInNormal = getSpacingInNormalDirection(
|
|
402
|
-
{ direction, spacing },
|
|
403
|
-
viewPlaneNormal
|
|
397
|
+
public getCurrentImageIdIndex = (
|
|
398
|
+
volumeId?: string,
|
|
399
|
+
useSlabThickness = true
|
|
400
|
+
): number => {
|
|
401
|
+
const { currentStepIndex } = getVolumeViewportScrollInfo(
|
|
402
|
+
this,
|
|
403
|
+
volumeId || this.getVolumeId(),
|
|
404
|
+
useSlabThickness
|
|
404
405
|
);
|
|
405
|
-
|
|
406
|
-
vec3.sub(sub, focalPoint, origin);
|
|
407
|
-
const distance = vec3.dot(sub, viewPlaneNormal);
|
|
408
|
-
|
|
409
|
-
// divide by the spacing in the normal direction to get the
|
|
410
|
-
// number of steps, and subtract 1 to get the index
|
|
411
|
-
return Math.round(Math.abs(distance) / spacingInNormal);
|
|
406
|
+
return currentStepIndex;
|
|
412
407
|
};
|
|
413
408
|
|
|
414
409
|
/**
|
|
@@ -438,6 +433,26 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
438
433
|
return getClosestImageId(volume, focalPoint, viewPlaneNormal);
|
|
439
434
|
};
|
|
440
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Gets a view target, allowing comparison between view positions as well
|
|
438
|
+
* as restoring views later.
|
|
439
|
+
* Add the referenced image id.
|
|
440
|
+
*/
|
|
441
|
+
public getViewReference(
|
|
442
|
+
viewRefSpecifier: ViewReferenceSpecifier = {}
|
|
443
|
+
): ViewReference {
|
|
444
|
+
const viewRef = super.getViewReference(viewRefSpecifier);
|
|
445
|
+
if (!viewRef?.volumeId) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const volume = cache.getVolume(viewRef.volumeId);
|
|
449
|
+
viewRef.referencedImageId = getClosestImageId(
|
|
450
|
+
volume,
|
|
451
|
+
viewRef.cameraFocalPoint,
|
|
452
|
+
viewRef.viewPlaneNormal
|
|
453
|
+
);
|
|
454
|
+
return viewRef;
|
|
455
|
+
}
|
|
441
456
|
/**
|
|
442
457
|
* Reset the viewport properties to the default values
|
|
443
458
|
*
|