@cornerstonejs/core 1.22.0 → 1.23.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 (111) hide show
  1. package/dist/cjs/RenderingEngine/StackViewport.js +8 -3
  2. package/dist/cjs/RenderingEngine/StackViewport.js.map +1 -1
  3. package/dist/cjs/RenderingEngine/Viewport.d.ts +3 -1
  4. package/dist/cjs/RenderingEngine/Viewport.js +65 -24
  5. package/dist/cjs/RenderingEngine/Viewport.js.map +1 -1
  6. package/dist/cjs/RenderingEngine/VolumeViewport.d.ts +1 -1
  7. package/dist/cjs/RenderingEngine/VolumeViewport.js +4 -4
  8. package/dist/cjs/RenderingEngine/VolumeViewport.js.map +1 -1
  9. package/dist/cjs/RenderingEngine/VolumeViewport3D.d.ts +1 -0
  10. package/dist/cjs/RenderingEngine/VolumeViewport3D.js +7 -0
  11. package/dist/cjs/RenderingEngine/VolumeViewport3D.js.map +1 -1
  12. package/dist/cjs/cache/classes/ImageVolume.js +1 -1
  13. package/dist/cjs/cache/classes/ImageVolume.js.map +1 -1
  14. package/dist/cjs/cache/classes/Surface.d.ts +22 -0
  15. package/dist/cjs/cache/classes/Surface.js +32 -0
  16. package/dist/cjs/cache/classes/Surface.js.map +1 -0
  17. package/dist/cjs/enums/Events.d.ts +2 -1
  18. package/dist/cjs/enums/Events.js +1 -0
  19. package/dist/cjs/enums/Events.js.map +1 -1
  20. package/dist/cjs/enums/GeometryType.d.ts +2 -1
  21. package/dist/cjs/enums/GeometryType.js +1 -0
  22. package/dist/cjs/enums/GeometryType.js.map +1 -1
  23. package/dist/cjs/loaders/geometryLoader.d.ts +2 -2
  24. package/dist/cjs/loaders/geometryLoader.js +6 -37
  25. package/dist/cjs/loaders/geometryLoader.js.map +1 -1
  26. package/dist/cjs/loaders/utils/contourSet/createContourSet.d.ts +2 -0
  27. package/dist/cjs/loaders/utils/contourSet/createContourSet.js +25 -0
  28. package/dist/cjs/loaders/utils/contourSet/createContourSet.js.map +1 -0
  29. package/dist/cjs/loaders/utils/contourSet/validateContourSet.d.ts +2 -0
  30. package/dist/cjs/loaders/utils/contourSet/validateContourSet.js +26 -0
  31. package/dist/cjs/loaders/utils/contourSet/validateContourSet.js.map +1 -0
  32. package/dist/cjs/loaders/utils/surface/createSurface.d.ts +2 -0
  33. package/dist/cjs/loaders/utils/surface/createSurface.js +27 -0
  34. package/dist/cjs/loaders/utils/surface/createSurface.js.map +1 -0
  35. package/dist/cjs/loaders/utils/surface/validateSurface.d.ts +2 -0
  36. package/dist/cjs/loaders/utils/surface/validateSurface.js +11 -0
  37. package/dist/cjs/loaders/utils/surface/validateSurface.js.map +1 -0
  38. package/dist/cjs/types/IActor.d.ts +1 -0
  39. package/dist/cjs/types/IGeometry.d.ts +2 -1
  40. package/dist/cjs/types/SurfaceData.d.ts +12 -0
  41. package/dist/cjs/types/SurfaceData.js +3 -0
  42. package/dist/cjs/types/SurfaceData.js.map +1 -0
  43. package/dist/cjs/types/index.d.ts +2 -1
  44. package/dist/cjs/utilities/getSpacingInNormalDirection.d.ts +5 -1
  45. package/dist/cjs/utilities/getSpacingInNormalDirection.js.map +1 -1
  46. package/dist/esm/RenderingEngine/StackViewport.js +8 -3
  47. package/dist/esm/RenderingEngine/StackViewport.js.map +1 -1
  48. package/dist/esm/RenderingEngine/Viewport.d.ts +3 -1
  49. package/dist/esm/RenderingEngine/Viewport.js +45 -15
  50. package/dist/esm/RenderingEngine/Viewport.js.map +1 -1
  51. package/dist/esm/RenderingEngine/VolumeViewport.d.ts +1 -1
  52. package/dist/esm/RenderingEngine/VolumeViewport.js +5 -5
  53. package/dist/esm/RenderingEngine/VolumeViewport.js.map +1 -1
  54. package/dist/esm/RenderingEngine/VolumeViewport3D.d.ts +1 -0
  55. package/dist/esm/RenderingEngine/VolumeViewport3D.js +7 -0
  56. package/dist/esm/RenderingEngine/VolumeViewport3D.js.map +1 -1
  57. package/dist/esm/cache/classes/ImageVolume.js +1 -1
  58. package/dist/esm/cache/classes/ImageVolume.js.map +1 -1
  59. package/dist/esm/cache/classes/Surface.d.ts +22 -0
  60. package/dist/esm/cache/classes/Surface.js +27 -0
  61. package/dist/esm/cache/classes/Surface.js.map +1 -0
  62. package/dist/esm/enums/Events.d.ts +2 -1
  63. package/dist/esm/enums/Events.js +1 -0
  64. package/dist/esm/enums/Events.js.map +1 -1
  65. package/dist/esm/enums/GeometryType.d.ts +2 -1
  66. package/dist/esm/enums/GeometryType.js +1 -0
  67. package/dist/esm/enums/GeometryType.js.map +1 -1
  68. package/dist/esm/loaders/geometryLoader.d.ts +2 -2
  69. package/dist/esm/loaders/geometryLoader.js +6 -37
  70. package/dist/esm/loaders/geometryLoader.js.map +1 -1
  71. package/dist/esm/loaders/utils/contourSet/createContourSet.d.ts +2 -0
  72. package/dist/esm/loaders/utils/contourSet/createContourSet.js +21 -0
  73. package/dist/esm/loaders/utils/contourSet/createContourSet.js.map +1 -0
  74. package/dist/esm/loaders/utils/contourSet/validateContourSet.d.ts +2 -0
  75. package/dist/esm/loaders/utils/contourSet/validateContourSet.js +22 -0
  76. package/dist/esm/loaders/utils/contourSet/validateContourSet.js.map +1 -0
  77. package/dist/esm/loaders/utils/surface/createSurface.d.ts +2 -0
  78. package/dist/esm/loaders/utils/surface/createSurface.js +23 -0
  79. package/dist/esm/loaders/utils/surface/createSurface.js.map +1 -0
  80. package/dist/esm/loaders/utils/surface/validateSurface.d.ts +2 -0
  81. package/dist/esm/loaders/utils/surface/validateSurface.js +7 -0
  82. package/dist/esm/loaders/utils/surface/validateSurface.js.map +1 -0
  83. package/dist/esm/types/IActor.d.ts +1 -0
  84. package/dist/esm/types/IGeometry.d.ts +2 -1
  85. package/dist/esm/types/SurfaceData.d.ts +12 -0
  86. package/dist/esm/types/SurfaceData.js +2 -0
  87. package/dist/esm/types/SurfaceData.js.map +1 -0
  88. package/dist/esm/types/index.d.ts +2 -1
  89. package/dist/esm/utilities/getSpacingInNormalDirection.d.ts +5 -1
  90. package/dist/esm/utilities/getSpacingInNormalDirection.js.map +1 -1
  91. package/dist/umd/index.js +1 -1
  92. package/dist/umd/index.js.map +1 -1
  93. package/package.json +3 -3
  94. package/src/RenderingEngine/StackViewport.ts +8 -3
  95. package/src/RenderingEngine/Viewport.ts +57 -17
  96. package/src/RenderingEngine/VolumeViewport.ts +9 -11
  97. package/src/RenderingEngine/VolumeViewport3D.ts +8 -0
  98. package/src/cache/classes/ImageVolume.ts +1 -1
  99. package/src/cache/classes/Surface.ts +49 -0
  100. package/src/enums/Events.ts +5 -0
  101. package/src/enums/GeometryType.ts +1 -0
  102. package/src/loaders/geometryLoader.ts +13 -63
  103. package/src/loaders/utils/contourSet/createContourSet.ts +29 -0
  104. package/src/loaders/utils/contourSet/validateContourSet.ts +38 -0
  105. package/src/loaders/utils/surface/createSurface.ts +31 -0
  106. package/src/loaders/utils/surface/validateSurface.ts +9 -0
  107. package/src/types/IActor.ts +2 -0
  108. package/src/types/IGeometry.ts +2 -1
  109. package/src/types/SurfaceData.ts +15 -0
  110. package/src/types/index.ts +4 -0
  111. package/src/utilities/getSpacingInNormalDirection.ts +2 -2
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cornerstonejs/core",
3
- "version": "1.22.0",
3
+ "version": "1.23.0",
4
4
  "description": "",
