@cornerstonejs/core 0.41.2 → 0.42.1
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/RenderingEngine.js +9 -0
- package/dist/cjs/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/cjs/RenderingEngine/Viewport.d.ts +5 -1
- package/dist/cjs/RenderingEngine/Viewport.js +66 -0
- package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
- package/dist/cjs/enums/Events.d.ts +1 -0
- package/dist/cjs/enums/Events.js +1 -0
- package/dist/cjs/enums/Events.js.map +1 -1
- package/dist/cjs/types/EventTypes.d.ts +9 -1
- package/dist/cjs/types/IViewport.d.ts +3 -0
- package/dist/cjs/types/ViewportInputOptions.d.ts +2 -0
- package/dist/cjs/types/displayArea.d.ts +9 -0
- package/dist/cjs/types/displayArea.js +3 -0
- package/dist/cjs/types/displayArea.js.map +1 -0
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/esm/RenderingEngine/RenderingEngine.js +9 -0
- package/dist/esm/RenderingEngine/RenderingEngine.js.map +1 -1
- package/dist/esm/RenderingEngine/Viewport.d.ts +5 -1
- package/dist/esm/RenderingEngine/Viewport.js +63 -0
- package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
- package/dist/esm/enums/Events.d.ts +1 -0
- package/dist/esm/enums/Events.js +1 -0
- package/dist/esm/enums/Events.js.map +1 -1
- package/dist/esm/types/EventTypes.d.ts +9 -1
- package/dist/esm/types/IViewport.d.ts +3 -0
- package/dist/esm/types/ViewportInputOptions.d.ts +2 -0
- package/dist/esm/types/displayArea.d.ts +9 -0
- package/dist/esm/types/displayArea.js +2 -0
- package/dist/esm/types/displayArea.js.map +1 -0
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +2 -2
- package/src/RenderingEngine/RenderingEngine.ts +15 -0
- package/src/RenderingEngine/Viewport.ts +105 -3
- package/src/enums/Events.ts +7 -0
- package/src/types/EventTypes.ts +23 -0
- package/src/types/IViewport.ts +9 -0
- package/src/types/ViewportInputOptions.ts +3 -1
- package/src/types/displayArea.ts +10 -0
- package/src/types/index.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"type": "individual",
|
|
52
52
|
"url": "https://ohif.org/donate"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "bf2fa6e9424f88d324d0226bb0a8921d9bc38bd7"
|
|
55
55
|
}
|
|
@@ -34,6 +34,9 @@ type ViewportDisplayCoords = {
|
|
|
34
34
|
sHeight: number;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
// Rendering engines seem to not like rendering things less than 2 pixels per side
|
|
38
|
+
const VIEWPORT_MIN_SIZE = 2;
|
|
39
|
+
|
|
37
40
|
/**
|
|
38
41
|
* A RenderingEngine takes care of the full pipeline of creating viewports and rendering
|
|
39
42
|
* them on a large offscreen canvas and transmitting this data back to the screen. This allows us
|
|
@@ -502,6 +505,7 @@ class RenderingEngine implements IRenderingEngine {
|
|
|
502
505
|
options = {
|
|
503
506
|
background: [0, 0, 0],
|
|
504
507
|
orientation: null,
|
|
508
|
+
displayArea: null,
|
|
505
509
|
};
|
|
506
510
|
|
|
507
511
|
if (type === ViewportType.ORTHOGRAPHIC) {
|
|
@@ -1115,6 +1119,8 @@ class RenderingEngine implements IRenderingEngine {
|
|
|
1115
1119
|
this._animationFrameHandle = null;
|
|
1116
1120
|
|
|
1117
1121
|
eventDetailArray.forEach((eventDetail) => {
|
|
1122
|
+
// Very small viewports won't have an element
|
|
1123
|
+
if (!eventDetail?.element) return;
|
|
1118
1124
|
triggerEvent(eventDetail.element, Events.IMAGE_RENDERED, eventDetail);
|
|
1119
1125
|
});
|
|
1120
1126
|
};
|
|
@@ -1165,6 +1171,15 @@ class RenderingEngine implements IRenderingEngine {
|
|
|
1165
1171
|
): EventTypes.ImageRenderedEventDetail[] {
|
|
1166
1172
|
let eventDetail;
|
|
1167
1173
|
|
|
1174
|
+
// Rendering engines start having issues without at least two pixels
|
|
1175
|
+
// in each direction
|
|
1176
|
+
if (
|
|
1177
|
+
viewport.sWidth < VIEWPORT_MIN_SIZE ||
|
|
1178
|
+
viewport.sHeight < VIEWPORT_MIN_SIZE
|
|
1179
|
+
) {
|
|
1180
|
+
console.log('Viewport is too small', viewport.sWidth, viewport.sHeight);
|
|
1181
|
+
return;
|
|
1182
|
+
}
|
|
1168
1183
|
if (viewportTypeUsesCustomRenderingPipeline(viewport.type) === true) {
|
|
1169
1184
|
eventDetail =
|
|
1170
1185
|
viewport.customRenderViewportToCanvas() as EventTypes.ImageRenderedEventDetail;
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
Point3,
|
|
22
22
|
FlipDirection,
|
|
23
23
|
EventTypes,
|
|
24
|
+
DisplayArea,
|
|
24
25
|
} from '../types';
|
|
25
26
|
import type { ViewportInput, IViewport } from '../types/IViewport';
|
|
26
27
|
import type { vtkSlabCamera } from './vtkClasses/vtkSlabCamera';
|
|
@@ -62,7 +63,7 @@ class Viewport implements IViewport {
|
|
|
62
63
|
_actors: Map<string, any>;
|
|
63
64
|
/** Default options for the viewport which includes orientation, viewPlaneNormal and backgroundColor */
|
|
64
65
|
readonly defaultOptions: any;
|
|
65
|
-
/** options for the viewport which includes orientation axis and
|
|
66
|
+
/** options for the viewport which includes orientation axis, backgroundColor and displayArea */
|
|
66
67
|
options: ViewportInputOptions;
|
|
67
68
|
private _suppressCameraModifiedEvents = false;
|
|
68
69
|
/** A flag representing if viewport methods should fire events or not */
|
|
@@ -72,6 +73,10 @@ class Viewport implements IViewport {
|
|
|
72
73
|
* the relative pan/zoom
|
|
73
74
|
*/
|
|
74
75
|
protected initialCamera: ICamera;
|
|
76
|
+
/** The camera that is defined for resetting displayArea to ensure absolute displayArea
|
|
77
|
+
* settings
|
|
78
|
+
*/
|
|
79
|
+
private fitToCanvasCamera: ICamera;
|
|
75
80
|
|
|
76
81
|
constructor(props: ViewportInput) {
|
|
77
82
|
this.id = props.id;
|
|
@@ -155,7 +160,9 @@ class Viewport implements IViewport {
|
|
|
155
160
|
|
|
156
161
|
// TODO When this is needed we need to move the camera position.
|
|
157
162
|
// We can steal some logic from the tools we build to do this.
|
|
158
|
-
|
|
163
|
+
if (this.options?.displayArea) {
|
|
164
|
+
this.setDisplayArea(this.options?.displayArea);
|
|
165
|
+
}
|
|
159
166
|
if (immediate) {
|
|
160
167
|
this.render();
|
|
161
168
|
}
|
|
@@ -528,6 +535,80 @@ class Viewport implements IViewport {
|
|
|
528
535
|
return intersections;
|
|
529
536
|
}
|
|
530
537
|
|
|
538
|
+
/**
|
|
539
|
+
* Sets the camera to an initial bounds. If
|
|
540
|
+
* resetPan and resetZoom are true it places the focal point at the center of
|
|
541
|
+
* the volume (or slice); otherwise, only the camera zoom and camera Pan or Zoom
|
|
542
|
+
* is reset for the current view.
|
|
543
|
+
* @param displayArea - The display area of interest.
|
|
544
|
+
* @param suppressEvents - If true, don't fire displayArea event.
|
|
545
|
+
*/
|
|
546
|
+
public setDisplayArea(
|
|
547
|
+
displayArea: DisplayArea,
|
|
548
|
+
suppressEvents = false
|
|
549
|
+
): void {
|
|
550
|
+
const { storeAsInitialCamera } = displayArea;
|
|
551
|
+
|
|
552
|
+
// make calculations relative to the fitToCanvasCamera view
|
|
553
|
+
this.setCamera(this.fitToCanvasCamera, false);
|
|
554
|
+
|
|
555
|
+
const { imageArea, imageCanvasPoint } = displayArea;
|
|
556
|
+
|
|
557
|
+
if (imageArea) {
|
|
558
|
+
const [areaX, areaY] = imageArea;
|
|
559
|
+
const zoom = Math.min(this.getZoom() / areaX, this.getZoom() / areaY);
|
|
560
|
+
this.setZoom(zoom, storeAsInitialCamera);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// getting the image info
|
|
564
|
+
const imageData = this.getDefaultImageData();
|
|
565
|
+
if (imageCanvasPoint && imageData) {
|
|
566
|
+
const { imagePoint, canvasPoint } = imageCanvasPoint;
|
|
567
|
+
const [canvasX, canvasY] = canvasPoint;
|
|
568
|
+
const devicePixelRatio = window?.devicePixelRatio || 1;
|
|
569
|
+
const validateCanvasPanX = this.sWidth / devicePixelRatio;
|
|
570
|
+
const validateCanvasPanY = this.sHeight / devicePixelRatio;
|
|
571
|
+
const canvasPanX = validateCanvasPanX * (canvasX - 0.5);
|
|
572
|
+
const canvasPanY = validateCanvasPanY * (canvasY - 0.5);
|
|
573
|
+
|
|
574
|
+
const dimensions = imageData.getDimensions();
|
|
575
|
+
const canvasZero = this.worldToCanvas([0, 0, 0]);
|
|
576
|
+
const canvasEdge = this.worldToCanvas(dimensions);
|
|
577
|
+
const canvasImage = [
|
|
578
|
+
canvasEdge[0] - canvasZero[0],
|
|
579
|
+
canvasEdge[1] - canvasZero[1],
|
|
580
|
+
];
|
|
581
|
+
const [imgWidth, imgHeight] = canvasImage;
|
|
582
|
+
const [imageX, imageY] = imagePoint;
|
|
583
|
+
const imagePanX = imgWidth * (0.5 - imageX);
|
|
584
|
+
const imagePanY = imgHeight * (0.5 - imageY);
|
|
585
|
+
|
|
586
|
+
const newPositionX = imagePanX + canvasPanX;
|
|
587
|
+
const newPositionY = imagePanY + canvasPanY;
|
|
588
|
+
|
|
589
|
+
const deltaPoint2: Point2 = [newPositionX, newPositionY];
|
|
590
|
+
this.setPan(deltaPoint2, storeAsInitialCamera);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (storeAsInitialCamera) {
|
|
594
|
+
this.options.displayArea = displayArea;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (!suppressEvents) {
|
|
598
|
+
const eventDetail: EventTypes.DisplayAreaModifiedEventDetail = {
|
|
599
|
+
viewportId: this.id,
|
|
600
|
+
displayArea: displayArea,
|
|
601
|
+
storeAsInitialCamera: storeAsInitialCamera,
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
triggerEvent(this.element, Events.DISPLAY_AREA_MODIFIED, eventDetail);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
public getDisplayArea(): DisplayArea | undefined {
|
|
609
|
+
return this.options?.displayArea;
|
|
610
|
+
}
|
|
611
|
+
|
|
531
612
|
/**
|
|
532
613
|
* Resets the camera based on the rendering volume(s) bounds. If
|
|
533
614
|
* resetPan and resetZoom are true it places the focal point at the center of
|
|
@@ -556,7 +637,6 @@ class Viewport implements IViewport {
|
|
|
556
637
|
});
|
|
557
638
|
|
|
558
639
|
const previousCamera = _cloneDeep(this.getCamera());
|
|
559
|
-
|
|
560
640
|
const bounds = renderer.computeVisiblePropBounds();
|
|
561
641
|
const focalPoint = <Point3>[0, 0, 0];
|
|
562
642
|
const imageData = this.getDefaultImageData();
|
|
@@ -673,6 +753,8 @@ class Viewport implements IViewport {
|
|
|
673
753
|
|
|
674
754
|
const modifiedCamera = _cloneDeep(this.getCamera());
|
|
675
755
|
|
|
756
|
+
this.setFitToCanvasCamera(_cloneDeep(this.getCamera()));
|
|
757
|
+
|
|
676
758
|
if (storeAsInitialCamera) {
|
|
677
759
|
this.setInitialCamera(modifiedCamera);
|
|
678
760
|
}
|
|
@@ -688,6 +770,16 @@ class Viewport implements IViewport {
|
|
|
688
770
|
|
|
689
771
|
this.triggerCameraModifiedEventIfNecessary(previousCamera, modifiedCamera);
|
|
690
772
|
|
|
773
|
+
if (
|
|
774
|
+
imageData &&
|
|
775
|
+
this.options?.displayArea &&
|
|
776
|
+
resetZoom &&
|
|
777
|
+
resetPan &&
|
|
778
|
+
resetToCenter
|
|
779
|
+
) {
|
|
780
|
+
this.setDisplayArea(this.options?.displayArea);
|
|
781
|
+
}
|
|
782
|
+
|
|
691
783
|
return true;
|
|
692
784
|
}
|
|
693
785
|
|
|
@@ -701,6 +793,16 @@ class Viewport implements IViewport {
|
|
|
701
793
|
this.initialCamera = camera;
|
|
702
794
|
}
|
|
703
795
|
|
|
796
|
+
/**
|
|
797
|
+
* Sets the provided camera as the displayArea camera.
|
|
798
|
+
* This allows computing differences applied later as compared to the initial
|
|
799
|
+
* position, for things like zoom and pan.
|
|
800
|
+
* @param camera - to store as the initial value.
|
|
801
|
+
*/
|
|
802
|
+
protected setFitToCanvasCamera(camera: ICamera): void {
|
|
803
|
+
this.fitToCanvasCamera = camera;
|
|
804
|
+
}
|
|
805
|
+
|
|
704
806
|
/**
|
|
705
807
|
* Helper function to return the current canvas pan value.
|
|
706
808
|
*
|
package/src/enums/Events.ts
CHANGED
|
@@ -38,6 +38,13 @@ enum Events {
|
|
|
38
38
|
* and see what event detail is included in {@link EventTypes.VoiModifiedEventDetail | VoiModified Event Detail }
|
|
39
39
|
*/
|
|
40
40
|
VOI_MODIFIED = 'CORNERSTONE_VOI_MODIFIED',
|
|
41
|
+
/**
|
|
42
|
+
* Triggers on the HTML element when viewport modifies its display area
|
|
43
|
+
*
|
|
44
|
+
* Make use of {@link EventTypes.DisplayAreaModifiedEvent | DisplayAreaModified Event Type } for typing your event listeners for DISPLAY_AREA_MODIFIED event,
|
|
45
|
+
* and see what event detail is included in {@link EventTypes.DisplayAreaModifiedEventDetail | DisplayAreaModified Event Detail }
|
|
46
|
+
*/
|
|
47
|
+
DISPLAY_AREA_MODIFIED = 'CORNERSTONE_DISPLAY_AREA_MODIFIED',
|
|
41
48
|
/**
|
|
42
49
|
* Triggers on the eventTarget when the element is disabled
|
|
43
50
|
*
|
package/src/types/EventTypes.ts
CHANGED
|
@@ -8,6 +8,8 @@ import type IImage from './IImage';
|
|
|
8
8
|
import type IImageVolume from './IImageVolume';
|
|
9
9
|
import type { VOIRange } from './voi';
|
|
10
10
|
import type VOILUTFunctionType from '../enums/VOILUTFunctionType';
|
|
11
|
+
import type DisplayArea from './displayArea';
|
|
12
|
+
|
|
11
13
|
/**
|
|
12
14
|
* CAMERA_MODIFIED Event's data
|
|
13
15
|
*/
|
|
@@ -40,6 +42,20 @@ type VoiModifiedEventDetail = {
|
|
|
40
42
|
VOILUTFunction?: VOILUTFunctionType;
|
|
41
43
|
};
|
|
42
44
|
|
|
45
|
+
/**
|
|
46
|
+
* DISPLAY_AREA_MODIFIED Event's data
|
|
47
|
+
*/
|
|
48
|
+
type DisplayAreaModifiedEventDetail = {
|
|
49
|
+
/** Viewport Unique ID in the renderingEngine */
|
|
50
|
+
viewportId: string;
|
|
51
|
+
/** new display area */
|
|
52
|
+
displayArea: DisplayArea;
|
|
53
|
+
/** Unique ID for the volume in the cache */
|
|
54
|
+
volumeId?: string;
|
|
55
|
+
/** Whether displayArea was stored as initial view */
|
|
56
|
+
storeAsInitialCamera?: boolean;
|
|
57
|
+
};
|
|
58
|
+
|
|
43
59
|
/**
|
|
44
60
|
* ELEMENT_DISABLED Event's data
|
|
45
61
|
*/
|
|
@@ -259,6 +275,11 @@ type CameraModifiedEvent = CustomEventType<CameraModifiedEventDetail>;
|
|
|
259
275
|
*/
|
|
260
276
|
type VoiModifiedEvent = CustomEventType<VoiModifiedEventDetail>;
|
|
261
277
|
|
|
278
|
+
/**
|
|
279
|
+
* DISPLAY_AREA_MODIFIED Event type
|
|
280
|
+
*/
|
|
281
|
+
type DisplayAreaModifiedEvent = CustomEventType<DisplayAreaModifiedEventDetail>;
|
|
282
|
+
|
|
262
283
|
/**
|
|
263
284
|
* ELEMENT_DISABLED Event type
|
|
264
285
|
*/
|
|
@@ -362,6 +383,8 @@ export type {
|
|
|
362
383
|
CameraModifiedEvent,
|
|
363
384
|
VoiModifiedEvent,
|
|
364
385
|
VoiModifiedEventDetail,
|
|
386
|
+
DisplayAreaModifiedEvent,
|
|
387
|
+
DisplayAreaModifiedEventDetail,
|
|
365
388
|
ElementDisabledEvent,
|
|
366
389
|
ElementDisabledEventDetail,
|
|
367
390
|
ElementEnabledEvent,
|
package/src/types/IViewport.ts
CHANGED
|
@@ -4,6 +4,7 @@ import Point3 from './Point3';
|
|
|
4
4
|
import ViewportInputOptions from './ViewportInputOptions';
|
|
5
5
|
import { ActorEntry } from './IActor';
|
|
6
6
|
import ViewportType from '../enums/ViewportType';
|
|
7
|
+
import DisplayArea from './displayArea';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Viewport interface for cornerstone viewports
|
|
@@ -73,6 +74,14 @@ interface IViewport {
|
|
|
73
74
|
render(): void;
|
|
74
75
|
/** set options for the viewport */
|
|
75
76
|
setOptions(options: ViewportInputOptions, immediate: boolean): void;
|
|
77
|
+
/** set displayArea for the viewport */
|
|
78
|
+
setDisplayArea(
|
|
79
|
+
displayArea: DisplayArea,
|
|
80
|
+
callResetCamera?: boolean,
|
|
81
|
+
suppressEvents?: boolean
|
|
82
|
+
);
|
|
83
|
+
/** returns the displayArea */
|
|
84
|
+
getDisplayArea(): DisplayArea | undefined;
|
|
76
85
|
/** reset camera and options*/
|
|
77
86
|
reset(immediate: boolean): void;
|
|
78
87
|
/** returns the canvas */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OrientationAxis } from '../enums';
|
|
2
2
|
import OrientationVectors from './OrientationVectors';
|
|
3
|
-
|
|
3
|
+
import DisplayArea from './displayArea';
|
|
4
4
|
/**
|
|
5
5
|
* This type defines the shape of viewport input options, so we can throw when it is incorrect.
|
|
6
6
|
*/
|
|
@@ -9,6 +9,8 @@ type ViewportInputOptions = {
|
|
|
9
9
|
background?: [number, number, number];
|
|
10
10
|
/** orientation of the viewport which can be either an Enum for axis Enums.OrientationAxis.[AXIAL|SAGITTAL|CORONAL|DEFAULT] or an object with viewPlaneNormal and viewUp */
|
|
11
11
|
orientation?: OrientationAxis | OrientationVectors;
|
|
12
|
+
/** displayArea of interest */
|
|
13
|
+
displayArea?: DisplayArea;
|
|
12
14
|
/** whether the events should be suppressed and not fired*/
|
|
13
15
|
suppressEvents?: boolean;
|
|
14
16
|
/**
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type DisplayArea = {
|
|
2
|
+
imageArea: [number, number]; // areaX, areaY
|
|
3
|
+
imageCanvasPoint: {
|
|
4
|
+
imagePoint: [number, number]; // imageX, imageY
|
|
5
|
+
canvasPoint: [number, number]; // canvasX, canvasY
|
|
6
|
+
};
|
|
7
|
+
storeAsInitialCamera: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default DisplayArea;
|
package/src/types/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type IEnabledElement from './IEnabledElement';
|
|
|
5
5
|
import type ICache from './ICache';
|
|
6
6
|
import type { IVolume, VolumeScalarData } from './IVolume';
|
|
7
7
|
import type { VOI, VOIRange } from './voi';
|
|
8
|
+
import type DisplayArea from './displayArea';
|
|
8
9
|
import type ImageLoaderFn from './ImageLoaderFn';
|
|
9
10
|
import type IImageVolume from './IImageVolume';
|
|
10
11
|
import type IDynamicImageVolume from './IDynamicImageVolume';
|
|
@@ -125,6 +126,7 @@ export type {
|
|
|
125
126
|
ViewportInputOptions,
|
|
126
127
|
VOIRange,
|
|
127
128
|
VOI,
|
|
129
|
+
DisplayArea,
|
|
128
130
|
FlipDirection,
|
|
129
131
|
ICachedImage,
|
|
130
132
|
ICachedVolume,
|