@ohif/app 3.13.0-beta.35 → 3.13.0-beta.39

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 (49) hide show
  1. package/dist/{147.bundle.9c245011849e09bd7904.js → 147.bundle.f71d384c49f50e23f795.js} +15 -40
  2. package/dist/{1608.bundle.417884758328a1fc04a9.js → 1608.bundle.c10d9aef452fe5a86d77.js} +2 -2
  3. package/dist/{1933.bundle.19f83b2c7881912dcc34.js → 1933.bundle.0aba0ce3d97d32bd3ca5.js} +2 -2
  4. package/dist/{2701.bundle.2cfa58ae04427d4c897d.js → 2701.bundle.28b3ca0e6ae5a13f78b3.js} +2 -2
  5. package/dist/{3138.bundle.4e151e0dbd74a8265f42.js → 3138.bundle.a377f868158dec8efdb0.js} +2 -2
  6. package/dist/{4202.bundle.9dc6af971a47981d2a5e.js → 4202.bundle.f11f02596e30a22d1105.js} +1 -1
  7. package/dist/{4287.bundle.d2d09ffd5cd8680fad8d.js → 4287.bundle.b7840e7b94cbbc102236.js} +3 -3
  8. package/dist/{4688.bundle.add6a6c6bb72fcd35ee3.js → 4688.bundle.324f320f177fe7f70db8.js} +130 -120
  9. package/dist/{4819.bundle.1ff04ae518bab5e59dc6.js → 4819.bundle.5aa5ed42843908dbb820.js} +4 -4
  10. package/dist/{5015.bundle.a35182426b6b4d2d1fe4.js → 5015.bundle.4f91f03ea8084a82657b.js} +2 -2
  11. package/dist/{5802.bundle.70d423c8b488cc56cc36.js → 5802.bundle.a3a398ddaac222cf08f7.js} +2 -2
  12. package/dist/{581.bundle.b70e5d2d0f3958df69f0.js → 581.bundle.f48ce2a0f0dae080154c.js} +7 -6
  13. package/dist/{6354.bundle.d8a592b03e9a5b7a66c2.js → 6354.bundle.929febcf6d326e582e00.js} +50 -45
  14. package/dist/{6386.bundle.c0618e49b65769ddf752.js → 6386.bundle.e75a2f70039dfe42f935.js} +11 -3
  15. package/dist/{7537.bundle.1a18959ceec98634bc48.js → 7537.bundle.b784154ebd4c85946642.js} +758 -679
  16. package/dist/{8305.bundle.7e577ab4f21ac44d355e.js → 8305.bundle.371dde3415de88db3f43.js} +2 -2
  17. package/dist/{8583.bundle.47394b6ef65ff3a4190c.js → 8583.bundle.f6c226c9fa6de90f2bcb.js} +2 -2
  18. package/dist/{6280.bundle.081861b7e685b28616c8.js → 9039.bundle.fd54c15934103ff3fd3b.js} +1470 -1259
  19. package/dist/{9195.bundle.a38804074672c87ad1ec.js → 9195.bundle.afd5483195e12e5cef8e.js} +8 -8
  20. package/dist/{9205.bundle.09c52845b43bd8513d50.js → 9205.bundle.7c4a29705386dcefd999.js} +1602 -1347
  21. package/dist/{933.bundle.ea9db108b8a4e3d51904.js → 9567.bundle.be350438bed4e656f278.js} +2690 -193
  22. package/dist/{9845.bundle.fe6930acb204e2fd8323.js → 9845.bundle.36b3563ae1dba65b6b9a.js} +2 -2
  23. package/dist/{9862.bundle.47e7574a486c30ab0dfd.js → 9862.bundle.f59f3a574a92024c8823.js} +1 -1
  24. package/dist/{app.bundle.3e902f3aba87f5fdaca0.js → app.bundle.6c3daf11c7fbd7e48175.js} +970 -811
  25. package/dist/app.bundle.css +1 -1
  26. package/dist/{compute.bundle.6016de6e5f7c25749422.js → compute.bundle.47da6b38c64751bdb9c4.js} +1 -1
  27. package/dist/{histogram-worker.bundle.5b679ce4142c803c80a4.js → histogram-worker.bundle.a2a50c4674d99c619ca7.js} +1 -1
  28. package/dist/index.html +1 -1
  29. package/dist/{interpolation.bundle.072a28b303f2dbafe05c.js → interpolation.bundle.53073c15cca1c5a41ae4.js} +1 -1
  30. package/dist/{polySeg.bundle.cdcc2c3d11009ccf112c.js → polySeg.bundle.8954fb59f99daeb3f0b0.js} +3 -3
  31. package/dist/sw.js +1 -1
  32. package/package.json +21 -21
  33. /package/dist/{1459.bundle.062605b72ad894597c40.js → 1459.bundle.4aef0d934c3a12aa66bb.js} +0 -0
  34. /package/dist/{2018.bundle.d8cf3001bae55516d13a.js → 2018.bundle.896e322e7c39599383f7.js} +0 -0
  35. /package/dist/{2075.bundle.16215ba94d714a1c905f.js → 2075.bundle.0e69a126a39539ff8e9a.js} +0 -0
  36. /package/dist/{213.bundle.5527b63c734814bca27c.js → 213.bundle.9a4de523c0842d7bd7fd.js} +0 -0
  37. /package/dist/{2424.bundle.7cf905346cf856a74d18.js → 2424.bundle.6a9ca8e7e84f5528c8d1.js} +0 -0
  38. /package/dist/{3461.bundle.19921563b1d9ee7c4599.js → 3461.bundle.b6304f280d7dc0ade73a.js} +0 -0
  39. /package/dist/{4507.bundle.816349fd19d1f7feb8cc.js → 4507.bundle.67c73fab897aa7040fce.js} +0 -0
  40. /package/dist/{5028.bundle.12210efc962029543cf8.js → 5028.bundle.71b240621417df1a6fab.js} +0 -0
  41. /package/dist/{5457.bundle.ce2a509fad38c7b5d23e.js → 5457.bundle.109f104b4520e6374fa6.js} +0 -0
  42. /package/dist/{5485.bundle.18ac74bcc1f62f4ff48a.js → 5485.bundle.a88fd5be3f5aa20dc643.js} +0 -0
  43. /package/dist/{6027.bundle.11593983ae8a72b4b10d.js → 6027.bundle.555553c951bba02afa54.js} +0 -0
  44. /package/dist/{7431.bundle.84b3d88ef94b97c84298.js → 7431.bundle.e5a9b628c993b78ff7db.js} +0 -0
  45. /package/dist/{7639.bundle.47fa2f67acb39082efe9.js → 7639.bundle.0f0b2419e43c7dc3b88a.js} +0 -0
  46. /package/dist/{8499.bundle.ef8d548ca8261c78ed2b.js → 8499.bundle.c179a028eae7170b397d.js} +0 -0
  47. /package/dist/{85.bundle.47697c7697f28e3d1865.js → 85.bundle.80b16edc06976de80ae6.js} +0 -0
  48. /package/dist/{8558.bundle.b7124f251785e778c3c1.js → 8558.bundle.f08683ca26d63fb8c0ef.js} +0 -0
  49. /package/dist/{9927.bundle.861ce96aab6eed8e6ff3.js → 9927.bundle.6966a86ab930197c8295.js} +0 -0