5
- "main": "dist/umd/index.js",
5
+ "main": "src/index.ts",
6
6
  "types": "dist/esm/index.d.ts",
7
7
  "module": "dist/esm/index.js",
8
8
  "repository": "https://github.com/cornerstonejs/cornerstone3D",
@@ -46,5 +46,5 @@
46
46
  "type": "individual",
47
47
  "url": "https://ohif.org/donate"
48
48
  },
49
- "gitHead": "ff226c7a2ed426dc568b8043d3bbbb1cdc993281"
49
+ "gitHead": "378523639b22b4aa8247118b215d68596f3dc54f"
50
50
  }
@@ -2197,9 +2197,14 @@ class StackViewport extends Viewport implements IStackViewport {
2197
2197
 
2198
2198
  // Create a VTK Image Slice actor to display the vtkImageData object
2199
2199
  const actor = this.createActorMapper(this._imageData);
2200
- const actors = [];
2201
- actors.push({ uid: this.id, actor });
2202
- this.setActors(actors);
2200
+ const oldActors = this.getActors();
2201
+ if (oldActors.length && oldActors[0].uid === this.id) {
2202
+ oldActors[0].actor = actor;
2203
+ } else {
2204
+ oldActors.unshift({ uid: this.id, actor });
2205
+ }
2206
+ this.setActors(oldActors);
2207
+
2203
2208
  // Adjusting the camera based on slice axis. this is required if stack
2204
2209
  // contains various image orientations (axial ct, sagittal xray)
2205
2210
  const { viewPlaneNormal, viewUp } = this._getCameraOrientation(direction);
@@ -12,7 +12,7 @@ import ViewportType from '../enums/ViewportType';
12
12
  import renderingEngineCache from './renderingEngineCache';
13
13
  import { triggerEvent, planar, isImageActor, actorIsA } from '../utilities';
14
14
  import hasNaNValues from '../utilities/hasNaNValues';
15
- import { RENDERING_DEFAULTS } from '../constants';
15
+ import { EPSILON, RENDERING_DEFAULTS } from '../constants';
16
16
  import type {
17
17
  ICamera,
18
18
  ActorEntry,
@@ -71,6 +71,8 @@ class Viewport implements IViewport {
71
71
  readonly defaultOptions: any;
72
72
  /** options for the viewport which includes orientation axis, backgroundColor and displayArea */
73
73
  options: ViewportInputOptions;
74
+ /** informs if a new actor was added before a resetCameraClippingRange phase */
75
+ protected newActorAdded = false;
74
76
  private _suppressCameraModifiedEvents = false;
75
77
  /** A flag representing if viewport methods should fire events or not */
76
78
  readonly suppressEvents: boolean;
@@ -481,6 +483,7 @@ class Viewport implements IViewport {
481
483
  const renderer = this.getRenderer();
482
484
  renderer.addActor(actor);
483
485
  this._actors.set(actorUID, Object.assign({}, actorEntry));
486
+ this.newActorAdded = true;
484
487
  }
485
488
 
486
489
  /**
@@ -1080,20 +1083,36 @@ class Viewport implements IViewport {
1080
1083
  vtkCamera.setClippingRange(clippingRange);
1081
1084
  }
1082
1085
 
1083
- // update clippingPlanes if volume viewports
1084
- const actorEntry = this.getDefaultActor();
1085
-
1086
- if (!actorEntry || !actorEntry.actor) {
1087
- return;
1088
- }
1089
-
1090
- const isImageSlice = actorIsA(actorEntry, 'vtkImageSlice');
1086
+ // update clipping range only if focal point changed of a new actor is added
1087
+ const prevFocalPoint = previousCamera.focalPoint;
1088
+ if (prevFocalPoint && focalPoint) {
1089
+ const currentViewPlaneNormal = <Point3>vtkCamera.getViewPlaneNormal();
1090
+ const deltaCamera = <Point3>[
1091
+ focalPoint[0] - prevFocalPoint[0],
1092
+ focalPoint[1] - prevFocalPoint[1],
1093
+ focalPoint[2] - prevFocalPoint[2],
1094
+ ];
1091
1095
 
1092
- if (!isImageSlice) {
1093
- this.updateClippingPlanesForActors(updatedCamera);
1094
- } else {
1095
- const renderer = this.getRenderer();
1096
- renderer.resetCameraClippingRange();
1096
+ const cameraModifiedOutOfPlane =
1097
+ Math.abs(vtkMath.dot(deltaCamera, currentViewPlaneNormal)) > EPSILON;
1098
+
1099
+ // only modify the clipping planes if the camera is modified out of plane
1100
+ // or a new actor is added and we need to update the clipping planes
1101
+ if (cameraModifiedOutOfPlane || this.newActorAdded) {
1102
+ const actorEntry = this.getDefaultActor();
1103
+ if (!actorEntry?.actor) {
1104
+ return;
1105
+ }
1106
+
1107
+ if (!actorIsA(actorEntry, 'vtkActor')) {
1108
+ this.updateClippingPlanesForActors(updatedCamera);
1109
+ }
1110
+
1111
+ if (actorIsA(actorEntry, 'vtkImageSlice')) {
1112
+ const renderer = this.getRenderer();
1113
+ renderer.resetCameraClippingRange();
1114
+ }
1115
+ }
1097
1116
  }
1098
1117
 
1099
1118
  if (storeAsInitialCamera) {
@@ -1133,9 +1152,11 @@ class Viewport implements IViewport {
1133
1152
  * Updates the actors clipping planes orientation from the camera properties
1134
1153
  * @param updatedCamera - ICamera
1135
1154
  */
1136
- protected updateClippingPlanesForActors(updatedCamera: ICamera): void {
1155
+ protected async updateClippingPlanesForActors(
1156
+ updatedCamera: ICamera
1157
+ ): Promise<void> {
1137
1158
  const actorEntries = this.getActors();
1138
- actorEntries.forEach((actorEntry) => {
1159
+ const allPromises = actorEntries.map(async (actorEntry) => {
1139
1160
  // we assume that the first two clipping plane of the mapper are always
1140
1161
  // the 'camera' clipping. Update clipping planes only if the actor is
1141
1162
  // a vtkVolume
@@ -1144,7 +1165,13 @@ class Viewport implements IViewport {
1144
1165
  }
1145
1166
 
1146
1167
  const mapper = actorEntry.actor.getMapper();
1147
- const vtkPlanes = mapper.getClippingPlanes();
1168
+ let vtkPlanes = actorEntry?.clippingFilter
1169
+ ? actorEntry.clippingFilter.getClippingPlanes()
1170
+ : mapper.getClippingPlanes();
1171
+
1172
+ if (vtkPlanes.length === 0 && actorEntry?.clippingFilter) {
1173
+ vtkPlanes = [vtkPlane.newInstance(), vtkPlane.newInstance()];
1174
+ }
1148
1175
 
1149
1176
  let slabThickness = RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS;
1150
1177
  if (actorEntry.slabThickness) {
@@ -1159,7 +1186,20 @@ class Viewport implements IViewport {
1159
1186
  viewPlaneNormal,
1160
1187
  focalPoint
1161
1188
  );
1189
+ triggerEvent(this.element, Events.CLIPPING_PLANES_UPDATED, {
1190
+ actorEntry,
1191
+ focalPoint,
1192
+ vtkPlanes,
1193
+ viewport: this,
1194
+ });
1162
1195
  });
1196
+
1197
+ await Promise.all(allPromises);
1198
+ this.posProcessNewActors();
1199
+ }
1200
+
1201
+ protected posProcessNewActors(): void {
1202
+ this.newActorAdded = false;
1163
1203
  }
1164
1204
 
1165
1205
  public setOrientationOfClippingPlanes(
@@ -17,6 +17,7 @@ import type { ViewportInput } from '../types/IViewport';
17
17
  import {
18
18
  actorIsA,
19
19
  getClosestImageId,
20
+ getSpacingInNormalDirection,
20
21
  isImageActor,
21
22
  triggerEvent,
22
23
  } from '../utilities';
@@ -244,7 +245,7 @@ class VolumeViewport extends BaseVolumeViewport {
244
245
  const mapper = actorEntry.actor.getMapper();
245
246
  const vtkPlanes = mapper.getClippingPlanes();
246
247
 
247
- if (vtkPlanes.length === 0) {
248
+ if (vtkPlanes.length === 0 && !actorEntry?.clippingFilter) {
248
249
  const clipPlane1 = vtkPlane.newInstance();
249
250
  const clipPlane2 = vtkPlane.newInstance();
250
251
  const newVtkPlanes = [clipPlane1, clipPlane2];
@@ -305,21 +306,18 @@ class VolumeViewport extends BaseVolumeViewport {
305
306
 
306
307
  /**
307
308
  * Uses the origin and focalPoint to calculate the slice index.
308
- * Todo: This only works if the imageIds are properly sorted
309
309
  *
310
- * @returns The slice index
310
+ * @returns The slice index in the direction of the view
311
311
  */
312
- public getCurrentImageIdIndex = (): number | undefined => {
312
+ public getCurrentImageIdIndex = (volumeId?: string): number => {
313
313
  const { viewPlaneNormal, focalPoint } = this.getCamera();
314
314
 
315
- // Todo: handle scenario of fusion of multiple volumes
316
- // we cannot only check number of actors, because we might have
317
- // segmentations ...
318
- const { origin, spacing } = this.getImageData();
315
+ const { origin, direction, spacing } = this.getImageData(volumeId);
319
316
 
320
- // how many steps are from the origin to the focal point in the
321
- // normal direction
322
- const spacingInNormal = spacing[2];
317
+ const spacingInNormal = getSpacingInNormalDirection(
318
+ { direction, spacing },
319
+ viewPlaneNormal
320
+ );
323
321
  const sub = vec3.create();
324
322
  vec3.sub(sub, focalPoint, origin);
325
323
  const distance = vec3.dot(sub, viewPlaneNormal);
@@ -46,6 +46,14 @@ class VolumeViewport3D extends BaseVolumeViewport {
46
46
  return null;
47
47
  };
48
48
 
49
+ posProcessNewActors(): void {
50
+ if (this.newActorAdded) {
51
+ const renderer = this.getRenderer();
52
+ renderer.resetCameraClippingRange();
53
+ }
54
+ super.posProcessNewActors();
55
+ }
56
+
49
57
  setSlabThickness(
50
58
  slabThickness: number,
51
59
  filterActorUIDs?: Array<string>
@@ -125,7 +125,7 @@ export class ImageVolume implements IImageVolume {
125
125
  return <VolumeScalarData>this.scalarData;
126
126
  }
127
127
 
128
- throw new Error('Unknow scalar data type');
128
+ throw new Error('Unknown scalar data type');
129
129
  }
130
130
 
131
131
  /**
@@ -0,0 +1,49 @@
1
+ import { SurfaceData, Point3 } from '../../types';
2
+
3
+ type SurfaceProps = {
4
+ id: string;
5
+ data: SurfaceData;
6
+ frameOfReferenceUID: string;
7
+ color?: Point3;
8
+ };
9
+
10
+ /**
11
+ * Surface class for storing surface data
12
+ */
13
+ export class Surface {
14
+ readonly id: string;
15
+ readonly sizeInBytes: number;
16
+ readonly frameOfReferenceUID: string;
17
+ private color: Point3 = [200, 0, 0]; // default color
18
+ private points: number[];
19
+ private polys: number[];
20
+
21
+ constructor(props: SurfaceProps) {
22
+ this.id = props.id;
23
+ this.points = props.data.points;
24
+ this.polys = props.data.polys;
25
+ this.color = props.color ?? this.color;
26
+ this.frameOfReferenceUID = props.frameOfReferenceUID;
27
+ this.sizeInBytes = this._getSizeInBytes();
28
+ }
29
+
30
+ _getSizeInBytes(): number {
31
+ return this.points.length * 4 + this.polys.length * 4;
32
+ }
33
+
34
+ public getColor(): Point3 {
35
+ return this.color;
36
+ }
37
+
38
+ public getPoints(): number[] {
39
+ return this.points;
40
+ }
41
+
42
+ public getPolys(): number[] {
43
+ return this.polys;
44
+ }
45
+
46
+ public getSizeInBytes(): number {
47
+ return this.sizeInBytes;
48
+ }
49
+ }
@@ -209,6 +209,11 @@ enum Events {
209
209
  * This is usually for signaling that the user may want a different volume for partially loaded volumes which is meant to optimize memory.
210
210
  */
211
211
  VOLUME_SCROLL_OUT_OF_BOUNDS = 'CORNERSTONE_VOLUME_SCROLL_OUT_OF_BOUNDS',
212
+
213
+ /**
214
+ * Triggers when the clipping planes has been updated
215
+ */
216
+ CLIPPING_PLANES_UPDATED = 'CORNERSTONE_CLIPPING_PLANES_UPDATED',
212
217
  // IMAGE_CACHE_FULL = 'CORNERSTONE_IMAGE_CACHE_FULL',
213
218
  // PRE_RENDER = 'CORNERSTONE_PRE_RENDER',
214
219
  // ELEMENT_RESIZED = 'CORNERSTONE_ELEMENT_RESIZED',
@@ -1,5 +1,6 @@
1
1
  enum GeometryType {
2
2
  CONTOUR = 'contour',
3
+ SURFACE = 'Surface',
3
4
  }
4
5
 
5
6
  export default GeometryType;
@@ -1,13 +1,14 @@
1
1
  import '@kitware/vtk.js/Rendering/Profiles/Geometry';
2
2
 
3
3
  import cache from '../cache';
4
- import { ContourSet } from '../cache/classes/ContourSet';
5
4
  import { GeometryType } from '../enums';
6
- import { IGeometry, PublicContourSetData } from '../types';
5
+ import { IGeometry, PublicContourSetData, PublicSurfaceData } from '../types';
6
+ import { createContourSet } from './utils/contourSet/createContourSet';
7
+ import { createSurface } from './utils/surface/createSurface';
7
8
 
8
9
  type GeometryOptions = {
9
10
  type: GeometryType;
10
- geometryData: PublicContourSetData; // | PublicClosedSurfaceData, ...
11
+ geometryData: PublicContourSetData | PublicSurfaceData;
11
12
  };
12
13
 
13
14
  /**
@@ -33,7 +34,15 @@ async function createAndCacheGeometry(
33
34
  }
34
35
 
35
36
  if (options.type === GeometryType.CONTOUR) {
36
- geometry = _createContourSet(geometryId, options.geometryData);
37
+ geometry = createContourSet(
38
+ geometryId,
39
+ options.geometryData as PublicContourSetData
40
+ );
41
+ } else if (options.type === GeometryType.SURFACE) {
42
+ geometry = createSurface(
43
+ geometryId,
44
+ options.geometryData as PublicSurfaceData
45
+ );
37
46
  } else {
38
47
  throw new Error('Unknown geometry type, Only CONTOUR is supported');
39
48
  }
@@ -47,63 +56,4 @@ async function createAndCacheGeometry(
47
56
  return geometry;
48
57
  }
49
58
 
50
- // Todo: this should be moved
51
- function _createContourSet(
52
- geometryId: string,
53
- contourSetData: PublicContourSetData
54
- ) {
55
- // validate the data to make sure it is a valid contour set
56
- if (!contourSetData || contourSetData.data.length === 0) {
57
- throw new Error(
58
- 'Invalid contour set data, see publicContourSetData type for more info'
59
- );
60
- }
61
-
62
- // make sure it each has id, and each has data of type Point3[]
63
- if (!contourSetData.id) {
64
- throw new Error(
65
- 'Invalid contour set data, each contour set must have an id'
66
- );
67
- }
68
-
69
- if (!contourSetData.data || !Array.isArray(contourSetData.data)) {
70
- throw new Error(
71
- 'Invalid contour set data, each contour set must have an array of contours'
72
- );
73
- }
74
-
75
- contourSetData.data.forEach((contourData) => {
76
- if (!contourData.points || !Array.isArray(contourData.points)) {
77
- throw new Error(
78
- 'Invalid contour set data, each contour must have an array of points'
79
- );
80
- }
81
-
82
- contourData.points.forEach((point) => {
83
- if (!point || !Array.isArray(point) || point.length !== 3) {
84
- throw new Error(
85
- 'Invalid contour set data, each point must be an array of length 3'
86
- );
87
- }
88
- });
89
- });
90
-
91
- const contourSet = new ContourSet({
92
- id: contourSetData.id,
93
- data: contourSetData.data,
94
- color: contourSetData.color,
95
- frameOfReferenceUID: contourSetData.frameOfReferenceUID,
96
- segmentIndex: contourSetData.segmentIndex,
97
- });
98
-
99
- const geometry: IGeometry = {
100
- id: geometryId,
101
- type: GeometryType.CONTOUR,
102
- data: contourSet,
103
- sizeInBytes: contourSet.getSizeInBytes(),
104
- };
105
-
106
- return geometry;
107
- }
108
-
109
59
  export { createAndCacheGeometry };
@@ -0,0 +1,29 @@
1
+ import { IGeometry, PublicContourSetData } from '../../../types';
2
+ import { GeometryType } from '../../../enums';
3
+ import { validateContourSet } from './validateContourSet';
4
+ import { ContourSet } from '../../../cache/classes/ContourSet';
5
+
6
+ export function createContourSet(
7
+ geometryId: string,
8
+ contourSetData: PublicContourSetData
9
+ ) {
10
+ // validate the data to make sure it is a valid contour set
11
+ validateContourSet(contourSetData);
12
+
13
+ const contourSet = new ContourSet({
14
+ id: contourSetData.id,
15
+ data: contourSetData.data,
16
+ color: contourSetData.color,
17
+ frameOfReferenceUID: contourSetData.frameOfReferenceUID,
18
+ segmentIndex: 1,
19
+ });
20
+
21
+ const geometry: IGeometry = {
22
+ id: geometryId,
23
+ type: GeometryType.CONTOUR,
24
+ data: contourSet,
25
+ sizeInBytes: contourSet.getSizeInBytes(),
26
+ };
27
+
28
+ return geometry;
29
+ }
@@ -0,0 +1,38 @@
1
+ import { PublicContourSetData } from '../../../types';
2
+
3
+ export function validateContourSet(contourSetData: PublicContourSetData) {
4
+ if (!contourSetData || contourSetData.data.length === 0) {
5
+ throw new Error(
6
+ 'Invalid contour set data, see publicContourSetData type for more info'
7
+ );
8
+ }
9
+
10
+ // make sure it each has id, and each has data of type Point3[]
11
+ if (!contourSetData.id) {
12
+ throw new Error(
13
+ 'Invalid contour set data, each contour set must have an id'
14
+ );
15
+ }
16
+
17
+ if (!contourSetData.data || !Array.isArray(contourSetData.data)) {
18
+ throw new Error(
19
+ 'Invalid contour set data, each contour set must have an array of contours'
20
+ );
21
+ }
22
+
23
+ contourSetData.data.forEach((contourData) => {
24
+ if (!contourData.points || !Array.isArray(contourData.points)) {
25
+ throw new Error(
26
+ 'Invalid contour set data, each contour must have an array of points'
27
+ );
28
+ }
29
+
30
+ contourData.points.forEach((point) => {
31
+ if (!point || !Array.isArray(point) || point.length !== 3) {
32
+ throw new Error(
33
+ 'Invalid contour set data, each point must be an array of length 3'
34
+ );
35
+ }
36
+ });
37
+ });
38
+ }
@@ -0,0 +1,31 @@
1
+ import { IGeometry, PublicSurfaceData } from '../../../types';
2
+ import { GeometryType } from '../../../enums';
3
+ import { validateSurface } from './validateSurface';
4
+ import { Surface } from '../../../cache/classes/Surface';
5
+
6
+ export function createSurface(
7
+ geometryId: string,
8
+ SurfaceData: PublicSurfaceData
9
+ ) {
10
+ // validate the data to make sure it is a valid contour set
11
+ validateSurface(SurfaceData);
12
+
13
+ const surface = new Surface({
14
+ id: SurfaceData.id,
15
+ color: SurfaceData.color,
16
+ frameOfReferenceUID: SurfaceData.frameOfReferenceUID,
17
+ data: {
18
+ points: SurfaceData.data.points,
19
+ polys: SurfaceData.data.polys,
20
+ },
21
+ });
22
+
23
+ const geometry: IGeometry = {
24
+ id: geometryId,
25
+ type: GeometryType.SURFACE,
26
+ data: surface,
27
+ sizeInBytes: surface.getSizeInBytes(),
28
+ };
29
+
30
+ return geometry;
31
+ }
@@ -0,0 +1,9 @@
1
+ import { PublicSurfaceData } from '../../../types';
2
+
3
+ export function validateSurface(contourSetData: PublicSurfaceData) {
4
+ const { data } = contourSetData;
5
+
6
+ if (!data.points || !data.polys) {
7
+ throw new Error('Invalid surface data');
8
+ }
9
+ }
@@ -20,4 +20,6 @@ export type ActorEntry = {
20
20
  referenceId?: string;
21
21
  /** slab thickness for the actor */
22
22
  slabThickness?: number;
23
+ /** clipping filter applied to actor surfaces*/
24
+ clippingFilter?: any;
23
25
  };
@@ -1,3 +1,4 @@
1
+ import { Surface } from '../cache/classes/Surface';
1
2
  import { GeometryType } from '../enums';
2
3
  import { IContourSet } from './IContourSet';
3
4
 
@@ -5,7 +6,7 @@ import { IContourSet } from './IContourSet';
5
6
  interface IGeometry {
6
7
  id: string;
7
8
  type: GeometryType;
8
- data: IContourSet; // | Array<IClosedSurface> , etc
9
+ data: IContourSet | Surface;
9
10
  sizeInBytes: number;
10
11
  }
11
12
 
@@ -0,0 +1,15 @@
1
+ import Point3 from './Point3';
2
+
3
+ type PublicSurfaceData = {
4
+ id: string;
5
+ data: SurfaceData;
6
+ frameOfReferenceUID: string;
7
+ color?: Point3;
8
+ };
9
+
10
+ type SurfaceData = {
11
+ points: number[];
12
+ polys: number[];
13
+ };
14
+
15
+ export type { PublicSurfaceData, SurfaceData };
@@ -72,6 +72,7 @@ import type {
72
72
  ContourSetData,
73
73
  ContourData,
74
74
  } from './ContourData';
75
+ import type { PublicSurfaceData, SurfaceData } from './SurfaceData';
75
76
  import type ICachedGeometry from './ICachedGeometry';
76
77
  import type { IContourSet } from './IContourSet';
77
78
  import type { IContour } from './IContour';
@@ -166,6 +167,9 @@ export type {
166
167
  ContourData,
167
168
  IContourSet,
168
169
  IContour,
170
+ // Surface
171
+ PublicSurfaceData,
172
+ SurfaceData,
169
173
  // Color
170
174
  RGB,
171
175
  ColormapPublic,
@@ -1,4 +1,4 @@
1
- import { vec3 } from 'gl-matrix';
1
+ import { mat3, vec3 } from 'gl-matrix';
2
2
  import { IImageVolume, Point3 } from '../types';
3
3
 
4
4
  /**
@@ -13,7 +13,7 @@ import { IImageVolume, Point3 } from '../types';
13
13
  * @returns
14
14
  */
15
15
  export default function getSpacingInNormalDirection(
16
- imageVolume: IImageVolume,
16
+ imageVolume: IImageVolume | { direction: mat3; spacing: Point3 },
17
17
  viewPlaneNormal: Point3
18
18
  ): number {
19
19
  const { direction, spacing } = imageVolume;