@cornerstonejs/core 3.7.17 → 3.8.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/cache/cache.d.ts +2 -0
- package/dist/esm/cache/cache.js +14 -0
- package/dist/esm/loaders/imageLoader.d.ts +1 -0
- package/dist/esm/loaders/imageLoader.js +6 -2
- package/dist/esm/loaders/volumeLoader.js +1 -0
- package/dist/esm/utilities/VoxelManager.d.ts +19 -12
- package/dist/esm/utilities/VoxelManager.js +30 -21
- package/dist/esm/utilities/historyMemo/index.d.ts +3 -0
- package/dist/esm/utilities/historyMemo/index.js +32 -0
- package/dist/esm/utilities/loadImageToCanvas.d.ts +4 -2
- package/dist/esm/utilities/renderToCanvasGPU.js +5 -0
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ declare class Cache {
|
|
|
4
4
|
private readonly _imageCache;
|
|
5
5
|
private readonly _volumeCache;
|
|
6
6
|
private readonly _imageIdsToVolumeIdCache;
|
|
7
|
+
private readonly _referencedImageIdToImageIdCache;
|
|
7
8
|
private readonly _geometryCache;
|
|
8
9
|
private _imageCacheSize;
|
|
9
10
|
private _maxCacheSize;
|
|
@@ -42,6 +43,7 @@ declare class Cache {
|
|
|
42
43
|
private _decacheGeometry;
|
|
43
44
|
incrementGeometryCacheSize: (increment: number) => void;
|
|
44
45
|
decrementGeometryCacheSize: (decrement: number) => void;
|
|
46
|
+
getImageByReferencedImageId: (referencedImageId: string) => IImage | undefined;
|
|
45
47
|
getImage: (imageId: string, minQuality?: ImageQualityStatus) => IImage | undefined;
|
|
46
48
|
setPartialImage(imageId: string, partialImage?: IImage): void;
|
|
47
49
|
getImageQuality(imageId: string): ImageQualityStatus;
|
package/dist/esm/cache/cache.js
CHANGED
|
@@ -10,6 +10,7 @@ class Cache {
|
|
|
10
10
|
this._imageCache = new Map();
|
|
11
11
|
this._volumeCache = new Map();
|
|
12
12
|
this._imageIdsToVolumeIdCache = new Map();
|
|
13
|
+
this._referencedImageIdToImageIdCache = new Map();
|
|
13
14
|
this._geometryCache = new Map();
|
|
14
15
|
this._imageCacheSize = 0;
|
|
15
16
|
this._maxCacheSize = 3 * ONE_GB;
|
|
@@ -43,6 +44,9 @@ class Cache {
|
|
|
43
44
|
throw new Error('Cannot decache an image with a shared cache key. You need to manually decache the volume first.');
|
|
44
45
|
}
|
|
45
46
|
const { imageLoadObject } = cachedImage;
|
|
47
|
+
if (cachedImage.image?.referencedImageId) {
|
|
48
|
+
this._referencedImageIdToImageIdCache.delete(cachedImage.image.referencedImageId);
|
|
49
|
+
}
|
|
46
50
|
if (imageLoadObject?.cancelFn) {
|
|
47
51
|
imageLoadObject.cancelFn();
|
|
48
52
|
}
|
|
@@ -200,6 +204,13 @@ class Cache {
|
|
|
200
204
|
this.decrementGeometryCacheSize = (decrement) => {
|
|
201
205
|
this._geometryCacheSize -= decrement;
|
|
202
206
|
};
|
|
207
|
+
this.getImageByReferencedImageId = (referencedImageId) => {
|
|
208
|
+
const imageId = this._referencedImageIdToImageIdCache.get(referencedImageId);
|
|
209
|
+
if (imageId) {
|
|
210
|
+
return this._imageCache.get(imageId)?.image;
|
|
211
|
+
}
|
|
212
|
+
return undefined;
|
|
213
|
+
};
|
|
203
214
|
this.getImage = (imageId, minQuality = ImageQualityStatus.FAR_REPLICATE) => {
|
|
204
215
|
if (imageId === undefined) {
|
|
205
216
|
throw new Error('getImage: imageId must not be undefined');
|
|
@@ -375,6 +386,9 @@ class Cache {
|
|
|
375
386
|
const eventDetails = {
|
|
376
387
|
image: cachedImage,
|
|
377
388
|
};
|
|
389
|
+
if (image.referencedImageId) {
|
|
390
|
+
this._referencedImageIdToImageIdCache.set(image.referencedImageId, imageId);
|
|
391
|
+
}
|
|
378
392
|
triggerEvent(eventTarget, Events.IMAGE_CACHE_IMAGE_ADDED, eventDetails);
|
|
379
393
|
cachedImage.sharedCacheKey = image.sharedCacheKey;
|
|
380
394
|
}
|
|
@@ -136,6 +136,7 @@ export function createAndCacheDerivedImage(referencedImageId, options = {}) {
|
|
|
136
136
|
origin: imagePlaneModule.imagePositionPatient,
|
|
137
137
|
direction: imagePlaneModule.imageOrientationPatient,
|
|
138
138
|
frameOfReferenceUID: imagePlaneModule.frameOfReferenceUID,
|
|
139
|
+
referencedImageId: referencedImageId,
|
|
139
140
|
});
|
|
140
141
|
localImage.referencedImageId = referencedImageId;
|
|
141
142
|
if (!cache.getImageLoadObject(imageId)) {
|
|
@@ -163,7 +164,7 @@ export function createAndCacheDerivedImages(referencedImageIds, options = {}) {
|
|
|
163
164
|
return images;
|
|
164
165
|
}
|
|
165
166
|
export function createAndCacheLocalImage(imageId, options) {
|
|
166
|
-
const { scalarData, origin, direction, targetBuffer, skipCreateBuffer, onCacheAdd, frameOfReferenceUID, voxelRepresentation, } = options;
|
|
167
|
+
const { scalarData, origin, direction, targetBuffer, skipCreateBuffer, onCacheAdd, frameOfReferenceUID, voxelRepresentation, referencedImageId, } = options;
|
|
167
168
|
const dimensions = options.dimensions;
|
|
168
169
|
const spacing = options.spacing;
|
|
169
170
|
if (!dimensions || !spacing) {
|
|
@@ -247,13 +248,15 @@ export function createAndCacheLocalImage(imageId, options) {
|
|
|
247
248
|
metadata: metadata[type] || {},
|
|
248
249
|
});
|
|
249
250
|
});
|
|
251
|
+
const id = imageId;
|
|
250
252
|
const voxelManager = (voxelRepresentation === VoxelManagerEnum.RLE &&
|
|
251
|
-
VoxelManager.createRLEImageVoxelManager({ dimensions })) ||
|
|
253
|
+
VoxelManager.createRLEImageVoxelManager({ dimensions, id })) ||
|
|
252
254
|
VoxelManager.createImageVoxelManager({
|
|
253
255
|
height,
|
|
254
256
|
width,
|
|
255
257
|
numberOfComponents,
|
|
256
258
|
scalarData: scalarDataToUse,
|
|
259
|
+
id,
|
|
257
260
|
});
|
|
258
261
|
let minPixelValue = scalarDataToUse[0];
|
|
259
262
|
let maxPixelValue = scalarDataToUse[0];
|
|
@@ -289,6 +292,7 @@ export function createAndCacheLocalImage(imageId, options) {
|
|
|
289
292
|
getPixelData: () => voxelManager.getScalarData(),
|
|
290
293
|
voxelManager,
|
|
291
294
|
sizeInBytes: scalarData.byteLength,
|
|
295
|
+
referencedImageId,
|
|
292
296
|
};
|
|
293
297
|
onCacheAdd?.(image);
|
|
294
298
|
cache.putImageSync(image.imageId, image);
|
|
@@ -27,6 +27,7 @@ export default class VoxelManager<T> {
|
|
|
27
27
|
sliceIndex: number;
|
|
28
28
|
slicePlane: number;
|
|
29
29
|
}) => PixelDataTypedArray;
|
|
30
|
+
get id(): string;
|
|
30
31
|
constructor(dimensions: any, options: {
|
|
31
32
|
_get: (index: number) => T;
|
|
32
33
|
_set?: (index: number, v: T) => boolean;
|
|
@@ -85,46 +86,52 @@ export default class VoxelManager<T> {
|
|
|
85
86
|
private setSliceDataValue;
|
|
86
87
|
private toNumber;
|
|
87
88
|
private static _createRGBScalarVolumeVoxelManager;
|
|
88
|
-
static createImageVolumeVoxelManager({ dimensions, imageIds, numberOfComponents, }: {
|
|
89
|
+
static createImageVolumeVoxelManager({ dimensions, imageIds, numberOfComponents, id, }: {
|
|
89
90
|
dimensions: Point3;
|
|
90
91
|
imageIds: string[];
|
|
91
92
|
numberOfComponents: number;
|
|
93
|
+
id?: string;
|
|
92
94
|
}): IVoxelManager<number> | IVoxelManager<RGB>;
|
|
93
|
-
static createScalarVolumeVoxelManager({ dimensions, scalarData, numberOfComponents, }: {
|
|
95
|
+
static createScalarVolumeVoxelManager({ dimensions, scalarData, numberOfComponents, id, }: {
|
|
94
96
|
dimensions: Point3;
|
|
95
97
|
scalarData: any;
|
|
96
98
|
numberOfComponents?: number;
|
|
99
|
+
id?: string;
|
|
97
100
|
}): IVoxelManager<number> | IVoxelManager<RGB>;
|
|
98
|
-
static createScalarDynamicVolumeVoxelManager({ imageIdGroups, dimensions, dimensionGroupNumber, timePoint, numberOfComponents, }: {
|
|
101
|
+
static createScalarDynamicVolumeVoxelManager({ imageIdGroups, dimensions, dimensionGroupNumber, timePoint, numberOfComponents, id, }: {
|
|
99
102
|
imageIdGroups: string[][];
|
|
100
103
|
dimensions: Point3;
|
|
101
104
|
dimensionGroupNumber?: number;
|
|
102
105
|
timePoint?: number;
|
|
103
106
|
numberOfComponents?: number;
|
|
107
|
+
id?: string;
|
|
104
108
|
}): IVoxelManager<number> | IVoxelManager<RGB>;
|
|
105
|
-
static createImageVoxelManager({ width, height, scalarData, numberOfComponents, }: {
|
|
109
|
+
static createImageVoxelManager({ width, height, scalarData, numberOfComponents, id, }: {
|
|
106
110
|
width: number;
|
|
107
111
|
height: number;
|
|
108
112
|
scalarData: PixelDataTypedArray;
|
|
109
113
|
numberOfComponents?: number;
|
|
114
|
+
id?: string;
|
|
110
115
|
}): IVoxelManager<number> | IVoxelManager<RGB>;
|
|
111
116
|
private static _createNumberVolumeVoxelManager;
|
|
112
|
-
static createMapVoxelManager<T>({ dimension, }: {
|
|
117
|
+
static createMapVoxelManager<T>({ dimension, id, }: {
|
|
113
118
|
dimension: Point3;
|
|
119
|
+
id?: string;
|
|
114
120
|
}): IVoxelManager<T>;
|
|
115
|
-
static createHistoryVoxelManager<T>(
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
static createRLEHistoryVoxelManager<T>(sourceVoxelManager: VoxelManager<T>): VoxelManager<T>;
|
|
119
|
-
static createLazyVoxelManager<T>({ dimensions, planeFactory, }: {
|
|
121
|
+
static createHistoryVoxelManager<T>(sourceVoxelManager: VoxelManager<T>, id?: string): VoxelManager<T>;
|
|
122
|
+
static createRLEHistoryVoxelManager<T>(sourceVoxelManager: VoxelManager<T>, id?: string): VoxelManager<T>;
|
|
123
|
+
static createLazyVoxelManager<T>({ dimensions, planeFactory, id, }: {
|
|
120
124
|
dimensions: Point3;
|
|
121
125
|
planeFactory: (width: number, height: number) => T;
|
|
126
|
+
id?: string;
|
|
122
127
|
}): VoxelManager<T>;
|
|
123
|
-
static createRLEVolumeVoxelManager<T>({ dimensions, }: {
|
|
128
|
+
static createRLEVolumeVoxelManager<T>({ dimensions, id, }: {
|
|
124
129
|
dimensions: Point3;
|
|
130
|
+
id?: string;
|
|
125
131
|
}): VoxelManager<T>;
|
|
126
|
-
static createRLEImageVoxelManager<T>({ dimensions, }: {
|
|
132
|
+
static createRLEImageVoxelManager<T>({ dimensions, id, }: {
|
|
127
133
|
dimensions: Point2;
|
|
134
|
+
id?: string;
|
|
128
135
|
}): VoxelManager<T>;
|
|
129
136
|
static addInstanceToImage(image: IImage): void;
|
|
130
137
|
static: any;
|
|
@@ -4,6 +4,9 @@ import isEqual from './isEqual';
|
|
|
4
4
|
import { iterateOverPointsInShapeVoxelManager } from './pointInShapeCallback';
|
|
5
5
|
const DEFAULT_RLE_SIZE = 5 * 1024;
|
|
6
6
|
export default class VoxelManager {
|
|
7
|
+
get id() {
|
|
8
|
+
return this._id;
|
|
9
|
+
}
|
|
7
10
|
constructor(dimensions, options) {
|
|
8
11
|
this.modifiedSlices = new Set();
|
|
9
12
|
this.boundsIJK = [
|
|
@@ -369,7 +372,7 @@ export default class VoxelManager {
|
|
|
369
372
|
}
|
|
370
373
|
return 0;
|
|
371
374
|
}
|
|
372
|
-
static _createRGBScalarVolumeVoxelManager({ dimensions, scalarData, numberOfComponents = 3, }) {
|
|
375
|
+
static _createRGBScalarVolumeVoxelManager({ dimensions, scalarData, numberOfComponents = 3, id, }) {
|
|
373
376
|
const voxels = new VoxelManager(dimensions, {
|
|
374
377
|
_get: (index) => {
|
|
375
378
|
index *= numberOfComponents;
|
|
@@ -379,7 +382,7 @@ export default class VoxelManager {
|
|
|
379
382
|
scalarData[index++],
|
|
380
383
|
];
|
|
381
384
|
},
|
|
382
|
-
_id: '_createRGBScalarVolumeVoxelManager',
|
|
385
|
+
_id: id || '_createRGBScalarVolumeVoxelManager',
|
|
383
386
|
_set: (index, v) => {
|
|
384
387
|
index *= 3;
|
|
385
388
|
const isChanged = !isEqual(scalarData[index], v);
|
|
@@ -396,7 +399,7 @@ export default class VoxelManager {
|
|
|
396
399
|
};
|
|
397
400
|
return voxels;
|
|
398
401
|
}
|
|
399
|
-
static createImageVolumeVoxelManager({ dimensions, imageIds, numberOfComponents = 1, }) {
|
|
402
|
+
static createImageVolumeVoxelManager({ dimensions, imageIds, numberOfComponents = 1, id, }) {
|
|
400
403
|
const pixelsPerSlice = dimensions[0] * dimensions[1];
|
|
401
404
|
function getPixelInfo(index) {
|
|
402
405
|
const sliceIndex = Math.floor(index / pixelsPerSlice);
|
|
@@ -449,7 +452,7 @@ export default class VoxelManager {
|
|
|
449
452
|
_set: setVoxelValue,
|
|
450
453
|
numberOfComponents,
|
|
451
454
|
_getConstructor,
|
|
452
|
-
_id: 'createImageVolumeVoxelManager',
|
|
455
|
+
_id: id || 'createImageVolumeVoxelManager',
|
|
453
456
|
});
|
|
454
457
|
voxelManager.getMiddleSliceData = () => {
|
|
455
458
|
const middleSliceIndex = Math.floor(dimensions[2] / 2);
|
|
@@ -563,7 +566,7 @@ export default class VoxelManager {
|
|
|
563
566
|
};
|
|
564
567
|
return voxelManager;
|
|
565
568
|
}
|
|
566
|
-
static createScalarVolumeVoxelManager({ dimensions, scalarData, numberOfComponents, }) {
|
|
569
|
+
static createScalarVolumeVoxelManager({ dimensions, scalarData, numberOfComponents, id, }) {
|
|
567
570
|
if (dimensions.length !== 3) {
|
|
568
571
|
throw new Error('Dimensions must be provided as [number, number, number] for [width, height, depth]');
|
|
569
572
|
}
|
|
@@ -581,14 +584,16 @@ export default class VoxelManager {
|
|
|
581
584
|
dimensions,
|
|
582
585
|
scalarData,
|
|
583
586
|
numberOfComponents,
|
|
587
|
+
id,
|
|
584
588
|
});
|
|
585
589
|
}
|
|
586
590
|
return VoxelManager._createNumberVolumeVoxelManager({
|
|
587
591
|
dimensions,
|
|
588
592
|
scalarData,
|
|
593
|
+
id,
|
|
589
594
|
});
|
|
590
595
|
}
|
|
591
|
-
static createScalarDynamicVolumeVoxelManager({ imageIdGroups, dimensions, dimensionGroupNumber = 1, timePoint = 0, numberOfComponents = 1, }) {
|
|
596
|
+
static createScalarDynamicVolumeVoxelManager({ imageIdGroups, dimensions, dimensionGroupNumber = 1, timePoint = 0, numberOfComponents = 1, id, }) {
|
|
592
597
|
let activeDimensionGroup = 0;
|
|
593
598
|
if (dimensionGroupNumber !== undefined) {
|
|
594
599
|
activeDimensionGroup = dimensionGroupNumber - 1;
|
|
@@ -615,13 +620,14 @@ export default class VoxelManager {
|
|
|
615
620
|
dimensions,
|
|
616
621
|
imageIds,
|
|
617
622
|
numberOfComponents,
|
|
623
|
+
id,
|
|
618
624
|
});
|
|
619
625
|
});
|
|
620
626
|
const voxelManager = new VoxelManager(dimensions, {
|
|
621
627
|
_get: (index) => voxelGroups[activeDimensionGroup]._get(index),
|
|
622
628
|
_set: (index, v) => voxelGroups[activeDimensionGroup]._set(index, v),
|
|
623
629
|
numberOfComponents,
|
|
624
|
-
_id: 'createScalarDynamicVolumeVoxelManager',
|
|
630
|
+
_id: id || 'createScalarDynamicVolumeVoxelManager',
|
|
625
631
|
});
|
|
626
632
|
voxelManager.getScalarDataLength = () => {
|
|
627
633
|
return voxelGroups[activeDimensionGroup].getScalarDataLength();
|
|
@@ -674,7 +680,7 @@ export default class VoxelManager {
|
|
|
674
680
|
};
|
|
675
681
|
return voxelManager;
|
|
676
682
|
}
|
|
677
|
-
static createImageVoxelManager({ width, height, scalarData, numberOfComponents = 1, }) {
|
|
683
|
+
static createImageVoxelManager({ width, height, scalarData, numberOfComponents = 1, id, }) {
|
|
678
684
|
const dimensions = [width, height, 1];
|
|
679
685
|
if (!numberOfComponents) {
|
|
680
686
|
numberOfComponents = scalarData.length / width / height;
|
|
@@ -689,14 +695,16 @@ export default class VoxelManager {
|
|
|
689
695
|
dimensions,
|
|
690
696
|
scalarData,
|
|
691
697
|
numberOfComponents,
|
|
698
|
+
id,
|
|
692
699
|
});
|
|
693
700
|
}
|
|
694
701
|
return VoxelManager._createNumberVolumeVoxelManager({
|
|
695
702
|
dimensions,
|
|
696
703
|
scalarData,
|
|
704
|
+
id,
|
|
697
705
|
});
|
|
698
706
|
}
|
|
699
|
-
static _createNumberVolumeVoxelManager({ dimensions, scalarData, }) {
|
|
707
|
+
static _createNumberVolumeVoxelManager({ dimensions, scalarData, id, }) {
|
|
700
708
|
const voxels = new VoxelManager(dimensions, {
|
|
701
709
|
_get: (index) => scalarData[index],
|
|
702
710
|
_set: (index, v) => {
|
|
@@ -705,7 +713,7 @@ export default class VoxelManager {
|
|
|
705
713
|
return isChanged;
|
|
706
714
|
},
|
|
707
715
|
_getConstructor: () => scalarData.constructor,
|
|
708
|
-
_id: '_createNumberVolumeVoxelManager',
|
|
716
|
+
_id: id || '_createNumberVolumeVoxelManager',
|
|
709
717
|
});
|
|
710
718
|
voxels.scalarData = scalarData;
|
|
711
719
|
voxels.clear = () => {
|
|
@@ -720,17 +728,17 @@ export default class VoxelManager {
|
|
|
720
728
|
};
|
|
721
729
|
return voxels;
|
|
722
730
|
}
|
|
723
|
-
static createMapVoxelManager({ dimension, }) {
|
|
731
|
+
static createMapVoxelManager({ dimension, id, }) {
|
|
724
732
|
const map = new Map();
|
|
725
733
|
const voxelManager = new VoxelManager(dimension, {
|
|
726
734
|
_get: map.get.bind(map),
|
|
727
735
|
_set: (index, v) => map.set(index, v) && true,
|
|
728
|
-
_id: 'createMapVoxelManager',
|
|
736
|
+
_id: id || 'createMapVoxelManager',
|
|
729
737
|
});
|
|
730
738
|
voxelManager.map = map;
|
|
731
739
|
return voxelManager;
|
|
732
740
|
}
|
|
733
|
-
static createHistoryVoxelManager(
|
|
741
|
+
static createHistoryVoxelManager(sourceVoxelManager, id) {
|
|
734
742
|
const map = new Map();
|
|
735
743
|
const { dimensions } = sourceVoxelManager;
|
|
736
744
|
const voxelManager = new VoxelManager(dimensions, {
|
|
@@ -748,14 +756,14 @@ export default class VoxelManager {
|
|
|
748
756
|
}
|
|
749
757
|
this.sourceVoxelManager.setAtIndex(index, v);
|
|
750
758
|
},
|
|
751
|
-
_id: 'createHistoryVoxelManager',
|
|
759
|
+
_id: id || 'createHistoryVoxelManager',
|
|
752
760
|
});
|
|
753
761
|
voxelManager.map = map;
|
|
754
762
|
voxelManager.scalarData = sourceVoxelManager.scalarData;
|
|
755
763
|
voxelManager.sourceVoxelManager = sourceVoxelManager;
|
|
756
764
|
return voxelManager;
|
|
757
765
|
}
|
|
758
|
-
static createRLEHistoryVoxelManager(sourceVoxelManager) {
|
|
766
|
+
static createRLEHistoryVoxelManager(sourceVoxelManager, id) {
|
|
759
767
|
const { dimensions } = sourceVoxelManager;
|
|
760
768
|
const map = new RLEVoxelMap(dimensions[0], dimensions[1], dimensions[2]);
|
|
761
769
|
const voxelManager = new VoxelManager(dimensions, {
|
|
@@ -780,13 +788,13 @@ export default class VoxelManager {
|
|
|
780
788
|
map.updateScalarData(scalarData);
|
|
781
789
|
return scalarData;
|
|
782
790
|
},
|
|
783
|
-
_id: 'createRLEHistoryVoxelManager',
|
|
791
|
+
_id: id || 'createRLEHistoryVoxelManager',
|
|
784
792
|
});
|
|
785
793
|
voxelManager.map = map;
|
|
786
794
|
voxelManager.sourceVoxelManager = sourceVoxelManager;
|
|
787
795
|
return voxelManager;
|
|
788
796
|
}
|
|
789
|
-
static createLazyVoxelManager({ dimensions, planeFactory, }) {
|
|
797
|
+
static createLazyVoxelManager({ dimensions, planeFactory, id, }) {
|
|
790
798
|
const map = new Map();
|
|
791
799
|
const [width, height] = dimensions;
|
|
792
800
|
const planeSize = width * height;
|
|
@@ -802,12 +810,12 @@ export default class VoxelManager {
|
|
|
802
810
|
layer[index % planeSize] = v;
|
|
803
811
|
return true;
|
|
804
812
|
},
|
|
805
|
-
_id: 'createLazyVoxelManager',
|
|
813
|
+
_id: id || 'createLazyVoxelManager',
|
|
806
814
|
});
|
|
807
815
|
voxelManager.map = map;
|
|
808
816
|
return voxelManager;
|
|
809
817
|
}
|
|
810
|
-
static createRLEVolumeVoxelManager({ dimensions, }) {
|
|
818
|
+
static createRLEVolumeVoxelManager({ dimensions, id, }) {
|
|
811
819
|
const [width, height, depth] = dimensions;
|
|
812
820
|
const map = new RLEVoxelMap(width, height, depth);
|
|
813
821
|
const voxelManager = new VoxelManager(dimensions, {
|
|
@@ -821,16 +829,17 @@ export default class VoxelManager {
|
|
|
821
829
|
map.updateScalarData(scalarData);
|
|
822
830
|
return scalarData;
|
|
823
831
|
},
|
|
824
|
-
_id: 'createRLEVolumeVoxelManager',
|
|
832
|
+
_id: id || 'createRLEVolumeVoxelManager',
|
|
825
833
|
});
|
|
826
834
|
voxelManager.map = map;
|
|
827
835
|
voxelManager.getPixelData = map.getPixelData.bind(map);
|
|
828
836
|
return voxelManager;
|
|
829
837
|
}
|
|
830
|
-
static createRLEImageVoxelManager({ dimensions, }) {
|
|
838
|
+
static createRLEImageVoxelManager({ dimensions, id, }) {
|
|
831
839
|
const [width, height] = dimensions;
|
|
832
840
|
return VoxelManager.createRLEVolumeVoxelManager({
|
|
833
841
|
dimensions: [width, height, 1],
|
|
842
|
+
id,
|
|
834
843
|
});
|
|
835
844
|
}
|
|
836
845
|
static addInstanceToImage(image) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export type Memo = {
|
|
2
2
|
restoreMemo: (undo?: boolean) => void;
|
|
3
3
|
commitMemo?: () => boolean;
|
|
4
|
+
id?: string;
|
|
5
|
+
operationType?: string;
|
|
4
6
|
};
|
|
5
7
|
export type Memoable = {
|
|
6
8
|
createMemo: () => Memo;
|
|
@@ -16,6 +18,7 @@ export declare class HistoryMemo {
|
|
|
16
18
|
get size(): number;
|
|
17
19
|
set size(newSize: number);
|
|
18
20
|
undo(items?: number): void;
|
|
21
|
+
undoIf(condition: (item: Memo) => boolean): boolean;
|
|
19
22
|
redo(items?: number): void;
|
|
20
23
|
push(item: Memo | Memoable): Memo;
|
|
21
24
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import eventTarget from '../../eventTarget';
|
|
2
|
+
const Events = {
|
|
3
|
+
HISTORY_UNDO: 'CORNERSTONE_TOOLS_HISTORY_UNDO',
|
|
4
|
+
HISTORY_REDO: 'CORNERSTONE_TOOLS_HISTORY_REDO',
|
|
5
|
+
};
|
|
1
6
|
export class HistoryMemo {
|
|
2
7
|
constructor(label = 'Tools', size = 50) {
|
|
3
8
|
this.position = -1;
|
|
@@ -21,17 +26,44 @@ export class HistoryMemo {
|
|
|
21
26
|
while (items > 0 && this.undoAvailable > 0) {
|
|
22
27
|
const item = this.ring[this.position];
|
|
23
28
|
item.restoreMemo(true);
|
|
29
|
+
if (item.id) {
|
|
30
|
+
eventTarget.dispatchEvent(new CustomEvent(Events.HISTORY_UNDO, {
|
|
31
|
+
detail: {
|
|
32
|
+
isUndo: true,
|
|
33
|
+
id: item.id,
|
|
34
|
+
operationType: item.operationType || 'annotation',
|
|
35
|
+
memo: item,
|
|
36
|
+
},
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
24
39
|
items--;
|
|
25
40
|
this.redoAvailable++;
|
|
26
41
|
this.undoAvailable--;
|
|
27
42
|
this.position = (this.position - 1 + this.size) % this.size;
|
|
28
43
|
}
|
|
29
44
|
}
|
|
45
|
+
undoIf(condition) {
|
|
46
|
+
if (this.undoAvailable > 0 && condition(this.ring[this.position])) {
|
|
47
|
+
this.undo();
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
30
52
|
redo(items = 1) {
|
|
31
53
|
while (items > 0 && this.redoAvailable > 0) {
|
|
32
54
|
const newPosition = (this.position + 1) % this.size;
|
|
33
55
|
const item = this.ring[newPosition];
|
|
34
56
|
item.restoreMemo(false);
|
|
57
|
+
if (item.id) {
|
|
58
|
+
eventTarget.dispatchEvent(new CustomEvent(Events.HISTORY_REDO, {
|
|
59
|
+
detail: {
|
|
60
|
+
isUndo: false,
|
|
61
|
+
id: item.id,
|
|
62
|
+
operationType: item.operationType || 'annotation',
|
|
63
|
+
memo: item,
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
35
67
|
items--;
|
|
36
68
|
this.position = newPosition;
|
|
37
69
|
this.undoAvailable++;
|
|
@@ -8,12 +8,14 @@ export interface FullImageLoadOptions {
|
|
|
8
8
|
viewPresentation: ViewPresentation;
|
|
9
9
|
imageId: undefined;
|
|
10
10
|
}
|
|
11
|
-
export
|
|
11
|
+
export type CanvasLoadPosition = {
|
|
12
12
|
origin: Point3;
|
|
13
13
|
topRight: Point3;
|
|
14
14
|
bottomLeft: Point3;
|
|
15
15
|
thicknessMm: number;
|
|
16
|
-
|
|
16
|
+
rightVector: Point3;
|
|
17
|
+
downVector: Point3;
|
|
18
|
+
};
|
|
17
19
|
export type LoadImageOptions = {
|
|
18
20
|
canvas: HTMLCanvasElement;
|
|
19
21
|
imageId?: string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { vec3 } from 'gl-matrix';
|
|
1
2
|
import getOrCreateCanvas, { EPSILON, } from '../RenderingEngine/helpers/getOrCreateCanvas';
|
|
2
3
|
import { ViewportType, Events } from '../enums';
|
|
3
4
|
import { getRenderingEngine } from '../RenderingEngine/getRenderingEngine';
|
|
@@ -70,6 +71,8 @@ export default function renderToCanvasGPU(canvas, imageOrVolume, modality = unde
|
|
|
70
71
|
0,
|
|
71
72
|
temporaryCanvas.height / devicePixelRatio,
|
|
72
73
|
]);
|
|
74
|
+
const rightVector = vec3.sub([0, 0, 0], viewport.canvasToWorld([1 / devicePixelRatio, 0]), origin);
|
|
75
|
+
const downVector = vec3.sub([0, 0, 0], viewport.canvasToWorld([0, 1 / devicePixelRatio]), origin);
|
|
73
76
|
const thicknessMm = 1;
|
|
74
77
|
elementRendered = true;
|
|
75
78
|
element.removeEventListener(Events.IMAGE_RENDERED, onImageRendered);
|
|
@@ -85,6 +88,8 @@ export default function renderToCanvasGPU(canvas, imageOrVolume, modality = unde
|
|
|
85
88
|
bottomLeft,
|
|
86
89
|
topRight,
|
|
87
90
|
thicknessMm,
|
|
91
|
+
rightVector,
|
|
92
|
+
downVector,
|
|
88
93
|
});
|
|
89
94
|
};
|
|
90
95
|
element.addEventListener(Events.IMAGE_RENDERED, onImageRendered);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cornerstonejs/core",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "Cornerstone3D Core",
|
|
5
5
|
"module": "./dist/esm/index.js",
|
|
6
6
|
"types": "./dist/esm/index.d.ts",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"type": "individual",
|
|
92
92
|
"url": "https://ohif.org/donate"
|
|
93
93
|
},
|
|
94
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "bc351a2bae5a5b2f93691a384222b71b26d5c263"
|
|
95
95
|
}
|