@@ -1,4 +1,4 @@
1
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[2075,6280],{
1
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[2075,9039],{
2
2
 
3
3
  /***/ 5057
4
4
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
@@ -348,6 +348,7 @@ __webpack_require__.d(__webpack_exports__, {
348
348
  addImageSlicesToViewports: () => (/* reexport */ helpers/* addImageSlicesToViewports */.ge),
349
349
  addVolumesToViewports: () => (/* reexport */ helpers/* addVolumesToViewports */.x),
350
350
  cache: () => (/* reexport */ cache_cache/* default */.Ay),
351
+ convertColorArrayToRgbString: () => (/* reexport */ convertColorArrayToRgbString/* convertColorArrayToRgbString */.J),
351
352
  convertMapperToNotSharedMapper: () => (/* reexport */ createVolumeMapper/* convertMapperToNotSharedMapper */.h),
352
353
  eventTarget: () => (/* reexport */ eventTarget/* default */.A),
353
354
  getConfiguration: () => (/* reexport */ init/* getConfiguration */.D0),
@@ -626,6 +627,8 @@ var decimatedVolumeLoader = __webpack_require__(18481);
626
627
  var utilities = __webpack_require__(85343);
627
628
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/triggerEvent.js
628
629
  var triggerEvent = __webpack_require__(69372);
630
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/convertColorArrayToRgbString.js
631
+ var convertColorArrayToRgbString = __webpack_require__(57652);
629
632
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/cornerstoneStreamingImageVolumeLoader.js
630
633
  var cornerstoneStreamingImageVolumeLoader = __webpack_require__(55500);
631
634
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/loaders/cornerstoneStreamingDynamicImageVolumeLoader.js
@@ -675,6 +678,7 @@ var helpers = __webpack_require__(40661);
675
678
 
676
679
 
677
680
 
681
+
678
682
 
679
683
 
680
684
  /***/ },
@@ -3231,6 +3235,7 @@ __webpack_require__.d(__webpack_exports__, {
3231
3235
  clip: () => (/* reexport */ utilities_clip),
3232
3236
  color: () => (/* reexport */ color_namespaceObject),
3233
3237
  colormap: () => (/* reexport */ colormap),
3238
+ convertColorArrayToRgbString: () => (/* reexport */ convertColorArrayToRgbString/* convertColorArrayToRgbString */.J),
3234
3239
  convertStackToVolumeViewport: () => (/* reexport */ convertStackToVolumeViewport),
3235
3240
  convertToGrayscale: () => (/* reexport */ convertToGrayscale),
3236
3241
  convertVolumeToStackViewport: () => (/* reexport */ convertVolumeToStackViewport),
@@ -4660,6 +4665,8 @@ function convertToGrayscale(scalarData, width, height) {
4660
4665
  }
4661
4666
  }
4662
4667
 
4668
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/convertColorArrayToRgbString.js
4669
+ var convertColorArrayToRgbString = __webpack_require__(57652);
4663
4670
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/RenderingEngine/index.js + 3 modules
4664
4671
  var RenderingEngine = __webpack_require__(90340);
4665
4672
  ;// ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/getViewportImageIds.js
@@ -5573,6 +5580,7 @@ var updatePlaneRestriction = __webpack_require__(41365);
5573
5580
 
5574
5581
 
5575
5582
 
5583
+
5576
5584
 
5577
5585
 
5578
5586
  const getViewportModality = (viewport, volumeId) => _getViewportModality(viewport, volumeId, cache/* default */.Ay.getVolume);
@@ -6347,7 +6355,7 @@ function toLowHighRange(windowWidth, windowCenter, voiLUTFunction = _enums_VOILU
6347
6355
 
6348
6356
  /***/ },
6349
6357
 
6350
- /***/ 4921
6358
+ /***/ 94836
6351
6359
  (__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) {
6352
6360
 
6353
6361
  "use strict";
@@ -7298,7 +7306,7 @@ var COLOR_LUT = __webpack_require__(93952);
7298
7306
 
7299
7307
 
7300
7308
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/version.js
7301
- const version = '4.18.2';
7309
+ const version = '4.19.0';
7302
7310
 
7303
7311
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/synchronizers/callbacks/cameraSyncCallback.js
7304
7312
  /* unused harmony import specifier */ var cameraSyncCallback_getRenderingEngine;
@@ -8251,6 +8259,65 @@ function _createCinePlayContext(viewport, playClipOptions) {
8251
8259
 
8252
8260
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/boundingBox/index.js
8253
8261
  var boundingBox = __webpack_require__(72282);
8262
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/DataModel/PolyData.js + 7 modules
8263
+ var PolyData = __webpack_require__(27480);
8264
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/Core/Points.js
8265
+ var Points = __webpack_require__(74973);
8266
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/Core/CellArray.js
8267
+ var CellArray = __webpack_require__(32461);
8268
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/Actor.js
8269
+ var Actor = __webpack_require__(44404);
8270
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/Mapper.js + 1 modules
8271
+ var Mapper = __webpack_require__(81418);
8272
+ ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/draw3D/addLine3DBetweenPoints.js
8273
+
8274
+
8275
+
8276
+
8277
+
8278
+ function addLine3DBetweenPoints(viewport, point1, point2, color = [0.7, 0.7, 0.7], uid = '', showHandles = true) {
8279
+ if (point1[0] === point2[0] &&
8280
+ point1[1] === point2[1] &&
8281
+ point1[2] === point2[2]) {
8282
+ return { actor: null, source: null };
8283
+ }
8284
+ const points = Points/* default.newInstance */.Ay.newInstance();
8285
+ points.setNumberOfPoints(2);
8286
+ points.setPoint(0, point1[0], point1[1], point1[2]);
8287
+ points.setPoint(1, point2[0], point2[1], point2[2]);
8288
+ const lines = CellArray/* default.newInstance */.Ay.newInstance({ values: [2, 0, 1] });
8289
+ const polyData = PolyData/* default.newInstance */.Ay.newInstance();
8290
+ polyData.setPoints(points);
8291
+ polyData.setLines(lines);
8292
+ const mapper = Mapper/* default.newInstance */.Ay.newInstance();
8293
+ mapper.setInputData(polyData);
8294
+ const actor = Actor/* default.newInstance */.Ay.newInstance();
8295
+ actor.setMapper(mapper);
8296
+ actor.getProperty().setColor(...color);
8297
+ actor.getProperty().setLineWidth(0.5);
8298
+ actor.getProperty().setOpacity(1.0);
8299
+ actor.getProperty().setInterpolationToFlat();
8300
+ actor.getProperty().setAmbient(1.0);
8301
+ actor.getProperty().setDiffuse(0.0);
8302
+ actor.getProperty().setSpecular(0.0);
8303
+ actor.setVisibility(showHandles);
8304
+ viewport.addActor({ actor, uid });
8305
+ return { actor, source: polyData };
8306
+ }
8307
+
8308
+ ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/draw3D/calculateAdaptiveSphereRadius.js
8309
+ function calculateAdaptiveSphereRadius(diagonal, config) {
8310
+ const scaleFactor = config.sphereRadiusScale || 0.01;
8311
+ const adaptiveRadius = diagonal * scaleFactor;
8312
+ const minRadius = config.minSphereRadius || 2;
8313
+ const maxRadius = config.maxSphereRadius || 50;
8314
+ return Math.max(minRadius, Math.min(maxRadius, adaptiveRadius));
8315
+ }
8316
+
8317
+ ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/draw3D/index.js
8318
+
8319
+
8320
+
8254
8321
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/planarFreehandROITool/smoothAnnotation.js
8255
8322
  var smoothAnnotation = __webpack_require__(61587);
8256
8323
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/planarFreehandROITool/index.js
@@ -10265,6 +10332,7 @@ function calculateFanGeometry(imageId) {
10265
10332
 
10266
10333
 
10267
10334
 
10335
+
10268
10336
 
10269
10337
 
10270
10338
  const roundNumber = esm.utilities.roundNumber;
@@ -11266,20 +11334,12 @@ class TrackballRotateTool extends base/* BaseTool */.oS {
11266
11334
  TrackballRotateTool.toolName = 'TrackballRotate';
11267
11335
  /* harmony default export */ const tools_TrackballRotateTool = ((/* unused pure expression or super */ null && (TrackballRotateTool)));
11268
11336
 
11269
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/DataModel/PolyData.js + 11 modules
11270
- var PolyData = __webpack_require__(12548);
11271
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/Core/Points.js
11272
- var Points = __webpack_require__(74973);
11273
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/Core/CellArray.js
11274
- var CellArray = __webpack_require__(32461);
11275
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/Actor.js
11276
- var Actor = __webpack_require__(44404);
11277
11337
  // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Filters/Sources/SphereSource.js
11278
11338
  var SphereSource = __webpack_require__(73435);
11279
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/Mapper.js + 1 modules
11280
- var Mapper = __webpack_require__(81418);
11281
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/DataModel/Plane.js + 1 modules
11282
- var Plane = __webpack_require__(43884);
11339
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/DataModel/Plane.js
11340
+ var Plane = __webpack_require__(49794);
11341
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/volumeCropping/index.js + 8 modules
11342
+ var volumeCropping = __webpack_require__(88380);
11283
11343
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/VolumeCroppingTool.js
11284
11344
 
11285
11345
 
@@ -11294,30 +11354,6 @@ var Plane = __webpack_require__(43884);
11294
11354
 
11295
11355
 
11296
11356
 
11297
- const PLANEINDEX = {
11298
- XMIN: 0,
11299
- XMAX: 1,
11300
- YMIN: 2,
11301
- YMAX: 3,
11302
- ZMIN: 4,
11303
- ZMAX: 5,
11304
- };
11305
- const SPHEREINDEX = {
11306
- XMIN: 0,
11307
- XMAX: 1,
11308
- YMIN: 2,
11309
- YMAX: 3,
11310
- ZMIN: 4,
11311
- ZMAX: 5,
11312
- XMIN_YMIN_ZMIN: 6,
11313
- XMIN_YMIN_ZMAX: 7,
11314
- XMIN_YMAX_ZMIN: 8,
11315
- XMIN_YMAX_ZMAX: 9,
11316
- XMAX_YMIN_ZMIN: 10,
11317
- XMAX_YMIN_ZMAX: 11,
11318
- XMAX_YMAX_ZMIN: 12,
11319
- XMAX_YMAX_ZMAX: 13,
11320
- };
11321
11357
  class VolumeCroppingTool extends base/* BaseTool */.oS {
11322
11358
  constructor(toolProps = {}, defaultToolProps = {
11323
11359
  configuration: {
@@ -11339,6 +11375,7 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11339
11375
  grabSpherePixelDistance: 20,
11340
11376
  rotateIncrementDegrees: 2,
11341
11377
  rotateSampleDistanceFactor: 2,
11378
+ rotateClippingPlanesIncrementDegrees: 5,
11342
11379
  },
11343
11380
  }) {
11344
11381
  super(toolProps, defaultToolProps);
@@ -11346,16 +11383,15 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11346
11383
  this._hasResolutionChanged = false;
11347
11384
  this.originalClippingPlanes = [];
11348
11385
  this.draggingSphereIndex = null;
11349
- this.toolCenter = [0, 0, 0];
11386
+ this.rotatePlanesOnDrag = false;
11350
11387
  this.cornerDragOffset = null;
11351
11388
  this.faceDragOffset = null;
11389
+ this.volumeDirectionVectors = null;
11352
11390
  this.sphereStates = [];
11353
11391
  this.edgeLines = {};
11354
11392
  this.onSetToolConfiguration = () => {
11355
- console.debug('Setting tool settoolconfiguration : volumeCropping');
11356
11393
  };
11357
11394
  this.onSetToolEnabled = () => {
11358
- console.debug('Setting tool enabled: volumeCropping');
11359
11395
  };
11360
11396
  this.onCameraModified = (evt) => {
11361
11397
  const { element } = evt.currentTarget
@@ -11398,9 +11434,16 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11398
11434
  this.faceDragOffset = null;
11399
11435
  }
11400
11436
  else {
11401
- const axisIdx = { x: 0, y: 1, z: 2 }[sphereState.axis];
11437
+ const directionVector = this._getDirectionVectorForAxis(sphereState.axis);
11438
+ const delta = [
11439
+ sphereState.point[0] - mouseWorld[0],
11440
+ sphereState.point[1] - mouseWorld[1],
11441
+ sphereState.point[2] - mouseWorld[2],
11442
+ ];
11402
11443
  this.faceDragOffset =
11403
- sphereState.point[axisIdx] - mouseWorld[axisIdx];
11444
+ delta[0] * directionVector[0] +
11445
+ delta[1] * directionVector[1] +
11446
+ delta[2] * directionVector[2];
11404
11447
  this.cornerDragOffset = null;
11405
11448
  }
11406
11449
  return true;
@@ -11455,118 +11498,143 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11455
11498
  return false;
11456
11499
  }
11457
11500
  if (sphereState.isCorner) {
11458
- const newCorner = this._calculateNewCornerPosition(world);
11459
- this._updateSpherePosition(sphereState, newCorner);
11460
- const axisFlags = this._parseCornerKey(sphereState.uid);
11461
- this._updateRelatedCorners(sphereState, newCorner, axisFlags);
11462
- this._updateFaceSpheresFromCorners();
11501
+ const newCorner = this.cornerDragOffset
11502
+ ? gl_matrix_esm/* vec3.add */.eR.add([0, 0, 0], world, this.cornerDragOffset)
11503
+ : world;
11504
+ const oldCorner = sphereState.point;
11505
+ const axisFlags = (0,volumeCropping.parseCornerKey)(sphereState.uid);
11506
+ const { xDir, yDir, zDir } = this._getDirectionVectors();
11507
+ if (!xDir || !yDir || !zDir)
11508
+ return false;
11509
+ const delta = [
11510
+ newCorner[0] - oldCorner[0],
11511
+ newCorner[1] - oldCorner[1],
11512
+ newCorner[2] - oldCorner[2],
11513
+ ];
11514
+ const deltaX = delta[0] * xDir[0] + delta[1] * xDir[1] + delta[2] * xDir[2];
11515
+ const deltaY = delta[0] * yDir[0] + delta[1] * yDir[1] + delta[2] * yDir[2];
11516
+ const deltaZ = delta[0] * zDir[0] + delta[1] * zDir[1] + delta[2] * zDir[2];
11517
+ if (axisFlags.isXMin) {
11518
+ const faceXMin = this.sphereStates[volumeCropping.SPHEREINDEX.XMIN];
11519
+ const newPoint = [
11520
+ faceXMin.point[0] + deltaX * xDir[0],
11521
+ faceXMin.point[1] + deltaX * xDir[1],
11522
+ faceXMin.point[2] + deltaX * xDir[2],
11523
+ ];
11524
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.XMIN, newPoint);
11525
+ }
11526
+ else if (axisFlags.isXMax) {
11527
+ const faceXMax = this.sphereStates[volumeCropping.SPHEREINDEX.XMAX];
11528
+ const newPoint = [
11529
+ faceXMax.point[0] + deltaX * xDir[0],
11530
+ faceXMax.point[1] + deltaX * xDir[1],
11531
+ faceXMax.point[2] + deltaX * xDir[2],
11532
+ ];
11533
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.XMAX, newPoint);
11534
+ }
11535
+ if (axisFlags.isYMin) {
11536
+ const faceYMin = this.sphereStates[volumeCropping.SPHEREINDEX.YMIN];
11537
+ const newPoint = [
11538
+ faceYMin.point[0] + deltaY * yDir[0],
11539
+ faceYMin.point[1] + deltaY * yDir[1],
11540
+ faceYMin.point[2] + deltaY * yDir[2],
11541
+ ];
11542
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.YMIN, newPoint);
11543
+ }
11544
+ else if (axisFlags.isYMax) {
11545
+ const faceYMax = this.sphereStates[volumeCropping.SPHEREINDEX.YMAX];
11546
+ const newPoint = [
11547
+ faceYMax.point[0] + deltaY * yDir[0],
11548
+ faceYMax.point[1] + deltaY * yDir[1],
11549
+ faceYMax.point[2] + deltaY * yDir[2],
11550
+ ];
11551
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.YMAX, newPoint);
11552
+ }
11553
+ if (axisFlags.isZMin) {
11554
+ const faceZMin = this.sphereStates[volumeCropping.SPHEREINDEX.ZMIN];
11555
+ const newPoint = [
11556
+ faceZMin.point[0] + deltaZ * zDir[0],
11557
+ faceZMin.point[1] + deltaZ * zDir[1],
11558
+ faceZMin.point[2] + deltaZ * zDir[2],
11559
+ ];
11560
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.ZMIN, newPoint);
11561
+ }
11562
+ else if (axisFlags.isZMax) {
11563
+ const faceZMax = this.sphereStates[volumeCropping.SPHEREINDEX.ZMAX];
11564
+ const newPoint = [
11565
+ faceZMax.point[0] + deltaZ * zDir[0],
11566
+ faceZMax.point[1] + deltaZ * zDir[1],
11567
+ faceZMax.point[2] + deltaZ * zDir[2],
11568
+ ];
11569
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.ZMAX, newPoint);
11570
+ }
11463
11571
  this._updateCornerSpheres();
11572
+ this._updateFaceSpheresFromCorners();
11464
11573
  }
11465
11574
  else {
11466
- const axisIdx = { x: 0, y: 1, z: 2 }[sphereState.axis];
11467
- let newValue = world[axisIdx];
11468
- if (this.faceDragOffset !== null) {
11469
- newValue += this.faceDragOffset;
11470
- }
11471
- sphereState.point[axisIdx] = newValue;
11472
- sphereState.sphereSource.setCenter(...sphereState.point);
11473
- sphereState.sphereSource.modified();
11575
+ const directionVector = this._getDirectionVectorForAxis(sphereState.axis);
11576
+ const delta = [
11577
+ world[0] - sphereState.point[0],
11578
+ world[1] - sphereState.point[1],
11579
+ world[2] - sphereState.point[2],
11580
+ ];
11581
+ const distanceAlongAxis = delta[0] * directionVector[0] +
11582
+ delta[1] * directionVector[1] +
11583
+ delta[2] * directionVector[2];
11584
+ const adjustedDistance = this.faceDragOffset !== null
11585
+ ? distanceAlongAxis + this.faceDragOffset
11586
+ : distanceAlongAxis;
11587
+ const newPoint = [
11588
+ sphereState.point[0] + adjustedDistance * directionVector[0],
11589
+ sphereState.point[1] + adjustedDistance * directionVector[1],
11590
+ sphereState.point[2] + adjustedDistance * directionVector[2],
11591
+ ];
11592
+ this._updateSpherePosition(this.draggingSphereIndex, newPoint);
11474
11593
  this._updateCornerSpheresFromFaces();
11475
11594
  this._updateFaceSpheresFromCorners();
11476
11595
  this._updateCornerSpheres();
11477
11596
  }
11478
11597
  this._updateClippingPlanesFromFaceSpheres(viewport);
11479
11598
  viewport.render();
11480
- this._triggerToolChangedEvent(sphereState);
11599
+ this._notifyClippingPlanesChanged();
11481
11600
  return true;
11482
11601
  };
11483
11602
  this._onControlToolChange = (evt) => {
11484
11603
  const viewport = this._getViewport();
11485
- if (!evt.detail.toolCenter) {
11486
- (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPING_TOOL_CHANGED, {
11487
- originalClippingPlanes: this.originalClippingPlanes,
11488
- viewportId: viewport.id,
11489
- renderingEngineId: viewport.renderingEngineId,
11490
- seriesInstanceUID: this.seriesInstanceUID,
11491
- });
11604
+ if (evt.detail.seriesInstanceUID !== this.seriesInstanceUID) {
11605
+ return;
11492
11606
  }
11493
- else {
11494
- if (evt.detail.seriesInstanceUID !== this.seriesInstanceUID) {
11495
- return;
11496
- }
11497
- const isMin = evt.detail.handleType === 'min';
11498
- const toolCenter = isMin
11499
- ? evt.detail.toolCenterMin
11500
- : evt.detail.toolCenterMax;
11501
- const normals = isMin
11502
- ? [
11503
- [1, 0, 0],
11504
- [0, 1, 0],
11505
- [0, 0, 1],
11506
- ]
11507
- : [
11508
- [-1, 0, 0],
11509
- [0, -1, 0],
11510
- [0, 0, -1],
11511
- ];
11512
- const planeIndices = isMin
11513
- ? [PLANEINDEX.XMIN, PLANEINDEX.YMIN, PLANEINDEX.ZMIN]
11514
- : [PLANEINDEX.XMAX, PLANEINDEX.YMAX, PLANEINDEX.ZMAX];
11515
- const sphereIndices = isMin
11516
- ? [SPHEREINDEX.XMIN, SPHEREINDEX.YMIN, SPHEREINDEX.ZMIN]
11517
- : [SPHEREINDEX.XMAX, SPHEREINDEX.YMAX, SPHEREINDEX.ZMAX];
11518
- const axes = ['x', 'y', 'z'];
11519
- const orientationAxes = [
11520
- esm.Enums.OrientationAxis.SAGITTAL,
11521
- esm.Enums.OrientationAxis.CORONAL,
11522
- esm.Enums.OrientationAxis.AXIAL,
11523
- ];
11524
- for (let i = 0; i < 3; ++i) {
11525
- const origin = [0, 0, 0];
11526
- origin[i] = toolCenter[i];
11527
- const plane = Plane/* default.newInstance */.Ay.newInstance({
11528
- origin,
11529
- normal: normals[i],
11530
- });
11531
- this.originalClippingPlanes[planeIndices[i]].origin = plane.getOrigin();
11532
- this.sphereStates[sphereIndices[i]].point[i] = plane.getOrigin()[i];
11533
- this.sphereStates[sphereIndices[i]].sphereSource.setCenter(...this.sphereStates[sphereIndices[i]].point);
11534
- this.sphereStates[sphereIndices[i]].sphereSource.modified();
11535
- const otherSphere = this.sphereStates.find((s, idx) => s.axis === axes[i] && idx !== sphereIndices[i]);
11536
- const newCenter = (otherSphere.point[i] + plane.getOrigin()[i]) / 2;
11537
- this.sphereStates.forEach((state) => {
11538
- if (!state.isCorner &&
11539
- state.axis !== axes[i] &&
11540
- !evt.detail.viewportOrientation.includes(orientationAxes[i])) {
11541
- state.point[i] = newCenter;
11542
- state.sphereSource.setCenter(state.point);
11543
- state.sphereActor.getProperty().setColor(state.color);
11544
- state.sphereSource.modified();
11545
- }
11546
- });
11547
- const volumeActor = viewport.getDefaultActor()?.actor;
11548
- if (volumeActor) {
11549
- const mapper = volumeActor.getMapper();
11550
- const clippingPlanes = mapper.getClippingPlanes();
11551
- if (clippingPlanes) {
11552
- clippingPlanes[planeIndices[i]].setOrigin(plane.getOrigin());
11553
- }
11554
- }
11555
- }
11607
+ if (evt.detail.clippingPlanes &&
11608
+ evt.detail.clippingPlanes.length >= volumeCropping.NUM_CLIPPING_PLANES) {
11609
+ this.originalClippingPlanes = (0,volumeCropping.copyClippingPlanes)(evt.detail.clippingPlanes);
11610
+ this._updateFaceSpheresFromClippingPlanes();
11611
+ this._updateCornerSpheresFromFaces();
11612
+ this._updateFaceSpheresFromCorners();
11556
11613
  this._updateCornerSpheres();
11614
+ const mapper = this._getVolumeMapper(viewport);
11615
+ if (mapper) {
11616
+ this._applyClippingPlanesToMapper(mapper);
11617
+ }
11557
11618
  viewport.render();
11619
+ this._notifyClippingPlanesChanged(viewport);
11620
+ }
11621
+ else {
11622
+ this._notifyClippingPlanesChanged(viewport);
11558
11623
  }
11559
11624
  };
11560
11625
  this._getViewportsInfo = () => {
11561
- const viewports = (0,ToolGroupManager.getToolGroup)(this.toolGroupId).viewportsInfo;
11562
- return viewports;
11626
+ const toolGroup = (0,ToolGroupManager.getToolGroup)(this.toolGroupId);
11627
+ return toolGroup?.viewportsInfo || [];
11563
11628
  };
11564
11629
  this._initialize3DViewports = (viewportsInfo) => {
11565
- if (!viewportsInfo || !viewportsInfo.length || !viewportsInfo[0]) {
11630
+ if (!viewportsInfo?.length || !viewportsInfo[0]) {
11566
11631
  console.warn('VolumeCroppingTool: No viewportsInfo available for initialization of volumecroppingtool.');
11567
11632
  return;
11568
11633
  }
11569
11634
  const viewport = this._getViewport();
11635
+ if (!viewport) {
11636
+ return;
11637
+ }
11570
11638
  const volumeActors = viewport.getActors();
11571
11639
  if (!volumeActors || volumeActors.length === 0) {
11572
11640
  console.warn('VolumeCroppingTool: No volume actors found in the viewport.');
@@ -11578,78 +11646,85 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11578
11646
  return;
11579
11647
  }
11580
11648
  this.seriesInstanceUID = imageData.seriesInstanceUID || 'unknown';
11581
- const worldBounds = imageData.getBounds();
11649
+ this.volumeDirectionVectors = (0,volumeCropping.extractVolumeDirectionVectors)(imageData);
11650
+ const { xDir, yDir, zDir } = this.volumeDirectionVectors;
11651
+ const dimensions = imageData.getDimensions();
11582
11652
  const cropFactor = this.configuration.initialCropFactor || 0.1;
11583
- const xRange = worldBounds[1] - worldBounds[0];
11584
- const yRange = worldBounds[3] - worldBounds[2];
11585
- const zRange = worldBounds[5] - worldBounds[4];
11586
- const xMin = worldBounds[0] + cropFactor * xRange;
11587
- const xMax = worldBounds[1] - cropFactor * xRange;
11588
- const yMin = worldBounds[2] + cropFactor * yRange;
11589
- const yMax = worldBounds[3] - cropFactor * yRange;
11590
- const zMin = worldBounds[4] + cropFactor * zRange;
11591
- const zMax = worldBounds[5] - cropFactor * zRange;
11592
- const planes = [];
11593
- const planeXmin = Plane/* default.newInstance */.Ay.newInstance({
11594
- origin: [xMin, 0, 0],
11595
- normal: [1, 0, 0],
11653
+ const xMin = cropFactor * dimensions[0];
11654
+ const xMax = (1 - cropFactor) * dimensions[0];
11655
+ const yMin = cropFactor * dimensions[1];
11656
+ const yMax = (1 - cropFactor) * dimensions[1];
11657
+ const zMin = cropFactor * dimensions[2];
11658
+ const zMax = (1 - cropFactor) * dimensions[2];
11659
+ const xCenter = (xMin + xMax) / 2;
11660
+ const yCenter = (yMin + yMax) / 2;
11661
+ const zCenter = (zMin + zMax) / 2;
11662
+ const faceXMin = imageData.indexToWorld([xMin, yCenter, zCenter]);
11663
+ const faceXMax = imageData.indexToWorld([xMax, yCenter, zCenter]);
11664
+ const faceYMin = imageData.indexToWorld([xCenter, yMin, zCenter]);
11665
+ const faceYMax = imageData.indexToWorld([xCenter, yMax, zCenter]);
11666
+ const faceZMin = imageData.indexToWorld([xCenter, yCenter, zMin]);
11667
+ const faceZMax = imageData.indexToWorld([xCenter, yCenter, zMax]);
11668
+ const planeXMin = Plane/* default.newInstance */.Ay.newInstance({
11669
+ origin: faceXMin,
11670
+ normal: xDir,
11596
11671
  });
11597
- const planeXmax = Plane/* default.newInstance */.Ay.newInstance({
11598
- origin: [xMax, 0, 0],
11599
- normal: [-1, 0, 0],
11672
+ const planeXMax = Plane/* default.newInstance */.Ay.newInstance({
11673
+ origin: faceXMax,
11674
+ normal: [-xDir[0], -xDir[1], -xDir[2]],
11600
11675
  });
11601
- const planeYmin = Plane/* default.newInstance */.Ay.newInstance({
11602
- origin: [0, yMin, 0],
11603
- normal: [0, 1, 0],
11676
+ const planeYMin = Plane/* default.newInstance */.Ay.newInstance({
11677
+ origin: faceYMin,
11678
+ normal: yDir,
11604
11679
  });
11605
- const planeYmax = Plane/* default.newInstance */.Ay.newInstance({
11606
- origin: [0, yMax, 0],
11607
- normal: [0, -1, 0],
11680
+ const planeYMax = Plane/* default.newInstance */.Ay.newInstance({
11681
+ origin: faceYMax,
11682
+ normal: [-yDir[0], -yDir[1], -yDir[2]],
11608
11683
  });
11609
- const planeZmin = Plane/* default.newInstance */.Ay.newInstance({
11610
- origin: [0, 0, zMin],
11611
- normal: [0, 0, 1],
11684
+ const planeZMin = Plane/* default.newInstance */.Ay.newInstance({
11685
+ origin: faceZMin,
11686
+ normal: zDir,
11612
11687
  });
11613
- const planeZmax = Plane/* default.newInstance */.Ay.newInstance({
11614
- origin: [0, 0, zMax],
11615
- normal: [0, 0, -1],
11688
+ const planeZMax = Plane/* default.newInstance */.Ay.newInstance({
11689
+ origin: faceZMax,
11690
+ normal: [-zDir[0], -zDir[1], -zDir[2]],
11616
11691
  });
11617
- const mapper = viewport
11618
- .getDefaultActor()
11619
- .actor.getMapper();
11620
- planes.push(planeXmin);
11621
- planes.push(planeXmax);
11622
- planes.push(planeYmin);
11623
- planes.push(planeYmax);
11624
- planes.push(planeZmin);
11625
- planes.push(planeZmax);
11692
+ const planes = [
11693
+ planeXMin,
11694
+ planeXMax,
11695
+ planeYMin,
11696
+ planeYMax,
11697
+ planeZMin,
11698
+ planeZMax,
11699
+ ];
11626
11700
  const originalPlanes = planes.map((plane) => ({
11627
11701
  origin: [...plane.getOrigin()],
11628
11702
  normal: [...plane.getNormal()],
11629
11703
  }));
11630
11704
  this.originalClippingPlanes = originalPlanes;
11631
- const sphereXminPoint = [xMin, (yMax + yMin) / 2, (zMax + zMin) / 2];
11632
- const sphereXmaxPoint = [xMax, (yMax + yMin) / 2, (zMax + zMin) / 2];
11633
- const sphereYminPoint = [(xMax + xMin) / 2, yMin, (zMax + zMin) / 2];
11634
- const sphereYmaxPoint = [(xMax + xMin) / 2, yMax, (zMax + zMin) / 2];
11635
- const sphereZminPoint = [(xMax + xMin) / 2, (yMax + yMin) / 2, zMin];
11636
- const sphereZmaxPoint = [(xMax + xMin) / 2, (yMax + yMin) / 2, zMax];
11637
- const adaptiveRadius = this._calculateAdaptiveSphereRadius(Math.sqrt(xRange * xRange + yRange * yRange + zRange * zRange));
11638
- this._addSphere(viewport, sphereXminPoint, 'x', 'min', null, adaptiveRadius);
11639
- this._addSphere(viewport, sphereXmaxPoint, 'x', 'max', null, adaptiveRadius);
11640
- this._addSphere(viewport, sphereYminPoint, 'y', 'min', null, adaptiveRadius);
11641
- this._addSphere(viewport, sphereYmaxPoint, 'y', 'max', null, adaptiveRadius);
11642
- this._addSphere(viewport, sphereZminPoint, 'z', 'min', null, adaptiveRadius);
11643
- this._addSphere(viewport, sphereZmaxPoint, 'z', 'max', null, adaptiveRadius);
11705
+ const diag0 = imageData.indexToWorld([0, 0, 0]);
11706
+ const diag1 = imageData.indexToWorld([
11707
+ dimensions[0],
11708
+ dimensions[1],
11709
+ dimensions[2],
11710
+ ]);
11711
+ const diagonal = gl_matrix_esm/* vec3.distance */.eR.distance(diag0, diag1);
11712
+ const adaptiveRadius = calculateAdaptiveSphereRadius(diagonal, this.configuration);
11713
+ this._addSphere(viewport, faceXMin, 'x', 'min', null, adaptiveRadius);
11714
+ this._addSphere(viewport, faceXMax, 'x', 'max', null, adaptiveRadius);
11715
+ this._addSphere(viewport, faceYMin, 'y', 'min', null, adaptiveRadius);
11716
+ this._addSphere(viewport, faceYMax, 'y', 'max', null, adaptiveRadius);
11717
+ this._addSphere(viewport, faceZMin, 'z', 'min', null, adaptiveRadius);
11718
+ this._addSphere(viewport, faceZMax, 'z', 'max', null, adaptiveRadius);
11644
11719
  const corners = [
11645
- [xMin, yMin, zMin],
11646
- [xMin, yMin, zMax],
11647
- [xMin, yMax, zMin],
11648
- [xMin, yMax, zMax],
11649
- [xMax, yMin, zMin],
11650
- [xMax, yMin, zMax],
11651
- [xMax, yMax, zMin],
11652
- [xMax, yMax, zMax],
11720
+ imageData.indexToWorld([xMin, yMin, zMin]),
11721
+ imageData.indexToWorld([xMin, yMin, zMax]),
11722
+ imageData.indexToWorld([xMin, yMax, zMin]),
11723
+ imageData.indexToWorld([xMin, yMax, zMax]),
11724
+ imageData.indexToWorld([xMax, yMin, zMin]),
11725
+ imageData.indexToWorld([xMax, yMin, zMax]),
11726
+ imageData.indexToWorld([xMax, yMax, zMin]),
11727
+ imageData.indexToWorld([xMax, yMax, zMax]),
11653
11728
  ];
11654
11729
  const cornerKeys = [
11655
11730
  'XMIN_YMIN_ZMIN',
@@ -11678,21 +11753,24 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11678
11753
  ['XMAX_YMIN_ZMIN', 'XMAX_YMIN_ZMAX'],
11679
11754
  ['XMAX_YMAX_ZMIN', 'XMAX_YMAX_ZMAX'],
11680
11755
  ];
11681
- edgeCornerPairs.forEach(([key1, key2], i) => {
11756
+ edgeCornerPairs.forEach(([key1, key2]) => {
11682
11757
  const state1 = this.sphereStates.find((s) => s.uid === `corner_${key1}`);
11683
11758
  const state2 = this.sphereStates.find((s) => s.uid === `corner_${key2}`);
11684
11759
  if (state1 && state2) {
11685
11760
  const uid = `edge_${key1}_${key2}`;
11686
- const { actor, source } = this._addLine3DBetweenPoints(viewport, state1.point, state2.point, [0.7, 0.7, 0.7], uid);
11761
+ const { actor, source } = addLine3DBetweenPoints(viewport, state1.point, state2.point, [0.7, 0.7, 0.7], uid, this.configuration.showHandles);
11687
11762
  this.edgeLines[uid] = { actor, source, key1, key2 };
11688
11763
  }
11689
11764
  });
11690
- mapper.addClippingPlane(planeXmin);
11691
- mapper.addClippingPlane(planeXmax);
11692
- mapper.addClippingPlane(planeYmin);
11693
- mapper.addClippingPlane(planeYmax);
11694
- mapper.addClippingPlane(planeZmin);
11695
- mapper.addClippingPlane(planeZmax);
11765
+ const mapper = viewport
11766
+ .getDefaultActor()
11767
+ .actor.getMapper();
11768
+ mapper.addClippingPlane(planeXMin);
11769
+ mapper.addClippingPlane(planeXMax);
11770
+ mapper.addClippingPlane(planeYMin);
11771
+ mapper.addClippingPlane(planeYMax);
11772
+ mapper.addClippingPlane(planeZMin);
11773
+ mapper.addClippingPlane(planeZMax);
11696
11774
  esm.eventTarget.addEventListener(enums.Events.VOLUMECROPPINGCONTROL_TOOL_CHANGED, (evt) => {
11697
11775
  this._onControlToolChange(evt);
11698
11776
  });
@@ -11706,107 +11784,14 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11706
11784
  return { viewport, world };
11707
11785
  };
11708
11786
  this._getViewport = () => {
11709
- const [viewport3D] = this._getViewportsInfo();
11710
- const renderingEngine = (0,esm.getRenderingEngine)(viewport3D.renderingEngineId);
11711
- return renderingEngine.getViewport(viewport3D.viewportId);
11712
- };
11713
- this._handleCornerSphereMovement = (sphereState, world, viewport) => {
11714
- const newCorner = this._calculateNewCornerPosition(world);
11715
- this._updateSpherePosition(sphereState, newCorner);
11716
- const axisFlags = this._parseCornerKey(sphereState.uid);
11717
- this._updateRelatedCorners(sphereState, newCorner, axisFlags);
11718
- this._updateAfterCornerMovement(viewport);
11719
- };
11720
- this._handleFaceSphereMovement = (sphereState, world, viewport) => {
11721
- const axisIdx = { x: 0, y: 1, z: 2 }[sphereState.axis];
11722
- let newValue = world[axisIdx];
11723
- if (this.faceDragOffset !== null) {
11724
- newValue += this.faceDragOffset;
11725
- }
11726
- sphereState.point[axisIdx] = newValue;
11727
- sphereState.sphereSource.setCenter(...sphereState.point);
11728
- sphereState.sphereSource.modified();
11729
- this._updateAfterFaceMovement(viewport);
11730
- };
11731
- this._calculateNewCornerPosition = (world) => {
11732
- let newCorner = [world[0], world[1], world[2]];
11733
- if (this.cornerDragOffset) {
11734
- newCorner = [
11735
- world[0] + this.cornerDragOffset[0],
11736
- world[1] + this.cornerDragOffset[1],
11737
- world[2] + this.cornerDragOffset[2],
11738
- ];
11739
- }
11740
- return newCorner;
11741
- };
11742
- this._parseCornerKey = (uid) => {
11743
- const cornerKey = uid.replace('corner_', '');
11744
- return {
11745
- isXMin: cornerKey.includes('XMIN'),
11746
- isXMax: cornerKey.includes('XMAX'),
11747
- isYMin: cornerKey.includes('YMIN'),
11748
- isYMax: cornerKey.includes('YMAX'),
11749
- isZMin: cornerKey.includes('ZMIN'),
11750
- isZMax: cornerKey.includes('ZMAX'),
11751
- };
11752
- };
11753
- this._updateSpherePosition = (sphereState, newPosition) => {
11754
- sphereState.point = newPosition;
11755
- sphereState.sphereSource.setCenter(...newPosition);
11756
- sphereState.sphereSource.modified();
11757
- };
11758
- this._updateRelatedCorners = (draggedSphere, newCorner, axisFlags) => {
11759
- this.sphereStates.forEach((state) => {
11760
- if (!state.isCorner || state === draggedSphere) {
11761
- return;
11762
- }
11763
- const key = state.uid.replace('corner_', '');
11764
- const shouldUpdate = this._shouldUpdateCorner(key, axisFlags);
11765
- if (shouldUpdate) {
11766
- this._updateCornerCoordinates(state, newCorner, key, axisFlags);
11767
- }
11768
- });
11769
- };
11770
- this._shouldUpdateCorner = (cornerKey, axisFlags) => {
11771
- return ((axisFlags.isXMin && cornerKey.includes('XMIN')) ||
11772
- (axisFlags.isXMax && cornerKey.includes('XMAX')) ||
11773
- (axisFlags.isYMin && cornerKey.includes('YMIN')) ||
11774
- (axisFlags.isYMax && cornerKey.includes('YMAX')) ||
11775
- (axisFlags.isZMin && cornerKey.includes('ZMIN')) ||
11776
- (axisFlags.isZMax && cornerKey.includes('ZMAX')));
11777
- };
11778
- this._updateCornerCoordinates = (state, newCorner, cornerKey, axisFlags) => {
11779
- if ((axisFlags.isXMin && cornerKey.includes('XMIN')) ||
11780
- (axisFlags.isXMax && cornerKey.includes('XMAX'))) {
11781
- state.point[0] = newCorner[0];
11782
- }
11783
- if ((axisFlags.isYMin && cornerKey.includes('YMIN')) ||
11784
- (axisFlags.isYMax && cornerKey.includes('YMAX'))) {
11785
- state.point[1] = newCorner[1];
11786
- }
11787
- if ((axisFlags.isZMin && cornerKey.includes('ZMIN')) ||
11788
- (axisFlags.isZMax && cornerKey.includes('ZMAX'))) {
11789
- state.point[2] = newCorner[2];
11787
+ const viewportsInfo = this._getViewportsInfo();
11788
+ if (!viewportsInfo || viewportsInfo.length === 0) {
11789
+ return null;
11790
11790
  }
11791
- state.sphereSource.setCenter(...state.point);
11792
- state.sphereSource.modified();
11793
- };
11794
- this._updateAfterCornerMovement = (viewport) => {
11795
- this._updateFaceSpheresFromCorners();
11796
- this._updateCornerSpheres();
11797
- this._updateClippingPlanesFromFaceSpheres(viewport);
11798
- };
11799
- this._updateAfterFaceMovement = (viewport) => {
11800
- this._updateCornerSpheresFromFaces();
11801
- this._updateClippingPlanesFromFaceSpheres(viewport);
11802
- };
11803
- this._triggerToolChangedEvent = (sphereState) => {
11804
- (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPING_TOOL_CHANGED, {
11805
- toolCenter: sphereState.point,
11806
- axis: sphereState.isCorner ? 'corner' : sphereState.axis,
11807
- draggingSphereIndex: this.draggingSphereIndex,
11808
- seriesInstanceUID: this.seriesInstanceUID,
11809
- });
11791
+ const [viewport3D] = viewportsInfo;
11792
+ const renderingEngine = (0,esm.getRenderingEngine)(viewport3D.renderingEngineId);
11793
+ const viewport = renderingEngine?.getViewport(viewport3D.viewportId);
11794
+ return viewport || null;
11810
11795
  };
11811
11796
  this._onNewVolume = () => {
11812
11797
  const viewportsInfo = this._getViewportsInfo();
@@ -11815,6 +11800,207 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11815
11800
  this.edgeLines = {};
11816
11801
  this._initialize3DViewports(viewportsInfo);
11817
11802
  };
11803
+ this._rotateClippingPlanes = (evt) => {
11804
+ const { element, currentPoints, lastPoints } = evt.detail;
11805
+ const currentPointsCanvas = currentPoints.canvas;
11806
+ const lastPointsCanvas = lastPoints.canvas;
11807
+ const rotateIncrementDegrees = this.configuration.rotateClippingPlanesIncrementDegrees ??
11808
+ this.configuration.rotateIncrementDegrees ??
11809
+ 5;
11810
+ const enabledElement = (0,esm.getEnabledElement)(element);
11811
+ const { viewport } = enabledElement;
11812
+ const camera = viewport.getCamera();
11813
+ const width = element.clientWidth;
11814
+ const height = element.clientHeight;
11815
+ const normalizedPosition = [
11816
+ currentPointsCanvas[0] / width,
11817
+ currentPointsCanvas[1] / height,
11818
+ ];
11819
+ const normalizedPreviousPosition = [
11820
+ lastPointsCanvas[0] / width,
11821
+ lastPointsCanvas[1] / height,
11822
+ ];
11823
+ const normalizedCenter = [0.5, 0.5];
11824
+ const radsq = (1.0 + Math.abs(normalizedCenter[0])) ** 2.0;
11825
+ const op = [normalizedPreviousPosition[0], 0, 0];
11826
+ const oe = [normalizedPosition[0], 0, 0];
11827
+ const opsq = op[0] ** 2;
11828
+ const oesq = oe[0] ** 2;
11829
+ const lop = opsq > radsq ? 0 : Math.sqrt(radsq - opsq);
11830
+ const loe = oesq > radsq ? 0 : Math.sqrt(radsq - oesq);
11831
+ const nop = [op[0], 0, lop];
11832
+ Core_Math/* default.normalize */.Ay.normalize(nop);
11833
+ const noe = [oe[0], 0, loe];
11834
+ Core_Math/* default.normalize */.Ay.normalize(noe);
11835
+ const dot = Core_Math/* default.dot */.Ay.dot(nop, noe);
11836
+ if (Math.abs(dot) > 0.0001) {
11837
+ const angleX = 20 *
11838
+ Math.acos(Core_Math/* default.clampValue */.Ay.clampValue(dot, -1.0, 1.0)) *
11839
+ Math.sign(normalizedPosition[0] - normalizedPreviousPosition[0]) *
11840
+ rotateIncrementDegrees;
11841
+ const upVec = camera.viewUp;
11842
+ const atV = camera.viewPlaneNormal;
11843
+ const rightV = [0, 0, 0];
11844
+ const forwardV = [0, 0, 0];
11845
+ Core_Math/* default.cross */.Ay.cross(upVec, atV, rightV);
11846
+ Core_Math/* default.normalize */.Ay.normalize(rightV);
11847
+ Core_Math/* default.cross */.Ay.cross(atV, rightV, forwardV);
11848
+ Core_Math/* default.normalize */.Ay.normalize(forwardV);
11849
+ const angleY = 20 *
11850
+ (normalizedPosition[1] - normalizedPreviousPosition[1]) *
11851
+ rotateIncrementDegrees;
11852
+ let rotationCenter;
11853
+ if (this.sphereStates.length >= volumeCropping.NUM_CLIPPING_PLANES) {
11854
+ const faces = [
11855
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMIN],
11856
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMAX],
11857
+ this.sphereStates[volumeCropping.SPHEREINDEX.YMIN],
11858
+ this.sphereStates[volumeCropping.SPHEREINDEX.YMAX],
11859
+ this.sphereStates[volumeCropping.SPHEREINDEX.ZMIN],
11860
+ this.sphereStates[volumeCropping.SPHEREINDEX.ZMAX],
11861
+ ];
11862
+ rotationCenter = [
11863
+ (faces[0].point[0] +
11864
+ faces[1].point[0] +
11865
+ faces[2].point[0] +
11866
+ faces[3].point[0] +
11867
+ faces[4].point[0] +
11868
+ faces[5].point[0]) /
11869
+ volumeCropping.NUM_CLIPPING_PLANES,
11870
+ (faces[0].point[1] +
11871
+ faces[1].point[1] +
11872
+ faces[2].point[1] +
11873
+ faces[3].point[1] +
11874
+ faces[4].point[1] +
11875
+ faces[5].point[1]) /
11876
+ volumeCropping.NUM_CLIPPING_PLANES,
11877
+ (faces[0].point[2] +
11878
+ faces[1].point[2] +
11879
+ faces[2].point[2] +
11880
+ faces[3].point[2] +
11881
+ faces[4].point[2] +
11882
+ faces[5].point[2]) /
11883
+ volumeCropping.NUM_CLIPPING_PLANES,
11884
+ ];
11885
+ }
11886
+ else {
11887
+ rotationCenter = [0, 0, 0];
11888
+ }
11889
+ const transformX = gl_matrix_esm/* mat4.identity */.pB.identity(new Float32Array(16));
11890
+ gl_matrix_esm/* mat4.translate */.pB.translate(transformX, transformX, rotationCenter);
11891
+ gl_matrix_esm/* mat4.rotate */.pB.rotate(transformX, transformX, (angleX * Math.PI) / 180, forwardV);
11892
+ gl_matrix_esm/* mat4.translate */.pB.translate(transformX, transformX, [
11893
+ -rotationCenter[0],
11894
+ -rotationCenter[1],
11895
+ -rotationCenter[2],
11896
+ ]);
11897
+ const transformY = gl_matrix_esm/* mat4.identity */.pB.identity(new Float32Array(16));
11898
+ gl_matrix_esm/* mat4.translate */.pB.translate(transformY, transformY, rotationCenter);
11899
+ gl_matrix_esm/* mat4.rotate */.pB.rotate(transformY, transformY, (angleY * Math.PI) / 180, rightV);
11900
+ gl_matrix_esm/* mat4.translate */.pB.translate(transformY, transformY, [
11901
+ -rotationCenter[0],
11902
+ -rotationCenter[1],
11903
+ -rotationCenter[2],
11904
+ ]);
11905
+ const transform = gl_matrix_esm/* mat4.create */.pB.create();
11906
+ gl_matrix_esm/* mat4.multiply */.pB.multiply(transform, transformY, transformX);
11907
+ const normalTransformX4 = gl_matrix_esm/* mat4.identity */.pB.identity(new Float32Array(16));
11908
+ gl_matrix_esm/* mat4.rotate */.pB.rotate(normalTransformX4, normalTransformX4, (angleX * Math.PI) / 180, forwardV);
11909
+ const normalTransformX = gl_matrix_esm/* mat3.create */.w0.create();
11910
+ gl_matrix_esm/* mat3.fromMat4 */.w0.fromMat4(normalTransformX, normalTransformX4);
11911
+ const normalTransformY4 = gl_matrix_esm/* mat4.identity */.pB.identity(new Float32Array(16));
11912
+ gl_matrix_esm/* mat4.rotate */.pB.rotate(normalTransformY4, normalTransformY4, (angleY * Math.PI) / 180, rightV);
11913
+ const normalTransformY = gl_matrix_esm/* mat3.create */.w0.create();
11914
+ gl_matrix_esm/* mat3.fromMat4 */.w0.fromMat4(normalTransformY, normalTransformY4);
11915
+ const normalTransform = gl_matrix_esm/* mat3.create */.w0.create();
11916
+ gl_matrix_esm/* mat3.multiply */.w0.multiply(normalTransform, normalTransformY, normalTransformX);
11917
+ for (let i = 0; i < this.originalClippingPlanes.length; ++i) {
11918
+ const plane = this.originalClippingPlanes[i];
11919
+ const originVec = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(plane.origin[0], plane.origin[1], plane.origin[2]);
11920
+ gl_matrix_esm/* vec3.transformMat4 */.eR.transformMat4(originVec, originVec, transform);
11921
+ plane.origin = [originVec[0], originVec[1], originVec[2]];
11922
+ const normalVec = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(plane.normal[0], plane.normal[1], plane.normal[2]);
11923
+ gl_matrix_esm/* vec3.transformMat3 */.eR.transformMat3(normalVec, normalVec, normalTransform);
11924
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(normalVec, normalVec);
11925
+ plane.normal = [normalVec[0], normalVec[1], normalVec[2]];
11926
+ }
11927
+ if (this.sphereStates.length >= volumeCropping.NUM_CLIPPING_PLANES) {
11928
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMIN].point = [
11929
+ ...this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMIN].origin,
11930
+ ];
11931
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMAX].point = [
11932
+ ...this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMAX].origin,
11933
+ ];
11934
+ this.sphereStates[volumeCropping.SPHEREINDEX.YMIN].point = [
11935
+ ...this.originalClippingPlanes[volumeCropping.PLANEINDEX.YMIN].origin,
11936
+ ];
11937
+ this.sphereStates[volumeCropping.SPHEREINDEX.YMAX].point = [
11938
+ ...this.originalClippingPlanes[volumeCropping.PLANEINDEX.YMAX].origin,
11939
+ ];
11940
+ this.sphereStates[volumeCropping.SPHEREINDEX.ZMIN].point = [
11941
+ ...this.originalClippingPlanes[volumeCropping.PLANEINDEX.ZMIN].origin,
11942
+ ];
11943
+ this.sphereStates[volumeCropping.SPHEREINDEX.ZMAX].point = [
11944
+ ...this.originalClippingPlanes[volumeCropping.PLANEINDEX.ZMAX].origin,
11945
+ ];
11946
+ [
11947
+ volumeCropping.SPHEREINDEX.XMIN,
11948
+ volumeCropping.SPHEREINDEX.XMAX,
11949
+ volumeCropping.SPHEREINDEX.YMIN,
11950
+ volumeCropping.SPHEREINDEX.YMAX,
11951
+ volumeCropping.SPHEREINDEX.ZMIN,
11952
+ volumeCropping.SPHEREINDEX.ZMAX,
11953
+ ].forEach((idx) => {
11954
+ const s = this.sphereStates[idx];
11955
+ s.sphereSource.setCenter(...s.point);
11956
+ s.sphereSource.modified();
11957
+ });
11958
+ const cornerIndices = [
11959
+ volumeCropping.SPHEREINDEX.XMIN_YMIN_ZMIN,
11960
+ volumeCropping.SPHEREINDEX.XMIN_YMIN_ZMAX,
11961
+ volumeCropping.SPHEREINDEX.XMIN_YMAX_ZMIN,
11962
+ volumeCropping.SPHEREINDEX.XMIN_YMAX_ZMAX,
11963
+ volumeCropping.SPHEREINDEX.XMAX_YMIN_ZMIN,
11964
+ volumeCropping.SPHEREINDEX.XMAX_YMIN_ZMAX,
11965
+ volumeCropping.SPHEREINDEX.XMAX_YMAX_ZMIN,
11966
+ volumeCropping.SPHEREINDEX.XMAX_YMAX_ZMAX,
11967
+ ];
11968
+ cornerIndices.forEach((idx) => {
11969
+ const cornerState = this.sphereStates[idx];
11970
+ if (cornerState) {
11971
+ const cornerVec = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(cornerState.point[0], cornerState.point[1], cornerState.point[2]);
11972
+ gl_matrix_esm/* vec3.transformMat4 */.eR.transformMat4(cornerVec, cornerVec, transform);
11973
+ cornerState.point = [
11974
+ cornerVec[0],
11975
+ cornerVec[1],
11976
+ cornerVec[2],
11977
+ ];
11978
+ cornerState.sphereSource.setCenter(...cornerState.point);
11979
+ cornerState.sphereSource.modified();
11980
+ }
11981
+ });
11982
+ Object.values(this.edgeLines).forEach(({ source, key1, key2 }) => {
11983
+ const state1 = this.sphereStates.find((s) => s.uid === `corner_${key1}`);
11984
+ const state2 = this.sphereStates.find((s) => s.uid === `corner_${key2}`);
11985
+ if (state1 && state2) {
11986
+ const points = source.getPoints();
11987
+ points.setPoint(0, state1.point[0], state1.point[1], state1.point[2]);
11988
+ points.setPoint(1, state2.point[0], state2.point[1], state2.point[2]);
11989
+ points.modified();
11990
+ source.modified();
11991
+ }
11992
+ });
11993
+ }
11994
+ this._updateClippingPlanes(viewport);
11995
+ viewport.render();
11996
+ (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPING_TOOL_CHANGED, {
11997
+ originalClippingPlanes: this.originalClippingPlanes,
11998
+ viewportId: viewport.id,
11999
+ renderingEngineId: viewport.renderingEngineId,
12000
+ seriesInstanceUID: this.seriesInstanceUID,
12001
+ });
12002
+ }
12003
+ };
11818
12004
  this._rotateCamera = (viewport, centerWorld, axis, angle) => {
11819
12005
  const vtkCamera = viewport.getVtkActiveCamera();
11820
12006
  const viewUp = vtkCamera.getViewUp();
@@ -11846,59 +12032,55 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11846
12032
  this.mouseDragCallback = this._dragCallback.bind(this);
11847
12033
  }
11848
12034
  onSetToolActive() {
11849
- if (this.sphereStates && this.sphereStates.length > 0) {
11850
- if (this.configuration.showHandles) {
11851
- this.setHandlesVisible(false);
11852
- this.setClippingPlanesVisible(false);
11853
- }
11854
- else {
11855
- this.setHandlesVisible(true);
11856
- this.setClippingPlanesVisible(true);
11857
- }
11858
- }
11859
- else {
11860
- const viewportsInfo = this._getViewportsInfo();
11861
- const subscribeToElementResize = () => {
11862
- viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
11863
- if (!this._resizeObservers.has(viewportId)) {
11864
- const { viewport } = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId) || { viewport: null };
11865
- if (!viewport) {
12035
+ const viewportsInfo = this._getViewportsInfo();
12036
+ const subscribeToElementResize = () => {
12037
+ viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
12038
+ if (!this._resizeObservers.has(viewportId)) {
12039
+ const { viewport } = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId) || { viewport: null };
12040
+ if (!viewport) {
12041
+ return;
12042
+ }
12043
+ const { element } = viewport;
12044
+ const resizeObserver = new ResizeObserver(() => {
12045
+ const element = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
12046
+ if (!element) {
11866
12047
  return;
11867
12048
  }
11868
- const { element } = viewport;
11869
- const resizeObserver = new ResizeObserver(() => {
11870
- const element = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
11871
- if (!element) {
11872
- return;
11873
- }
11874
- const { viewport } = element;
11875
- const viewPresentation = viewport.getViewPresentation();
11876
- viewport.resetCamera();
11877
- viewport.setViewPresentation(viewPresentation);
11878
- viewport.render();
11879
- });
11880
- resizeObserver.observe(element);
11881
- this._resizeObservers.set(viewportId, resizeObserver);
11882
- }
11883
- });
11884
- };
11885
- subscribeToElementResize();
11886
- this._viewportAddedListener = (evt) => {
11887
- if (evt.detail.toolGroupId === this.toolGroupId) {
11888
- subscribeToElementResize();
12049
+ const { viewport } = element;
12050
+ const viewPresentation = viewport.getViewPresentation();
12051
+ viewport.resetCamera();
12052
+ viewport.setViewPresentation(viewPresentation);
12053
+ viewport.render();
12054
+ });
12055
+ resizeObserver.observe(element);
12056
+ this._resizeObservers.set(viewportId, resizeObserver);
11889
12057
  }
11890
- };
11891
- esm.eventTarget.addEventListener(enums.Events.TOOLGROUP_VIEWPORT_ADDED, this._viewportAddedListener);
11892
- this._unsubscribeToViewportNewVolumeSet(viewportsInfo);
11893
- this._subscribeToViewportNewVolumeSet(viewportsInfo);
12058
+ });
12059
+ };
12060
+ subscribeToElementResize();
12061
+ this._viewportAddedListener = (evt) => {
12062
+ if (evt.detail.toolGroupId === this.toolGroupId) {
12063
+ subscribeToElementResize();
12064
+ }
12065
+ };
12066
+ esm.eventTarget.addEventListener(enums.Events.TOOLGROUP_VIEWPORT_ADDED, this._viewportAddedListener);
12067
+ this._unsubscribeToViewportNewVolumeSet(viewportsInfo);
12068
+ this._subscribeToViewportNewVolumeSet(viewportsInfo);
12069
+ if (this.sphereStates && this.sphereStates.length === 0) {
12070
+ this.originalClippingPlanes = [];
11894
12071
  this._initialize3DViewports(viewportsInfo);
12072
+ }
12073
+ this.configuration.showClippingPlanes = false;
12074
+ this.configuration.showHandles = false;
12075
+ const viewport = this._getViewport();
12076
+ if (viewport &&
12077
+ this.originalClippingPlanes &&
12078
+ this.originalClippingPlanes.length > 0) {
12079
+ this._updateClippingPlanes(viewport);
11895
12080
  if (this.sphereStates && this.sphereStates.length > 0) {
11896
- this.setHandlesVisible(true);
11897
- }
11898
- else {
11899
- this.originalClippingPlanes = [];
11900
- this._initialize3DViewports(viewportsInfo);
12081
+ this._updateHandlesVisibility();
11901
12082
  }
12083
+ viewport.render();
11902
12084
  }
11903
12085
  }
11904
12086
  onSetToolDisabled() {
@@ -11916,30 +12098,7 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11916
12098
  setHandlesVisible(visible) {
11917
12099
  this.configuration.showHandles = visible;
11918
12100
  if (visible) {
11919
- this.sphereStates[SPHEREINDEX.XMIN].point[0] =
11920
- this.originalClippingPlanes[PLANEINDEX.XMIN].origin[0];
11921
- this.sphereStates[SPHEREINDEX.XMAX].point[0] =
11922
- this.originalClippingPlanes[PLANEINDEX.XMAX].origin[0];
11923
- this.sphereStates[SPHEREINDEX.YMIN].point[1] =
11924
- this.originalClippingPlanes[PLANEINDEX.YMIN].origin[1];
11925
- this.sphereStates[SPHEREINDEX.YMAX].point[1] =
11926
- this.originalClippingPlanes[PLANEINDEX.YMAX].origin[1];
11927
- this.sphereStates[SPHEREINDEX.ZMIN].point[2] =
11928
- this.originalClippingPlanes[PLANEINDEX.ZMIN].origin[2];
11929
- this.sphereStates[SPHEREINDEX.ZMAX].point[2] =
11930
- this.originalClippingPlanes[PLANEINDEX.ZMAX].origin[2];
11931
- [
11932
- SPHEREINDEX.XMIN,
11933
- SPHEREINDEX.XMAX,
11934
- SPHEREINDEX.YMIN,
11935
- SPHEREINDEX.YMAX,
11936
- SPHEREINDEX.ZMIN,
11937
- SPHEREINDEX.ZMAX,
11938
- ].forEach((idx) => {
11939
- const s = this.sphereStates[idx];
11940
- s.sphereSource.setCenter(...s.point);
11941
- s.sphereSource.modified();
11942
- });
12101
+ this._updateFaceSpheresFromClippingPlanes();
11943
12102
  this._updateCornerSpheres();
11944
12103
  }
11945
12104
  this._updateHandlesVisibility();
@@ -11959,14 +12118,38 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11959
12118
  this.configuration.showClippingPlanes = visible;
11960
12119
  const viewport = this._getViewport();
11961
12120
  this._updateClippingPlanes(viewport);
12121
+ if (this.sphereStates && this.sphereStates.length > 0) {
12122
+ this.configuration.showHandles = visible;
12123
+ this._updateHandlesVisibility();
12124
+ }
12125
+ if (visible &&
12126
+ viewport &&
12127
+ this.originalClippingPlanes?.length >= volumeCropping.NUM_CLIPPING_PLANES) {
12128
+ this._notifyClippingPlanesChanged(viewport);
12129
+ }
11962
12130
  viewport.render();
11963
12131
  }
12132
+ getRotatePlanesOnDrag() {
12133
+ return this.rotatePlanesOnDrag;
12134
+ }
12135
+ setRotatePlanesOnDrag(enable) {
12136
+ this.rotatePlanesOnDrag = enable;
12137
+ const viewport = this._getViewport();
12138
+ if (viewport) {
12139
+ viewport.render();
12140
+ }
12141
+ }
11964
12142
  _dragCallback(evt) {
11965
12143
  const { element, currentPoints, lastPoints } = evt.detail;
11966
12144
  if (this.draggingSphereIndex !== null) {
11967
12145
  this._onMouseMoveSphere(evt);
11968
12146
  }
11969
12147
  else {
12148
+ const shiftKey = evt.detail.event?.shiftKey ?? false;
12149
+ if (this.rotatePlanesOnDrag === true || shiftKey) {
12150
+ this._rotateClippingPlanes(evt);
12151
+ return;
12152
+ }
11970
12153
  const currentPointsCanvas = currentPoints.canvas;
11971
12154
  const lastPointsCanvas = lastPoints.canvas;
11972
12155
  const { rotateIncrementDegrees } = this.configuration;
@@ -12022,13 +12205,6 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12022
12205
  }
12023
12206
  _updateClippingPlanes(viewport) {
12024
12207
  const actorEntry = viewport.getDefaultActor();
12025
- if (!actorEntry || !actorEntry.actor) {
12026
- if (!viewport._missingActorWarned) {
12027
- console.warn('VolumeCroppingTool._updateClippingPlanes: No default actor found in viewport.');
12028
- viewport._missingActorWarned = true;
12029
- }
12030
- return;
12031
- }
12032
12208
  const actor = actorEntry.actor;
12033
12209
  const mapper = actor.getMapper();
12034
12210
  const matrix = actor.getMatrix();
@@ -12080,35 +12256,6 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12080
12256
  }
12081
12257
  });
12082
12258
  }
12083
- _addLine3DBetweenPoints(viewport, point1, point2, color = [0.7, 0.7, 0.7], uid = '') {
12084
- if (point1[0] === point2[0] &&
12085
- point1[1] === point2[1] &&
12086
- point1[2] === point2[2]) {
12087
- return { actor: null, source: null };
12088
- }
12089
- const points = Points/* default.newInstance */.Ay.newInstance();
12090
- points.setNumberOfPoints(2);
12091
- points.setPoint(0, point1[0], point1[1], point1[2]);
12092
- points.setPoint(1, point2[0], point2[1], point2[2]);
12093
- const lines = CellArray/* default.newInstance */.Ay.newInstance({ values: [2, 0, 1] });
12094
- const polyData = PolyData/* default.newInstance */.Ay.newInstance();
12095
- polyData.setPoints(points);
12096
- polyData.setLines(lines);
12097
- const mapper = Mapper/* default.newInstance */.Ay.newInstance();
12098
- mapper.setInputData(polyData);
12099
- const actor = Actor/* default.newInstance */.Ay.newInstance();
12100
- actor.setMapper(mapper);
12101
- actor.getProperty().setColor(...color);
12102
- actor.getProperty().setLineWidth(0.5);
12103
- actor.getProperty().setOpacity(1.0);
12104
- actor.getProperty().setInterpolationToFlat();
12105
- actor.getProperty().setAmbient(1.0);
12106
- actor.getProperty().setDiffuse(0.0);
12107
- actor.getProperty().setSpecular(0.0);
12108
- actor.setVisibility(this.configuration.showHandles);
12109
- viewport.addActor({ actor, uid });
12110
- return { actor, source: polyData };
12111
- }
12112
12259
  _addSphere(viewport, point, axis, position, cornerKey = null, adaptiveRadius) {
12113
12260
  const uid = cornerKey ? `corner_${cornerKey}` : `${axis}_${position}`;
12114
12261
  const sphereState = this.sphereStates.find((s) => s.uid === uid);
@@ -12137,9 +12284,10 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12137
12284
  color = sphereColors.CORONAL || [0.0, 1.0, 0.0];
12138
12285
  }
12139
12286
  const idx = this.sphereStates.findIndex((s) => s.uid === uid);
12287
+ const pointCopy = [point[0], point[1], point[2]];
12140
12288
  if (idx === -1) {
12141
12289
  this.sphereStates.push({
12142
- point: point.slice(),
12290
+ point: pointCopy,
12143
12291
  axis,
12144
12292
  uid,
12145
12293
  sphereSource,
@@ -12149,185 +12297,248 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12149
12297
  });
12150
12298
  }
12151
12299
  else {
12152
- this.sphereStates[idx].point = point.slice();
12300
+ this.sphereStates[idx].point = pointCopy;
12153
12301
  this.sphereStates[idx].sphereSource = sphereSource;
12154
12302
  }
12155
- const existingActors = viewport.getActors();
12156
- const existing = existingActors.find((a) => a.uid === uid);
12157
- if (existing) {
12158
- return;
12159
- }
12160
12303
  sphereActor.getProperty().setColor(color);
12161
12304
  sphereActor.setVisibility(this.configuration.showHandles);
12162
12305
  viewport.addActor({ actor: sphereActor, uid: uid });
12163
12306
  }
12164
- _calculateAdaptiveSphereRadius(diagonal) {
12165
- const baseRadius = this.configuration.sphereRadius !== undefined
12166
- ? this.configuration.sphereRadius
12167
- : 8;
12168
- const scaleFactor = this.configuration.sphereRadiusScale || 0.01;
12169
- const adaptiveRadius = diagonal * scaleFactor;
12170
- const minRadius = this.configuration.minSphereRadius || 2;
12171
- const maxRadius = this.configuration.maxSphereRadius || 50;
12172
- return Math.max(minRadius, Math.min(maxRadius, adaptiveRadius));
12307
+ _getDirectionVectorForAxis(axis) {
12308
+ if (this.originalClippingPlanes &&
12309
+ this.originalClippingPlanes.length >= volumeCropping.NUM_CLIPPING_PLANES) {
12310
+ switch (axis) {
12311
+ case 'x':
12312
+ return this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMIN]
12313
+ .normal;
12314
+ case 'y':
12315
+ return this.originalClippingPlanes[volumeCropping.PLANEINDEX.YMIN]
12316
+ .normal;
12317
+ case 'z':
12318
+ return this.originalClippingPlanes[volumeCropping.PLANEINDEX.ZMIN]
12319
+ .normal;
12320
+ default:
12321
+ return [1, 0, 0];
12322
+ }
12323
+ }
12324
+ if (!this.volumeDirectionVectors) {
12325
+ if (axis === 'x')
12326
+ return [1, 0, 0];
12327
+ if (axis === 'y')
12328
+ return [0, 1, 0];
12329
+ if (axis === 'z')
12330
+ return [0, 0, 1];
12331
+ return [1, 0, 0];
12332
+ }
12333
+ switch (axis) {
12334
+ case 'x':
12335
+ return this.volumeDirectionVectors.xDir;
12336
+ case 'y':
12337
+ return this.volumeDirectionVectors.yDir;
12338
+ case 'z':
12339
+ return this.volumeDirectionVectors.zDir;
12340
+ default:
12341
+ return [1, 0, 0];
12342
+ }
12343
+ }
12344
+ _getVolumeActor(viewport) {
12345
+ const vp = viewport || this._getViewport();
12346
+ return vp?.getDefaultActor()?.actor;
12347
+ }
12348
+ _getVolumeMapper(viewport) {
12349
+ const actor = this._getVolumeActor(viewport);
12350
+ return actor?.getMapper();
12351
+ }
12352
+ _applyClippingPlanesToMapper(mapper) {
12353
+ mapper.removeAllClippingPlanes();
12354
+ for (let i = 0; i < volumeCropping.NUM_CLIPPING_PLANES; ++i) {
12355
+ const plane = Plane/* default.newInstance */.Ay.newInstance({
12356
+ origin: this.originalClippingPlanes[i].origin,
12357
+ normal: this.originalClippingPlanes[i].normal,
12358
+ });
12359
+ mapper.addClippingPlane(plane);
12360
+ }
12173
12361
  }
12174
12362
  _updateClippingPlanesFromFaceSpheres(viewport) {
12175
12363
  const mapper = viewport.getDefaultActor().actor.getMapper();
12176
- this.originalClippingPlanes[0].origin = [
12177
- ...this.sphereStates[SPHEREINDEX.XMIN].point,
12364
+ this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMIN].origin = [
12365
+ ...this.sphereStates[volumeCropping.SPHEREINDEX.XMIN].point,
12178
12366
  ];
12179
- this.originalClippingPlanes[1].origin = [
12180
- ...this.sphereStates[SPHEREINDEX.XMAX].point,
12367
+ this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMAX].origin = [
12368
+ ...this.sphereStates[volumeCropping.SPHEREINDEX.XMAX].point,
12181
12369
  ];
12182
- this.originalClippingPlanes[2].origin = [
12183
- ...this.sphereStates[SPHEREINDEX.YMIN].point,
12370
+ this.originalClippingPlanes[volumeCropping.PLANEINDEX.YMIN].origin = [
12371
+ ...this.sphereStates[volumeCropping.SPHEREINDEX.YMIN].point,
12184
12372
  ];
12185
- this.originalClippingPlanes[3].origin = [
12186
- ...this.sphereStates[SPHEREINDEX.YMAX].point,
12373
+ this.originalClippingPlanes[volumeCropping.PLANEINDEX.YMAX].origin = [
12374
+ ...this.sphereStates[volumeCropping.SPHEREINDEX.YMAX].point,
12187
12375
  ];
12188
- this.originalClippingPlanes[4].origin = [
12189
- ...this.sphereStates[SPHEREINDEX.ZMIN].point,
12376
+ this.originalClippingPlanes[volumeCropping.PLANEINDEX.ZMIN].origin = [
12377
+ ...this.sphereStates[volumeCropping.SPHEREINDEX.ZMIN].point,
12190
12378
  ];
12191
- this.originalClippingPlanes[5].origin = [
12192
- ...this.sphereStates[SPHEREINDEX.ZMAX].point,
12379
+ this.originalClippingPlanes[volumeCropping.PLANEINDEX.ZMAX].origin = [
12380
+ ...this.sphereStates[volumeCropping.SPHEREINDEX.ZMAX].point,
12193
12381
  ];
12194
- mapper.removeAllClippingPlanes();
12195
- for (let i = 0; i < 6; ++i) {
12196
- const origin = this.originalClippingPlanes[i].origin;
12197
- const normal = this.originalClippingPlanes[i].normal;
12198
- const plane = Plane/* default.newInstance */.Ay.newInstance({
12199
- origin,
12200
- normal,
12201
- });
12202
- mapper.addClippingPlane(plane);
12203
- }
12382
+ this._applyClippingPlanesToMapper(mapper);
12204
12383
  }
12205
12384
  _updateCornerSpheresFromFaces() {
12206
- const xMin = this.sphereStates[SPHEREINDEX.XMIN].point[0];
12207
- const xMax = this.sphereStates[SPHEREINDEX.XMAX].point[0];
12208
- const yMin = this.sphereStates[SPHEREINDEX.YMIN].point[1];
12209
- const yMax = this.sphereStates[SPHEREINDEX.YMAX].point[1];
12210
- const zMin = this.sphereStates[SPHEREINDEX.ZMIN].point[2];
12211
- const zMax = this.sphereStates[SPHEREINDEX.ZMAX].point[2];
12385
+ const { xDir, yDir, zDir } = this._getDirectionVectors();
12386
+ if (!xDir || !yDir || !zDir)
12387
+ return;
12388
+ const faceXMin = this.sphereStates[volumeCropping.SPHEREINDEX.XMIN].point;
12389
+ const faceXMax = this.sphereStates[volumeCropping.SPHEREINDEX.XMAX].point;
12390
+ const faceYMin = this.sphereStates[volumeCropping.SPHEREINDEX.YMIN].point;
12391
+ const faceYMax = this.sphereStates[volumeCropping.SPHEREINDEX.YMAX].point;
12392
+ const faceZMin = this.sphereStates[volumeCropping.SPHEREINDEX.ZMIN].point;
12393
+ const faceZMax = this.sphereStates[volumeCropping.SPHEREINDEX.ZMAX].point;
12212
12394
  const corners = [
12213
- { key: 'XMIN_YMIN_ZMIN', pos: [xMin, yMin, zMin] },
12214
- { key: 'XMIN_YMIN_ZMAX', pos: [xMin, yMin, zMax] },
12215
- { key: 'XMIN_YMAX_ZMIN', pos: [xMin, yMax, zMin] },
12216
- { key: 'XMIN_YMAX_ZMAX', pos: [xMin, yMax, zMax] },
12217
- { key: 'XMAX_YMIN_ZMIN', pos: [xMax, yMin, zMin] },
12218
- { key: 'XMAX_YMIN_ZMAX', pos: [xMax, yMin, zMax] },
12219
- { key: 'XMAX_YMAX_ZMIN', pos: [xMax, yMax, zMin] },
12220
- { key: 'XMAX_YMAX_ZMAX', pos: [xMax, yMax, zMax] },
12395
+ {
12396
+ key: 'XMIN_YMIN_ZMIN',
12397
+ pos: this._calculateCornerFromFaces(faceXMin, faceYMin, faceZMin, xDir, yDir, zDir),
12398
+ },
12399
+ {
12400
+ key: 'XMIN_YMIN_ZMAX',
12401
+ pos: this._calculateCornerFromFaces(faceXMin, faceYMin, faceZMax, xDir, yDir, zDir),
12402
+ },
12403
+ {
12404
+ key: 'XMIN_YMAX_ZMIN',
12405
+ pos: this._calculateCornerFromFaces(faceXMin, faceYMax, faceZMin, xDir, yDir, zDir),
12406
+ },
12407
+ {
12408
+ key: 'XMIN_YMAX_ZMAX',
12409
+ pos: this._calculateCornerFromFaces(faceXMin, faceYMax, faceZMax, xDir, yDir, zDir),
12410
+ },
12411
+ {
12412
+ key: 'XMAX_YMIN_ZMIN',
12413
+ pos: this._calculateCornerFromFaces(faceXMax, faceYMin, faceZMin, xDir, yDir, zDir),
12414
+ },
12415
+ {
12416
+ key: 'XMAX_YMIN_ZMAX',
12417
+ pos: this._calculateCornerFromFaces(faceXMax, faceYMin, faceZMax, xDir, yDir, zDir),
12418
+ },
12419
+ {
12420
+ key: 'XMAX_YMAX_ZMIN',
12421
+ pos: this._calculateCornerFromFaces(faceXMax, faceYMax, faceZMin, xDir, yDir, zDir),
12422
+ },
12423
+ {
12424
+ key: 'XMAX_YMAX_ZMAX',
12425
+ pos: this._calculateCornerFromFaces(faceXMax, faceYMax, faceZMax, xDir, yDir, zDir),
12426
+ },
12221
12427
  ];
12222
12428
  for (const corner of corners) {
12223
- const state = this.sphereStates.find((s) => s.uid === `corner_${corner.key}`);
12224
- if (state) {
12225
- state.point[0] = corner.pos[0];
12226
- state.point[1] = corner.pos[1];
12227
- state.point[2] = corner.pos[2];
12228
- state.sphereSource.setCenter(...state.point);
12229
- state.sphereSource.modified();
12429
+ const stateIndex = this.sphereStates.findIndex((s) => s.uid === `corner_${corner.key}`);
12430
+ if (stateIndex !== -1) {
12431
+ this._updateSpherePosition(stateIndex, corner.pos);
12230
12432
  }
12231
12433
  }
12232
12434
  }
12233
12435
  _updateFaceSpheresFromCorners() {
12436
+ if (!this.volumeDirectionVectors)
12437
+ return;
12234
12438
  const corners = [
12235
- this.sphereStates[SPHEREINDEX.XMIN_YMIN_ZMIN].point,
12236
- this.sphereStates[SPHEREINDEX.XMIN_YMIN_ZMAX].point,
12237
- this.sphereStates[SPHEREINDEX.XMIN_YMAX_ZMIN].point,
12238
- this.sphereStates[SPHEREINDEX.XMIN_YMAX_ZMAX].point,
12239
- this.sphereStates[SPHEREINDEX.XMAX_YMIN_ZMIN].point,
12240
- this.sphereStates[SPHEREINDEX.XMAX_YMIN_ZMAX].point,
12241
- this.sphereStates[SPHEREINDEX.XMAX_YMAX_ZMIN].point,
12242
- this.sphereStates[SPHEREINDEX.XMAX_YMAX_ZMAX].point,
12243
- ];
12244
- const xs = corners.map((p) => p[0]);
12245
- const ys = corners.map((p) => p[1]);
12246
- const zs = corners.map((p) => p[2]);
12247
- const xMin = Math.min(...xs), xMax = Math.max(...xs);
12248
- const yMin = Math.min(...ys), yMax = Math.max(...ys);
12249
- const zMin = Math.min(...zs), zMax = Math.max(...zs);
12250
- this.sphereStates[SPHEREINDEX.XMIN].point = [
12251
- xMin,
12252
- (yMin + yMax) / 2,
12253
- (zMin + zMax) / 2,
12254
- ];
12255
- this.sphereStates[SPHEREINDEX.XMAX].point = [
12256
- xMax,
12257
- (yMin + yMax) / 2,
12258
- (zMin + zMax) / 2,
12259
- ];
12260
- this.sphereStates[SPHEREINDEX.YMIN].point = [
12261
- (xMin + xMax) / 2,
12262
- yMin,
12263
- (zMin + zMax) / 2,
12264
- ];
12265
- this.sphereStates[SPHEREINDEX.YMAX].point = [
12266
- (xMin + xMax) / 2,
12267
- yMax,
12268
- (zMin + zMax) / 2,
12269
- ];
12270
- this.sphereStates[SPHEREINDEX.ZMIN].point = [
12271
- (xMin + xMax) / 2,
12272
- (yMin + yMax) / 2,
12273
- zMin,
12274
- ];
12275
- this.sphereStates[SPHEREINDEX.ZMAX].point = [
12276
- (xMin + xMax) / 2,
12277
- (yMin + yMax) / 2,
12278
- zMax,
12439
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMIN_YMIN_ZMIN].point,
12440
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMIN_YMIN_ZMAX].point,
12441
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMIN_YMAX_ZMIN].point,
12442
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMIN_YMAX_ZMAX].point,
12443
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMAX_YMIN_ZMIN].point,
12444
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMAX_YMIN_ZMAX].point,
12445
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMAX_YMAX_ZMIN].point,
12446
+ this.sphereStates[volumeCropping.SPHEREINDEX.XMAX_YMAX_ZMAX].point,
12279
12447
  ];
12280
- [
12281
- SPHEREINDEX.XMIN,
12282
- SPHEREINDEX.XMAX,
12283
- SPHEREINDEX.YMIN,
12284
- SPHEREINDEX.YMAX,
12285
- SPHEREINDEX.ZMIN,
12286
- SPHEREINDEX.ZMAX,
12287
- ].forEach((idx) => {
12288
- const s = this.sphereStates[idx];
12289
- s.sphereSource.setCenter(...s.point);
12290
- s.sphereSource.modified();
12291
- });
12448
+ const faceXMin = this._averagePoints([
12449
+ corners[0],
12450
+ corners[1],
12451
+ corners[2],
12452
+ corners[3],
12453
+ ]);
12454
+ const faceXMax = this._averagePoints([
12455
+ corners[4],
12456
+ corners[5],
12457
+ corners[6],
12458
+ corners[7],
12459
+ ]);
12460
+ const faceYMin = this._averagePoints([
12461
+ corners[0],
12462
+ corners[1],
12463
+ corners[4],
12464
+ corners[5],
12465
+ ]);
12466
+ const faceYMax = this._averagePoints([
12467
+ corners[2],
12468
+ corners[3],
12469
+ corners[6],
12470
+ corners[7],
12471
+ ]);
12472
+ const faceZMin = this._averagePoints([
12473
+ corners[0],
12474
+ corners[2],
12475
+ corners[4],
12476
+ corners[6],
12477
+ ]);
12478
+ const faceZMax = this._averagePoints([
12479
+ corners[1],
12480
+ corners[3],
12481
+ corners[5],
12482
+ corners[7],
12483
+ ]);
12484
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.XMIN, faceXMin);
12485
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.XMAX, faceXMax);
12486
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.YMIN, faceYMin);
12487
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.YMAX, faceYMax);
12488
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.ZMIN, faceZMin);
12489
+ this._updateSpherePosition(volumeCropping.SPHEREINDEX.ZMAX, faceZMax);
12292
12490
  }
12293
12491
  _updateCornerSpheres() {
12294
- const xMin = this.sphereStates[SPHEREINDEX.XMIN].point[0];
12295
- const xMax = this.sphereStates[SPHEREINDEX.XMAX].point[0];
12296
- const yMin = this.sphereStates[SPHEREINDEX.YMIN].point[1];
12297
- const yMax = this.sphereStates[SPHEREINDEX.YMAX].point[1];
12298
- const zMin = this.sphereStates[SPHEREINDEX.ZMIN].point[2];
12299
- const zMax = this.sphereStates[SPHEREINDEX.ZMAX].point[2];
12492
+ const { xDir, yDir, zDir } = this._getDirectionVectors();
12493
+ if (!xDir || !yDir || !zDir)
12494
+ return;
12495
+ const faceXMin = this.sphereStates[volumeCropping.SPHEREINDEX.XMIN].point;
12496
+ const faceXMax = this.sphereStates[volumeCropping.SPHEREINDEX.XMAX].point;
12497
+ const faceYMin = this.sphereStates[volumeCropping.SPHEREINDEX.YMIN].point;
12498
+ const faceYMax = this.sphereStates[volumeCropping.SPHEREINDEX.YMAX].point;
12499
+ const faceZMin = this.sphereStates[volumeCropping.SPHEREINDEX.ZMIN].point;
12500
+ const faceZMax = this.sphereStates[volumeCropping.SPHEREINDEX.ZMAX].point;
12300
12501
  const corners = [
12301
- { key: 'XMIN_YMIN_ZMIN', pos: [xMin, yMin, zMin] },
12302
- { key: 'XMIN_YMIN_ZMAX', pos: [xMin, yMin, zMax] },
12303
- { key: 'XMIN_YMAX_ZMIN', pos: [xMin, yMax, zMin] },
12304
- { key: 'XMIN_YMAX_ZMAX', pos: [xMin, yMax, zMax] },
12305
- { key: 'XMAX_YMIN_ZMIN', pos: [xMax, yMin, zMin] },
12306
- { key: 'XMAX_YMIN_ZMAX', pos: [xMax, yMin, zMax] },
12307
- { key: 'XMAX_YMAX_ZMIN', pos: [xMax, yMax, zMin] },
12308
- { key: 'XMAX_YMAX_ZMAX', pos: [xMax, yMax, zMax] },
12502
+ {
12503
+ key: 'XMIN_YMIN_ZMIN',
12504
+ pos: this._calculateCornerFromProjection(faceXMin, faceYMin, faceZMin, xDir, yDir, zDir),
12505
+ },
12506
+ {
12507
+ key: 'XMIN_YMIN_ZMAX',
12508
+ pos: this._calculateCornerFromProjection(faceXMin, faceYMin, faceZMax, xDir, yDir, zDir),
12509
+ },
12510
+ {
12511
+ key: 'XMIN_YMAX_ZMIN',
12512
+ pos: this._calculateCornerFromProjection(faceXMin, faceYMax, faceZMin, xDir, yDir, zDir),
12513
+ },
12514
+ {
12515
+ key: 'XMIN_YMAX_ZMAX',
12516
+ pos: this._calculateCornerFromProjection(faceXMin, faceYMax, faceZMax, xDir, yDir, zDir),
12517
+ },
12518
+ {
12519
+ key: 'XMAX_YMIN_ZMIN',
12520
+ pos: this._calculateCornerFromProjection(faceXMax, faceYMin, faceZMin, xDir, yDir, zDir),
12521
+ },
12522
+ {
12523
+ key: 'XMAX_YMIN_ZMAX',
12524
+ pos: this._calculateCornerFromProjection(faceXMax, faceYMin, faceZMax, xDir, yDir, zDir),
12525
+ },
12526
+ {
12527
+ key: 'XMAX_YMAX_ZMIN',
12528
+ pos: this._calculateCornerFromProjection(faceXMax, faceYMax, faceZMin, xDir, yDir, zDir),
12529
+ },
12530
+ {
12531
+ key: 'XMAX_YMAX_ZMAX',
12532
+ pos: this._calculateCornerFromProjection(faceXMax, faceYMax, faceZMax, xDir, yDir, zDir),
12533
+ },
12309
12534
  ];
12310
12535
  for (const corner of corners) {
12311
- const state = this.sphereStates.find((s) => s.uid === `corner_${corner.key}`);
12312
- if (state) {
12313
- state.point[0] = corner.pos[0];
12314
- state.point[1] = corner.pos[1];
12315
- state.point[2] = corner.pos[2];
12316
- state.sphereSource.setCenter(...state.point);
12317
- state.sphereSource.modified();
12536
+ const stateIndex = this.sphereStates.findIndex((s) => s.uid === `corner_${corner.key}`);
12537
+ if (stateIndex !== -1) {
12538
+ this._updateSpherePosition(stateIndex, corner.pos);
12318
12539
  }
12319
12540
  }
12320
- Object.values(this.edgeLines).forEach(({ source, key1, key2 }) => {
12321
- const state1 = this.sphereStates.find((s) => s.uid === `corner_${key1}`);
12322
- const state2 = this.sphereStates.find((s) => s.uid === `corner_${key2}`);
12323
- if (state1 && state2) {
12324
- const points = source.getPoints();
12325
- points.setPoint(0, state1.point[0], state1.point[1], state1.point[2]);
12326
- points.setPoint(1, state2.point[0], state2.point[1], state2.point[2]);
12327
- points.modified();
12328
- source.modified();
12329
- }
12330
- });
12541
+ this._updateEdgeLines();
12331
12542
  }
12332
12543
  _unsubscribeToViewportNewVolumeSet(viewportsInfo) {
12333
12544
  viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
@@ -12343,14 +12554,111 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12343
12554
  element.addEventListener(esm.Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, this._onNewVolume);
12344
12555
  });
12345
12556
  }
12557
+ _getDirectionVectors() {
12558
+ const hasPlanes = this.originalClippingPlanes?.length >= volumeCropping.NUM_CLIPPING_PLANES;
12559
+ return {
12560
+ xDir: hasPlanes
12561
+ ? this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMIN].normal
12562
+ : this.volumeDirectionVectors?.xDir || [1, 0, 0],
12563
+ yDir: hasPlanes
12564
+ ? this.originalClippingPlanes[volumeCropping.PLANEINDEX.YMIN].normal
12565
+ : this.volumeDirectionVectors?.yDir || [0, 1, 0],
12566
+ zDir: hasPlanes
12567
+ ? this.originalClippingPlanes[volumeCropping.PLANEINDEX.ZMIN].normal
12568
+ : this.volumeDirectionVectors?.zDir || [0, 0, 1],
12569
+ };
12570
+ }
12571
+ _updateSpherePosition(sphereIndex, newPoint) {
12572
+ const state = this.sphereStates[sphereIndex];
12573
+ if (state) {
12574
+ state.point = newPoint;
12575
+ state.sphereSource.setCenter(...newPoint);
12576
+ state.sphereSource.modified();
12577
+ }
12578
+ }
12579
+ _updateFaceSpheresFromClippingPlanes() {
12580
+ const faceMappings = [
12581
+ { sphereIdx: volumeCropping.SPHEREINDEX.XMIN, planeIdx: volumeCropping.PLANEINDEX.XMIN },
12582
+ { sphereIdx: volumeCropping.SPHEREINDEX.XMAX, planeIdx: volumeCropping.PLANEINDEX.XMAX },
12583
+ { sphereIdx: volumeCropping.SPHEREINDEX.YMIN, planeIdx: volumeCropping.PLANEINDEX.YMIN },
12584
+ { sphereIdx: volumeCropping.SPHEREINDEX.YMAX, planeIdx: volumeCropping.PLANEINDEX.YMAX },
12585
+ { sphereIdx: volumeCropping.SPHEREINDEX.ZMIN, planeIdx: volumeCropping.PLANEINDEX.ZMIN },
12586
+ { sphereIdx: volumeCropping.SPHEREINDEX.ZMAX, planeIdx: volumeCropping.PLANEINDEX.ZMAX },
12587
+ ];
12588
+ faceMappings.forEach(({ sphereIdx, planeIdx }) => {
12589
+ const newPoint = [
12590
+ ...this.originalClippingPlanes[planeIdx].origin,
12591
+ ];
12592
+ this._updateSpherePosition(sphereIdx, newPoint);
12593
+ });
12594
+ }
12595
+ _averagePoints(points) {
12596
+ const sum = points.reduce((acc, p) => [acc[0] + p[0], acc[1] + p[1], acc[2] + p[2]], [0, 0, 0]);
12597
+ return [
12598
+ sum[0] / points.length,
12599
+ sum[1] / points.length,
12600
+ sum[2] / points.length,
12601
+ ];
12602
+ }
12603
+ _notifyClippingPlanesChanged(viewport) {
12604
+ const eventData = {
12605
+ originalClippingPlanes: this.originalClippingPlanes,
12606
+ seriesInstanceUID: this.seriesInstanceUID,
12607
+ };
12608
+ if (viewport) {
12609
+ eventData.viewportId = viewport.id;
12610
+ eventData.renderingEngineId = viewport.renderingEngineId;
12611
+ }
12612
+ (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPING_TOOL_CHANGED, eventData);
12613
+ }
12614
+ _calculateCornerFromFaces(faceX, faceY, faceZ, xDir, yDir, zDir) {
12615
+ const deltaXY = [
12616
+ faceY[0] - faceX[0],
12617
+ faceY[1] - faceX[1],
12618
+ faceY[2] - faceX[2],
12619
+ ];
12620
+ const distY = deltaXY[0] * yDir[0] + deltaXY[1] * yDir[1] + deltaXY[2] * yDir[2];
12621
+ const deltaXZ = [
12622
+ faceZ[0] - faceX[0],
12623
+ faceZ[1] - faceX[1],
12624
+ faceZ[2] - faceX[2],
12625
+ ];
12626
+ const distZ = deltaXZ[0] * zDir[0] + deltaXZ[1] * zDir[1] + deltaXZ[2] * zDir[2];
12627
+ return [
12628
+ faceX[0] + distY * yDir[0] + distZ * zDir[0],
12629
+ faceX[1] + distY * yDir[1] + distZ * zDir[1],
12630
+ faceX[2] + distY * yDir[2] + distZ * zDir[2],
12631
+ ];
12632
+ }
12633
+ _calculateCornerFromProjection(faceX, faceY, faceZ, xDir, yDir, zDir) {
12634
+ const dX = faceX[0] * xDir[0] + faceX[1] * xDir[1] + faceX[2] * xDir[2];
12635
+ const dY = faceY[0] * yDir[0] + faceY[1] * yDir[1] + faceY[2] * yDir[2];
12636
+ const dZ = faceZ[0] * zDir[0] + faceZ[1] * zDir[1] + faceZ[2] * zDir[2];
12637
+ return [
12638
+ dX * xDir[0] + dY * yDir[0] + dZ * zDir[0],
12639
+ dX * xDir[1] + dY * yDir[1] + dZ * zDir[1],
12640
+ dX * xDir[2] + dY * yDir[2] + dZ * zDir[2],
12641
+ ];
12642
+ }
12643
+ _updateEdgeLines() {
12644
+ Object.values(this.edgeLines).forEach(({ source, key1, key2 }) => {
12645
+ const state1 = this.sphereStates.find((s) => s.uid === `corner_${key1}`);
12646
+ const state2 = this.sphereStates.find((s) => s.uid === `corner_${key2}`);
12647
+ if (state1 && state2) {
12648
+ const points = source.getPoints();
12649
+ points.setPoint(0, state1.point[0], state1.point[1], state1.point[2]);
12650
+ points.setPoint(1, state2.point[0], state2.point[1], state2.point[2]);
12651
+ points.modified();
12652
+ source.modified();
12653
+ }
12654
+ });
12655
+ }
12346
12656
  }
