@cornerstonejs/tools 1.14.2 → 1.14.4
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/store/SynchronizerManager/Synchronizer.js +10 -2
- package/dist/cjs/store/SynchronizerManager/Synchronizer.js.map +1 -1
- package/dist/cjs/synchronizers/callbacks/stackImageSyncCallback.js +25 -22
- package/dist/cjs/synchronizers/callbacks/stackImageSyncCallback.js.map +1 -1
- package/dist/cjs/synchronizers/callbacks/voiSyncCallback.js +1 -1
- package/dist/cjs/synchronizers/callbacks/voiSyncCallback.js.map +1 -1
- package/dist/cjs/tools/annotation/AngleTool.js +1 -1
- package/dist/cjs/tools/annotation/AngleTool.js.map +1 -1
- package/dist/esm/store/SynchronizerManager/Synchronizer.js +10 -2
- package/dist/esm/store/SynchronizerManager/Synchronizer.js.map +1 -1
- package/dist/esm/synchronizers/callbacks/stackImageSyncCallback.js +26 -23
- package/dist/esm/synchronizers/callbacks/stackImageSyncCallback.js.map +1 -1
- package/dist/esm/synchronizers/callbacks/voiSyncCallback.js +1 -1
- package/dist/esm/synchronizers/callbacks/voiSyncCallback.js.map +1 -1
- package/dist/esm/tools/annotation/AngleTool.js +1 -1
- package/dist/esm/tools/annotation/AngleTool.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +3 -3
- package/src/store/SynchronizerManager/Synchronizer.ts +16 -8
- package/src/synchronizers/callbacks/stackImageSyncCallback.ts +63 -68
- package/src/synchronizers/callbacks/voiSyncCallback.ts +1 -1
- package/src/tools/annotation/AngleTool.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/tools",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.4",
|
|
4
4
|
"description": "Cornerstone3D Tools",
|
|
5
5
|
"main": "dist/umd/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@cornerstonejs/core": "^1.14.
|
|
32
|
+
"@cornerstonejs/core": "^1.14.4",
|
|
33
33
|
"lodash.clonedeep": "4.5.0",
|
|
34
34
|
"lodash.get": "^4.4.2"
|
|
35
35
|
},
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"type": "individual",
|
|
53
53
|
"url": "https://ohif.org/donate"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "96dc1772a2f77a7626c07e19434b42753e9d4188"
|
|
56
56
|
}
|
|
@@ -205,6 +205,7 @@ class Synchronizer {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
this._ignoreFiredEvents = true;
|
|
208
|
+
const promises = [];
|
|
208
209
|
try {
|
|
209
210
|
for (let i = 0; i < this._targetViewports.length; i++) {
|
|
210
211
|
const targetViewport = this._targetViewports[i];
|
|
@@ -214,19 +215,26 @@ class Synchronizer {
|
|
|
214
215
|
if (targetIsSource) {
|
|
215
216
|
continue;
|
|
216
217
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
218
|
+
promises.push(
|
|
219
|
+
this._eventHandler(
|
|
220
|
+
this,
|
|
221
|
+
sourceViewport,
|
|
222
|
+
targetViewport,
|
|
223
|
+
sourceEvent,
|
|
224
|
+
this._options
|
|
225
|
+
)
|
|
224
226
|
);
|
|
225
227
|
}
|
|
226
228
|
} catch (ex) {
|
|
227
229
|
console.warn(`Synchronizer, for: ${this._eventName}`, ex);
|
|
228
230
|
} finally {
|
|
229
|
-
|
|
231
|
+
if (promises.length) {
|
|
232
|
+
Promise.allSettled(promises).then(() => {
|
|
233
|
+
this._ignoreFiredEvents = false;
|
|
234
|
+
});
|
|
235
|
+
} else {
|
|
236
|
+
this._ignoreFiredEvents = false;
|
|
237
|
+
}
|
|
230
238
|
}
|
|
231
239
|
}
|
|
232
240
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { vec3 } from 'gl-matrix';
|
|
1
|
+
import { vec3, mat4 } from 'gl-matrix';
|
|
2
2
|
import {
|
|
3
3
|
getRenderingEngine,
|
|
4
4
|
Types,
|
|
@@ -8,28 +8,27 @@ import {
|
|
|
8
8
|
import { Synchronizer } from '../../store';
|
|
9
9
|
import { jumpToSlice } from '../../utilities';
|
|
10
10
|
import areViewportsCoplanar from './areViewportsCoplanar ';
|
|
11
|
+
|
|
12
|
+
const getSpatialRegistration = (targetId, sourceId) =>
|
|
13
|
+
utilities.spatialRegistrationMetadataProvider.get(
|
|
14
|
+
'spatialRegistrationModule',
|
|
15
|
+
[targetId, sourceId]
|
|
16
|
+
);
|
|
17
|
+
|
|
11
18
|
/**
|
|
12
19
|
* Synchronizer callback to synchronize the source viewport image to the
|
|
13
|
-
* target viewports closest image in its stack.
|
|
20
|
+
* target viewports closest image in its stack.
|
|
14
21
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
22
|
+
* This synchronizer does a setup (which can already be predefined as required)
|
|
23
|
+
* to register the target and soruce viewports. The registration will default
|
|
24
|
+
* to the identity registration if the same FOR is present in both viewports,
|
|
25
|
+
* unless the option `useInitialPosition` is set in the target viewport.
|
|
19
26
|
*
|
|
20
|
-
*
|
|
21
|
-
* registrationMetadataProvider to
|
|
22
|
-
* for mapping between the source and target viewport if so it is used to
|
|
23
|
-
* and is applied to the imagePositionPatient of the source viewport's to
|
|
24
|
-
* get the imagePositionPatient of the target viewport's closest image in
|
|
25
|
-
* its stack.
|
|
26
|
-
* Note for 2) The consuming apps using Cornerstone3D (OHIF, etc) are responsible
|
|
27
|
-
* to provide such data in the registrationMetadataProvider. This can be done
|
|
27
|
+
* The consuming apps using Cornerstone3D (OHIF, etc) MAY provide such data in
|
|
28
|
+
* the registrationMetadataProvider to override the data here. This can be done
|
|
28
29
|
* by various methods 1) Using spatialRegistrationModule inside dicom 2) assuming
|
|
29
30
|
* the user has actually manually scrolled the target viewport to the correct
|
|
30
31
|
* slice before initiating the synchronization 3) using some other method
|
|
31
|
-
* But overall, the consuming app is responsible for providing the data.
|
|
32
|
-
*
|
|
33
32
|
*
|
|
34
33
|
* @param synchronizerInstance - The Instance of the Synchronizer
|
|
35
34
|
* @param sourceViewport - The list of IDs defining the source viewport.
|
|
@@ -53,13 +52,16 @@ export default async function stackImageSyncCallback(
|
|
|
53
52
|
sourceViewport.viewportId
|
|
54
53
|
) as Types.IStackViewport;
|
|
55
54
|
|
|
55
|
+
const options = synchronizerInstance.getOptions(targetViewport.viewportId);
|
|
56
|
+
|
|
57
|
+
if (options?.disabled) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
const tViewport = renderingEngine.getViewport(
|
|
57
62
|
targetViewport.viewportId
|
|
58
63
|
) as Types.IStackViewport;
|
|
59
64
|
|
|
60
|
-
const frameOfReferenceUID1 = sViewport.getFrameOfReferenceUID();
|
|
61
|
-
const frameOfReferenceUID2 = tViewport.getFrameOfReferenceUID();
|
|
62
|
-
|
|
63
65
|
const imageId1 = sViewport.getCurrentImageId();
|
|
64
66
|
const imagePlaneModule1 = metaData.get('imagePlaneModule', imageId1);
|
|
65
67
|
const sourceImagePositionPatient = imagePlaneModule1.imagePositionPatient;
|
|
@@ -70,69 +72,62 @@ export default async function stackImageSyncCallback(
|
|
|
70
72
|
return;
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
// if the frame of reference is different we need to use the registrationMetadataProvider
|
|
76
|
+
// and add that to the imagePositionPatient of the source viewport to get the
|
|
77
|
+
// imagePositionPatient of the target viewport's closest image in its stack
|
|
78
|
+
let registrationMatrixMat4 = getSpatialRegistration(
|
|
79
|
+
targetViewport.viewportId,
|
|
80
|
+
sourceViewport.viewportId
|
|
81
|
+
);
|
|
80
82
|
|
|
83
|
+
if (!registrationMatrixMat4) {
|
|
84
|
+
const frameOfReferenceUID1 = sViewport.getFrameOfReferenceUID();
|
|
85
|
+
const frameOfReferenceUID2 = tViewport.getFrameOfReferenceUID();
|
|
81
86
|
if (
|
|
82
|
-
|
|
83
|
-
|
|
87
|
+
frameOfReferenceUID1 === frameOfReferenceUID2 &&
|
|
88
|
+
options.useInitialPosition !== false
|
|
84
89
|
) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
// if the frame of reference is different we need to use the registrationMetadataProvider
|
|
94
|
-
// and add that to the imagePositionPatient of the source viewport to get the
|
|
95
|
-
// imagePositionPatient of the target viewport's closest image in its stack
|
|
96
|
-
const registrationMatrixMat4 =
|
|
97
|
-
utilities.spatialRegistrationMetadataProvider.get(
|
|
98
|
-
'spatialRegistrationModule',
|
|
99
|
-
[targetViewport.viewportId, sourceViewport.viewportId]
|
|
90
|
+
registrationMatrixMat4 = mat4.identity(mat4.create());
|
|
91
|
+
} else {
|
|
92
|
+
utilities.calculateViewportsSpatialRegistration(sViewport, tViewport);
|
|
93
|
+
registrationMatrixMat4 = getSpatialRegistration(
|
|
94
|
+
targetViewport.viewportId,
|
|
95
|
+
sourceViewport.viewportId
|
|
100
96
|
);
|
|
101
|
-
|
|
97
|
+
}
|
|
102
98
|
if (!registrationMatrixMat4) {
|
|
103
|
-
|
|
104
|
-
`No registration matrix found for sourceViewport: ${sourceViewport.viewportId} and targetViewport: ${targetViewport.viewportId}, viewports with different frameOfReferenceUIDs must have a registration matrix in the registrationMetadataProvider. Use calculateViewportsRegistrationMatrix to calculate the matrix.`
|
|
105
|
-
);
|
|
99
|
+
return;
|
|
106
100
|
}
|
|
101
|
+
}
|
|
107
102
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
// apply the registration matrix to the source viewport's imagePositionPatient
|
|
104
|
+
// to get the target viewport's imagePositionPatient
|
|
105
|
+
const targetImagePositionPatientWithRegistrationMatrix = vec3.transformMat4(
|
|
106
|
+
vec3.create(),
|
|
107
|
+
sourceImagePositionPatient,
|
|
108
|
+
registrationMatrixMat4
|
|
109
|
+
);
|
|
115
110
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
// find the closest image in the target viewport's stack to the
|
|
112
|
+
// targetImagePositionPatientWithRegistrationMatrix
|
|
113
|
+
const closestImageIdIndex2 = _getClosestImageIdIndex(
|
|
114
|
+
targetImagePositionPatientWithRegistrationMatrix,
|
|
115
|
+
targetImageIds
|
|
116
|
+
);
|
|
122
117
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
118
|
+
if (
|
|
119
|
+
closestImageIdIndex2.index !== -1 &&
|
|
120
|
+
tViewport.getCurrentImageIdIndex() !== closestImageIdIndex2.index
|
|
121
|
+
) {
|
|
122
|
+
await jumpToSlice(tViewport.element, {
|
|
123
|
+
imageIndex: closestImageIdIndex2.index,
|
|
124
|
+
});
|
|
131
125
|
}
|
|
132
126
|
}
|
|
133
127
|
|
|
134
128
|
function _getClosestImageIdIndex(targetPoint, imageIds) {
|
|
135
129
|
// todo: this does not assume orientation yet, but that can be added later
|
|
130
|
+
// todo: handle multiframe images
|
|
136
131
|
return imageIds.reduce(
|
|
137
132
|
(closestImageIdIndex, imageId, index) => {
|
|
138
133
|
const { imagePositionPatient } = metaData.get(
|