@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.
@@ -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;
@@ -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
  }
@@ -17,6 +17,7 @@ interface LocalImageOptions {
17
17
  spacing?: Point2;
18
18
  origin?: Point3;
19
19
  direction?: Mat3;
20
+ referencedImageId?: string;
20
21
  skipCreateBuffer?: boolean;
21
22
  onCacheAdd?: (image: IImage) => void;
22
23
  }
@@ -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);
@@ -200,6 +200,7 @@ export function createLocalVolume(volumeId, options = {}) {
200
200
  imageIds,
201
201
  dimensions,
202
202
  numberOfComponents: 1,
203
+ id: volumeId,
203
204
  });
204
205
  imageVolume.voxelManager = voxelManager;
205
206
  if (!preventCache) {
@@ -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>({ sourceVoxelManager, }: {
116
- sourceVoxelManager: VoxelManager<T>;
117
- }): VoxelManager<T>;
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({ sourceVoxelManager, }) {
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 interface CanvasLoadPosition {
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.7.17",
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": "9a5dc66176f5172fd3bb11ebcf37f9b8667ab3c4"
94
+ "gitHead": "bc351a2bae5a5b2f93691a384222b71b26d5c263"
95
95
  }