@cornerstonejs/adapters 3.31.0 → 3.31.2

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 (41) hide show
  1. package/dist/esm/adapters/Cornerstone/Bidirectional.js +1 -0
  2. package/dist/esm/adapters/Cornerstone/MeasurementReport.js +1 -0
  3. package/dist/esm/adapters/Cornerstone3D/Angle.d.ts +23 -62
  4. package/dist/esm/adapters/Cornerstone3D/Angle.js +29 -141
  5. package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.d.ts +13 -27
  6. package/dist/esm/adapters/Cornerstone3D/ArrowAnnotate.js +26 -144
  7. package/dist/esm/adapters/Cornerstone3D/BaseAdapter3D.d.ts +2 -12
  8. package/dist/esm/adapters/Cornerstone3D/BaseAdapter3D.js +13 -42
  9. package/dist/esm/adapters/Cornerstone3D/Bidirectional.d.ts +23 -80
  10. package/dist/esm/adapters/Cornerstone3D/Bidirectional.js +33 -167
  11. package/dist/esm/adapters/Cornerstone3D/CircleROI.d.ts +16 -33
  12. package/dist/esm/adapters/Cornerstone3D/CircleROI.js +28 -129
  13. package/dist/esm/adapters/Cornerstone3D/CobbAngle.d.ts +23 -62
  14. package/dist/esm/adapters/Cornerstone3D/CobbAngle.js +22 -144
  15. package/dist/esm/adapters/Cornerstone3D/EllipticalROI.d.ts +7 -29
  16. package/dist/esm/adapters/Cornerstone3D/EllipticalROI.js +25 -176
  17. package/dist/esm/adapters/Cornerstone3D/KeyImage.d.ts +8 -10
  18. package/dist/esm/adapters/Cornerstone3D/KeyImage.js +2 -2
  19. package/dist/esm/adapters/Cornerstone3D/Length.d.ts +15 -44
  20. package/dist/esm/adapters/Cornerstone3D/Length.js +28 -121
  21. package/dist/esm/adapters/Cornerstone3D/MeasurementReport.d.ts +57 -38
  22. package/dist/esm/adapters/Cornerstone3D/MeasurementReport.js +66 -30
  23. package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.d.ts +16 -41
  24. package/dist/esm/adapters/Cornerstone3D/PlanarFreehandROI.js +25 -132
  25. package/dist/esm/adapters/Cornerstone3D/Probe.d.ts +7 -21
  26. package/dist/esm/adapters/Cornerstone3D/Probe.js +12 -39
  27. package/dist/esm/adapters/Cornerstone3D/RectangleROI.d.ts +1 -1
  28. package/dist/esm/adapters/Cornerstone3D/RectangleROI.js +7 -2
  29. package/dist/esm/adapters/Cornerstone3D/UltrasoundDirectional.d.ts +6 -15
  30. package/dist/esm/adapters/Cornerstone3D/UltrasoundDirectional.js +6 -2
  31. package/dist/esm/adapters/helpers/index.d.ts +3 -0
  32. package/dist/esm/adapters/helpers/index.js +3 -0
  33. package/dist/esm/adapters/helpers/scoordToWorld.d.ts +5 -0
  34. package/dist/esm/adapters/helpers/scoordToWorld.js +32 -0
  35. package/dist/esm/adapters/helpers/toPoint3.d.ts +3 -0
  36. package/dist/esm/adapters/helpers/toPoint3.js +18 -0
  37. package/dist/esm/adapters/helpers/toScoordType.d.ts +23 -0
  38. package/dist/esm/adapters/helpers/toScoordType.js +33 -0
  39. package/dist/esm/adapters/index.js +1 -0
  40. package/dist/esm/version.d.ts +1 -1
  41. package/package.json +5 -5
@@ -1,27 +1,37 @@
1
+ import { type Types as CSTypes } from "@cornerstonejs/core";
2
+ import type { Types } from "@cornerstonejs/tools";
3
+ type Annotation = Types.Annotation;
1
4
  type SpatialCoordinatesState = {
2
5
  description?: string;
3
6
  sopInstanceUid?: string;
4
- annotation: {
5
- annotationUID: string;
6
- metadata: {
7
- toolName: string;
8
- referencedImageId?: string;
9
- FrameOfReferenceUID: string;
10
- label: string;
11
- };
12
- data?: unknown;
13
- };
7
+ annotation: Annotation;
14
8
  finding?: unknown;
15
9
  findingSites?: unknown;
16
10
  };