12347
12657
  VolumeCroppingTool.toolName = 'VolumeCropping';
12348
12658
  /* harmony default export */ const tools_VolumeCroppingTool = ((/* unused pure expression or super */ null && (VolumeCroppingTool)));
12349
12659
 
12350
12660
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/cursors/elementCursor.js
12351
12661
  var elementCursor = __webpack_require__(7001);
12352
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/vec2/liangBarksyClip.js
12353
- var liangBarksyClip = __webpack_require__(35381);
12354
12662
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/stateManagement/annotation/annotationLocking.js
12355
12663
  var annotationLocking = __webpack_require__(2076);
12356
12664
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/VolumeCroppingControlTool.js
@@ -12369,13 +12677,6 @@ var annotationLocking = __webpack_require__(2076);
12369
12677
 
12370
12678
 
12371
12679
 
12372
- const { RENDERING_DEFAULTS } = esm.CONSTANTS;
12373
- function defaultReferenceLineColor() {
12374
- return 'rgb(0, 200, 0)';
12375
- }
12376
- function defaultReferenceLineControllable() {
12377
- return true;
12378
- }
12379
12680
  const OPERATION = {
12380
12681
  DRAG: 1,
12381
12682
  ROTATE: 2,
@@ -12408,12 +12709,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12408
12709
  },
