@cornerstonejs/core 4.15.33 → 4.16.0
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/esm/RenderingEngine/BaseVolumeViewport.d.ts +2 -1
- package/dist/esm/RenderingEngine/BaseVolumeViewport.js +22 -5
- package/dist/esm/RenderingEngine/VolumeViewport.js +20 -3
- package/dist/esm/RenderingEngine/helpers/getCameraVectors.d.ts +2 -0
- package/dist/esm/RenderingEngine/helpers/getCameraVectors.js +114 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { mat4 } from 'gl-matrix';
|
|
2
|
-
import type { BlendModes, InterpolationType
|
|
2
|
+
import type { BlendModes, InterpolationType } from '../enums';
|
|
3
|
+
import { OrientationAxis } from '../enums';
|
|
3
4
|
import type { FlipDirection, IImageData, IVolumeInput, OrientationVectors, Point2, Point3, VolumeViewportProperties, ViewReferenceSpecifier, ReferenceCompatibleOptions, ViewReference, ICamera } from '../types';
|
|
4
5
|
import type { VoiModifiedEventDetail } from '../types/EventTypes';
|
|
5
6
|
import type { PlaneRestriction, ViewportInput } from '../types/IViewport';
|
|
@@ -4,7 +4,7 @@ import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunc
|
|
|
4
4
|
import { vec2, vec3 } from 'gl-matrix';
|
|
5
5
|
import cache from '../cache/cache';
|
|
6
6
|
import { MPR_CAMERA_VALUES, RENDERING_DEFAULTS, VIEWPORT_PRESETS, } from '../constants';
|
|
7
|
-
import { Events, MetadataModules, ViewportStatus, VOILUTFunctionType, } from '../enums';
|
|
7
|
+
import { Events, MetadataModules, OrientationAxis, ViewportStatus, VOILUTFunctionType, } from '../enums';
|
|
8
8
|
import ViewportType from '../enums/ViewportType';
|
|
9
9
|
import eventTarget from '../eventTarget';
|
|
10
10
|
import { getShouldUseCPURendering } from '../init';
|
|
@@ -1116,21 +1116,38 @@ class BaseVolumeViewport extends Viewport {
|
|
|
1116
1116
|
}
|
|
1117
1117
|
}
|
|
1118
1118
|
else if (typeof orientation === 'string') {
|
|
1119
|
-
if (orientation ===
|
|
1119
|
+
if (orientation === OrientationAxis.ACQUISITION) {
|
|
1120
1120
|
return this._getAcquisitionPlaneOrientation();
|
|
1121
1121
|
}
|
|
1122
|
-
else if (orientation ===
|
|
1123
|
-
orientation.includes('_reformat')) {
|
|
1122
|
+
else if (orientation === OrientationAxis.REFORMAT) {
|
|
1124
1123
|
return getCameraVectors(this, {
|
|
1125
1124
|
useViewportNormal: true,
|
|
1126
1125
|
});
|
|
1127
1126
|
}
|
|
1127
|
+
else if (orientation === OrientationAxis.AXIAL_REFORMAT ||
|
|
1128
|
+
orientation === OrientationAxis.SAGITTAL_REFORMAT ||
|
|
1129
|
+
orientation === OrientationAxis.CORONAL_REFORMAT) {
|
|
1130
|
+
let baseOrientation;
|
|
1131
|
+
if (orientation === OrientationAxis.AXIAL_REFORMAT) {
|
|
1132
|
+
baseOrientation = OrientationAxis.AXIAL;
|
|
1133
|
+
}
|
|
1134
|
+
else if (orientation === OrientationAxis.SAGITTAL_REFORMAT) {
|
|
1135
|
+
baseOrientation = OrientationAxis.SAGITTAL;
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
baseOrientation = OrientationAxis.CORONAL;
|
|
1139
|
+
}
|
|
1140
|
+
return getCameraVectors(this, {
|
|
1141
|
+
useViewportNormal: true,
|
|
1142
|
+
orientation: baseOrientation,
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1128
1145
|
else if (MPR_CAMERA_VALUES[orientation]) {
|
|
1129
1146
|
this.viewportProperties.orientation = orientation;
|
|
1130
1147
|
return MPR_CAMERA_VALUES[orientation];
|
|
1131
1148
|
}
|
|
1132
1149
|
}
|
|
1133
|
-
throw new Error(`Invalid orientation: ${orientation}. Valid orientations are: ${Object.keys(MPR_CAMERA_VALUES).join(', ')}`);
|
|
1150
|
+
throw new Error(`Invalid orientation: ${orientation}. Valid orientations are: ${Object.keys(MPR_CAMERA_VALUES).join(', ')}, ${OrientationAxis.ACQUISITION}, ${OrientationAxis.REFORMAT}, ${OrientationAxis.AXIAL_REFORMAT}, ${OrientationAxis.SAGITTAL_REFORMAT}, ${OrientationAxis.CORONAL_REFORMAT}`);
|
|
1134
1151
|
}
|
|
1135
1152
|
_getAcquisitionPlaneOrientation() {
|
|
1136
1153
|
const actorEntry = this.getDefaultActor();
|
|
@@ -161,12 +161,29 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
161
161
|
if (orientation === OrientationAxis.ACQUISITION) {
|
|
162
162
|
({ viewPlaneNormal, viewUp } = super._getAcquisitionPlaneOrientation());
|
|
163
163
|
}
|
|
164
|
-
else if (orientation === OrientationAxis.REFORMAT
|
|
165
|
-
orientation.includes('_reformat')) {
|
|
164
|
+
else if (orientation === OrientationAxis.REFORMAT) {
|
|
166
165
|
({ viewPlaneNormal, viewUp } = getCameraVectors(this, {
|
|
167
166
|
useViewportNormal: true,
|
|
168
167
|
}));
|
|
169
168
|
}
|
|
169
|
+
else if (orientation === OrientationAxis.AXIAL_REFORMAT ||
|
|
170
|
+
orientation === OrientationAxis.SAGITTAL_REFORMAT ||
|
|
171
|
+
orientation === OrientationAxis.CORONAL_REFORMAT) {
|
|
172
|
+
let baseOrientation;
|
|
173
|
+
if (orientation === OrientationAxis.AXIAL_REFORMAT) {
|
|
174
|
+
baseOrientation = OrientationAxis.AXIAL;
|
|
175
|
+
}
|
|
176
|
+
else if (orientation === OrientationAxis.SAGITTAL_REFORMAT) {
|
|
177
|
+
baseOrientation = OrientationAxis.SAGITTAL;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
baseOrientation = OrientationAxis.CORONAL;
|
|
181
|
+
}
|
|
182
|
+
({ viewPlaneNormal, viewUp } = getCameraVectors(this, {
|
|
183
|
+
useViewportNormal: true,
|
|
184
|
+
orientation: baseOrientation,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
170
187
|
else if (MPR_CAMERA_VALUES[orientation]) {
|
|
171
188
|
({ viewPlaneNormal, viewUp } = MPR_CAMERA_VALUES[orientation]);
|
|
172
189
|
}
|
|
@@ -178,7 +195,7 @@ class VolumeViewport extends BaseVolumeViewport {
|
|
|
178
195
|
viewUp,
|
|
179
196
|
});
|
|
180
197
|
this.viewportProperties.orientation = orientation;
|
|
181
|
-
this.resetCamera();
|
|
198
|
+
this.resetCamera({ suppressEvents: true });
|
|
182
199
|
}
|
|
183
200
|
else {
|
|
184
201
|
({ viewPlaneNormal, viewUp } = orientation);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Enums from '../../enums';
|
|
2
2
|
import type * as Types from '../../types';
|
|
3
|
+
import type OrientationVectors from '../../types/OrientationVectors';
|
|
3
4
|
import { vec3 } from 'gl-matrix';
|
|
4
5
|
export interface CameraPositionConfig {
|
|
5
6
|
orientation?: Enums.OrientationAxis;
|
|
@@ -16,3 +17,4 @@ export declare function getCameraVectors(viewport: Types.IBaseVolumeViewport, co
|
|
|
16
17
|
viewRight: [number, number, number];
|
|
17
18
|
};
|
|
18
19
|
export declare function getOrientationFromScanAxisNormal(scanAxisNormal: vec3): Enums.OrientationAxis;
|
|
20
|
+
export declare function getAcquisitionPlaneReformatOrientation(imageOrientationPatient: number[]): OrientationVectors | null;
|
|
@@ -19,6 +19,22 @@ export function calculateCameraPosition(rowCosineVec, colCosineVec, scanAxisNorm
|
|
|
19
19
|
case OrientationAxis.CORONAL_REFORMAT:
|
|
20
20
|
referenceCameraValues = MPR_CAMERA_VALUES.coronal;
|
|
21
21
|
break;
|
|
22
|
+
case OrientationAxis.REFORMAT:
|
|
23
|
+
const autoDetected = getOrientationFromScanAxisNormal(scanAxisNormal);
|
|
24
|
+
switch (autoDetected) {
|
|
25
|
+
case OrientationAxis.AXIAL:
|
|
26
|
+
referenceCameraValues = MPR_CAMERA_VALUES.axial;
|
|
27
|
+
break;
|
|
28
|
+
case OrientationAxis.SAGITTAL:
|
|
29
|
+
referenceCameraValues = MPR_CAMERA_VALUES.sagittal;
|
|
30
|
+
break;
|
|
31
|
+
case OrientationAxis.CORONAL:
|
|
32
|
+
referenceCameraValues = MPR_CAMERA_VALUES.coronal;
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
referenceCameraValues = MPR_CAMERA_VALUES.axial;
|
|
36
|
+
}
|
|
37
|
+
break;
|
|
22
38
|
default:
|
|
23
39
|
referenceCameraValues = MPR_CAMERA_VALUES.axial;
|
|
24
40
|
break;
|
|
@@ -97,7 +113,7 @@ export function getCameraVectors(viewport, config) {
|
|
|
97
113
|
if (useViewportNormal) {
|
|
98
114
|
normalPlaneForOrientation = viewport.getCamera().viewPlaneNormal;
|
|
99
115
|
}
|
|
100
|
-
if (!orientation) {
|
|
116
|
+
if (!orientation || orientation === OrientationAxis.REFORMAT) {
|
|
101
117
|
orientation = getOrientationFromScanAxisNormal(normalPlaneForOrientation);
|
|
102
118
|
}
|
|
103
119
|
return calculateCameraPosition(rowCosineVec, colCosineVec, scanAxisNormal, orientation);
|
|
@@ -120,3 +136,100 @@ export function getOrientationFromScanAxisNormal(scanAxisNormal) {
|
|
|
120
136
|
return OrientationAxis.CORONAL;
|
|
121
137
|
}
|
|
122
138
|
}
|
|
139
|
+
export function getAcquisitionPlaneReformatOrientation(imageOrientationPatient) {
|
|
140
|
+
if (!imageOrientationPatient || imageOrientationPatient.length !== 6) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
const rowVec = vec3.fromValues(imageOrientationPatient[0], imageOrientationPatient[1], imageOrientationPatient[2]);
|
|
144
|
+
const colVec = vec3.fromValues(imageOrientationPatient[3], imageOrientationPatient[4], imageOrientationPatient[5]);
|
|
145
|
+
const scanAxisNormal = vec3.create();
|
|
146
|
+
vec3.cross(scanAxisNormal, rowVec, colVec);
|
|
147
|
+
vec3.normalize(rowVec, rowVec);
|
|
148
|
+
vec3.normalize(colVec, colVec);
|
|
149
|
+
vec3.normalize(scanAxisNormal, scanAxisNormal);
|
|
150
|
+
const negRowVec = vec3.create();
|
|
151
|
+
vec3.negate(negRowVec, rowVec);
|
|
152
|
+
const negColVec = vec3.create();
|
|
153
|
+
vec3.negate(negColVec, colVec);
|
|
154
|
+
const negScanAxisNormal = vec3.create();
|
|
155
|
+
vec3.negate(negScanAxisNormal, scanAxisNormal);
|
|
156
|
+
const acquisitionVectors = [
|
|
157
|
+
{ vec: rowVec, name: 'row' },
|
|
158
|
+
{ vec: colVec, name: 'col' },
|
|
159
|
+
{ vec: scanAxisNormal, name: 'scanAxis' },
|
|
160
|
+
{ vec: negRowVec, name: '-row' },
|
|
161
|
+
{ vec: negColVec, name: '-col' },
|
|
162
|
+
{ vec: negScanAxisNormal, name: '-scanAxis' },
|
|
163
|
+
];
|
|
164
|
+
const standardViews = [
|
|
165
|
+
{
|
|
166
|
+
name: 'axial',
|
|
167
|
+
viewPlaneNormal: vec3.fromValues(MPR_CAMERA_VALUES.axial.viewPlaneNormal[0], MPR_CAMERA_VALUES.axial.viewPlaneNormal[1], MPR_CAMERA_VALUES.axial.viewPlaneNormal[2]),
|
|
168
|
+
viewUp: vec3.fromValues(MPR_CAMERA_VALUES.axial.viewUp[0], MPR_CAMERA_VALUES.axial.viewUp[1], MPR_CAMERA_VALUES.axial.viewUp[2]),
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'sagittal',
|
|
172
|
+
viewPlaneNormal: vec3.fromValues(MPR_CAMERA_VALUES.sagittal.viewPlaneNormal[0], MPR_CAMERA_VALUES.sagittal.viewPlaneNormal[1], MPR_CAMERA_VALUES.sagittal.viewPlaneNormal[2]),
|
|
173
|
+
viewUp: vec3.fromValues(MPR_CAMERA_VALUES.sagittal.viewUp[0], MPR_CAMERA_VALUES.sagittal.viewUp[1], MPR_CAMERA_VALUES.sagittal.viewUp[2]),
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'coronal',
|
|
177
|
+
viewPlaneNormal: vec3.fromValues(MPR_CAMERA_VALUES.coronal.viewPlaneNormal[0], MPR_CAMERA_VALUES.coronal.viewPlaneNormal[1], MPR_CAMERA_VALUES.coronal.viewPlaneNormal[2]),
|
|
178
|
+
viewUp: vec3.fromValues(MPR_CAMERA_VALUES.coronal.viewUp[0], MPR_CAMERA_VALUES.coronal.viewUp[1], MPR_CAMERA_VALUES.coronal.viewUp[2]),
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
let bestAlignment = -Infinity;
|
|
182
|
+
let bestViewPlaneNormal = null;
|
|
183
|
+
let bestViewUp = null;
|
|
184
|
+
for (const standardView of standardViews) {
|
|
185
|
+
let bestPairScore = -Infinity;
|
|
186
|
+
let bestPairViewPlaneNormal = null;
|
|
187
|
+
let bestPairViewUp = null;
|
|
188
|
+
for (let i = 0; i < acquisitionVectors.length; i++) {
|
|
189
|
+
for (let j = 0; j < acquisitionVectors.length; j++) {
|
|
190
|
+
if (i === j)
|
|
191
|
+
continue;
|
|
192
|
+
const v1 = acquisitionVectors[i].vec;
|
|
193
|
+
const v2 = acquisitionVectors[j].vec;
|
|
194
|
+
const dotProduct = Math.abs(vec3.dot(v1, v2));
|
|
195
|
+
if (dotProduct > 0.1)
|
|
196
|
+
continue;
|
|
197
|
+
const score1 = Math.abs(vec3.dot(v1, standardView.viewPlaneNormal));
|
|
198
|
+
const score2 = Math.abs(vec3.dot(v2, standardView.viewUp));
|
|
199
|
+
const totalScore = score1 + score2;
|
|
200
|
+
const score1Swapped = Math.abs(vec3.dot(v2, standardView.viewPlaneNormal));
|
|
201
|
+
const score2Swapped = Math.abs(vec3.dot(v1, standardView.viewUp));
|
|
202
|
+
const totalScoreSwapped = score1Swapped + score2Swapped;
|
|
203
|
+
if (totalScoreSwapped > totalScore &&
|
|
204
|
+
totalScoreSwapped > bestPairScore) {
|
|
205
|
+
bestPairScore = totalScoreSwapped;
|
|
206
|
+
bestPairViewPlaneNormal = v2;
|
|
207
|
+
bestPairViewUp = v1;
|
|
208
|
+
}
|
|
209
|
+
else if (totalScore > bestPairScore) {
|
|
210
|
+
bestPairScore = totalScore;
|
|
211
|
+
bestPairViewPlaneNormal = v1;
|
|
212
|
+
bestPairViewUp = v2;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (bestPairScore > bestAlignment &&
|
|
217
|
+
bestPairViewPlaneNormal &&
|
|
218
|
+
bestPairViewUp) {
|
|
219
|
+
bestAlignment = bestPairScore;
|
|
220
|
+
bestViewPlaneNormal = bestPairViewPlaneNormal;
|
|
221
|
+
bestViewUp = bestPairViewUp;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!bestViewPlaneNormal || !bestViewUp) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
return {
|
|
228
|
+
viewPlaneNormal: [
|
|
229
|
+
bestViewPlaneNormal[0],
|
|
230
|
+
bestViewPlaneNormal[1],
|
|
231
|
+
bestViewPlaneNormal[2],
|
|
232
|
+
],
|
|
233
|
+
viewUp: [bestViewUp[0], bestViewUp[1], bestViewUp[2]],
|
|
234
|
+
};
|
|
235
|
+
}
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "4.
|
|
1
|
+
export declare const version = "4.16.0";
|
package/dist/esm/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '4.
|
|
1
|
+
export const version = '4.16.0';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.16.0",
|
|
4
4
|
"description": "Cornerstone3D Core",
|
|
5
5
|
"module": "./dist/esm/index.js",
|
|
6
6
|
"types": "./dist/esm/index.d.ts",
|
|
@@ -97,5 +97,5 @@
|
|
|
97
97
|
"type": "individual",
|
|
98
98
|
"url": "https://ohif.org/donate"
|
|
99
99
|
},
|
|
100
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "894fe3bebbbaae27c5aa58b758616988ba173ee3"
|
|
101
101
|
}
|