11
+ type ScoordType = {
12
+ GraphicData: number[];
13
+ };
17
14
  type SetupMeasurementData = {
18
15
  defaultState: SpatialCoordinatesState;
19
- NUMGroup: Record<string, unknown>;
20
- SCOORDGroup?: Record<string, unknown>;
16
+ state?: SpatialCoordinatesState;
17
+ is3DMeasurement?: boolean;
18
+ scoord?: ScoordType;
19
+ worldCoords?: CSTypes.Point3[];
20
+ scoordArgs?: {
21
+ referencedImageId: string;
22
+ is3DMeasurement: boolean;
23
+ };
24
+ NUMGroup: {
25
+ MeasuredValueSequence: {
26
+ NumericValue: number;
27
+ };
28
+ };
29
+ SCOORDGroup?: ScoordType;
21
30
  ReferencedSOPSequence?: Record<string, unknown>;
22
31
  ReferencedSOPInstanceUID?: string;
32
+ referencedImageId?: string;
23
33
  ReferencedFrameNumber?: string;
24
- SCOORD3DGroup?: Record<string, unknown>;
34
+ SCOORD3DGroup?: ScoordType;
25
35
  FrameOfReferenceUID?: string;
26
36
  };
27
37
  type SpatialCoordinatesData = Omit<SetupMeasurementData, "defaultState" | "NUMGroup"> & {
@@ -38,17 +48,17 @@ export interface MeasurementAdapter {
38
48
  trackingIdentifiers: Set<string>;
39
49
  parentType: string;
40
50
  init(toolType: string, representation: any, options?: AdapterOptions): any;
41
- getMeasurementData(measurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any, trackingIdentifier: string): any;
51
+ getMeasurementData(measurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, trackingIdentifier: string): any;
42
52
  isValidCornerstoneTrackingIdentifier(trackingIdentifier: string): boolean;
43
- getTID300RepresentationArguments(tool: any, worldToImageCoords: any): Record<string, unknown>;
53
+ getTID300RepresentationArguments(tool: any, is3DMeasurement: any): Record<string, unknown>;
44
54
  }
45
55
  export default class MeasurementReport {
46
56
  static CORNERSTONE_3D_TAG: string;
47
57
  static measurementAdapterByToolType: Map<string, MeasurementAdapter>;
48
58
  static measurementAdapterByTrackingIdentifier: Map<string, MeasurementAdapter>;
49
- static getTID300ContentItem(tool: any, ReferencedSOPSequence: any, toolClass: any, worldToImageCoords: any): any;
59
+ static getTID300ContentItem(tool: any, ReferencedSOPSequence: any, toolClass: any, is3DMeasurement: any): any;
50
60
  static codeValueMatch: (group: any, code: any, oldCode?: any) => boolean;
51
- static getMeasurementGroup(toolType: any, toolData: any, ReferencedSOPSequence: any, worldToImageCoords: any): any;
61
+ static getMeasurementGroup(toolType: any, toolData: any, ReferencedSOPSequence: any, is3DMeasurement: any): any;
52
62
  static getCornerstoneLabelFromDefaultState(defaultState: any): any;
53
63
  static generateDatasetMeta(): {
54
64
  FileMetaInformationVersion: {
@@ -77,7 +87,28 @@ export default class MeasurementReport {
77
87
  toolType: any;
78
88
  sopInstanceUIDToImageIdMap: any;
79
89
  metadata: any;
80
- }): SpatialCoordinatesData;
90
+ }): {
91
+ SCOORDGroup: any;
92
+ ReferencedSOPSequence: any;
93
+ ReferencedSOPInstanceUID: any;
94
+ ReferencedFrameNumber: any;
95
+ referencedImageId: any;
96
+ state: {
97
+ description: any;
98
+ sopInstanceUid: any;
99
+ annotation: {
100
+ data: {
101
+ annotationUID: any;
102
+ };
103
+ annotationUID: any;
104
+ metadata: {
105
+ toolName: any;
106
+ referencedImageId: any;
107
+ FrameOfReferenceUID: any;
108
+ };
109
+ };
110
+ };
111
+ };
81
112
  static processSCOORD3DGroup({ SCOORD3DGroup, toolType }: {
82
113
  SCOORD3DGroup: any;
83
114
  toolType: any;
@@ -96,28 +127,16 @@ export default class MeasurementReport {
96
127
  findingSiteGroups: any;
97
128
  toolType: any;
98
129
  }): {
99
- defaultState: {
100
- finding: any;
101
- findingSites: any;
102
- description?: string;
103
- sopInstanceUid?: string;
104
- annotation: {
105
- annotationUID: string;
106
- metadata: {
107
- toolName: string;
108
- referencedImageId?: string;
109
- FrameOfReferenceUID: string;
110
- label: string;
111
- };
112
- data?: unknown;
113
- };
114
- };
130
+ defaultState: SpatialCoordinatesState;
131
+ state: SpatialCoordinatesState;
115
132
  NUMGroup: any;
116
- SCOORDGroup: Record<string, unknown>;
133
+ scoord: ScoordType;
134
+ SCOORDGroup: ScoordType;
117
135
  ReferencedSOPSequence: Record<string, unknown>;
118
136
  ReferencedSOPInstanceUID: string;
137
+ referencedImageId: string;
119
138
  ReferencedFrameNumber: string;
120
- SCOORD3DGroup: Record<string, unknown>;
139
+ SCOORD3DGroup: ScoordType;
121
140
  FrameOfReferenceUID: string;
122
141
  };
123
142
  static getSetupMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any, toolType: any): SetupMeasurementData;
@@ -137,8 +156,8 @@ export default class MeasurementReport {
137
156
  toolData: any;
138
157
  toolTypes: any;
139
158
  }): string;