12409
12710
  }) {
12410
12711
  super(toolProps, defaultToolProps);
12411
- this._virtualAnnotations = [];
12412
- this.sphereStates = [];
12413
- this.draggingSphereIndex = null;
12414
- this.toolCenter = [0, 0, 0];
12415
- this.toolCenterMin = [0, 0, 0];
12416
- this.toolCenterMax = [0, 0, 0];
12712
+ this.clippingPlanes = [];
12417
12713
  this.initializeViewport = ({ renderingEngineId, viewportId, }) => {
12418
12714
  if (!renderingEngineId || !viewportId) {
12419
12715
  console.warn('VolumeCroppingControlTool: Missing renderingEngineId or viewportId');
@@ -12424,15 +12720,21 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12424
12720
  return;
12425
12721
  }
12426
12722
  const { viewport } = enabledElement;
12427
- this._updateToolCentersFromViewport(viewport);
12723
+ const volumeActors = viewport.getActors();
12724
+ if (volumeActors && volumeActors.length > 0) {
12725
+ const imageData = volumeActors[0].actor.getMapper().getInputData();
12726
+ if (imageData) {
12727
+ this.seriesInstanceUID = imageData.seriesInstanceUID || 'unknown';
12728
+ }
12729
+ }
12428
12730
  const { element } = viewport;
12429
- const { position, focalPoint, viewPlaneNormal } = viewport.getCamera();
12731
+ const { position, focalPoint } = viewport.getCamera();
12430
12732
  let annotations = this._getAnnotations(enabledElement);
12431
12733
  annotations = this.filterInteractableAnnotationsForElement(element, annotations);
12432
12734
  if (annotations?.length) {
12433
12735
  (0,annotationState.removeAnnotation)(annotations[0].annotationUID);
12434
12736
  }
12435
- const orientation = this._getOrientationFromNormal(viewport.getCamera().viewPlaneNormal);
12737
+ const orientation = (0,volumeCropping.getOrientationFromNormal)(viewport.getCamera().viewPlaneNormal);
12436
12738
  const annotation = {
12437
12739
  highlighted: false,
12438
12740
  metadata: {
@@ -12442,11 +12744,11 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12442
12744
  },
12443
12745
  data: {
12444
12746
  handles: {
12445
- toolCenter: this.toolCenter,
12446
- toolCenterMin: this.toolCenterMin,
12447
- toolCenterMax: this.toolCenterMax,
12747
+ activeOperation: null,
12748
+ clippingPlanes: this.clippingPlanes.length > 0
12749
+ ? (0,volumeCropping.copyClippingPlanes)(this.clippingPlanes)
12750
+ : [],
12448
12751
  },
12449
- activeOperation: null,
12450
12752
  activeViewportIds: [],
12451
12753
  viewportId,
12452
12754
  referenceLines: [],
@@ -12454,10 +12756,6 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12454
12756
  },
12455
12757
  };
12456
12758
  (0,annotationState.addAnnotation)(annotation, element);
12457
- return {
12458
- normal: viewPlaneNormal,
12459
- point: viewport.canvasToWorld([100, 100]),
12460
- };
12461
12759
  };
12462
12760
  this._getViewportsInfo = () => {
12463
12761
  const viewports = (0,ToolGroupManager.getToolGroup)(this.toolGroupId).viewportsInfo;
@@ -12490,139 +12788,22 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12490
12788
  }
12491
12789
  viewport.render();
12492
12790
  }
