@cornerstonejs/tools 3.5.3 → 3.6.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.
Files changed (36) hide show
  1. package/dist/esm/config.d.ts +7 -0
  2. package/dist/esm/enums/WorkerTypes.d.ts +2 -1
  3. package/dist/esm/enums/WorkerTypes.js +1 -0
  4. package/dist/esm/index.d.ts +2 -2
  5. package/dist/esm/index.js +2 -2
  6. package/dist/esm/tools/annotation/BidirectionalTool.d.ts +3 -0
  7. package/dist/esm/tools/annotation/BidirectionalTool.js +39 -1
  8. package/dist/esm/tools/index.d.ts +2 -1
  9. package/dist/esm/tools/index.js +2 -1
  10. package/dist/esm/tools/segmentation/SegmentBidirectionalTool.d.ts +27 -0
  11. package/dist/esm/tools/segmentation/SegmentBidirectionalTool.js +253 -0
  12. package/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js +5 -10
  13. package/dist/esm/types/CalculatorTypes.d.ts +15 -3
  14. package/dist/esm/types/ToolSpecificAnnotationTypes.d.ts +34 -0
  15. package/dist/esm/utilities/contours/generateContourSetsFromLabelmap.js +1 -0
  16. package/dist/esm/utilities/math/basic/BasicStatsCalculator.js +68 -5
  17. package/dist/esm/utilities/registerComputeWorker.js +4 -1
  18. package/dist/esm/utilities/segmentation/VolumetricCalculator.js +1 -0
  19. package/dist/esm/utilities/segmentation/contourAndFindLargestBidirectional.js +7 -5
  20. package/dist/esm/utilities/segmentation/findLargestBidirectional.d.ts +5 -0
  21. package/dist/esm/utilities/segmentation/findLargestBidirectional.js +1 -1
  22. package/dist/esm/utilities/segmentation/getOrCreateSegmentationVolume.js +5 -1
  23. package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentationVolume.d.ts +1 -0
  24. package/dist/esm/utilities/segmentation/getReferenceVolumeForSegmentationVolume.js +20 -0
  25. package/dist/esm/utilities/segmentation/getSegmentLargestBidirectional.d.ts +5 -0
  26. package/dist/esm/utilities/segmentation/getSegmentLargestBidirectional.js +54 -0
  27. package/dist/esm/utilities/segmentation/getStatistics.js +42 -107
  28. package/dist/esm/utilities/segmentation/index.d.ts +3 -1
  29. package/dist/esm/utilities/segmentation/index.js +3 -1
  30. package/dist/esm/utilities/segmentation/isLineInSegment.d.ts +13 -1
  31. package/dist/esm/utilities/segmentation/isLineInSegment.js +20 -12
  32. package/dist/esm/utilities/segmentation/segmentContourAction.js +1 -0
  33. package/dist/esm/utilities/segmentation/utilsForWorker.d.ts +38 -0
  34. package/dist/esm/utilities/segmentation/utilsForWorker.js +125 -0
  35. package/dist/esm/workers/computeWorker.js +284 -40
  36. package/package.json +3 -3