140
- static generateReport(toolState: any, metadataProvider: any, worldToImageCoords: any, options: any): any;
141
- static generateToolState(dataset: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any, hooks: any): {};
159
+ static generateReport(toolState: any, metadataProvider: any, options: any): any;
160
+ static generateToolState(dataset: any, sopInstanceUIDToImageIdMap: any, metadata: any, hooks: any): {};
142
161
  static registerTool(toolAdapter: MeasurementAdapter, replace?: boolean | ((original: any) => void)): void;
143
162
  static registerTrackingIdentifier(toolClass: any, ...trackingIdentifiers: string[]): void;
144
163
  static getAdapterForTrackingIdentifier(trackingIdentifier: string): MeasurementAdapter;
@@ -1,11 +1,13 @@
1
- import { utilities, derivations, normalizers, data } from 'dcmjs';
2
- import { cache } from '@cornerstonejs/core';
1
+ import { utilities as utilities$1, derivations, normalizers, data } from 'dcmjs';
2
+ import { utilities, cache } from '@cornerstonejs/core';
3
3
  import CORNERSTONE_3D_TAG from './cornerstone3DTag.js';
4
4
  import { toArray } from '../helpers/toArray.js';
5
5
  import { codeMeaningEquals } from '../helpers/codeMeaningEquals.js';
6
6
  import 'buffer';
7
7
  import { copyStudyTags } from '../helpers/copyStudyTags.js';
8
8
  import { copySeriesTags } from '../helpers/copySeriesTags.js';
9
+ import { scoordToWorld } from '../helpers/scoordToWorld.js';
10
+ import { toPoint3 } from '../helpers/toPoint3.js';
9
11
  import CodingScheme from './CodingScheme.js';
10
12
  import { NO_IMAGE_ID } from './constants/index.js';
11
13
 
@@ -13,7 +15,7 @@ var _MeasurementReport;
13
15
  const {
14
16
  TID1500,
15
17
  addAccessors
16
- } = utilities;
18
+ } = utilities$1;
17
19
  const {
18
20
  StructuredReport
19
21
  } = derivations;
@@ -40,20 +42,20 @@ const FINDING_SITE_OLD = {
40
42
  CodeValue: "G-C0E3"
41
43
  };