12493
- this._computeToolCenter(viewportsInfo);
12791
+ this._initializeViewports(viewportsInfo);
12494
12792
  };
12495
- this.computeToolCenter = () => {
12496
- const viewportsInfo = this._getViewportsInfo();
12497
- };
12498
- this._computeToolCenter = (viewportsInfo) => {
12499
- if (!viewportsInfo || !viewportsInfo[0]) {
12500
- console.warn(' _computeToolCenter : No valid viewportsInfo for computeToolCenter.');
12793
+ this._initializeViewports = (viewportsInfo) => {
12794
+ if (!viewportsInfo?.length || !viewportsInfo[0]) {
12795
+ console.warn('VolumeCroppingControlTool: No valid viewportsInfo for initialization.');
12501
12796
  return;
12502
12797
  }
12503
- const orientationIds = ['AXIAL', 'CORONAL', 'SAGITTAL'];
12504
- const presentOrientations = viewportsInfo
12505
- .map((vp) => {
12506
- if (vp.renderingEngineId) {
12507
- const renderingEngine = (0,esm.getRenderingEngine)(vp.renderingEngineId);
12508
- const viewport = renderingEngine.getViewport(vp.viewportId);
12509
- if (viewport && viewport.getCamera) {
12510
- const orientation = this._getOrientationFromNormal(viewport.getCamera().viewPlaneNormal);
12511
- if (orientation) {
12512
- return orientation;
12513
- }
12514
- }
12515
- }
12516
- return null;
12517
- })
12518
- .filter(Boolean);
12519
- const missingOrientation = orientationIds.find((id) => !presentOrientations.includes(id));
12520
- const presentNormals = [];
12521
- const presentCenters = [];
12522
- const presentViewportInfos = viewportsInfo.filter((vp) => {
12523
- let orientation = null;
12524
- if (vp.renderingEngineId) {
12525
- const renderingEngine = (0,esm.getRenderingEngine)(vp.renderingEngineId);
12526
- const viewport = renderingEngine.getViewport(vp.viewportId);
12527
- if (viewport && viewport.getCamera) {
12528
- orientation = this._getOrientationFromNormal(viewport.getCamera().viewPlaneNormal);
12529
- }
12530
- }
12531
- return orientation && orientationIds.includes(orientation);
12532
- });
12533
- presentViewportInfos.forEach((vpInfo) => {
12534
- const { normal, point } = this.initializeViewport(vpInfo);
12535
- presentNormals.push(normal);
12536
- presentCenters.push(point);
12798
+ viewportsInfo.forEach((vpInfo) => {
12799
+ this.initializeViewport(vpInfo);
12537
12800
  });
12538
- if (presentViewportInfos.length === 2 && missingOrientation) {
12539
- const virtualNormal = [0, 0, 0];
12540
- gl_matrix_esm/* vec3.cross */.eR.cross(virtualNormal, presentNormals[0], presentNormals[1]);
12541
- gl_matrix_esm/* vec3.normalize */.eR.normalize(virtualNormal, virtualNormal);
12542
- const virtualCenter = [
12543
- (presentCenters[0][0] + presentCenters[1][0]) / 2,
12544
- (presentCenters[0][1] + presentCenters[1][1]) / 2,
12545
- (presentCenters[0][2] + presentCenters[1][2]) / 2,
12546
- ];
12547
- const orientation = null;
12548
- const virtualAnnotation = {
12549
- highlighted: false,
12550
- metadata: {
12551
- cameraPosition: [...virtualCenter],
12552
- cameraFocalPoint: [...virtualCenter],
12553
- toolName: this.getToolName(),
12554
- },
12555
- data: {
12556
- handles: {
12557
- activeOperation: null,
12558
- toolCenter: this.toolCenter,
12559
- toolCenterMin: this.toolCenterMin,
12560
- toolCenterMax: this.toolCenterMax,
12561
- },
12562
- activeViewportIds: [],
12563
- viewportId: missingOrientation,
12564
- referenceLines: [],
12565
- orientation,
12566
- },
12567
- isVirtual: true,
12568
- virtualNormal,
12569
- };
12570
- this._virtualAnnotations = [virtualAnnotation];
12571
- }
12572
- else if (presentViewportInfos.length === 1) {
12573
- let presentOrientation = null;
12574
- const vpInfo = presentViewportInfos[0];
12575
- if (vpInfo.renderingEngineId) {
12576
- const renderingEngine = (0,esm.getRenderingEngine)(vpInfo.renderingEngineId);
12577
- const viewport = renderingEngine.getViewport(vpInfo.viewportId);
12578
- if (viewport && viewport.getCamera) {
12579
- presentOrientation = this._getOrientationFromNormal(viewport.getCamera().viewPlaneNormal);
12580
- }
12581
- }
12582
- const presentCenter = presentCenters[0];
12583
- const canonicalNormals = {
12584
- AXIAL: [0, 0, 1],
12585
- CORONAL: [0, 1, 0],
12586
- SAGITTAL: [1, 0, 0],
12587
- };
12588
- const missingIds = orientationIds.filter((id) => id !== presentOrientation);
12589
- const virtualAnnotations = missingIds.map((orientation) => {
12590
- const normal = canonicalNormals[orientation];
12591
- const virtualAnnotation = {
12592
- highlighted: false,
12593
- metadata: {
12594
- cameraPosition: [...presentCenter],
12595
- cameraFocalPoint: [...presentCenter],
12596
- toolName: this.getToolName(),
12597
- },
12598
- data: {
12599
- handles: {
12600
- activeOperation: null,
12601
- toolCenter: this.toolCenter,
12602
- toolCenterMin: this.toolCenterMin,
12603
- toolCenterMax: this.toolCenterMax,
12604
- },
12605
- activeViewportIds: [],
12606
- viewportId: orientation,
12607
- referenceLines: [],
12608
- orientation,
12609
- },
12610
- isVirtual: true,
12611
- virtualNormal: normal,
12612
- };
12613
- return virtualAnnotation;
12614
- });
12615
- this._virtualAnnotations = virtualAnnotations;
12616
- }
12617
- if (viewportsInfo && viewportsInfo.length) {
12618
- (0,triggerAnnotationRenderForViewportIds/* default */.A)(viewportsInfo.map(({ viewportId }) => viewportId));
12619
- }
12801
+ (0,triggerAnnotationRenderForViewportIds/* default */.A)(viewportsInfo.map(({ viewportId }) => viewportId));
12620
12802
  };
12621
12803
  this.cancel = () => {
12622
- console.log('Not implemented yet');
12623
12804
  };
12624
12805
  this.isPointNearTool = (element, annotation, canvasCoords, proximity) => {
12625
- if (this._pointNearTool(element, annotation, canvasCoords, 6)) {
12806
+ if (this._pointNearTool(element, annotation, canvasCoords, volumeCropping.POINT_PROXIMITY_THRESHOLD_PIXELS)) {
12626
12807
  return true;
12627
12808
  }
12628
12809
  return false;
@@ -12654,13 +12835,8 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12654
12835
  if (!data.handles) {
12655
12836
  continue;
12656
12837
  }
12657
- const previousActiveOperation = data.handles.activeOperation;
12658
- const previousActiveViewportIds = data.activeViewportIds && data.activeViewportIds.length > 0
12659
- ? [...data.activeViewportIds]
12660
- : [];
12661
12838
  data.activeViewportIds = [];
12662
- let near = false;
12663
- near = this._pointNearTool(element, annotation, canvasCoords, 6);
12839
+ const near = this._pointNearTool(element, annotation, canvasCoords, volumeCropping.POINT_PROXIMITY_THRESHOLD_PIXELS);
12664
12840
  const nearToolAndNotMarkedActive = near && !highlighted;
12665
12841
  const notNearToolAndMarkedActive = !near && highlighted;
12666
12842
  if (nearToolAndNotMarkedActive || notNearToolAndMarkedActive) {
@@ -12677,12 +12853,9 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12677
12853
  const enabledElement = (0,esm.getEnabledElement)(element);
12678
12854
  let orientation = null;
12679
12855
  if (enabledElement.viewport && enabledElement.viewport.getCamera) {
12680
- orientation = this._getOrientationFromNormal(enabledElement.viewport.getCamera().viewPlaneNormal);
12856
+ orientation = (0,volumeCropping.getOrientationFromNormal)(enabledElement.viewport.getCamera().viewPlaneNormal);
12681
12857
  }
12682
12858
  const filtered = annotations.filter((annotation) => {
12683
- if (annotation.isVirtual) {
12684
- return true;
12685
- }
12686
12859
  if (annotation.data.orientation &&
12687
12860
  orientation &&
12688
12861
  annotation.data.orientation === orientation) {
@@ -12699,7 +12872,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12699
12872
  const s2_x = q2[0] - q1[0];
12700
12873
  const s2_y = q2[1] - q1[1];
12701
12874
  const denom = -s2_x * s1_y + s1_x * s2_y;
12702
- if (Math.abs(denom) < 1e-8) {
12875
+ if (Math.abs(denom) < volumeCropping.LINE_INTERSECTION_TOLERANCE) {
12703
12876
  return null;
12704
12877
  }
12705
12878
  const s = (-s1_y * (p1[0] - q1[0]) + s1_x * (p1[1] - q1[1])) / denom;
@@ -12716,10 +12889,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12716
12889
  let renderStatus = false;
12717
12890
  const { viewport, renderingEngine } = enabledElement;
12718
12891
  const { element } = viewport;
12719
- let annotations = this._getAnnotations(enabledElement);
12720
- if (this._virtualAnnotations && this._virtualAnnotations.length) {
12721
- annotations = annotations.concat(this._virtualAnnotations);
12722
- }
12892
+ const annotations = this._getAnnotations(enabledElement);
12723
12893
  const camera = viewport.getCamera();
12724
12894
  const filteredToolAnnotations = this.filterInteractableAnnotationsForElement(element, annotations);
12725
12895
  const viewportAnnotation = filteredToolAnnotations[0];
@@ -12730,135 +12900,65 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12730
12900
  const { clientWidth, clientHeight } = viewport.canvas;
12731
12901
  const canvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
12732
12902
  const data = viewportAnnotation.data;
12733
- const otherViewportAnnotations = annotations;
12734
- const volumeCroppingCenterCanvasMin = viewport.worldToCanvas(this.toolCenterMin);
12735
- const volumeCroppingCenterCanvasMax = viewport.worldToCanvas(this.toolCenterMax);
12736
- const referenceLines = [];
12737
- const canvasBox = [0, 0, clientWidth, clientHeight];
12738
- otherViewportAnnotations.forEach((annotation) => {
12739
- const data = annotation.data;
12740
- const isVirtual = 'isVirtual' in annotation &&
12741
- annotation.isVirtual === true;
12742
- data.handles.toolCenter = this.toolCenter;
12743
- let otherViewport, otherCamera, clientWidth, clientHeight, otherCanvasDiagonalLength, otherCanvasCenter, otherViewportCenterWorld;
12744
- if (isVirtual) {
12745
- const realViewports = viewportsInfo.filter((vp) => vp.viewportId !== data.viewportId);
12746
- if (realViewports.length === 2) {
12747
- const vp1 = renderingEngine.getViewport(realViewports[0].viewportId);
12748
- const vp2 = renderingEngine.getViewport(realViewports[1].viewportId);
12749
- const normal1 = vp1.getCamera().viewPlaneNormal;
12750
- const normal2 = vp2.getCamera().viewPlaneNormal;
12751
- const virtualNormal = gl_matrix_esm/* vec3.create */.eR.create();
12752
- gl_matrix_esm/* vec3.cross */.eR.cross(virtualNormal, normal1, normal2);
12753
- gl_matrix_esm/* vec3.normalize */.eR.normalize(virtualNormal, virtualNormal);
12754
- otherCamera = {
12755
- viewPlaneNormal: virtualNormal,
12756
- position: data.handles.toolCenter,
12757
- focalPoint: data.handles.toolCenter,
12758
- viewUp: [0, 1, 0],
12759
- };
12760
- clientWidth = viewport.canvas.clientWidth;
12761
- clientHeight = viewport.canvas.clientHeight;
12762
- otherCanvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
12763
- otherCanvasCenter = [clientWidth * 0.5, clientHeight * 0.5];
12764
- otherViewportCenterWorld = data.handles.toolCenter;
12765
- otherViewport = {
12766
- id: data.viewportId,
12767
- canvas: viewport.canvas,
12768
- canvasToWorld: () => data.handles.toolCenter,
12769
- };
12770
- }
12771
- else {
12772
- const virtualNormal = annotation
12773
- .virtualNormal ?? [0, 0, 1];
12774
- otherCamera = {
12775
- viewPlaneNormal: virtualNormal,
12776
- position: data.handles.toolCenter,
12777
- focalPoint: data.handles.toolCenter,
12778
- viewUp: [0, 1, 0],
12779
- };
12780
- clientWidth = viewport.canvas.clientWidth;
12781
- clientHeight = viewport.canvas.clientHeight;
12782
- otherCanvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
12783
- otherCanvasCenter = [clientWidth * 0.5, clientHeight * 0.5];
12784
- otherViewportCenterWorld = data.handles.toolCenter;
12785
- otherViewport = {
12786
- id: data.viewportId,
12787
- canvas: viewport.canvas,
12788
- canvasToWorld: () => data.handles.toolCenter,
12789
- };
12790
- }
12903
+ let clippingPlanes = viewportAnnotation.data.handles.clippingPlanes;
12904
+ if (!clippingPlanes || clippingPlanes.length < volumeCropping.NUM_CLIPPING_PLANES) {
12905
+ if (this.clippingPlanes &&
12906
+ this.clippingPlanes.length >= volumeCropping.NUM_CLIPPING_PLANES) {
12907
+ clippingPlanes = this.clippingPlanes;
12908
+ data.handles.clippingPlanes = (0,volumeCropping.copyClippingPlanes)(this.clippingPlanes);
12791
12909
  }
12792
12910
  else {
12793
- otherViewport = renderingEngine.getViewport(data.viewportId);
12794
- otherCamera = otherViewport.getCamera();
12795
- clientWidth = otherViewport.canvas.clientWidth;
12796
- clientHeight = otherViewport.canvas.clientHeight;
12797
- otherCanvasDiagonalLength = Math.sqrt(clientWidth * clientWidth + clientHeight * clientHeight);
12798
- otherCanvasCenter = [clientWidth * 0.5, clientHeight * 0.5];
12799
- otherViewportCenterWorld =
12800
- otherViewport.canvasToWorld(otherCanvasCenter);
12911
+ return false;
12912
+ }
12913
+ }
12914
+ const { viewPlaneNormal, focalPoint } = camera;
12915
+ const referenceLines = [];
12916
+ const planeTypes = [
12917
+ 'min',
12918
+ 'max',
12919
+ 'min',
12920
+ 'max',
12921
+ 'min',
12922
+ 'max',
12923
+ ];
12924
+ for (let planeIndex = 0; planeIndex < volumeCropping.NUM_CLIPPING_PLANES; planeIndex++) {
12925
+ const clippingPlane = clippingPlanes[planeIndex];
12926
+ const intersection = (0,volumeCropping.computePlanePlaneIntersection)(clippingPlane, viewPlaneNormal, focalPoint);
12927
+ if (!intersection) {
12928
+ continue;
12929
+ }
12930
+ const lineBounds = (0,volumeCropping.findLineBoundsIntersection)(intersection.point, intersection.direction, viewport);
12931
+ if (!lineBounds) {
12932
+ continue;
12801
12933
  }
12802
- const otherViewportControllable = this._getReferenceLineControllable(otherViewport.id);
12803
- const direction = [0, 0, 0];
12804
- Core_Math/* default.cross */.Ay.cross(camera.viewPlaneNormal, otherCamera.viewPlaneNormal, direction);
12805
- Core_Math/* default.normalize */.Ay.normalize(direction);
12806
- Core_Math/* default.multiplyScalar */.Ay.multiplyScalar(direction, otherCanvasDiagonalLength);
12807
- const pointWorld0 = [0, 0, 0];
12808
- Core_Math/* default.add */.Ay.add(otherViewportCenterWorld, direction, pointWorld0);
12809
- const pointWorld1 = [0, 0, 0];
12810
- Core_Math/* default.subtract */.Ay.subtract(otherViewportCenterWorld, direction, pointWorld1);
12811
- const pointCanvas0 = viewport.worldToCanvas(pointWorld0);
12812
- const otherViewportCenterCanvas = viewport.worldToCanvas([
12813
- otherViewportCenterWorld[0] ?? 0,
12814
- otherViewportCenterWorld[1] ?? 0,
12815
- otherViewportCenterWorld[2] ?? 0,
12816
- ]);
12817
- const canvasUnitVectorFromCenter = gl_matrix_esm/* vec2.create */.Zc.create();
12818
- gl_matrix_esm/* vec2.subtract */.Zc.subtract(canvasUnitVectorFromCenter, pointCanvas0, otherViewportCenterCanvas);
12819
- gl_matrix_esm/* vec2.normalize */.Zc.normalize(canvasUnitVectorFromCenter, canvasUnitVectorFromCenter);
12820
- const canvasVectorFromCenterLong = gl_matrix_esm/* vec2.create */.Zc.create();
12821
- gl_matrix_esm/* vec2.scale */.Zc.scale(canvasVectorFromCenterLong, canvasUnitVectorFromCenter, canvasDiagonalLength * 100);
12822
- const refLinesCenterMin = otherViewportControllable
12823
- ? gl_matrix_esm/* vec2.clone */.Zc.clone(volumeCroppingCenterCanvasMin)
12824
- : gl_matrix_esm/* vec2.clone */.Zc.clone(otherViewportCenterCanvas);
12825
- const refLinePointMinOne = gl_matrix_esm/* vec2.create */.Zc.create();
12826
- const refLinePointMinTwo = gl_matrix_esm/* vec2.create */.Zc.create();
12827
- gl_matrix_esm/* vec2.add */.Zc.add(refLinePointMinOne, refLinesCenterMin, canvasVectorFromCenterLong);
12828
- gl_matrix_esm/* vec2.subtract */.Zc.subtract(refLinePointMinTwo, refLinesCenterMin, canvasVectorFromCenterLong);
12829
- (0,liangBarksyClip/* default */.A)(refLinePointMinOne, refLinePointMinTwo, canvasBox);
12830
- referenceLines.push([
12831
- otherViewport,
12832
- refLinePointMinOne,
12833
- refLinePointMinTwo,
12834
- 'min',
12835
- ]);
12836
- const refLinesCenterMax = otherViewportControllable
12837
- ? gl_matrix_esm/* vec2.clone */.Zc.clone(volumeCroppingCenterCanvasMax)
12838
- : gl_matrix_esm/* vec2.clone */.Zc.clone(otherViewportCenterCanvas);
12839
- const refLinePointMaxOne = gl_matrix_esm/* vec2.create */.Zc.create();
12840
- const refLinePointMaxTwo = gl_matrix_esm/* vec2.create */.Zc.create();
12841
- gl_matrix_esm/* vec2.add */.Zc.add(refLinePointMaxOne, refLinesCenterMax, canvasVectorFromCenterLong);
12842
- gl_matrix_esm/* vec2.subtract */.Zc.subtract(refLinePointMaxTwo, refLinesCenterMax, canvasVectorFromCenterLong);
12843
- (0,liangBarksyClip/* default */.A)(refLinePointMaxOne, refLinePointMaxTwo, canvasBox);
12844
12934
  referenceLines.push([
12845
- otherViewport,
12846
- refLinePointMaxOne,
12847
- refLinePointMaxTwo,
12848
- 'max',
12935
+ {
12936
+ id: viewport.id,
12937
+ canvas: viewport.canvas,
12938
+ },
12939
+ lineBounds.start,
12940
+ lineBounds.end,
12941
+ planeTypes[planeIndex],
12942
+ planeIndex,
12849
12943
  ]);
12850
- });
12944
+ }
12851
12945
  data.referenceLines = referenceLines;
12852
12946
  const viewportColor = this._getReferenceLineColor(viewport.id);
12853
- const color = viewportColor !== undefined ? viewportColor : 'rgb(200, 200, 200)';
12947
+ const defaultColor = viewportColor !== undefined ? viewportColor : 'rgb(200, 200, 200)';
12854
12948
  referenceLines.forEach((line, lineIndex) => {
12949
+ const [otherViewport, startPoint, endPoint, type, planeIndex] = line;
12950
+ if (planeIndex === undefined ||
12951
+ planeIndex < 0 ||
12952
+ planeIndex >= volumeCropping.NUM_CLIPPING_PLANES) {
12953
+ return;
12954
+ }
12855
12955
  const intersections = [];
12856
12956
  for (let j = 0; j < referenceLines.length; ++j) {
12857
12957
  if (j === lineIndex) {
12858
12958
  continue;
12859
12959
  }
12860
12960
  const otherLine = referenceLines[j];
12861
- const intersection = lineIntersection2D(line[1], line[2], otherLine[1], otherLine[2]);
12961
+ const intersection = lineIntersection2D(startPoint, endPoint, otherLine[1], otherLine[2]);
12862
12962
  if (intersection) {
12863
12963
  intersections.push({
12864
12964
  with: otherLine[3],
@@ -12866,32 +12966,12 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12866
12966
  });
12867
12967
  }
12868
12968
  }
12869
- const otherViewport = line[0];
12870
- let orientation = null;
12871
- if (otherViewport && otherViewport.id) {
12872
- const annotationForViewport = annotations.find((a) => a.data.viewportId === otherViewport.id);
12873
- if (annotationForViewport && annotationForViewport.data.orientation) {
12874
- orientation = String(annotationForViewport.data.orientation).toUpperCase();
12875
- }
12876
- else {
12877
- const idUpper = otherViewport.id.toUpperCase();
12878
- if (idUpper.includes('AXIAL')) {
12879
- orientation = 'AXIAL';
12880
- }
12881
- else if (idUpper.includes('CORONAL')) {
12882
- orientation = 'CORONAL';
12883
- }
12884
- else if (idUpper.includes('SAGITTAL')) {
12885
- orientation = 'SAGITTAL';
12886
- }
12887
- }
12888
- }
12969
+ const colorKey = (0,volumeCropping.getColorKeyForPlaneIndex)(planeIndex);
12889
12970
  const lineColors = this.configuration.lineColors || {};
12890
- const colorArr = lineColors[orientation] ||
12891
- lineColors.unknown || [1.0, 0.0, 0.0];
12892
- const color = Array.isArray(colorArr)
12893
- ? `rgb(${colorArr.map((v) => Math.round(v * 255)).join(',')})`
12894
- : colorArr;
12971
+ const colorArr = colorKey
12972
+ ? lineColors[colorKey] || lineColors.UNKNOWN || [1.0, 0.0, 0.0]
12973
+ : [1.0, 0.0, 0.0];
12974
+ const color = (0,esm.convertColorArrayToRgbString)(colorArr);
12895
12975
  const viewportControllable = this._getReferenceLineControllable(otherViewport.id);
12896
12976
  const selectedViewportId = data.activeViewportIds.find((id) => id === otherViewport.id);
12897
12977
  let lineWidth = this.configuration.lineWidth ?? 1.5;
@@ -12901,28 +12981,29 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12901
12981
  if (lineActive) {
12902
12982
  lineWidth = this.configuration.activeLineWidth ?? 2.5;
12903
12983
  }
12904
- const lineUID = `${lineIndex}`;
12905
- if (viewportControllable) {
12906
- if (intersections.length === 2) {
12907
- (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID, intersections[0].point, intersections[1].point, {
12908
- color,
12909
- lineWidth,
12910
- });
12911
- }
12912
- if (this.configuration.extendReferenceLines &&
12913
- intersections.length === 2) {
12914
- if (this.configuration.extendReferenceLines &&
12915
- intersections.length === 2) {
12916
- const sortedIntersections = intersections
12917
- .map((intersection) => ({
12918
- ...intersection,
12919
- distance: gl_matrix_esm/* vec2.distance */.Zc.distance(line[1], intersection.point),
12920
- }))
12921
- .sort((a, b) => a.distance - b.distance);
12922
- (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID + '_dashed_before', line[1], sortedIntersections[0].point, { color, lineWidth, lineDash: [4, 4] });
12923
- (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID + '_dashed_after', sortedIntersections[1].point, line[2], { color, lineWidth, lineDash: [4, 4] });
12924
- }
12925
- }
12984
+ const lineUID = `plane_${planeIndex}`;
12985
+ if (intersections.length === 2) {
12986
+ (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID, intersections[0].point, intersections[1].point, {
12987
+ color,
12988
+ lineWidth,
12989
+ });
12990
+ }
12991
+ else {
12992
+ (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID, startPoint, endPoint, {
12993
+ color,
12994
+ lineWidth,
12995
+ });
12996
+ }
12997
+ if (this.configuration.extendReferenceLines &&
12998
+ intersections.length === 2) {
12999
+ const sortedIntersections = intersections
13000
+ .map((intersection) => ({
13001
+ ...intersection,
13002
+ distance: gl_matrix_esm/* vec2.distance */.Zc.distance(startPoint, intersection.point),
13003
+ }))
13004
+ .sort((a, b) => a.distance - b.distance);
13005
+ (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID + '_dashed_before', startPoint, sortedIntersections[0].point, { color, lineWidth, lineDash: [4, 4] });
13006
+ (0,drawingSvg.drawLine)(svgDrawingHelper, annotationUID, lineUID + '_dashed_after', sortedIntersections[1].point, endPoint, { color, lineWidth, lineDash: [4, 4] });
12926
13007
  }
12927
13008
  });
12928
13009
  renderStatus = true;
@@ -12936,7 +13017,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12936
13017
  ];
12937
13018
  const circleRadius = viewportIndicatorsConfig?.circleRadius || canvasDiagonalLength * 0.01;
12938
13019
  const circleUID = '0';
12939
- (0,drawingSvg.drawCircle)(svgDrawingHelper, annotationUID, circleUID, referenceColorCoordinates, circleRadius, { color, fill: color });
13020
+ (0,drawingSvg.drawCircle)(svgDrawingHelper, annotationUID, circleUID, referenceColorCoordinates, circleRadius, { color: defaultColor, fill: defaultColor });
12940
13021
  }
12941
13022
  return renderStatus;
12942
13023
  };
@@ -12958,40 +13039,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12958
13039
  if (evt.detail.seriesInstanceUID !== this.seriesInstanceUID) {
12959
13040
  return;
12960
13041
  }
12961
- const { draggingSphereIndex, toolCenter } = evt.detail;
12962
- const newMin = [...this.toolCenterMin];
12963
- const newMax = [...this.toolCenterMax];
12964
- if (draggingSphereIndex >= 0 && draggingSphereIndex <= 5) {
12965
- const axis = Math.floor(draggingSphereIndex / 2);
12966
- const isMin = draggingSphereIndex % 2 === 0;
12967
- (isMin ? newMin : newMax)[axis] = toolCenter[axis];
12968
- this.setToolCenter(newMin, 'min');
12969
- this.setToolCenter(newMax, 'max');
12970
- return;
12971
- }
12972
- if (draggingSphereIndex >= 6 && draggingSphereIndex <= 13) {
12973
- const idx = draggingSphereIndex;
12974
- if (idx < 10) {
12975
- newMin[0] = toolCenter[0];
12976
- }
12977
- else {
12978
- newMax[0] = toolCenter[0];
12979
- }
12980
- if ([6, 7, 10, 11].includes(idx)) {
12981
- newMin[1] = toolCenter[1];
12982
- }
12983
- else {
12984
- newMax[1] = toolCenter[1];
12985
- }
12986
- if (idx % 2 === 0) {
12987
- newMin[2] = toolCenter[2];
12988
- }
12989
- else {
12990
- newMax[2] = toolCenter[2];
12991
- }
12992
- this.setToolCenter(newMin, 'min');
12993
- this.setToolCenter(newMax, 'max');
12994
- }
13042
+ return;
12995
13043
  }
12996
13044
  };
12997
13045
  this._onNewVolume = () => {
@@ -12999,72 +13047,28 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
12999
13047
  if (viewportsInfo && viewportsInfo.length > 0) {
13000
13048
  const { viewportId, renderingEngineId } = viewportsInfo[0];
13001
13049
  const renderingEngine = (0,esm.getRenderingEngine)(renderingEngineId);
13050
+ if (!renderingEngine) {
13051
+ return;
13052
+ }
13002
13053
  const viewport = renderingEngine.getViewport(viewportId);
13054
+ if (!viewport) {
13055
+ return;
13056
+ }
13003
13057
  const volumeActors = viewport.getActors();
13004
13058
  if (volumeActors.length > 0) {
13005
13059
  const imageData = volumeActors[0].actor.getMapper().getInputData();
13006
13060
  if (imageData) {
13007
13061
  this.seriesInstanceUID = imageData.seriesInstanceUID;
13008
- this._updateToolCentersFromViewport(viewport);
13009
- const annotations = (0,annotationState.getAnnotations)(this.getToolName(), viewportId) || [];
13010
- annotations.forEach((annotation) => {
13011
- if (annotation.data && annotation.data.handles) {
13012
- annotation.data.handles.toolCenter = [...this.toolCenter];
13013
- }
13014
- });
13015
13062
  }
13016
13063
  }
13017
13064
  }
13018
- this._computeToolCenter(viewportsInfo);
13065
+ this._initializeViewports(viewportsInfo);
13019
13066
  (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPINGCONTROL_TOOL_CHANGED, {
13020
13067
  toolGroupId: this.toolGroupId,
13021
13068
  viewportsInfo: viewportsInfo,
13022
13069
  seriesInstanceUID: this.seriesInstanceUID,
13023
13070
  });
13024
13071
  };
13025
- this._getAnnotationsForViewportsWithDifferentCameras = (enabledElement, annotations) => {
13026
- const { viewportId, renderingEngine, viewport } = enabledElement;
13027
- const otherViewportAnnotations = annotations.filter((annotation) => annotation.data.viewportId !== viewportId);
13028
- if (!otherViewportAnnotations || !otherViewportAnnotations.length) {
13029
- return [];
13030
- }
13031
- const camera = viewport.getCamera();
13032
- const { viewPlaneNormal, position } = camera;
13033
- const viewportsWithDifferentCameras = otherViewportAnnotations.filter((annotation) => {
13034
- const { viewportId } = annotation.data;
13035
- const targetViewport = renderingEngine.getViewport(viewportId);
13036
- const cameraOfTarget = targetViewport.getCamera();
13037
- return !(esm.utilities.isEqual(cameraOfTarget.viewPlaneNormal, viewPlaneNormal, 1e-2) && esm.utilities.isEqual(cameraOfTarget.position, position, 1));
13038
- });
13039
- return viewportsWithDifferentCameras;
13040
- };
13041
- this._filterViewportWithSameOrientation = (enabledElement, referenceAnnotation, annotations) => {
13042
- const { renderingEngine } = enabledElement;
13043
- const { data } = referenceAnnotation;
13044
- const viewport = renderingEngine.getViewport(data.viewportId);
13045
- const linkedViewportAnnotations = annotations.filter((annotation) => {
13046
- const { data } = annotation;
13047
- const otherViewport = renderingEngine.getViewport(data.viewportId);
13048
- const otherViewportControllable = this._getReferenceLineControllable(otherViewport.id);
13049
- return otherViewportControllable === true;
13050
- });
13051
- if (!linkedViewportAnnotations || !linkedViewportAnnotations.length) {
13052
- return [];
13053
- }
13054
- const camera = viewport.getCamera();
13055
- const viewPlaneNormal = camera.viewPlaneNormal;
13056
- Core_Math/* default.normalize */.Ay.normalize(viewPlaneNormal);
13057
- const otherViewportsAnnotationsWithSameCameraDirection = linkedViewportAnnotations.filter((annotation) => {
13058
- const { viewportId } = annotation.data;
13059
- const otherViewport = renderingEngine.getViewport(viewportId);
13060
- const otherCamera = otherViewport.getCamera();
13061
- const otherViewPlaneNormal = otherCamera.viewPlaneNormal;
13062
- Core_Math/* default.normalize */.Ay.normalize(otherViewPlaneNormal);
13063
- return (esm.utilities.isEqual(viewPlaneNormal, otherViewPlaneNormal, 1e-2) &&
13064
- esm.utilities.isEqual(camera.viewUp, otherCamera.viewUp, 1e-2));
13065
- });
13066
- return otherViewportsAnnotationsWithSameCameraDirection;
13067
- };
13068
13072
  this._activateModify = (element) => {
13069
13073
  state/* state */.wk.isInteractingWithTool = !this.configuration.mobile?.enabled;
13070
13074
  element.addEventListener(enums.Events.MOUSE_UP, this._endCallback);
@@ -13116,48 +13120,71 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13116
13120
  return;
13117
13121
  }
13118
13122
  const { handles } = viewportAnnotation.data;
13119
- if (handles.activeOperation === OPERATION.DRAG) {
13120
- if (handles.activeType === 'min') {
13121
- this.toolCenterMin[0] += delta[0];
13122
- this.toolCenterMin[1] += delta[1];
13123
- this.toolCenterMin[2] += delta[2];
13123
+ const clippingPlanes = handles.clippingPlanes;
13124
+ if (handles.activeOperation === OPERATION.DRAG &&
13125
+ clippingPlanes &&
13126
+ clippingPlanes.length >= volumeCropping.NUM_CLIPPING_PLANES) {
13127
+ if (handles.activePlaneIndex !== undefined &&
13128
+ handles.activePlaneIndex >= 0 &&
13129
+ handles.activePlaneIndex < volumeCropping.NUM_CLIPPING_PLANES) {
13130
+ const planeIndex = handles.activePlaneIndex;
13131
+ const plane = clippingPlanes[planeIndex];
13132
+ const normal = plane.normal;
13133
+ const dotProd = Core_Math/* default.dot */.Ay.dot(delta, normal);
13134
+ const moveDistance = dotProd;
13135
+ plane.origin[0] += normal[0] * moveDistance;
13136
+ plane.origin[1] += normal[1] * moveDistance;
13137
+ plane.origin[2] += normal[2] * moveDistance;
13124
13138
  }
13125
- else if (handles.activeType === 'max') {
13126
- this.toolCenterMax[0] += delta[0];
13127
- this.toolCenterMax[1] += delta[1];
13128
- this.toolCenterMax[2] += delta[2];
13139
+ else if (handles.activeType === 'min') {
13140
+ clippingPlanes[0].origin[0] += delta[0];
13141
+ clippingPlanes[2].origin[1] += delta[1];
13142
+ clippingPlanes[4].origin[2] += delta[2];
13129
13143
  }
13130
- else {
13131
- this.toolCenter[0] += delta[0];
13132
- this.toolCenter[1] += delta[1];
13133
- this.toolCenter[2] += delta[2];
13144
+ else if (handles.activeType === 'max') {
13145
+ clippingPlanes[1].origin[0] += delta[0];
13146
+ clippingPlanes[3].origin[1] += delta[1];
13147
+ clippingPlanes[5].origin[2] += delta[2];
13134
13148
  }
13149
+ this.clippingPlanes = (0,volumeCropping.copyClippingPlanes)(clippingPlanes);
13135
13150
  const viewportsInfo = this._getViewportsInfo();
13151
+ viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
13152
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
13153
+ if (enabledElement) {
13154
+ const annotations = this._getAnnotations(enabledElement);
13155
+ annotations.forEach((annotation) => {
13156
+ if (annotation.data?.handles) {
13157
+ annotation.data.handles.clippingPlanes = (0,volumeCropping.copyClippingPlanes)(this.clippingPlanes);
13158
+ }
13159
+ });
13160
+ }
13161
+ });
13136
13162
  (0,triggerAnnotationRenderForViewportIds/* default */.A)(viewportsInfo.map(({ viewportId }) => viewportId));
13137
13163
  (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPINGCONTROL_TOOL_CHANGED, {
13138
13164
  toolGroupId: this.toolGroupId,
13139
- toolCenter: this.toolCenter,
13140
- toolCenterMin: this.toolCenterMin,
13141
- toolCenterMax: this.toolCenterMax,
13165
+ clippingPlanes: this.clippingPlanes,
13142
13166
  handleType: handles.activeType,
13143
- viewportOrientation: [],
13144
13167
  seriesInstanceUID: this.seriesInstanceUID,
13145
13168
  });
13146
13169
  }
13147
13170
  };
13148
13171
  this._getReferenceLineColor =
13149
13172
  toolProps.configuration?.getReferenceLineColor ||
13150
- defaultReferenceLineColor;
13173
+ (() => 'rgb(0, 200, 0)');
13151
13174
  this._getReferenceLineControllable =
13152
- toolProps.configuration?.getReferenceLineControllable ||
13153
- defaultReferenceLineControllable;
13175
+ toolProps.configuration?.getReferenceLineControllable || (() => true);
13154
13176
  const viewportsInfo = (0,ToolGroupManager.getToolGroup)(this.toolGroupId)?.viewportsInfo;
13155
13177
  esm.eventTarget.addEventListener(enums.Events.VOLUMECROPPING_TOOL_CHANGED, this._onSphereMoved);
13156
13178
  if (viewportsInfo && viewportsInfo.length > 0) {
13157
13179
  const { viewportId, renderingEngineId } = viewportsInfo[0];
13158
- const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
13159
13180
  const renderingEngine = (0,esm.getRenderingEngine)(renderingEngineId);
13181
+ if (!renderingEngine) {
13182
+ return;
13183
+ }
13160
13184
  const viewport = renderingEngine.getViewport(viewportId);
13185
+ if (!viewport) {
13186
+ return;
13187
+ }
13161
13188
  const volumeActors = viewport.getActors();
13162
13189
  if (!volumeActors || !volumeActors.length) {
13163
13190
  console.warn(`VolumeCroppingControlTool: No volume actors found in viewport ${viewportId}.`);
@@ -13165,67 +13192,11 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13165
13192
  }
13166
13193
  const imageData = volumeActors[0].actor.getMapper().getInputData();
13167
13194
  if (imageData) {
13168
- const dimensions = imageData.getDimensions();
13169
- const spacing = imageData.getSpacing();
13170
- const origin = imageData.getOrigin();
13171
13195
  this.seriesInstanceUID = imageData.seriesInstanceUID || 'unknown';
13172
- const cropFactor = this.configuration.initialCropFactor ?? 0.2;
13173
- this.toolCenter = [
13174
- origin[0] + cropFactor * (dimensions[0] - 1) * spacing[0],
13175
- origin[1] + cropFactor * (dimensions[1] - 1) * spacing[1],
13176
- origin[2] + cropFactor * (dimensions[2] - 1) * spacing[2],
13177
- ];
13178
- const maxCropFactor = 1 - cropFactor;
13179
- this.toolCenterMin = [
13180
- origin[0] + cropFactor * (dimensions[0] - 1) * spacing[0],
13181
- origin[1] + cropFactor * (dimensions[1] - 1) * spacing[1],
13182
- origin[2] + cropFactor * (dimensions[2] - 1) * spacing[2],
13183
- ];
13184
- this.toolCenterMax = [
13185
- origin[0] + maxCropFactor * (dimensions[0] - 1) * spacing[0],
13186
- origin[1] + maxCropFactor * (dimensions[1] - 1) * spacing[1],
13187
- origin[2] + maxCropFactor * (dimensions[2] - 1) * spacing[2],
13188
- ];
13189
13196
  }
13190
13197
  }
13191
13198
  }
13192
- _updateToolCentersFromViewport(viewport) {
13193
- const volumeActors = viewport.getActors();
13194
- if (!volumeActors || !volumeActors.length) {
13195
- return;
13196
- }
13197
- const imageData = volumeActors[0].actor.getMapper().getInputData();
13198
- if (!imageData) {
13199
- return;
13200
- }
13201
- this.seriesInstanceUID = imageData.seriesInstanceUID || 'unknown';
13202
- const dimensions = imageData.getDimensions();
13203
- const spacing = imageData.getSpacing();
13204
- const origin = imageData.getOrigin();
13205
- const cropFactor = this.configuration.initialCropFactor ?? 0.2;
13206
- const cropStart = cropFactor / 2;
13207
- const cropEnd = 1 - cropFactor / 2;
13208
- this.toolCenter = [
13209
- origin[0] +
13210
- ((cropStart + cropEnd) / 2) * (dimensions[0] - 1) * spacing[0],
13211
- origin[1] +
13212
- ((cropStart + cropEnd) / 2) * (dimensions[1] - 1) * spacing[1],
13213
- origin[2] +
13214
- ((cropStart + cropEnd) / 2) * (dimensions[2] - 1) * spacing[2],
13215
- ];
13216
- this.toolCenterMin = [
13217
- origin[0] + cropStart * (dimensions[0] - 1) * spacing[0],
13218
- origin[1] + cropStart * (dimensions[1] - 1) * spacing[1],
13219
- origin[2] + cropStart * (dimensions[2] - 1) * spacing[2],
13220
- ];
13221
- this.toolCenterMax = [
13222
- origin[0] + cropEnd * (dimensions[0] - 1) * spacing[0],
13223
- origin[1] + cropEnd * (dimensions[1] - 1) * spacing[1],
13224
- origin[2] + cropEnd * (dimensions[2] - 1) * spacing[2],
13225
- ];
13226
- }
13227
13199
  onSetToolInactive() {
13228
- console.debug(`VolumeCroppingControlTool: onSetToolInactive called for tool ${this.getToolName()}`);
13229
13200
  }
13230
13201
  onSetToolActive() {
13231
13202
  const viewportsInfo = this._getViewportsInfo();
@@ -13241,7 +13212,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13241
13212
  if (!anyAnnotationExists) {
13242
13213
  this._unsubscribeToViewportNewVolumeSet(viewportsInfo);
13243
13214
  this._subscribeToViewportNewVolumeSet(viewportsInfo);
13244
- this._computeToolCenter(viewportsInfo);
13215
+ this._initializeViewports(viewportsInfo);
13245
13216
  (0,esm.triggerEvent)(esm.eventTarget, enums.Events.VOLUMECROPPINGCONTROL_TOOL_CHANGED, {
13246
13217
  toolGroupId: this.toolGroupId,
13247
13218
  viewportsInfo: viewportsInfo,
@@ -13265,13 +13236,12 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13265
13236
  }
13266
13237
  }
13267
13238
  onSetToolEnabled() {
13268
- console.debug(`VolumeCroppingControlTool: onSetToolEnabled called for tool ${this.getToolName()}`);
13269
- const viewportsInfo = this._getViewportsInfo();
13239
+ esm.eventTarget.addEventListener(enums.Events.VOLUMECROPPING_TOOL_CHANGED, this._onSphereMoved);
13270
13240
  }
13271
13241
  onSetToolDisabled() {
13272
- console.debug(`VolumeCroppingControlTool: onSetToolDisabled called for tool ${this.getToolName()}`);
13273
13242
  const viewportsInfo = this._getViewportsInfo();
13274
13243
  this._unsubscribeToViewportNewVolumeSet(viewportsInfo);
13244
+ esm.eventTarget.removeEventListener(enums.Events.VOLUMECROPPING_TOOL_CHANGED, this._onSphereMoved);
13275
13245
  viewportsInfo.forEach(({ renderingEngineId, viewportId }) => {
13276
13246
  const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
13277
13247
  if (!enabledElement) {
@@ -13285,176 +13255,24 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13285
13255
  }
13286
13256
  });
13287
13257
  }
13288
- _getOrientationFromNormal(normal) {
13289
- if (!normal) {
13290
- return null;
13291
- }
13292
- const canonical = {
13293
- AXIAL: [0, 0, 1],
13294
- CORONAL: [0, 1, 0],
13295
- SAGITTAL: [1, 0, 0],
13296
- };
13297
- const tol = 1e-2;
13298
- for (const [key, value] of Object.entries(canonical)) {
13299
- if (Math.abs(normal[0] - value[0]) < tol &&
13300
- Math.abs(normal[1] - value[1]) < tol &&
13301
- Math.abs(normal[2] - value[2]) < tol) {
13302
- return key;
13303
- }
13304
- if (Math.abs(normal[0] + value[0]) < tol &&
13305
- Math.abs(normal[1] + value[1]) < tol &&
13306
- Math.abs(normal[2] + value[2]) < tol) {
13307
- return key;
13308
- }
13309
- }
13310
- return null;
13311
- }
13312
13258
  _syncWithVolumeCroppingTool(originalClippingPlanes) {
13313
- const planes = originalClippingPlanes;
13314
- if (planes.length >= 6) {
13315
- this.toolCenterMin = [
13316
- planes[0].origin[0],
13317
- planes[2].origin[1],
13318
- planes[4].origin[2],
13319
- ];
13320
- this.toolCenterMax = [
13321
- planes[1].origin[0],
13322
- planes[3].origin[1],
13323
- planes[5].origin[2],
13324
- ];
13325
- this.toolCenter = [
13326
- (this.toolCenterMin[0] + this.toolCenterMax[0]) / 2,
13327
- (this.toolCenterMin[1] + this.toolCenterMax[1]) / 2,
13328
- (this.toolCenterMin[2] + this.toolCenterMax[2]) / 2,
13329
- ];
13330
- const viewportsInfo = this._getViewportsInfo();
13331
- viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
13332
- const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
13333
- if (enabledElement) {
13334
- const annotations = this._getAnnotations(enabledElement);
13335
- annotations.forEach((annotation) => {
13336
- if (annotation.data &&
13337
- annotation.data.handles &&
13338
- annotation.data.orientation) {
13339
- const orientation = annotation.data.orientation;
13340
- if (orientation === 'AXIAL') {
13341
- annotation.data.handles.toolCenterMin = [
13342
- planes[0].origin[0],
13343
- planes[2].origin[1],
13344
- annotation.data.handles.toolCenterMin[2],
13345
- ];
13346
- annotation.data.handles.toolCenterMax = [
13347
- planes[1].origin[0],
13348
- planes[3].origin[1],
13349
- annotation.data.handles.toolCenterMax[2],
13350
- ];
13351
- }
13352
- else if (orientation === 'CORONAL') {
13353
- annotation.data.handles.toolCenterMin = [
13354
- planes[0].origin[0],
13355
- annotation.data.handles.toolCenterMin[1],
13356
- planes[4].origin[2],
13357
- ];
13358
- annotation.data.handles.toolCenterMax = [
13359
- planes[1].origin[0],
13360
- annotation.data.handles.toolCenterMax[1],
13361
- planes[5].origin[2],
13362
- ];
13363
- }
13364
- else if (orientation === 'SAGITTAL') {
13365
- annotation.data.handles.toolCenterMin = [
13366
- annotation.data.handles.toolCenterMin[0],
13367
- planes[2].origin[1],
13368
- planes[4].origin[2],
13369
- ];
13370
- annotation.data.handles.toolCenterMax = [
13371
- annotation.data.handles.toolCenterMax[0],
13372
- planes[3].origin[1],
13373
- planes[5].origin[2],
13374
- ];
13375
- }
13376
- annotation.data.handles.toolCenter = [
13377
- (annotation.data.handles.toolCenterMin[0] +
13378
- annotation.data.handles.toolCenterMax[0]) /
13379
- 2,
13380
- (annotation.data.handles.toolCenterMin[1] +
13381
- annotation.data.handles.toolCenterMax[1]) /
13382
- 2,
13383
- (annotation.data.handles.toolCenterMin[2] +
13384
- annotation.data.handles.toolCenterMax[2]) /
13385
- 2,
13386
- ];
13387
- }
13388
- });
13389
- }
13390
- });
13391
- if (this._virtualAnnotations && this._virtualAnnotations.length > 0) {
13392
- this._virtualAnnotations.forEach((annotation) => {
13393
- if (annotation.data &&
13394
- annotation.data.handles &&
13395
- annotation.data.orientation) {
13396
- const orientation = annotation.data.orientation.toUpperCase();
13397
- if (orientation === 'AXIAL') {
13398
- annotation.data.handles.toolCenterMin = [
13399
- planes[0].origin[0],
13400
- planes[2].origin[1],
13401
- annotation.data.handles.toolCenterMin[2],
13402
- ];
13403
- annotation.data.handles.toolCenterMax = [
13404
- planes[1].origin[0],
13405
- planes[3].origin[1],
13406
- annotation.data.handles.toolCenterMax[2],
13407
- ];
13408
- }
13409
- else if (orientation === 'CORONAL') {
13410
- annotation.data.handles.toolCenterMin = [
13411
- planes[0].origin[0],
13412
- annotation.data.handles.toolCenterMin[1],
13413
- planes[4].origin[2],
13414
- ];
13415
- annotation.data.handles.toolCenterMax = [
13416
- planes[1].origin[0],
13417
- annotation.data.handles.toolCenterMax[1],
13418
- planes[5].origin[2],
13419
- ];
13420
- }
13421
- else if (orientation === 'SAGITTAL') {
13422
- annotation.data.handles.toolCenterMin = [
13423
- annotation.data.handles.toolCenterMin[0],
13424
- planes[2].origin[1],
13425
- planes[4].origin[2],
13426
- ];
13427
- annotation.data.handles.toolCenterMax = [
13428
- annotation.data.handles.toolCenterMax[0],
13429
- planes[3].origin[1],
13430
- planes[5].origin[2],
13431
- ];
13432
- }
13433
- annotation.data.handles.toolCenter = [
13434
- (annotation.data.handles.toolCenterMin[0] +
13435
- annotation.data.handles.toolCenterMax[0]) /
13436
- 2,
13437
- (annotation.data.handles.toolCenterMin[1] +
13438
- annotation.data.handles.toolCenterMax[1]) /
13439
- 2,
13440
- (annotation.data.handles.toolCenterMin[2] +
13441
- annotation.data.handles.toolCenterMax[2]) /
13442
- 2,
13443
- ];
13259
+ if (!originalClippingPlanes ||
13260
+ originalClippingPlanes.length < volumeCropping.NUM_CLIPPING_PLANES) {
13261
+ return;
13262
+ }
13263
+ this.clippingPlanes = (0,volumeCropping.copyClippingPlanes)(originalClippingPlanes);
13264
+ const viewportsInfo = this._getViewportsInfo();
13265
+ viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
13266
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
13267
+ if (enabledElement) {
13268
+ const annotations = this._getAnnotations(enabledElement);
13269
+ annotations.forEach((annotation) => {
13270
+ if (annotation.data?.handles) {
13271
+ annotation.data.handles.clippingPlanes = (0,volumeCropping.copyClippingPlanes)(this.clippingPlanes);
13444
13272
  }
13445
13273
  });
13446
13274
  }
13447
- (0,triggerAnnotationRenderForViewportIds/* default */.A)(viewportsInfo.map(({ viewportId }) => viewportId));
13448
- }
13449
- }
13450
- setToolCenter(toolCenter, handleType) {
13451
- if (handleType === 'min') {
13452
- this.toolCenterMin = [...toolCenter];
13453
- }
13454
- else if (handleType === 'max') {
13455
- this.toolCenterMax = [...toolCenter];
13456
- }
13457
- const viewportsInfo = this._getViewportsInfo();
13275
+ });
13458
13276
  (0,triggerAnnotationRenderForViewportIds/* default */.A)(viewportsInfo.map(({ viewportId }) => viewportId));
13459
13277
  }
13460
13278
  addNewAnnotation(evt) {
@@ -13479,7 +13297,6 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13479
13297
  continue;
13480
13298
  }
13481
13299
  viewportIdArray.push(otherViewport.id);
13482
- i++;
13483
13300
  }
13484
13301
  data.activeViewportIds = [...viewportIdArray];
13485
13302
  data.handles.activeOperation = OPERATION.DRAG;
@@ -13505,51 +13322,22 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13505
13322
  element.addEventListener(esm.Enums.Events.VOLUME_VIEWPORT_NEW_VOLUME, this._onNewVolume);
13506
13323
  });
13507
13324
  }
13508
- _applyDeltaShiftToSelectedViewportCameras(renderingEngine, viewportsAnnotationsToUpdate, delta) {
13509
- viewportsAnnotationsToUpdate.forEach((annotation) => {
13510
- this._applyDeltaShiftToViewportCamera(renderingEngine, annotation, delta);
13511
- });
13512
- }
13513
- _applyDeltaShiftToViewportCamera(renderingEngine, annotation, delta) {
13514
- const { data } = annotation;
13515
- const viewport = renderingEngine.getViewport(data.viewportId);
13516
- const camera = viewport.getCamera();
13517
- const normal = camera.viewPlaneNormal;
13518
- const dotProd = Core_Math/* default.dot */.Ay.dot(delta, normal);
13519
- const projectedDelta = [...normal];
13520
- Core_Math/* default.multiplyScalar */.Ay.multiplyScalar(projectedDelta, dotProd);
13521
- if (Math.abs(projectedDelta[0]) > 1e-3 ||
13522
- Math.abs(projectedDelta[1]) > 1e-3 ||
13523
- Math.abs(projectedDelta[2]) > 1e-3) {
13524
- const newFocalPoint = [0, 0, 0];
13525
- const newPosition = [0, 0, 0];
13526
- Core_Math/* default.add */.Ay.add(camera.focalPoint, projectedDelta, newFocalPoint);
13527
- Core_Math/* default.add */.Ay.add(camera.position, projectedDelta, newPosition);
13528
- viewport.setCamera({
13529
- focalPoint: newFocalPoint,
13530
- position: newPosition,
13531
- });
13532
- viewport.render();
13533
- }
13534
- }
13535
13325
  _pointNearTool(element, annotation, canvasCoords, proximity) {
13536
13326
  const { data } = annotation;
13537
13327
  const referenceLines = data.referenceLines;
13538
13328
  const viewportIdArray = [];
13539
13329
  if (referenceLines) {
13540
13330
  for (let i = 0; i < referenceLines.length; ++i) {
13541
- const otherViewport = referenceLines[i][0];
13542
- const start1 = referenceLines[i][1];
13543
- const end1 = referenceLines[i][2];
13544
- const type = referenceLines[i][3];
13545
- const distance1 = math_line.distanceToPoint(start1, end1, [
13331
+ const [otherViewport, startPoint, endPoint, type, planeIndex] = referenceLines[i];
13332
+ const distance = math_line.distanceToPoint(startPoint, endPoint, [
13546
13333
  canvasCoords[0],
13547
13334
  canvasCoords[1],
13548
13335
  ]);
13549
- if (distance1 <= proximity) {
13336
+ if (distance <= proximity) {
13550
13337
  viewportIdArray.push(otherViewport.id);
13551
- data.handles.activeOperation = 1;
13338
+ data.handles.activeOperation = OPERATION.DRAG;
13552
13339
  data.handles.activeType = type;
13340
+ data.handles.activePlaneIndex = planeIndex;
13553
13341
  }
13554
13342
  }
13555
13343
  }
@@ -13557,7 +13345,7 @@ class VolumeCroppingControlTool extends base/* AnnotationTool */.EC {
13557
13345
  this.editData = {
13558
13346
  annotation,
13559
13347
  };
13560
- return data.handles.activeOperation === 1 ? true : false;
13348
+ return data.handles.activeOperation === OPERATION.DRAG ? true : false;
13561
13349
  }
13562
13350
  }
13563
13351
  VolumeCroppingControlTool.toolName = 'VolumeCroppingControl';
@@ -14439,6 +14227,8 @@ MIPJumpToClickTool.toolName = 'MIPJumpToClickTool';
14439
14227
 
14440
14228
  // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Common/Core/MatrixBuilder.js
14441
14229
  var MatrixBuilder = __webpack_require__(90364);
14230
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/vec2/liangBarksyClip.js
14231
+ var liangBarksyClip = __webpack_require__(35381);
14442
14232
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/CrosshairsTool.js
14443
14233
 
14444
14234
 
@@ -14457,11 +14247,11 @@ var MatrixBuilder = __webpack_require__(90364);
14457
14247
 
14458
14248
 
14459
14249
 
14460
- const { RENDERING_DEFAULTS: CrosshairsTool_RENDERING_DEFAULTS } = esm.CONSTANTS;
14461
- function CrosshairsTool_defaultReferenceLineColor() {
14250
+ const { RENDERING_DEFAULTS } = esm.CONSTANTS;
14251
+ function defaultReferenceLineColor() {
14462
14252
  return 'rgb(0, 200, 0)';
14463
14253
  }
14464
- function CrosshairsTool_defaultReferenceLineControllable() {
14254
+ function defaultReferenceLineControllable() {
14465
14255
  return true;
14466
14256
  }
14467
14257
  function defaultReferenceLineDraggableRotatable() {
@@ -15571,10 +15361,10 @@ class CrosshairsTool extends base/* AnnotationTool */.EC {
15571
15361
  slabThicknessValue += mod;
15572
15362
  }
15573
15363
  slabThicknessValue = Math.abs(slabThicknessValue);
15574
- slabThicknessValue = Math.max(CrosshairsTool_RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS, slabThicknessValue);
15364
+ slabThicknessValue = Math.max(RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS, slabThicknessValue);
15575
15365
  const near = this._pointNearReferenceLine(viewportAnnotation, canvasCoords, 6, otherViewport);
15576
15366
  if (near) {
15577
- slabThicknessValue = CrosshairsTool_RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS;
15367
+ slabThicknessValue = RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS;
15578
15368
  }
15579
15369
  const toolGroup = (0,ToolGroupManager.getToolGroupForViewport)(otherViewport.id, renderingEngine.id);
15580
15370
  const crosshairsInstance = toolGroup.getToolInstance(this.getToolName());
@@ -15799,10 +15589,10 @@ class CrosshairsTool extends base/* AnnotationTool */.EC {
15799
15589
  };
15800
15590
  this._getReferenceLineColor =
15801
15591
  toolProps.configuration?.getReferenceLineColor ||
15802
- CrosshairsTool_defaultReferenceLineColor;
15592
+ defaultReferenceLineColor;
15803
15593
  this._getReferenceLineControllable =
15804
15594
  toolProps.configuration?.getReferenceLineControllable ||
15805
- CrosshairsTool_defaultReferenceLineControllable;
15595
+ defaultReferenceLineControllable;
15806
15596
  this._getReferenceLineDraggableRotatable =
15807
15597
  toolProps.configuration?.getReferenceLineDraggableRotatable ||
15808
15598
  defaultReferenceLineDraggableRotatable;
@@ -15978,7 +15768,7 @@ class CrosshairsTool extends base/* AnnotationTool */.EC {
15978
15768
  actorUIDs = filterActorUIDsToSetSlabThickness;
15979
15769
  }
15980
15770
  let blendModeToUse = this.configuration.slabThicknessBlendMode;
15981
- if (slabThickness === CrosshairsTool_RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS) {
15771
+ if (slabThickness === RENDERING_DEFAULTS.MINIMUM_SLAB_THICKNESS) {
15982
15772
  blendModeToUse = esm.Enums.BlendModes.COMPOSITE;
15983
15773
  }
15984
15774
  const immediate = false;
@@ -29212,8 +29002,8 @@ PaintFillTool.toolName = 'PaintFill';
29212
29002
 
29213
29003
  // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Interaction/Widgets/OrientationMarkerWidget.js + 1 modules
29214
29004
  var OrientationMarkerWidget = __webpack_require__(53489);
29215
- // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor.js + 2 modules
29216
- var AnnotatedCubeActor = __webpack_require__(83338);
29005
+ // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor.js + 1 modules
29006
+ var AnnotatedCubeActor = __webpack_require__(91960);
29217
29007
  // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/Rendering/Core/AxesActor.js + 4 modules
29218
29008
  var AxesActor = __webpack_require__(10341);
29219
29009
  // EXTERNAL MODULE: ../../../node_modules/@kitware/vtk.js/IO/XML/XMLPolyDataReader.js + 4 modules
@@ -29506,6 +29296,425 @@ class OrientationMarkerTool extends base/* BaseTool */.oS {
29506
29296
  OrientationMarkerTool.toolName = 'OrientationMarker';
29507
29297
  /* harmony default export */ const tools_OrientationMarkerTool = ((/* unused pure expression or super */ null && (OrientationMarkerTool)));
29508
29298
 
29299
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/vtkjs/OrientationControllerWidget/index.js + 6 modules
29300
+ var OrientationControllerWidget = __webpack_require__(14770);
29301
+ ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/OrientationControllerTool.js
29302
+
29303
+
29304
+
29305
+
29306
+
29307
+
29308
+ const ADD_MARKER_DELAY_MS = 500;
29309
+ const POSITION_RETRY_DELAY_MS = 1000;
29310
+ const FACE_COLOR_SCHEMES = {
29311
+ marker: {
29312
+ topBottom: [0, 0, 255],
29313
+ frontBack: [0, 255, 255],
29314
+ leftRight: [255, 255, 0],
29315
+ },
29316
+ gray: {
29317
+ topBottom: [180, 180, 180],
29318
+ frontBack: [180, 180, 180],
29319
+ leftRight: [180, 180, 180],
29320
+ },
29321
+ rgy: {
29322
+ topBottom: [255, 0, 0],
29323
+ frontBack: [0, 255, 0],
29324
+ leftRight: [255, 255, 0],
29325
+ },
29326
+ };
29327
+ const LETTER_COLOR_SCHEMES = {
29328
+ mixed: {
29329
+ zMinus: [255, 255, 255],
29330
+ zPlus: [255, 255, 255],
29331
+ yMinus: [255, 255, 255],
29332
+ yPlus: [255, 255, 255],
29333
+ xMinus: [0, 0, 0],
29334
+ xPlus: [0, 0, 0],
29335
+ },
29336
+ rgy: {
29337
+ zMinus: [255, 255, 255],
29338
+ zPlus: [255, 255, 255],
29339
+ yMinus: [255, 255, 255],
29340
+ yPlus: [255, 255, 255],
29341
+ xMinus: [0, 0, 0],
29342
+ xPlus: [0, 0, 0],
29343
+ },
29344
+ white: {
29345
+ zMinus: [255, 255, 255],
29346
+ zPlus: [255, 255, 255],
29347
+ yMinus: [255, 255, 255],
29348
+ yPlus: [255, 255, 255],
29349
+ xMinus: [255, 255, 255],
29350
+ xPlus: [255, 255, 255],
29351
+ },
29352
+ black: {
29353
+ zMinus: [0, 0, 0],
29354
+ zPlus: [0, 0, 0],
29355
+ yMinus: [0, 0, 0],
29356
+ yPlus: [0, 0, 0],
29357
+ xMinus: [0, 0, 0],
29358
+ xPlus: [0, 0, 0],
29359
+ },
29360
+ };
29361
+ const DEFAULT_FACE_COLOR_SCHEME = 'rgy';
29362
+ const DEFAULT_LETTER_COLOR_SCHEME = 'mixed';
29363
+ const ANIMATE_RESET_CAMERA_OPTIONS = {
29364
+ resetZoom: false,
29365
+ resetPan: true,
29366
+ resetToCenter: true,
29367
+ };
29368
+ class OrientationControllerTool extends base/* BaseTool */.oS {
29369
+ static { this.toolName = 'OrientationControllerTool'; }
29370
+ constructor(toolProps = {}, defaultToolProps = {
29371
+ supportedInteractionTypes: ['Mouse'],
29372
+ configuration: {
29373
+ enabled: true,
29374
+ opacity: 1.0,
29375
+ size: 0.04,
29376
+ position: 'bottom-right',
29377
+ colorScheme: 'rgy',
29378
+ letterColorScheme: 'mixed',
29379
+ showEdgeFaces: true,
29380
+ showCornerFaces: true,
29381
+ keepOrientationUp: true,
29382
+ },
29383
+ }) {
29384
+ super(toolProps, defaultToolProps);
29385
+ this.widget = new OrientationControllerWidget/* vtkOrientationControllerWidget */.C();
29386
+ this.resizeObservers = new Map();
29387
+ this.cameraHandlers = new Map();
29388
+ this._getViewportsInfo = () => {
29389
+ const viewports = (0,ToolGroupManager.getToolGroup)(this.toolGroupId)?.viewportsInfo;
29390
+ return viewports || [];
29391
+ };
29392
+ this.onSetToolConfiguration = () => {
29393
+ const viewportsInfo = this._getViewportsInfo();
29394
+ const hasActiveMarkers = viewportsInfo.some(({ viewportId }) => {
29395
+ return this.widget.getActors(viewportId) !== null;
29396
+ });
29397
+ if (hasActiveMarkers) {
29398
+ this.removeMarkers();
29399
+ this.addMarkers();
29400
+ }
29401
+ };
29402
+ this.onViewportAdded = (evt) => {
29403
+ const { viewportId, renderingEngineId, toolGroupId } = evt.detail;
29404
+ if (toolGroupId !== this.toolGroupId) {
29405
+ return;
29406
+ }
29407
+ if (this.widget.getActors(viewportId)) {
29408
+ return;
29409
+ }
29410
+ setTimeout(() => {
29411
+ this.addMarkerToViewport(viewportId, renderingEngineId);
29412
+ }, ADD_MARKER_DELAY_MS);
29413
+ };
29414
+ this.onViewportRemoved = (evt) => {
29415
+ const { viewportId, renderingEngineId, toolGroupId } = evt.detail;
29416
+ if (toolGroupId !== this.toolGroupId) {
29417
+ return;
29418
+ }
29419
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
29420
+ if (enabledElement) {
29421
+ const { viewport } = enabledElement;
29422
+ if (viewport.isOrientationChangeable()) {
29423
+ this.widget.removeActorsFromViewport(viewportId, viewport);
29424
+ }
29425
+ const cameraHandler = this.cameraHandlers.get(viewportId);
29426
+ if (cameraHandler) {
29427
+ viewport.element.removeEventListener(esm.Enums.Events.CAMERA_MODIFIED, cameraHandler);
29428
+ this.cameraHandlers.delete(viewportId);
29429
+ }
29430
+ }
29431
+ this.widget.cleanup(viewportId);
29432
+ const resizeObserver = this.resizeObservers.get(viewportId);
29433
+ if (resizeObserver) {
29434
+ resizeObserver.disconnect();
29435
+ this.resizeObservers.delete(viewportId);
29436
+ }
29437
+ };
29438
+ this.addMarkers = () => {
29439
+ const viewportsInfo = this._getViewportsInfo();
29440
+ viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
29441
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
29442
+ if (!enabledElement) {
29443
+ return;
29444
+ }
29445
+ const { viewport } = enabledElement;
29446
+ if (!viewport.isOrientationChangeable()) {
29447
+ return;
29448
+ }
29449
+ if (this.widget.getActors(viewportId)) {
29450
+ return;
29451
+ }
29452
+ setTimeout(() => {
29453
+ this.addMarkerToViewport(viewportId, renderingEngineId);
29454
+ }, ADD_MARKER_DELAY_MS);
29455
+ });
29456
+ };
29457
+ this.onCameraModified = (evt) => {
29458
+ const { viewportId } = evt.detail;
29459
+ if (!viewportId) {
29460
+ return;
29461
+ }
29462
+ const actors = this.widget.getActors(viewportId);
29463
+ if (!actors) {
29464
+ return;
29465
+ }
29466
+ const viewportsInfo = this._getViewportsInfo();
29467
+ const viewportInfo = viewportsInfo.find((vp) => vp.viewportId === viewportId);
29468
+ if (!viewportInfo) {
29469
+ return;
29470
+ }
29471
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, viewportInfo.renderingEngineId);
29472
+ if (!enabledElement) {
29473
+ return;
29474
+ }
29475
+ const { viewport } = enabledElement;
29476
+ if (!viewport.isOrientationChangeable()) {
29477
+ return;
29478
+ }
29479
+ const volumeViewport = viewport;
29480
+ this.widget.positionActors(volumeViewport, actors, this.getPositionConfig());
29481
+ viewport.render();
29482
+ };
29483
+ }
29484
+ getPositionConfig() {
29485
+ return {
29486
+ position: this.configuration.position || 'bottom-right',
29487
+ size: this.configuration.size || 0.04,
29488
+ };
29489
+ }
29490
+ getFaceColors() {
29491
+ const colorScheme = this.configuration.colorScheme || 'rgy';
29492
+ if (this.configuration.faceColors) {
29493
+ const provided = this.configuration.faceColors;
29494
+ if (provided.topBottom && provided.frontBack && provided.leftRight) {
29495
+ return {
29496
+ topBottom: provided.topBottom,
29497
+ frontBack: provided.frontBack,
29498
+ leftRight: provided.leftRight,
29499
+ };
29500
+ }
29501
+ }
29502
+ return (FACE_COLOR_SCHEMES[colorScheme] ??
29503
+ FACE_COLOR_SCHEMES[DEFAULT_FACE_COLOR_SCHEME]);
29504
+ }
29505
+ getLetterColors() {
29506
+ const letterColorScheme = this.configuration.letterColorScheme || 'mixed';
29507
+ return (LETTER_COLOR_SCHEMES[letterColorScheme] ??
29508
+ LETTER_COLOR_SCHEMES[DEFAULT_LETTER_COLOR_SCHEME]);
29509
+ }
29510
+ onSetToolEnabled() {
29511
+ this.removeMarkers();
29512
+ this.addMarkers();
29513
+ esm.eventTarget.addEventListener(enums.Events.TOOLGROUP_VIEWPORT_ADDED, this.onViewportAdded);
29514
+ esm.eventTarget.addEventListener(enums.Events.TOOLGROUP_VIEWPORT_REMOVED, this.onViewportRemoved);
29515
+ }
29516
+ onSetToolDisabled() {
29517
+ this.removeMarkers();
29518
+ esm.eventTarget.removeEventListener(enums.Events.TOOLGROUP_VIEWPORT_ADDED, this.onViewportAdded);
29519
+ esm.eventTarget.removeEventListener(enums.Events.TOOLGROUP_VIEWPORT_REMOVED, this.onViewportRemoved);
29520
+ }
29521
+ removeMarkers() {
29522
+ const viewportsInfo = this._getViewportsInfo();
29523
+ viewportsInfo.forEach(({ viewportId, renderingEngineId }) => {
29524
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
29525
+ if (enabledElement) {
29526
+ const { viewport } = enabledElement;
29527
+ if (viewport.isOrientationChangeable()) {
29528
+ this.widget.removeActorsFromViewport(viewportId, viewport);
29529
+ }
29530
+ const cameraHandler = this.cameraHandlers.get(viewportId);
29531
+ if (cameraHandler) {
29532
+ viewport.element.removeEventListener(esm.Enums.Events.CAMERA_MODIFIED, cameraHandler);
29533
+ this.cameraHandlers.delete(viewportId);
29534
+ }
29535
+ }
29536
+ const resizeObserver = this.resizeObservers.get(viewportId);
29537
+ if (resizeObserver) {
29538
+ resizeObserver.disconnect();
29539
+ this.resizeObservers.delete(viewportId);
29540
+ }
29541
+ });
29542
+ this.widget.cleanup();
29543
+ this.resizeObservers.forEach((observer) => observer.disconnect());
29544
+ this.resizeObservers.clear();
29545
+ this.cameraHandlers.clear();
29546
+ }
29547
+ createAnnotatedRhombActor() {
29548
+ const faceColors = this.getFaceColors();
29549
+ const letterColors = this.getLetterColors();
29550
+ return this.widget.createActors({
29551
+ faceColors,
29552
+ letterColors,
29553
+ opacity: this.configuration.opacity ?? 1.0,
29554
+ showEdgeFaces: this.configuration.showEdgeFaces !== false,
29555
+ showCornerFaces: this.configuration.showCornerFaces !== false,
29556
+ });
29557
+ }
29558
+ addMarkerToViewport(viewportId, renderingEngineId) {
29559
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
29560
+ if (!enabledElement) {
29561
+ console.warn('OrientationControllerTool: No enabled element found');
29562
+ return;
29563
+ }
29564
+ const { viewport } = enabledElement;
29565
+ if (!viewport.isOrientationChangeable()) {
29566
+ console.warn('OrientationControllerTool: Viewport does not support orientation changes');
29567
+ return;
29568
+ }
29569
+ const element = viewport.element;
29570
+ const volumeViewport = viewport;
29571
+ const actors = this.createAnnotatedRhombActor();
29572
+ this.widget.addActorsToViewport(viewportId, volumeViewport, actors);
29573
+ const positioned = this.widget.positionActors(volumeViewport, actors, this.getPositionConfig());
29574
+ if (!positioned) {
29575
+ console.warn('OrientationControllerTool: Initial positioning failed, retrying...');
29576
+ setTimeout(() => {
29577
+ const repositioned = this.widget.positionActors(volumeViewport, actors, this.getPositionConfig());
29578
+ if (repositioned) {
29579
+ viewport.render();
29580
+ }
29581
+ else {
29582
+ console.error('OrientationControllerTool: Retry positioning also failed');
29583
+ }
29584
+ }, POSITION_RETRY_DELAY_MS);
29585
+ }
29586
+ else {
29587
+ viewport.render();
29588
+ }
29589
+ this.widget.syncOverlayViewport(viewportId, volumeViewport);
29590
+ this.widget.setupPicker(viewportId, actors);
29591
+ this.widget.setupMouseHandlers(viewportId, element, volumeViewport, actors, {
29592
+ onFacePicked: (result) => {
29593
+ const orientation = this.widget.getOrientationForFace(result.cellId);
29594
+ if (orientation) {
29595
+ this.animateCameraToOrientation(volumeViewport, orientation.viewPlaneNormal, orientation.viewUp);
29596
+ }
29597
+ },
29598
+ onFaceHover: (result) => {
29599
+ if (result && result.actorIndex !== 0) {
29600
+ this.widget.highlightFace(result.pickedActor, result.cellId, volumeViewport, false);
29601
+ }
29602
+ else {
29603
+ this.widget.clearHighlight();
29604
+ }
29605
+ },
29606
+ });
29607
+ const resizeObserver = new ResizeObserver(() => {
29608
+ this.updateMarkerPosition(viewportId, renderingEngineId);
29609
+ });
29610
+ resizeObserver.observe(element);
29611
+ this.resizeObservers.set(viewportId, resizeObserver);
29612
+ const cameraHandler = (evt) => {
29613
+ const detail = evt.detail;
29614
+ if (detail.viewportId === viewportId) {
29615
+ this.onCameraModified(evt);
29616
+ }
29617
+ };
29618
+ element.addEventListener(esm.Enums.Events.CAMERA_MODIFIED, cameraHandler);
29619
+ this.cameraHandlers.set(viewportId, cameraHandler);
29620
+ }
29621
+ updateMarkerPosition(viewportId, renderingEngineId) {
29622
+ const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
29623
+ if (!enabledElement) {
29624
+ return;
29625
+ }
29626
+ const actors = this.widget.getActors(viewportId);
29627
+ if (!actors) {
29628
+ return;
29629
+ }
29630
+ const { viewport } = enabledElement;
29631
+ if (!viewport.isOrientationChangeable()) {
29632
+ return;
29633
+ }
29634
+ this.widget.positionActors(viewport, actors, this.getPositionConfig());
29635
+ this.widget.syncOverlayViewport(viewportId, viewport);
29636
+ viewport.render();
29637
+ }
29638
+ animateCameraToOrientation(viewport, targetViewPlaneNormal, targetViewUp) {
29639
+ const keepOrientationUp = this.configuration.keepOrientationUp !== false;
29640
+ const renderer = viewport.getRenderer();
29641
+ const camera = renderer.getActiveCamera();
29642
+ const directionOfProjection = camera.getDirectionOfProjection();
29643
+ const startViewUpArray = camera.getViewUp();
29644
+ const startForward = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(-directionOfProjection[0], -directionOfProjection[1], -directionOfProjection[2]);
29645
+ const startUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(startViewUpArray[0], startViewUpArray[1], startViewUpArray[2]);
29646
+ const startRight = gl_matrix_esm/* vec3.create */.eR.create();
29647
+ gl_matrix_esm/* vec3.cross */.eR.cross(startRight, startUp, startForward);
29648
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(startRight, startRight);
29649
+ const startMatrix = gl_matrix_esm/* mat4.fromValues */.pB.fromValues(startRight[0], startRight[1], startRight[2], 0, startUp[0], startUp[1], startUp[2], 0, startForward[0], startForward[1], startForward[2], 0, 0, 0, 0, 1);
29650
+ let targetUp;
29651
+ if (keepOrientationUp) {
29652
+ targetUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(targetViewUp[0], targetViewUp[1], targetViewUp[2]);
29653
+ }
29654
+ else {
29655
+ const currentUp = gl_matrix_esm/* vec3.normalize */.eR.normalize(gl_matrix_esm/* vec3.create */.eR.create(), startUp);
29656
+ const normalizedForward = gl_matrix_esm/* vec3.create */.eR.create();
29657
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(normalizedForward, targetViewPlaneNormal);
29658
+ const dot = gl_matrix_esm/* vec3.dot */.eR.dot(currentUp, normalizedForward);
29659
+ targetUp = gl_matrix_esm/* vec3.create */.eR.create();
29660
+ gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(targetUp, currentUp, normalizedForward, -dot);
29661
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(targetUp, targetUp);
29662
+ if (gl_matrix_esm/* vec3.length */.eR.length(targetUp) < 0.001) {
29663
+ if (Math.abs(normalizedForward[2]) < 0.9) {
29664
+ targetUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(0, 0, 1);
29665
+ }
29666
+ else {
29667
+ targetUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(0, 1, 0);
29668
+ }
29669
+ const dot2 = gl_matrix_esm/* vec3.dot */.eR.dot(targetUp, normalizedForward);
29670
+ gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(targetUp, targetUp, normalizedForward, -dot2);
29671
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(targetUp, targetUp);
29672
+ }
29673
+ }
29674
+ const targetRight = gl_matrix_esm/* vec3.create */.eR.create();
29675
+ gl_matrix_esm/* vec3.cross */.eR.cross(targetRight, targetUp, targetViewPlaneNormal);
29676
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(targetRight, targetRight);
29677
+ const targetMatrix = gl_matrix_esm/* mat4.fromValues */.pB.fromValues(targetRight[0], targetRight[1], targetRight[2], 0, targetUp[0], targetUp[1], targetUp[2], 0, targetViewPlaneNormal[0], targetViewPlaneNormal[1], targetViewPlaneNormal[2], 0, 0, 0, 0, 1);
29678
+ const startQuat = gl_matrix_esm/* mat4.getRotation */.pB.getRotation(gl_matrix_esm/* quat.create */.Yu.create(), startMatrix);
29679
+ const targetQuat = gl_matrix_esm/* mat4.getRotation */.pB.getRotation(gl_matrix_esm/* quat.create */.Yu.create(), targetMatrix);
29680
+ let dotProduct = gl_matrix_esm/* quat.dot */.Yu.dot(startQuat, targetQuat);
29681
+ if (dotProduct < 0) {
29682
+ gl_matrix_esm/* quat.scale */.Yu.scale(targetQuat, targetQuat, -1);
29683
+ dotProduct = -dotProduct;
29684
+ }
29685
+ const threshold = 0.99996;
29686
+ if (dotProduct > threshold) {
29687
+ return;
29688
+ }
29689
+ const steps = 10;
29690
+ const duration = 150;
29691
+ const stepDuration = duration / steps;
29692
+ let currentStep = 0;
29693
+ const animate = () => {
29694
+ currentStep++;
29695
+ const t = currentStep / steps;
29696
+ const easedT = t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
29697
+ const interpolatedQuat = gl_matrix_esm/* quat.create */.Yu.create();
29698
+ gl_matrix_esm/* quat.slerp */.Yu.slerp(interpolatedQuat, startQuat, targetQuat, easedT);
29699
+ const interpolatedMatrix = gl_matrix_esm/* mat4.create */.pB.create();
29700
+ gl_matrix_esm/* mat4.fromQuat */.pB.fromQuat(interpolatedMatrix, interpolatedQuat);
29701
+ const interpolatedForward = interpolatedMatrix.slice(8, 11);
29702
+ const interpolatedUp = interpolatedMatrix.slice(4, 7);
29703
+ viewport.setCamera({
29704
+ viewPlaneNormal: interpolatedForward,
29705
+ viewUp: interpolatedUp,
29706
+ });
29707
+ viewport.resetCamera(ANIMATE_RESET_CAMERA_OPTIONS);
29708
+ viewport.render();
29709
+ if (currentStep < steps) {
29710
+ setTimeout(animate, stepDuration);
29711
+ }
29712
+ };
29713
+ animate();
29714
+ }
29715
+ }
29716
+ /* harmony default export */ const tools_OrientationControllerTool = ((/* unused pure expression or super */ null && (OrientationControllerTool)));
29717
+
29509
29718
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/stateManagement/segmentation/activeSegmentation.js + 1 modules
29510
29719
  var segmentation_activeSegmentation = __webpack_require__(26228);
29511
29720
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/stateManagement/segmentation/segmentIndex.js
@@ -30195,6 +30404,7 @@ class LabelMapEditWithContourTool extends PlanarFreehandContourSegmentationTool/
30195
30404
 
30196
30405
 
30197
30406
 
30407
+
30198
30408
 
30199
30409
 
30200
30410
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/rectangle/index.js
@@ -33822,6 +34032,7 @@ function normalizeSegmentationInput(segmentationInput) {
33822
34032
  return {
33823
34033
  segmentationId,
33824
34034
  label: config?.label ?? null,
34035
+ fallbackLabel: config?.fallbackLabel ?? null,
33825
34036
  cachedStats: config?.cachedStats ?? {},
33826
34037
  segments: normalizedSegments,
33827
34038
  representationData: {