@@ -0,0 +1,38 @@
1
+ export declare const triggerWorkerProgress: (workerType: any, progress: any) => void;
2
+ export declare const getSegmentationDataForWorker: (segmentationId: any, segmentIndices: any) => {
3
+ operationData: {
4
+ segmentationId: any;
5
+ volumeId: string;
6
+ imageIds: string[];
7
+ };
8
+ segVolumeId: string;
9
+ segImageIds: string[];
10
+ reconstructableVolume: boolean;
11
+ indices: any;
12
+ };
13
+ export declare const prepareVolumeStrategyDataForWorker: (operationData: any) => {
14
+ segmentationImageData: any;
15
+ segmentationScalarData: any;
16
+ imageScalarData: any;
17
+ segmentationVoxelManager: any;
18
+ imageVoxelManager: any;
19
+ imageData: any;
20
+ };
21
+ export declare const prepareImageInfo: (imageVoxelManager: any, imageData: any) => {
22
+ scalarData: any;
23
+ dimensions: any;
24
+ spacing: any;
25
+ origin: any;
26
+ direction: any;
27
+ };
28
+ export declare const prepareStackDataForWorker: (segImageIds: any) => {
29
+ segmentationInfo: any[];
30
+ imageInfo: any[];
31
+ };
32
+ export declare const getImageReferenceInfo: (segVolumeId: any, segImageIds: any) => {
33
+ refImageId: any;
34
+ modalityUnitOptions: {
35
+ isPreScaled: boolean;
36
+ isSuvScaled: boolean;
37
+ };
38
+ };
@@ -0,0 +1,125 @@
1
+ import { cache, utilities, eventTarget, Enums, triggerEvent, metaData, } from '@cornerstonejs/core';
2
+ import { getActiveSegmentIndex } from '../../stateManagement/segmentation/getActiveSegmentIndex';
3
+ import { getSegmentation } from '../../stateManagement/segmentation/getSegmentation';
4
+ import { getStrategyData } from '../../tools/segmentation/strategies/utils/getStrategyData';
5
+ import ensureSegmentationVolume from '../../tools/segmentation/strategies/compositions/ensureSegmentationVolume';
6
+ import ensureImageVolume from '../../tools/segmentation/strategies/compositions/ensureImageVolume';
7
+ export const triggerWorkerProgress = (workerType, progress) => {
8
+ triggerEvent(eventTarget, Enums.Events.WEB_WORKER_PROGRESS, {
9
+ progress,
10
+ type: workerType,
11
+ });
12
+ };
13
+ export const getSegmentationDataForWorker = (segmentationId, segmentIndices) => {
14
+ const segmentation = getSegmentation(segmentationId);
15
+ const { representationData } = segmentation;
16
+ const { Labelmap } = representationData;
17
+ if (!Labelmap) {
18
+ console.debug('No labelmap found for segmentation', segmentationId);
19
+ return null;
20
+ }
21
+ const segVolumeId = Labelmap.volumeId;
22
+ const segImageIds = Labelmap.imageIds;
23
+ const operationData = {
24
+ segmentationId,
25
+ volumeId: segVolumeId,
26
+ imageIds: segImageIds,
27
+ };
28
+ let reconstructableVolume = false;
29
+ if (segImageIds) {
30
+ const refImageIds = segImageIds.map((imageId) => {
31
+ const image = cache.getImage(imageId);
32
+ return image.referencedImageId;
33
+ });
34
+ reconstructableVolume = utilities.isValidVolume(refImageIds);
35
+ }
36
+ let indices = segmentIndices;
37
+ if (!indices) {
38
+ indices = [getActiveSegmentIndex(segmentationId)];
39
+ }
40
+ else if (!Array.isArray(indices)) {
41
+ indices = [indices, 255];
42
+ }
43
+ return {
44
+ operationData,
45
+ segVolumeId,
46
+ segImageIds,
47
+ reconstructableVolume,
48
+ indices,
49
+ };
50
+ };
51
+ export const prepareVolumeStrategyDataForWorker = (operationData) => {
52
+ return getStrategyData({
53
+ operationData,
54
+ strategy: {
55
+ ensureSegmentationVolumeFor3DManipulation: ensureSegmentationVolume.ensureSegmentationVolumeFor3DManipulation,
56
+ ensureImageVolumeFor3DManipulation: ensureImageVolume.ensureImageVolumeFor3DManipulation,
57
+ },
58
+ });
59
+ };
60
+ export const prepareImageInfo = (imageVoxelManager, imageData) => {
61
+ const imageScalarData = imageVoxelManager.getCompleteScalarDataArray();
62
+ return {
63
+ scalarData: imageScalarData,
64
+ dimensions: imageData.getDimensions(),
65
+ spacing: imageData.getSpacing(),
66
+ origin: imageData.getOrigin(),
67
+ direction: imageData.getDirection(),
68
+ };
69
+ };
70
+ export const prepareStackDataForWorker = (segImageIds) => {
71
+ const segmentationInfo = [];
72
+ const imageInfo = [];
73
+ for (const segImageId of segImageIds) {
74
+ const segImage = cache.getImage(segImageId);
75
+ const segPixelData = segImage.getPixelData();
76
+ const { origin, direction, spacing, dimensions } = utilities.getImageDataMetadata(segImage);
77
+ segmentationInfo.push({
78
+ scalarData: segPixelData,
79
+ dimensions,
80
+ spacing,
81
+ origin,
82
+ direction,
83
+ });
84
+ const refImageId = segImage.referencedImageId;
85
+ if (refImageId) {
86
+ const refImage = cache.getImage(refImageId);
87
+ const refPixelData = refImage.getPixelData();
88
+ const refVoxelManager = refImage.voxelManager;
89
+ const refSpacing = [
90
+ refImage.rowPixelSpacing,
91
+ refImage.columnPixelSpacing,
92
+ ];
93
+ imageInfo.push({
94
+ scalarData: refPixelData,
95
+ dimensions: refVoxelManager
96
+ ? refVoxelManager.dimensions
97
+ : [refImage.columns, refImage.rows, 1],
98
+ spacing: refSpacing,
99
+ });
100
+ }
101
+ }
102
+ return { segmentationInfo, imageInfo };
103
+ };
104
+ export const getImageReferenceInfo = (segVolumeId, segImageIds) => {
105
+ let refImageId;
106
+ if (segVolumeId) {
107
+ const segmentationVolume = cache.getVolume(segVolumeId);
108
+ const imageIds = segmentationVolume.imageIds;
109
+ const cachedImage = cache.getImage(imageIds[0]);
110
+ if (cachedImage) {
111
+ refImageId = cachedImage.referencedImageId;
112
+ }
113
+ }
114
+ else if (segImageIds?.length) {
115
+ const segImage = cache.getImage(segImageIds[0]);
116
+ refImageId = segImage.referencedImageId;
117
+ }
118
+ const refImage = cache.getImage(refImageId);
119
+ const scalingModule = metaData.get('scalingModule', refImageId);
120
+ const modalityUnitOptions = {
121
+ isPreScaled: Boolean(refImage.preScale?.scaled),
122
+ isSuvScaled: typeof scalingModule?.suvbw === 'number',
123
+ };
124
+ return { refImageId, modalityUnitOptions };
125
+ };
@@ -1,27 +1,44 @@
1
1
  import { expose } from 'comlink';