42
44
  class MeasurementReport {
43
- static getTID300ContentItem(tool, ReferencedSOPSequence, toolClass, worldToImageCoords) {
44
- const args = toolClass.getTID300RepresentationArguments(tool, worldToImageCoords);
45
+ static getTID300ContentItem(tool, ReferencedSOPSequence, toolClass, is3DMeasurement) {
46
+ const args = toolClass.getTID300RepresentationArguments(tool, is3DMeasurement);
45
47
  args.ReferencedSOPSequence = ReferencedSOPSequence;
46
48
  const TID300Measurement = new toolClass.TID300Representation(args);
47
49
  return TID300Measurement;
48
50
  }
49
- static getMeasurementGroup(toolType, toolData, ReferencedSOPSequence, worldToImageCoords) {
51
+ static getMeasurementGroup(toolType, toolData, ReferencedSOPSequence, is3DMeasurement) {
50
52
  const toolTypeData = toolData[toolType];
51
53
  const toolClass = this.measurementAdapterByToolType.get(toolType);
52
54
  if (!toolTypeData || !toolTypeData.data || !toolTypeData.data.length || !toolClass) {
53
55
  return;
54
56
  }
55
57
  const Measurements = toolTypeData.data.map(tool => {
56
- return this.getTID300ContentItem(tool, ReferencedSOPSequence, toolClass, worldToImageCoords);
58
+ return this.getTID300ContentItem(tool, ReferencedSOPSequence, toolClass, is3DMeasurement);
57
59
  });
58
60
  return new TID1501MeasurementGroup(Measurements);
59
61
  }
@@ -110,21 +112,25 @@ class MeasurementReport {
110
112
  } = ReferencedSOPSequence;
111
113
  const referencedImageId = sopInstanceUIDToImageIdMap[ReferencedSOPInstanceUID];
112
114
  const imagePlaneModule = metadata.get("imagePlaneModule", referencedImageId);
115
+ const annotationUID = DicomMetaDictionary.uid();
113
116
  return {
114
117
  SCOORDGroup,
115
118
  ReferencedSOPSequence,
116
119
  ReferencedSOPInstanceUID,
117
120
  ReferencedFrameNumber,
121
+ referencedImageId,
118
122
  state: {
119
123
  description: undefined,
120
124
  sopInstanceUid: ReferencedSOPInstanceUID,
121
125
  annotation: {
122
- annotationUID: DicomMetaDictionary.uid(),
126
+ data: {
127
+ annotationUID
128
+ },
129
+ annotationUID,
123
130
  metadata: {
124
131
  toolName: toolType,
125
132
  referencedImageId,
126
- FrameOfReferenceUID: imagePlaneModule.frameOfReferenceUID,
127
- label: ""
133
+ FrameOfReferenceUID: imagePlaneModule.frameOfReferenceUID
128
134
  }
129
135
  }
130
136
  }
@@ -135,21 +141,26 @@ class MeasurementReport {
135
141
  SCOORD3DGroup,
136
142
  toolType
137
143
  } = _ref2;
138
- return {
144
+ const annotationUID = DicomMetaDictionary.uid();
145
+ const toolData = {
139
146
  SCOORD3DGroup,
140
147
  FrameOfReferenceUID: SCOORD3DGroup.ReferencedFrameOfReferenceUID,
141
148
  state: {
142
149
  description: undefined,
143
150
  annotation: {
144
- annotationUID: DicomMetaDictionary.uid(),
151
+ annotationUID,
152
+ data: {
153
+ annotationUID
154
+ },
145
155
  metadata: {
146
156
  toolName: toolType,
147
- FrameOfReferenceUID: SCOORD3DGroup.ReferencedFrameOfReferenceUID,
148
- label: ""
157
+ FrameOfReferenceUID: SCOORD3DGroup.ReferencedFrameOfReferenceUID
149
158
  }
150
159
  }
151
160
  }
152
161
  };
162
+ utilities.updatePlaneRestriction(toPoint3(SCOORD3DGroup.GraphicData), toolData.state.annotation.metadata);
163
+ return toolData;
153
164
  }
154
165
  static getSpatialCoordinatesState(_ref3) {
155
166
  let {
@@ -192,7 +203,8 @@ class MeasurementReport {
192
203
  ReferencedSOPInstanceUID,
193
204
  ReferencedFrameNumber,
194
205
  SCOORD3DGroup,
195
- FrameOfReferenceUID
206
+ FrameOfReferenceUID,
207
+ referencedImageId
196
208
  } = this.getSpatialCoordinatesState({
197
209
  NUMGroup,
198
210
  sopInstanceUIDToImageIdMap,
@@ -203,21 +215,21 @@ class MeasurementReport {
203
215
  const findingSites = findingSiteGroups.map(fsg => {
204
216
  return addAccessors(fsg.ConceptCodeSequence);
205
217
  });
206
- const defaultState = {
207
- ...state,
208
- finding,
209
- findingSites
210
- };
211
- if (defaultState.finding) {
212
- defaultState.description = defaultState.finding.CodeMeaning;
218
+ state.finding = finding;
219
+ state.findingSites = findingSites;
220
+ if (finding) {
221
+ state.description = finding.CodeMeaning;
213
222
  }
214
- defaultState.annotation.metadata.label = MeasurementReport.getCornerstoneLabelFromDefaultState(defaultState);
223
+ state.annotation.data.label = MeasurementReport.getCornerstoneLabelFromDefaultState(state);
215
224
  return {
216
- defaultState,
225
+ defaultState: state,
226
+ state,
217
227
  NUMGroup,
228
+ scoord: SCOORD3DGroup || SCOORDGroup,
218
229
  SCOORDGroup,
219
230
  ReferencedSOPSequence,
220
231
  ReferencedSOPInstanceUID,
232
+ referencedImageId,
221
233
  ReferencedFrameNumber,
222
234
  SCOORD3DGroup,
223
235
  FrameOfReferenceUID
@@ -231,7 +243,7 @@ class MeasurementReport {
231
243
  const findingGroup = contentSequenceArr.find(group => this.codeValueMatch(group, FINDING));
232
244
  const findingSiteGroups = contentSequenceArr.filter(group => this.codeValueMatch(group, FINDING_SITE, FINDING_SITE_OLD)) || [];
233
245
  const NUMGroup = contentSequenceArr.find(group => group.ValueType === "NUM");
234
- return this.processSpatialCoordinatesGroup({
246
+ const spatialGroup = this.processSpatialCoordinatesGroup({
235
247
  NUMGroup,
236
248
  sopInstanceUIDToImageIdMap,
237
249
  metadata,
@@ -239,6 +251,23 @@ class MeasurementReport {
239
251
  findingSiteGroups,
240
252
  toolType
241
253
  });
254
+ const {
255
+ referencedImageId
256
+ } = spatialGroup.state.annotation.metadata;
257
+ const is3DMeasurement = !!spatialGroup.SCOORD3DGroup;
258
+ const scoordArgs = {
259
+ referencedImageId,
260
+ is3DMeasurement
261
+ };
262
+ const scoord = spatialGroup.SCOORD3DGroup || spatialGroup.SCOORDGroup;
263
+ const worldCoords = scoordToWorld(scoordArgs, scoord);
264
+ return {
265
+ ...spatialGroup,
266
+ is3DMeasurement,
267
+ scoordArgs,
268
+ scoord,
269
+ worldCoords
270
+ };
242
271
  }
243
272
  static generateReferencedSOPSequence(_ref5) {
244
273
  let {
@@ -286,10 +315,13 @@ class MeasurementReport {
286
315
  const referenceToolData = toolData?.[toolTypes?.[0]]?.data?.[0];
287
316
  const volumeId = referenceToolData?.metadata?.volumeId;
288
317
  const volume = cache.getVolume(volumeId);
318
+ if (!volume) {
319
+ throw new Error(`No volume found for ${volumeId}`);
320
+ }
289
321
  const imageId = volume.imageIds[0];
290
322
  return imageId;
291
323
  }
292
- static generateReport(toolState, metadataProvider, worldToImageCoords, options) {
324
+ static generateReport(toolState, metadataProvider, options) {
293
325
  let allMeasurementGroups = [];
294
326
  const sopInstanceUIDsToSeriesInstanceUIDMap = {};
295
327
  const derivationSourceDatasets = [];
@@ -298,6 +330,7 @@ class MeasurementReport {
298
330
  Object.keys(toolState).forEach(imageId => {
299
331
  const toolData = toolState[imageId];
300
332
  const toolTypes = Object.keys(toolData);
333
+ const is3DMeasurement = imageId === NO_IMAGE_ID;
301
334
  const ReferencedSOPSequence = this.generateReferencedSOPSequence({
302
335
  toolData,
303
336
  toolTypes,
@@ -306,12 +339,12 @@ class MeasurementReport {
306
339
  sopInstanceUIDsToSeriesInstanceUIDMap,
307
340
  derivationSourceDatasets
308
341
  });
309
- if (imageId === NO_IMAGE_ID) {
342
+ if (is3DMeasurement) {
310
343
  is3DSR = true;
311
344
  }
312
345
  const measurementGroups = [];
313
346
  toolTypes.forEach(toolType => {
314
- const group = this.getMeasurementGroup(toolType, toolData, ReferencedSOPSequence, worldToImageCoords);
347
+ const group = this.getMeasurementGroup(toolType, toolData, ReferencedSOPSequence, is3DMeasurement);
315
348
  if (group) {
316
349
  measurementGroups.push(group);
317
350
  }
@@ -331,10 +364,13 @@ class MeasurementReport {
331
364
  report.SpecificCharacterSet = "ISO_IR 192";
332
365
  if (is3DSR) {
333
366
  report.dataset.SOPClassUID = DicomMetaDictionary.sopClassUIDsByName.Comprehensive3DSR;
367
+ if (!report.dataset.SOPClassUID) {
368
+ throw new Error(`NO sop class defined for Comprehensive3DSR in ${JSON.stringify(DicomMetaDictionary.sopClassUIDsByName)}`);
369
+ }
334
370
  }
335
371
  return report;
336
372
  }
337
- static generateToolState(dataset, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, hooks) {
373
+ static generateToolState(dataset, sopInstanceUIDToImageIdMap, metadata, hooks) {
338
374
  if (dataset.ContentTemplateSequence.TemplateIdentifier !== "1500") {
339
375
  throw new Error("This package can currently only interpret DICOM SR TID 1500");
340
376
  }
@@ -356,7 +392,7 @@ class MeasurementReport {
356
392
  const trackingUniqueIdentifierValue = trackingUniqueIdentifierGroup?.UID;
357
393
  const toolAdapter = hooks?.getToolClass?.(measurementGroup, dataset, this.measurementAdapterByToolType) || this.getAdapterForTrackingIdentifier(trackingIdentifierValue);
358
394
  if (toolAdapter) {
359
- const measurement = toolAdapter.getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata, trackingIdentifierValue);
395
+ const measurement = toolAdapter.getMeasurementData(measurementGroup, sopInstanceUIDToImageIdMap, metadata, trackingIdentifierValue);
360
396
  measurement.TrackingUniqueIdentifier = trackingUniqueIdentifierValue;
361
397
  console.log(`=== ${toolAdapter.toolType} ===`);
362
398
  console.log(measurement);
@@ -1,48 +1,23 @@
1
1
  import BaseAdapter3D from "./BaseAdapter3D";
2
2
  declare class PlanarFreehandROI extends BaseAdapter3D {
3
3
  static closedContourThreshold: number;
4
- static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, imageToWorldCoords: any, metadata: any): any;
5
- static getMeasurementDataFromScoord({ defaultState, SCOORDGroup, imageToWorldCoords, NUMGroup, ReferencedFrameNumber }: {
6
- defaultState: any;
7
- SCOORDGroup: any;
8
- imageToWorldCoords: any;
9
- NUMGroup: any;
10
- ReferencedFrameNumber: any;
11
- }): any;
12
- static getMeasurementDataFromScoord3D({ defaultState, SCOORD3DGroup }: {
13
- defaultState: any;
14
- SCOORD3DGroup: any;
15
- }): any;
16
- static getTID300RepresentationArguments(tool: any, worldToImageCoords: any): {
17
- points: any;
18
- area: any;
19
- areaUnit: any;
20
- perimeter: any;
21
- modalityUnit: any;
22
- mean: any;
23
- max: any;
24
- stdDev: any;
25
- trackingIdentifierTextValue: string;
26
- finding: any;
27
- findingSites: any;
28
- ReferencedFrameOfReferenceUID: any;
29
- use3DSpatialCoordinates: boolean;
30
- } | {
31
- points: any;
32
- area: any;
33
- areaUnit: any;
34
- perimeter: any;
35
- modalityUnit: any;
36
- mean: any;
37
- max: any;
38
- stdDev: any;
39
- trackingIdentifierTextValue: string;
40
- finding: any;
41
- findingSites: any;
42
- use3DSpatialCoordinates: boolean;
4
+ static getMeasurementData(MeasurementGroup: any, sopInstanceUIDToImageIdMap: any, metadata: any): {
5
+ description?: string;
6
+ sopInstanceUid?: string;
7
+ annotation: import("packages/tools/dist/esm/types").Annotation;
8
+ finding?: unknown;
9
+ findingSites?: unknown;
43
10
  };
44
- static getTID300RepresentationArgumentsSCOORD3D(tool: any): {
45
- points: any;
11
+ static getTID300RepresentationArguments(tool: any, is3DMeasurement?: boolean): {
12
+ points: ({
13
+ x: any;
14
+ y: any;
15
+ z: any;
16
+ } | {
17
+ x: number;
18
+ y: number;
19
+ z?: undefined;
20
+ })[];
46
21
  area: any;
47
22
  areaUnit: any;
48
23
  perimeter: any;
@@ -2,54 +2,25 @@ import MeasurementReport from './MeasurementReport.js';
2
2
  import { utilities } from 'dcmjs';
3
3
  import { vec3 } from 'gl-matrix';
4
4
  import BaseAdapter3D from './BaseAdapter3D.js';
5
+ import 'buffer';
6
+ import { toScoords } from '../helpers/toScoordType.js';
7
+ import '@cornerstonejs/core';
5
8
 
6
9
  var _PlanarFreehandROI;
7
10
  const {
8
11
  Polyline: TID300Polyline
9
12
  } = utilities.TID300;
10
13
  class PlanarFreehandROI extends BaseAdapter3D {
11
- static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, imageToWorldCoords, metadata) {
14
+ static getMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata) {
12
15
  const {
13
- defaultState,
16
+ state,
14
17
  NUMGroup,
15
- SCOORDGroup,
16
- SCOORD3DGroup,
18
+ scoord,
19
+ scoordArgs,
20
+ worldCoords,
21
+ referencedImageId,
17
22
  ReferencedFrameNumber
18
- } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, PlanarFreehandROI.toolType);
19
- if (SCOORDGroup) {
20
- return this.getMeasurementDataFromScoord({
21
- defaultState,
22
- SCOORDGroup,
23
- imageToWorldCoords,
24
- NUMGroup,
25
- ReferencedFrameNumber
26
- });
27
- } else if (SCOORD3DGroup) {
28
- return this.getMeasurementDataFromScoord3D({
29
- defaultState,
30
- SCOORD3DGroup
31
- });
32
- } else {
33
- throw new Error("Can't get measurement data with missing SCOORD and SCOORD3D groups.");
34
- }
35
- }
36
- static getMeasurementDataFromScoord(_ref) {
37
- let {
38
- defaultState,
39
- SCOORDGroup,
40
- imageToWorldCoords,
41
- NUMGroup,
42
- ReferencedFrameNumber
43
- } = _ref;
44
- const referencedImageId = defaultState.annotation.metadata.referencedImageId;
45
- const {
46
- GraphicData
47
- } = SCOORDGroup;
48
- const worldCoords = [];
49
- for (let i = 0; i < GraphicData.length; i += 2) {
50
- const point = imageToWorldCoords(referencedImageId, [GraphicData[i], GraphicData[i + 1]]);
51
- worldCoords.push(point);
52
- }
23
+ } = MeasurementReport.getSetupMeasurementData(MeasurementGroup, sopInstanceUIDToImageIdMap, metadata, this.toolType);
53
24
  const distanceBetweenFirstAndLastPoint = vec3.distance(worldCoords[worldCoords.length - 1], worldCoords[0]);
54
25
  let isOpenContour = true;
55
26
  if (distanceBetweenFirstAndLastPoint < this.closedContourThreshold) {
@@ -60,8 +31,8 @@ class PlanarFreehandROI extends BaseAdapter3D {
60
31
  if (isOpenContour) {
61
32
  points.push(worldCoords[0], worldCoords[worldCoords.length - 1]);
62
33
  }
63
- const state = defaultState;
64
34
  state.annotation.data = {
35
+ ...state.annotation.data,
65
36
  contour: {
66
37
  polyline: worldCoords,
67
38
  closed: !isOpenContour
@@ -73,56 +44,19 @@ class PlanarFreehandROI extends BaseAdapter3D {
73
44
  hasMoved: false
74
45
  }
75
46
  },
76
- cachedStats: {
47
+ frameNumber: ReferencedFrameNumber
48
+ };
49
+ if (referencedImageId) {
50
+ state.annotation.data.cachedStats = {
77
51
  [`imageId:${referencedImageId}`]: {
78
52
  area: NUMGroup ? NUMGroup.MeasuredValueSequence.NumericValue : null
79
53
  }
80
- },
81
- frameNumber: ReferencedFrameNumber
82
- };
83
- return state;
84
- }
85
- static getMeasurementDataFromScoord3D(_ref2) {
86
- let {
87
- defaultState,
88
- SCOORD3DGroup
89
- } = _ref2;
90
- const {
91
- GraphicData
92
- } = SCOORD3DGroup;
93
- const worldCoords = [];
94
- for (let i = 0; i < GraphicData.length; i += 3) {
95
- const point = [GraphicData[i], GraphicData[i + 1], GraphicData[i + 2]];
96
- worldCoords.push(point);
54
+ };
97
55
  }
98
- const distanceBetweenFirstAndLastPoint = vec3.distance(worldCoords[worldCoords.length - 1], worldCoords[0]);
99
- let isOpenContour = true;
100
- if (distanceBetweenFirstAndLastPoint < this.closedContourThreshold) {
101
- worldCoords.pop();
102
- isOpenContour = false;
103
- }
104
- const points = [];
105
- if (isOpenContour) {
106
- points.push(worldCoords[0], worldCoords[worldCoords.length - 1]);
107
- }
108
- const state = defaultState;
109
- state.annotation.data = {
110
- contour: {
111
- polyline: worldCoords,
112
- closed: !isOpenContour
113
- },
114
- handles: {
115
- points,
116
- activeHandleIndex: null,
117
- textBox: {
118
- hasMoved: false
119
- }
120
- },
121
- cachedStats: {}
122
- };
123
56
  return state;
124
57
  }
125
- static getTID300RepresentationArguments(tool, worldToImageCoords) {
58
+ static getTID300RepresentationArguments(tool) {
59
+ let is3DMeasurement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
126
60
  const {
127
61
  data,
128
62
  finding,
@@ -137,13 +71,14 @@ class PlanarFreehandROI extends BaseAdapter3D {
137
71
  const {
138
72
  referencedImageId
139
73
  } = metadata;
140
- if (!referencedImageId) {
141
- return this.getTID300RepresentationArgumentsSCOORD3D(tool);
142
- }
143
- const points = polyline.map(worldPos => worldToImageCoords(referencedImageId, worldPos));
74
+ const scoordProps = {
75
+ is3DMeasurement,
76
+ referencedImageId
77
+ };
78
+ const points = toScoords(scoordProps, polyline);
144
79
  if (!isOpenContour) {
145
80
  const firstPoint = points[0];
146
- points.push([firstPoint[0], firstPoint[1]]);
81
+ points.push(firstPoint);
147
82
  }
148
83
  const {
149
84
  area,
@@ -166,52 +101,10 @@ class PlanarFreehandROI extends BaseAdapter3D {
166
101
  trackingIdentifierTextValue: this.trackingIdentifierTextValue,
167
102
  finding,
168
103
  findingSites: findingSites || [],
104
+ ReferencedFrameOfReferenceUID: is3DMeasurement ? metadata.FrameOfReferenceUID : null,
169
105
  use3DSpatialCoordinates: false
170
106
  };
171
107
  }
172
- static getTID300RepresentationArgumentsSCOORD3D(tool) {
173
- const {
174
- data,
175
- finding,
176
- findingSites,
177
- metadata
178
- } = tool;
179
- const {
180
- polyline,
181
- closed
182
- } = data.contour;
183
- const isOpenContour = closed !== true;
184
- const points = polyline;
185
- if (!isOpenContour) {
186
- const firstPoint = points[0];
187
- points.push([firstPoint[0], firstPoint[1], firstPoint[2]]);
188
- }
189
- const cachedStatsKeys = Object.keys(data.cachedStats)[0];
190
- const {
191
- area = undefined,
192
- areaUnit = undefined,
193
- modalityUnit = undefined,
194
- perimeter = undefined,
195
- mean = undefined,
196
- max = undefined,
197
- stdDev = undefined
198
- } = cachedStatsKeys ? data.cachedStats[cachedStatsKeys] : {};
199
- return {
200
- points,
201
- area,
202
- areaUnit,
203
- perimeter,
204
- modalityUnit,
205
- mean,
206
- max,
207
- stdDev,
208
- trackingIdentifierTextValue: this.trackingIdentifierTextValue,
209
- finding,
210
- findingSites: findingSites || [],
211
- ReferencedFrameOfReferenceUID: metadata.FrameOfReferenceUID,
212
- use3DSpatialCoordinates: true
213
- };
214
- }
215
108
  }
216
109
  _PlanarFreehandROI = PlanarFreehandROI;
217
110
  _PlanarFreehandROI.closedContourThreshold = 1e-5;