2
2
  import { utilities } from '@cornerstonejs/core';
3
3
  import SegmentStatsCalculator from '../utilities/segmentation/SegmentStatsCalculator';
4
+ import { getSegmentLargestBidirectional } from '../utilities/segmentation';
5
+ import vtkImageMarchingSquares from '@kitware/vtk.js/Filters/General/ImageMarchingSquares';
6
+ import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
7
+ import vtkImageData from '@kitware/vtk.js/Common/DataModel/ImageData';
8
+ import { getDeduplicatedVTKPolyDataPoints } from '../utilities/contours/getDeduplicatedVTKPolyDataPoints';
9
+ import { findContoursFromReducedSet } from '../utilities/contours/contourFinder';
10
+ import { createBidirectionalForSlice } from '../utilities/segmentation/findLargestBidirectional';
11
+ import { createIsInSegmentMetadata } from '../utilities/segmentation/isLineInSegment';
4
12
  const { VoxelManager } = utilities;
5
13
  const computeWorker = {
6
- calculateSegmentsStatisticsVolume: (args) => {
7
- const { segmentationInfo, imageInfo, indices, mode } = args;
8
- const { scalarData: segmentationScalarData, dimensions: segmentationDimensions, spacing: segmentationSpacing, } = segmentationInfo;
9
- const { scalarData: imageScalarData, dimensions: imageDimensions } = imageInfo;
10
- if (segmentationDimensions[0] !== imageDimensions[0] ||
11
- segmentationDimensions[1] !== imageDimensions[1] ||
12
- segmentationDimensions[2] !== imageDimensions[2]) {
13
- throw new Error('Dimensions do not match to calculate statistics, different dimensions not supported yet');
14
- }
15
- const segVoxelManager = VoxelManager.createScalarVolumeVoxelManager({
16
- dimensions: segmentationDimensions,
17
- scalarData: segmentationScalarData,
18
- });
19
- const imageVoxelManager = VoxelManager.createScalarVolumeVoxelManager({
20
- dimensions: imageDimensions,
21
- scalarData: imageScalarData,
14
+ createVoxelManager: (dimensions, scalarData) => {
15
+ return VoxelManager.createScalarVolumeVoxelManager({
16
+ dimensions,
17
+ scalarData,
22
18
  });
23
- SegmentStatsCalculator.statsInit({ storePointData: false, indices, mode });
24
- segVoxelManager.forEach(({ value, pointIJK, index }) => {
19
+ },
20
+ createDataStructure: (info) => {
21
+ const { scalarData, dimensions, spacing, origin, direction } = info;
22
+ const voxelManager = computeWorker.createVoxelManager(dimensions, scalarData);
23
+ return {
24
+ voxelManager,
25
+ dimensions,
26
+ spacing,
27
+ origin,
28
+ direction,
29
+ scalarData,
30
+ };
31
+ },
32
+ createVTKImageData: (dimensions, origin, direction, spacing) => {
33
+ const imageData = vtkImageData.newInstance();
34
+ imageData.setDimensions(dimensions);
35
+ imageData.setOrigin(origin);
36
+ imageData.setDirection(direction);
37
+ imageData.setSpacing(spacing);
38
+ return imageData;
39
+ },
40
+ processSegmentStatistics: (segVoxelManager, imageVoxelManager, indices, bounds) => {
41
+ segVoxelManager.forEach(({ value, pointIJK, pointLPS, index }) => {
25
42
  if (indices.indexOf(value) === -1) {
26
43
  return;
27
44
  }
@@ -30,10 +47,60 @@ const computeWorker = {
30
47
  segmentIndex: value,
31
48
  value: imageValue,
32
49
  pointIJK,
50
+ pointLPS,
33
51
  });
34
52
  }, {
35
- boundsIJK: imageVoxelManager.getDefaultBounds(),
53
+ boundsIJK: bounds || imageVoxelManager.getDefaultBounds(),
36
54
  });
55
+ },
56
+ performMarchingSquares: (imageData, sliceIndex = null, slicingMode = null) => {
57
+ const options = {};
58
+ if (sliceIndex !== null) {
59
+ options.slice = sliceIndex;
60
+ }
61
+ if (slicingMode !== null) {
62
+ options.slicingMode = slicingMode;
63
+ }
64
+ const mSquares = vtkImageMarchingSquares.newInstance(options);
65
+ mSquares.setInputData(imageData);
66
+ mSquares.setContourValues([1]);
67
+ mSquares.setMergePoints(false);
68
+ return mSquares.getOutputData();
69
+ },
70
+ createContoursFromPolyData: (msOutput, sliceIndex = null) => {
71
+ const reducedSet = getDeduplicatedVTKPolyDataPoints(msOutput);
72
+ if (reducedSet.points?.length) {
73
+ const contours = findContoursFromReducedSet(reducedSet.lines);
74
+ return {
75
+ contours,
76
+ polyData: reducedSet,
77
+ };
78
+ }
79
+ return null;
80
+ },
81
+ createSegmentsFromIndices: (indices) => {
82
+ return [null, ...indices.map((index) => ({ segmentIndex: index }))];
83
+ },
84
+ getArgsFromInfo: (args) => {
85
+ const { segmentationInfo, imageInfo } = args;
86
+ const getSegmentationData = () => {
87
+ return computeWorker.createDataStructure(segmentationInfo);
88
+ };
89
+ const getImageData = () => {
90
+ return computeWorker.createDataStructure(imageInfo);
91
+ };
92
+ return {
93
+ segmentation: segmentationInfo && getSegmentationData(),
94
+ image: imageInfo && getImageData(),
95
+ };
96
+ },
97
+ calculateSegmentsStatisticsVolume: (args) => {
98
+ const { mode, indices } = args;
99
+ const { segmentation, image } = computeWorker.getArgsFromInfo(args);
100
+ const { voxelManager: segVoxelManager, spacing: segmentationSpacing } = segmentation;
101
+ const { voxelManager: imageVoxelManager } = image;
102
+ SegmentStatsCalculator.statsInit({ storePointData: false, indices, mode });
103
+ computeWorker.processSegmentStatistics(segVoxelManager, imageVoxelManager, indices);
37
104
  const stats = SegmentStatsCalculator.getStatistics({
38
105
  spacing: segmentationSpacing,
39
106
  unit: 'mm',
@@ -52,27 +119,9 @@ const computeWorker = {
52
119
  segInfo.dimensions[1],
53
120
  1,
54
121
  ];
55
- const segVoxelManager = VoxelManager.createScalarVolumeVoxelManager({
56
- dimensions: segDimensions,
57
- scalarData: segInfo.scalarData,
58
- });
59
- const imageVoxelManager = VoxelManager.createScalarVolumeVoxelManager({
60
- dimensions: segDimensions,
61
- scalarData: imgInfo.scalarData,
62
- });
63
- segVoxelManager.forEach(({ value, pointIJK, index }) => {
64
- if (indices.indexOf(value) === -1) {
65
- return;
66
- }
67
- const imageValue = imageVoxelManager.getAtIndex(index);
68
- SegmentStatsCalculator.statsCallback({
69
- segmentIndex: value,
70
- value: imageValue,
71
- pointIJK,
72
- });
73
- }, {
74
- boundsIJK: imageVoxelManager.getDefaultBounds(),
75
- });
122
+ const segVoxelManager = computeWorker.createVoxelManager(segDimensions, segInfo.scalarData);
123
+ const imageVoxelManager = computeWorker.createVoxelManager(segDimensions, imgInfo.scalarData);
124
+ computeWorker.processSegmentStatistics(segVoxelManager, imageVoxelManager, indices);
76
125
  }
77
126
  const spacing = segmentationInfo[0].spacing;
78
127
  const stats = SegmentStatsCalculator.getStatistics({
@@ -81,5 +130,200 @@ const computeWorker = {
81
130
  });
82
131
  return stats;
83
132
  },
133
+ getSegmentLargestBidirectionalInternal: (args) => {
134
+ const { segmentationInfo, imageInfo, indices, mode, isStack } = args;
135
+ let segmentation;
136
+ if (!isStack) {
137
+ ({ segmentation } = computeWorker.getArgsFromInfo(args));
138
+ }
139
+ else {
140
+ ({ segmentation } = computeWorker.getArgsFromInfo({
141
+ segmentationInfo: segmentationInfo[0],
142
+ }));
143
+ }
144
+ const { voxelManager, dimensions, origin, direction, spacing } = segmentation;
145
+ const stackDimensions = isStack
146
+ ? [dimensions[0], dimensions[1], 2]
147
+ : dimensions;
148
+ const stackSpacing = isStack ? [spacing[0], spacing[1], 1] : spacing;
149
+ const imageData = computeWorker.createVTKImageData(stackDimensions, origin, direction, stackSpacing);
150
+ let contourSets;
151
+ if (!isStack) {
152
+ contourSets = computeWorker.generateContourSetsFromLabelmapVolume({
153
+ segmentation,
154
+ indices,
155
+ imageData,
156
+ mode,
157
+ });
158
+ }
159
+ else {
160
+ contourSets = computeWorker.generateContourSetsFromLabelmapStack({
161
+ segmentationInfo,
162
+ indices,
163
+ mode,
164
+ });
165
+ }
166
+ const bidirectionalData = [];
167
+ for (let i = 0; i < contourSets.length; i++) {
168
+ const contourSet = contourSets[i];
169
+ const { segmentIndex } = contourSet.segment;
170
+ const contours = contourSet.sliceContours;
171
+ let maxBidirectional;
172
+ const isInSegment = createIsInSegmentMetadata({
173
+ dimensions,
174
+ imageData,
175
+ voxelManager,
176
+ segmentIndex,
177
+ });
178
+ for (const sliceContour of contours) {
179
+ const bidirectional = createBidirectionalForSlice(sliceContour, isInSegment, maxBidirectional);
180
+ if (!bidirectional) {
181
+ continue;
182
+ }
183
+ maxBidirectional = bidirectional;
184
+ }
185
+ if (maxBidirectional) {
186
+ bidirectionalData.push({
187
+ segmentIndex,
188
+ majorAxis: maxBidirectional.majorAxis,
189
+ minorAxis: maxBidirectional.minorAxis,
190
+ maxMajor: maxBidirectional.maxMajor,
191
+ maxMinor: maxBidirectional.maxMinor,
192
+ });
193
+ }
194
+ }
195
+ return bidirectionalData;
196
+ },
197
+ generateContourSetsFromLabelmapVolume: (args) => {
198
+ const { segmentation, indices, imageData } = args;
199
+ const { voxelManager, dimensions, scalarData, origin, direction, spacing } = segmentation;
200
+ const numSlices = dimensions[2];
201
+ const pixelsPerSlice = dimensions[0] * dimensions[1];
202
+ const segments = computeWorker.createSegmentsFromIndices(indices);
203
+ for (let z = 0; z < numSlices; z++) {
204
+ for (let y = 0; y < dimensions[1]; y++) {
205
+ const index = y * dimensions[0] + z * pixelsPerSlice;
206
+ scalarData[index] = 0;
207
+ scalarData[index + dimensions[0] - 1] = 0;
208
+ }
209
+ }
210
+ const ContourSets = [];
211
+ const numSegments = segments.length;
212
+ for (let segIndex = 0; segIndex < numSegments; segIndex++) {
213
+ const segment = segments[segIndex];
214
+ if (!segment) {
215
+ continue;
216
+ }
217
+ const segmentIndex = segment.segmentIndex;
218
+ const sliceContours = [];
219
+ const scalars = vtkDataArray.newInstance({
220
+ name: 'Scalars',
221
+ numberOfComponents: 1,
222
+ size: pixelsPerSlice * numSlices,
223
+ dataType: 'Uint8Array',
224
+ });
225
+ for (let sliceIndex = 0; sliceIndex < numSlices; sliceIndex++) {
226
+ if (computeWorker.isSliceEmptyForSegmentVolume(sliceIndex, scalarData, pixelsPerSlice, segmentIndex)) {
227
+ continue;
228
+ }
229
+ const frameStart = sliceIndex * pixelsPerSlice;
230
+ try {
231
+ for (let i = 0; i < pixelsPerSlice; i++) {
232
+ const value = scalarData[i + frameStart];
233
+ if (value === segmentIndex) {
234
+ scalars.setValue(i + frameStart, 1);
235
+ }
236
+ else {
237
+ scalars.setValue(i, 0);
238
+ }
239
+ }
240
+ const imageDataCopy = vtkImageData.newInstance();
241
+ imageDataCopy.shallowCopy(imageData);
242
+ imageDataCopy.getPointData().setScalars(scalars);
243
+ const msOutput = computeWorker.performMarchingSquares(imageDataCopy, sliceIndex);
244
+ const contourData = computeWorker.createContoursFromPolyData(msOutput, sliceIndex);
245
+ if (contourData) {
246
+ sliceContours.push(contourData);
247
+ }
248
+ }
249
+ catch (e) {
250
+ console.warn(sliceIndex);
251
+ console.warn(e);
252
+ }
253
+ }
254
+ const ContourSet = {
255
+ sliceContours,
256
+ segment,
257
+ };
258
+ ContourSets.push(ContourSet);
259
+ }
260
+ return ContourSets;
261
+ },
262
+ generateContourSetsFromLabelmapStack: (args) => {
263
+ const { segmentationInfo, indices } = args;
264
+ let ContourSets = [];
265
+ for (let i = 0; i < segmentationInfo.length; i++) {
266
+ const segInfo = segmentationInfo[i];
267
+ const dimensions = segInfo.dimensions;
268
+ const segScalarData = segInfo.scalarData;
269
+ const { spacing, direction, origin } = segInfo;
270
+ const segments = computeWorker.createSegmentsFromIndices(indices);
271
+ const pixelsPerSlice = dimensions[0] * dimensions[1];
272
+ const numSegments = segments.length;
273
+ for (let segIndex = 0; segIndex < numSegments; segIndex++) {
274
+ const segment = segments[segIndex];
275
+ if (!segment) {
276
+ continue;
277
+ }
278
+ const segmentIndex = segment.segmentIndex;
279
+ if (computeWorker.isSliceEmptyForSegmentVolume(0, segScalarData, pixelsPerSlice, segmentIndex)) {
280
+ continue;
281
+ }
282
+ const sliceContours = [];
283
+ const filteredData = new Uint8Array(segScalarData.length);
284
+ for (let i = 0; i < segScalarData.length; i++) {
285
+ if (segScalarData[i] === segmentIndex) {
286
+ filteredData[i] = 1;
287
+ }
288
+ else {
289
+ filteredData[i] = 0;
290
+ }
291
+ }
292
+ const scalarArray = vtkDataArray.newInstance({
293
+ name: 'Pixels',
294
+ numberOfComponents: 1,
295
+ values: filteredData,
296
+ });
297
+ const imageData = computeWorker.createVTKImageData(dimensions, origin, direction, [spacing[0], spacing[1], 1]);
298
+ imageData.getPointData().setScalars(scalarArray);
299
+ try {
300
+ const msOutput = computeWorker.performMarchingSquares(imageData, null, 2);
301
+ const contourData = computeWorker.createContoursFromPolyData(msOutput);
302
+ if (contourData) {
303
+ sliceContours.push(contourData);
304
+ }
305
+ }
306
+ catch (e) {
307
+ console.warn(e);
308
+ }
309
+ const ContourSet = {
310
+ sliceContours,
311
+ segment,
312
+ };
313
+ ContourSets.push(ContourSet);
314
+ }
315
+ }
316
+ return ContourSets;
317
+ },
318
+ isSliceEmptyForSegmentVolume: (sliceIndex, segData, pixelsPerSlice, segIndex) => {
319
+ const startIdx = sliceIndex * pixelsPerSlice;
320
+ const endIdx = startIdx + pixelsPerSlice;
321
+ for (let i = startIdx; i < endIdx; i++) {
322
+ if (segData[i] === segIndex) {
323
+ return false;
324
+ }
325
+ }
326
+ return true;
327
+ },
84
328
  };
85
329
  expose(computeWorker);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/tools",
3
- "version": "3.5.3",
3
+ "version": "3.6.0",
4
4
  "description": "Cornerstone3D Tools",
5
5
  "types": "./dist/esm/index.d.ts",
6
6
  "module": "./dist/esm/index.js",
@@ -103,7 +103,7 @@
103
103
  "canvas": "^2.11.2"
104
104
  },
105
105
  "peerDependencies": {
106
- "@cornerstonejs/core": "^3.5.3",
106
+ "@cornerstonejs/core": "^3.6.0",
107
107
  "@kitware/vtk.js": "32.12.0",
108
108
  "@types/d3-array": "^3.0.4",
109
109
  "@types/d3-interpolate": "^3.0.1",
@@ -122,5 +122,5 @@
122
122
  "type": "individual",
123
123
  "url": "https://ohif.org/donate"
124
124
  },
125
- "gitHead": "42ffdeabf1ed0bd2871db808bf198d5e3f4f4c94"
125
+ "gitHead": "480e48c2a25ce79a4a90be6fe180d1bcdd1b831e"
126
126
  }