@ohif/app 3.8.0-beta.28 → 3.8.0-beta.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/{12.bundle.9143213c69b6d81bb096.js → 12.bundle.abb6ab88fda1125f3b47.js} +9 -11
  2. package/dist/{125.bundle.253395f320b72180da63.js → 125.bundle.df666cb677e5a8982157.js} +4 -5
  3. package/dist/{170.bundle.4d78d3772d1acb65fded.js → 170.bundle.57dff48fc09ba5fa844b.js} +50 -69
  4. package/dist/{181.bundle.87f1df4f401b8023cfd1.js → 181.bundle.ae92b8a551d041d06e90.js} +58 -70
  5. package/dist/181.css +1 -1
  6. package/dist/{185.bundle.09cc8eea4e4056374e36.js → 185.bundle.0251703d5b77f265cc11.js} +21 -26
  7. package/dist/{19.bundle.d6a9a105cb89ce17cc8b.js → 19.bundle.55796dd5a6dfecf02682.js} +112 -127
  8. package/dist/{199.bundle.6f0caf3db1c473be990d.js → 199.bundle.f62693c1405b52bc6580.js} +18 -20
  9. package/dist/{202.bundle.a607e9ab460999d8c0c8.js → 202.bundle.0ca2f2479d2578f539b0.js} +9 -1
  10. package/dist/{220.bundle.f7e1c96c94245e70f2be.js → 223.bundle.d4ac6ef2cfe47a9c4afc.js} +4422 -3671
  11. package/dist/{23.bundle.e008ad788170f2ed5569.js → 23.bundle.9d989522a6e4fdcb9c72.js} +1 -1
  12. package/dist/{250.bundle.5634282a01bd6e15b70d.js → 250.bundle.09c69d348a5d965debc8.js} +17 -22
  13. package/dist/{281.bundle.ed6f4765a49b67b6fa43.js → 281.bundle.a934356f89499eb6ec48.js} +23 -25
  14. package/dist/{359.bundle.f935bae2cc0ad1065f50.js → 359.bundle.1f2a03766e18f1e3cca4.js} +24 -27
  15. package/dist/{410.bundle.caba83fcaf6ee8caabe6.js → 410.bundle.b59d9d09407856f9babc.js} +22 -26
  16. package/dist/{417.bundle.af0a207c29b109f84159.js → 417.bundle.5c66801d23d0e98c00e6.js} +2 -2
  17. package/dist/{451.bundle.57c21db5d003c75e9d61.js → 451.bundle.68a551a7d1746cf904cb.js} +26 -32
  18. package/dist/{456.bundle.a2574e369e5fd60c0ed7.js → 456.bundle.475e0e878872ad61e39e.js} +392 -515
  19. package/dist/{466.bundle.e59923d0514cbfa2482a.js → 466.bundle.667b31151880a262d475.js} +101 -130
  20. package/dist/{471.bundle.49c8d281adbae4a2c4df.js → 471.bundle.5809b10f75c8fc2f7167.js} +27 -33
  21. package/dist/{483.bundle.ef869872fd6fd7aa5b6b.js → 483.bundle.775438e850fbee318b63.js} +128 -170
  22. package/dist/{485.bundle.8667a696ac2eaf99e4fa.js → 485.bundle.5b6c33cc43d8f3470642.js} +1 -1
  23. package/dist/{506.bundle.c7927979078083de7126.js → 506.bundle.dcae1c16f61651daa74d.js} +13 -18
  24. package/dist/{530.bundle.a03b6f942ace3e1baa1e.js → 530.bundle.f904325ef4195d69ac0e.js} +10 -3
  25. package/dist/{26.bundle.c92012465cee00a2a708.js → 566.bundle.4840518afd323372c70f.js} +1136 -442
  26. package/dist/{613.bundle.dae1b29d8c4912dde32c.js → 613.bundle.d080a15569910ff63fc8.js} +19 -24
  27. package/dist/{661.bundle.65dd579322b265c6e321.js → 661.bundle.28ef6d8cd035876bd8e2.js} +40 -12
  28. package/dist/{686.bundle.dccef1f36e4bc79bcc48.js → 686.bundle.62c827fe4f0d054c164e.js} +4 -5
  29. package/dist/{687.bundle.96fde3d28aaeeeea7b8f.js → 687.bundle.fc36244c7ec3b1146f13.js} +19 -35
  30. package/dist/{738.bundle.99bc9fe71e5dccd0b0cd.js → 738.bundle.7c78f93180d8405b167c.js} +434 -596
  31. package/dist/{814.bundle.76638a0bfd57b81339fa.js → 814.bundle.9c9805cd0d54a8ea9697.js} +9 -11
  32. package/dist/{822.bundle.775a62e1f79c403f3aed.js → 822.bundle.55759fd8e9b0b489cc6b.js} +13 -15
  33. package/dist/{886.bundle.c8dd3ecc42a4253de278.js → 886.bundle.4496fc7fb83b8c897d20.js} +18 -22
  34. package/dist/{95.bundle.db9d2d504abc5dd4fdfa.js → 95.bundle.d7a9f450bed3b770504d.js} +3 -3
  35. package/dist/{965.bundle.39dda96bd5335d372afb.js → 965.bundle.26d8f982af77f304a038.js} +91 -115
  36. package/dist/{app.bundle.75411c4a0421eb19f478.js → app.bundle.88eb088709ac23e29da0.js} +4643 -5947
  37. package/dist/app.bundle.css +11 -11
  38. package/dist/{dicom-microscopy-viewer.bundle.2c146384eb9466d02ff8.js → dicom-microscopy-viewer.bundle.a7d5060eead13771e784.js} +1 -1
  39. package/dist/index.html +1 -1
  40. package/dist/sw.js +1 -1
  41. package/package.json +17 -17
@@ -1,6 +1,6 @@
1
- (self["webpackChunk"] = self["webpackChunk"] || []).push([[26],{
1
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[566],{
2
2
 
3
- /***/ 1026:
3
+ /***/ 74566:
4
4
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
5
5
 
6
6
  "use strict";
@@ -82,6 +82,7 @@ __webpack_require__.d(enums_namespaceObject, {
82
82
  KeyboardBindings: () => (KeyboardBindings),
83
83
  MouseBindings: () => (MouseBindings),
84
84
  SegmentationRepresentations: () => (enums_SegmentationRepresentations),
85
+ StrategyCallbacks: () => (enums_StrategyCallbacks),
85
86
  Swipe: () => (Swipe),
86
87
  ToolModes: () => (enums_ToolModes)
87
88
  });
@@ -294,7 +295,8 @@ var ellipse_namespaceObject = {};
294
295
  __webpack_require__.r(ellipse_namespaceObject);
295
296
  __webpack_require__.d(ellipse_namespaceObject, {
296
297
  getCanvasEllipseCorners: () => (getCanvasEllipseCorners),
297
- pointInEllipse: () => (pointInEllipse)
298
+ pointInEllipse: () => (pointInEllipse),
299
+ precalculatePointInEllipse: () => (precalculatePointInEllipse)
298
300
  });
299
301
 
300
302
  // NAMESPACE OBJECT: ../../../node_modules/@cornerstonejs/tools/dist/esm/cursors/index.js
@@ -646,8 +648,8 @@ __webpack_require__.d(synchronizers_namespaceObject, {
646
648
  var types_namespaceObject = {};
647
649
  __webpack_require__.r(types_namespaceObject);
648
650
 
649
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 363 modules
650
- var esm = __webpack_require__(56959);
651
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 364 modules
652
+ var esm = __webpack_require__(27968);
651
653
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/enums/ToolBindings.js
652
654
  var MouseBindings;
653
655
  (function (MouseBindings) {
@@ -754,6 +756,22 @@ var Swipe;
754
756
  })(Swipe || (Swipe = {}));
755
757
 
756
758
 
759
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/enums/StrategyCallbacks.js
760
+ var StrategyCallbacks;
761
+ (function (StrategyCallbacks) {
762
+ StrategyCallbacks["OnInteractionStart"] = "onInteractionStart";
763
+ StrategyCallbacks["OnInteractionEnd"] = "onInteractionEnd";
764
+ StrategyCallbacks["Preview"] = "preview";
765
+ StrategyCallbacks["RejectPreview"] = "rejectPreview";
766
+ StrategyCallbacks["AcceptPreview"] = "acceptPreview";
767
+ StrategyCallbacks["Fill"] = "fill";
768
+ StrategyCallbacks["StrategyFunction"] = "strategyFunction";
769
+ StrategyCallbacks["CreateIsInThreshold"] = "createIsInThreshold";
770
+ StrategyCallbacks["Initialize"] = "initialize";
771
+ StrategyCallbacks["INTERNAL_setValue"] = "setValue";
772
+ })(StrategyCallbacks || (StrategyCallbacks = {}));
773
+ /* harmony default export */ const enums_StrategyCallbacks = (StrategyCallbacks);
774
+
757
775
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/enums/index.js
758
776
 
759
777
 
@@ -763,6 +781,7 @@ var Swipe;
763
781
 
764
782
 
765
783
 
784
+
766
785
  // EXTERNAL MODULE: ../../../node_modules/lodash.clonedeep/index.js
767
786
  var lodash_clonedeep = __webpack_require__(11677);
768
787
  var lodash_clonedeep_default = /*#__PURE__*/__webpack_require__.n(lodash_clonedeep);
@@ -4264,7 +4283,14 @@ function getColorForSegmentIndex(toolGroupId, segmentationRepresentationUID, seg
4264
4283
  }
4265
4284
  const { colorLUTIndex } = segmentationRepresentation;
4266
4285
  const colorLUT = getColorLUT(colorLUTIndex);
4267
- return colorLUT[segmentIndex];
4286
+ let colorValue = colorLUT[segmentIndex];
4287
+ if (!colorValue) {
4288
+ if (typeof segmentIndex !== 'number') {
4289
+ throw new Error(`Can't create colour for LUT index ${segmentIndex}`);
4290
+ }
4291
+ colorValue = colorLUT[segmentIndex] = [0, 0, 0, 0];
4292
+ }
4293
+ return colorValue;
4268
4294
  }
4269
4295
  function setColorForSegmentIndex(toolGroupId, segmentationRepresentationUID, segmentIndex, color) {
4270
4296
  const colorReference = getColorForSegmentIndex(toolGroupId, segmentationRepresentationUID, segmentIndex);
@@ -4421,7 +4447,11 @@ class BaseTool {
4421
4447
  }
4422
4448
  applyActiveStrategy(enabledElement, operationData) {
4423
4449
  const { strategies, activeStrategy } = this.configuration;
4424
- return strategies[activeStrategy].call(this, enabledElement, operationData);
4450
+ return strategies[activeStrategy]?.call(this, enabledElement, operationData);
4451
+ }
4452
+ applyActiveStrategyCallback(enabledElement, operationData, callbackType) {
4453
+ const { strategies, activeStrategy } = this.configuration;
4454
+ return strategies[activeStrategy][callbackType]?.call(this, enabledElement, operationData);
4425
4455
  }
4426
4456
  setConfiguration(newConfiguration) {
4427
4457
  this.configuration = esm.utilities.deepMerge(this.configuration, newConfiguration);
@@ -4648,7 +4678,6 @@ function drawCircle(svgDrawingHelper, annotationUID, circleUID, center, radius,
4648
4678
  /* harmony default export */ const drawingSvg_drawCircle = (drawCircle);
4649
4679
 
4650
4680
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/drawingSvg/drawEllipseByCoordinates.js
4651
- 2;
4652
4681
 
4653
4682
 
4654
4683
 
@@ -4666,7 +4695,7 @@ function drawEllipseByCoordinates(svgDrawingHelper, annotationUID, ellipseUID, c
4666
4695
  const [bottom, top, left, right] = canvasCoordinates;
4667
4696
  const w = Math.hypot(left[0] - right[0], left[1] - right[1]);
4668
4697
  const h = Math.hypot(top[0] - bottom[0], top[1] - bottom[1]);
4669
- const angle = Math.atan2(left[1] - right[1], left[0] - right[0]) * 180 / Math.PI;
4698
+ const angle = (Math.atan2(left[1] - right[1], left[0] - right[0]) * 180) / Math.PI;
4670
4699
  const center = [(left[0] + right[0]) / 2, (top[1] + bottom[1]) / 2];
4671
4700
  const radiusX = w / 2;
4672
4701
  const radiusY = h / 2;
@@ -4677,7 +4706,7 @@ function drawEllipseByCoordinates(svgDrawingHelper, annotationUID, ellipseUID, c
4677
4706
  ry: `${radiusY}`,
4678
4707
  stroke: color,
4679
4708
  fill: 'transparent',
4680
- 'transform': `rotate(${angle} ${center[0]} ${center[1]})`,
4709
+ transform: `rotate(${angle} ${center[0]} ${center[1]})`,
4681
4710
  'stroke-width': strokeWidth,
4682
4711
  'stroke-dasharray': lineDash,
4683
4712
  };
@@ -4703,7 +4732,7 @@ function drawEllipse(svgDrawingHelper, annotationUID, ellipseUID, corner1, corne
4703
4732
  const bottom = [(corner1[0] + corner2[0]) / 2, corner2[1]];
4704
4733
  const left = [corner1[0], (corner1[1] + corner2[1]) / 2];
4705
4734
  const right = [corner2[0], (corner1[1] + corner2[1]) / 2];
4706
- drawingSvg_drawEllipseByCoordinates(svgDrawingHelper, annotationUID, ellipseUID, [bottom, top, left, right], options = {}, dataId = '');
4735
+ drawingSvg_drawEllipseByCoordinates(svgDrawingHelper, annotationUID, ellipseUID, [bottom, top, left, right], (options = {}), (dataId = ''));
4707
4736
  }
4708
4737
  /* harmony default export */ const drawingSvg_drawEllipse = (drawEllipse);
4709
4738
 
@@ -11706,10 +11735,11 @@ function pointInShapeCallback(imageData, pointInShapeFn, callback, boundsIJK) {
11706
11735
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/sphere/pointInSphere.js
11707
11736
  function pointInSphere(sphere, pointLPS) {
11708
11737
  const { center, radius } = sphere;
11738
+ const radius2 = sphere.radius2 || radius * radius;
11709
11739
  return ((pointLPS[0] - center[0]) * (pointLPS[0] - center[0]) +
11710
11740
  (pointLPS[1] - center[1]) * (pointLPS[1] - center[1]) +
11711
11741
  (pointLPS[2] - center[2]) * (pointLPS[2] - center[2]) <=
11712
- radius ** 2);
11742
+ radius2);
11713
11743
  }
11714
11744
 
11715
11745
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/sphere/index.js
@@ -11866,20 +11896,581 @@ function roundNumber(value, precision = 2) {
11866
11896
  }
11867
11897
  /* harmony default export */ const utilities_roundNumber = (roundNumber);
11868
11898
 
11869
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/utils/isWithinThreshold.js
11870
- function isWithinThreshold(index, imageScalarData, strategySpecificConfiguration) {
11871
- const { THRESHOLD_INSIDE_CIRCLE } = strategySpecificConfiguration;
11872
- const voxelValue = imageScalarData[index];
11873
- const { threshold } = THRESHOLD_INSIDE_CIRCLE;
11874
- return threshold[0] <= voxelValue && voxelValue <= threshold[1];
11899
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/ellipse/pointInEllipse.js
11900
+ function pointInEllipse(ellipse, pointLPS, inverts = {}) {
11901
+ if (!inverts.precalculated) {
11902
+ precalculatePointInEllipse(ellipse, inverts);
11903
+ }
11904
+ return inverts.precalculated(pointLPS);
11875
11905
  }
11876
- /* harmony default export */ const utils_isWithinThreshold = (isWithinThreshold);
11906
+ const precalculatePointInEllipse = (ellipse, inverts = {}) => {
11907
+ const { xRadius, yRadius, zRadius } = ellipse;
11908
+ if (inverts.invXRadiusSq === undefined ||
11909
+ inverts.invYRadiusSq === undefined ||
11910
+ inverts.invZRadiusSq === undefined) {
11911
+ inverts.invXRadiusSq = xRadius !== 0 ? 1 / xRadius ** 2 : 0;
11912
+ inverts.invYRadiusSq = yRadius !== 0 ? 1 / yRadius ** 2 : 0;
11913
+ inverts.invZRadiusSq = zRadius !== 0 ? 1 / zRadius ** 2 : 0;
11914
+ }
11915
+ const { invXRadiusSq, invYRadiusSq, invZRadiusSq } = inverts;
11916
+ const { center } = ellipse;
11917
+ const [centerL, centerP, centerS] = center;
11918
+ inverts.precalculated = (pointLPS) => {
11919
+ const dx = pointLPS[0] - centerL;
11920
+ let inside = dx * dx * invXRadiusSq;
11921
+ if (inside > 1) {
11922
+ return false;
11923
+ }
11924
+ const dy = pointLPS[1] - centerP;
11925
+ inside += dy * dy * invYRadiusSq;
11926
+ if (inside > 1) {
11927
+ return false;
11928
+ }
11929
+ const dz = pointLPS[2] - centerS;
11930
+ inside += dz * dz * invZRadiusSq;
11931
+ return inside <= 1;
11932
+ };
11933
+ return inverts;
11934
+ };
11935
+
11936
+
11937
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/ellipse/getCanvasEllipseCorners.js
11938
+ function getCanvasEllipseCorners(ellipseCanvasPoints) {
11939
+ const [bottom, top, left, right] = ellipseCanvasPoints;
11940
+ const topLeft = [left[0], top[1]];
11941
+ const bottomRight = [right[0], bottom[1]];
11942
+ return [topLeft, bottomRight];
11943
+ }
11944
+
11945
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/ellipse/index.js
11946
+
11947
+
11948
+
11949
+
11950
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/determineSegmentIndex.js
11951
+
11952
+
11953
+ /* harmony default export */ const determineSegmentIndex = ({
11954
+ [enums_StrategyCallbacks.Initialize]: (operationData) => {
11955
+ const { strategySpecificConfiguration } = operationData;
11956
+ if (!strategySpecificConfiguration) {
11957
+ return;
11958
+ }
11959
+ const { centerSegmentIndex } = strategySpecificConfiguration;
11960
+ if (centerSegmentIndex) {
11961
+ operationData.segmentIndex = centerSegmentIndex.segmentIndex;
11962
+ }
11963
+ },
11964
+ [enums_StrategyCallbacks.OnInteractionStart]: (operationData) => {
11965
+ const { segmentIndex, previewSegmentIndex, segmentationVoxelManager: segmentationVoxelManager, centerIJK, strategySpecificConfiguration, imageVoxelManager: imageVoxelManager, segmentationImageData, preview, } = operationData;
11966
+ if (!strategySpecificConfiguration?.useCenterSegmentIndex) {
11967
+ return;
11968
+ }
11969
+ delete strategySpecificConfiguration.centerSegmentIndex;
11970
+ let hasSegmentIndex = false;
11971
+ let hasPreviewIndex = false;
11972
+ const callback = ({ value }) => {
11973
+ hasSegmentIndex ||= value === segmentIndex;
11974
+ hasPreviewIndex ||= value === previewSegmentIndex;
11975
+ };
11976
+ pointInShapeCallback(segmentationImageData, imageVoxelManager.isInObject, callback, segmentationVoxelManager.boundsIJK);
11977
+ if (!hasSegmentIndex && !hasPreviewIndex) {
11978
+ return;
11979
+ }
11980
+ let existingValue = segmentationVoxelManager.getAtIJKPoint(centerIJK);
11981
+ if (existingValue === previewSegmentIndex) {
11982
+ if (preview) {
11983
+ existingValue = preview.segmentIndex;
11984
+ }
11985
+ else {
11986
+ return;
11987
+ }
11988
+ }
11989
+ else if (hasPreviewIndex) {
11990
+ existingValue = null;
11991
+ }
11992
+ operationData.segmentIndex = existingValue;
11993
+ strategySpecificConfiguration.centerSegmentIndex = {
11994
+ segmentIndex: existingValue,
11995
+ };
11996
+ },
11997
+ });
11998
+
11999
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/dynamicThreshold.js
12000
+
12001
+ /* harmony default export */ const dynamicThreshold = ({
12002
+ [enums_StrategyCallbacks.Initialize]: (operationData) => {
12003
+ const { centerIJK, strategySpecificConfiguration, segmentationVoxelManager: segmentationVoxelManager, imageVoxelManager: imageVoxelManager, segmentIndex, } = operationData;
12004
+ const { THRESHOLD } = strategySpecificConfiguration;
12005
+ if (!THRESHOLD?.isDynamic || !centerIJK || !segmentIndex) {
12006
+ return;
12007
+ }
12008
+ const { boundsIJK } = segmentationVoxelManager;
12009
+ const { threshold: oldThreshold, dynamicRadius = 0 } = THRESHOLD;
12010
+ const useDelta = oldThreshold ? 0 : dynamicRadius;
12011
+ const nestedBounds = boundsIJK.map((ijk, idx) => {
12012
+ const [min, max] = ijk;
12013
+ return [
12014
+ Math.max(min, centerIJK[idx] - useDelta),
12015
+ Math.min(max, centerIJK[idx] + useDelta),
12016
+ ];
12017
+ });
12018
+ const threshold = oldThreshold || [Infinity, -Infinity];
12019
+ const callback = ({ value }) => {
12020
+ threshold[0] = Math.min(value, threshold[0]);
12021
+ threshold[1] = Math.max(value, threshold[1]);
12022
+ };
12023
+ imageVoxelManager.forEach(callback, { boundsIJK: nestedBounds });
12024
+ operationData.strategySpecificConfiguration.THRESHOLD.threshold = threshold;
12025
+ },
12026
+ [enums_StrategyCallbacks.OnInteractionStart]: (operationData) => {
12027
+ const { strategySpecificConfiguration, preview } = operationData;
12028
+ if (!strategySpecificConfiguration?.THRESHOLD?.isDynamic && !preview) {
12029
+ return;
12030
+ }
12031
+ strategySpecificConfiguration.THRESHOLD.threshold = null;
12032
+ },
12033
+ });
12034
+
12035
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/erase.js
12036
+
12037
+ /* harmony default export */ const erase = ({
12038
+ [enums_StrategyCallbacks.Initialize]: (operationData) => {
12039
+ operationData.segmentIndex = 0;
12040
+ },
12041
+ });
12042
+
12043
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/segmentation/floodFill.js
12044
+ function floodFill(getter, seed, options = {}) {
12045
+ const onFlood = options.onFlood;
12046
+ const onBoundary = options.onBoundary;
12047
+ const equals = options.equals || defaultEquals;
12048
+ const diagonals = options.diagonals || false;
12049
+ const startNode = get(seed);
12050
+ const permutations = prunedPermutations();
12051
+ const stack = [];
12052
+ const flooded = [];
12053
+ const visits = {};
12054
+ const bounds = {};
12055
+ stack.push({ currentArgs: seed });
12056
+ while (stack.length > 0) {
12057
+ flood(stack.pop());
12058
+ }
12059
+ return {
12060
+ flooded,
12061
+ boundaries: boundaries(),
12062
+ };
12063
+ function flood(job) {
12064
+ const getArgs = job.currentArgs;
12065
+ const prevArgs = job.previousArgs;
12066
+ if (visited(getArgs)) {
12067
+ return;
12068
+ }
12069
+ markAsVisited(getArgs);
12070
+ if (member(getArgs)) {
12071
+ markAsFlooded(getArgs);
12072
+ pushAdjacent(getArgs);
12073
+ }
12074
+ else {
12075
+ markAsBoundary(prevArgs);
12076
+ }
12077
+ }
12078
+ function visited(key) {
12079
+ return visits[key] === true;
12080
+ }
12081
+ function markAsVisited(key) {
12082
+ visits[key] = true;
12083
+ }
12084
+ function member(getArgs) {
12085
+ const node = safely(get, [getArgs]);
12086
+ return safely(equals, [node, startNode]);
12087
+ }
12088
+ function markAsFlooded(getArgs) {
12089
+ flooded.push(getArgs);
12090
+ if (onFlood) {
12091
+ onFlood(...getArgs);
12092
+ }
12093
+ }
12094
+ function markAsBoundary(prevArgs) {
12095
+ bounds[prevArgs] = prevArgs;
12096
+ if (onBoundary) {
12097
+ onBoundary(...prevArgs);
12098
+ }
12099
+ }
12100
+ function pushAdjacent(getArgs) {
12101
+ for (let i = 0; i < permutations.length; i += 1) {
12102
+ const perm = permutations[i];
12103
+ const nextArgs = getArgs.slice(0);
12104
+ for (let j = 0; j < getArgs.length; j += 1) {
12105
+ nextArgs[j] += perm[j];
12106
+ }
12107
+ stack.push({
12108
+ currentArgs: nextArgs,
12109
+ previousArgs: getArgs,
12110
+ });
12111
+ }
12112
+ }
12113
+ function get(getArgs) {
12114
+ return getter(...getArgs);
12115
+ }
12116
+ function safely(f, args) {
12117
+ try {
12118
+ return f(...args);
12119
+ }
12120
+ catch (error) {
12121
+ return;
12122
+ }
12123
+ }
12124
+ function prunedPermutations() {
12125
+ const permutations = permute(seed.length);
12126
+ return permutations.filter(function (perm) {
12127
+ const count = countNonZeroes(perm);
12128
+ return count !== 0 && (count === 1 || diagonals);
12129
+ });
12130
+ }
12131
+ function permute(length) {
12132
+ const perms = [];
12133
+ const permutation = function (string) {
12134
+ return string.split('').map(function (c) {
12135
+ return parseInt(c, 10) - 1;
12136
+ });
12137
+ };
12138
+ for (let i = 0; i < Math.pow(3, length); i += 1) {
12139
+ const string = lpad(i.toString(3), '0', length);
12140
+ perms.push(permutation(string));
12141
+ }
12142
+ return perms;
12143
+ }
12144
+ function boundaries() {
12145
+ const array = [];
12146
+ for (const key in bounds) {
12147
+ if (bounds[key] !== undefined) {
12148
+ array.unshift(bounds[key]);
12149
+ }
12150
+ }
12151
+ return array;
12152
+ }
12153
+ }
12154
+ function defaultEquals(a, b) {
12155
+ return a === b;
12156
+ }
12157
+ function countNonZeroes(array) {
12158
+ let count = 0;
12159
+ for (let i = 0; i < array.length; i += 1) {
12160
+ if (array[i] !== 0) {
12161
+ count += 1;
12162
+ }
12163
+ }
12164
+ return count;
12165
+ }
12166
+ function lpad(string, character, length) {
12167
+ const array = new Array(length + 1);
12168
+ const pad = array.join(character);
12169
+ return (pad + string).slice(-length);
12170
+ }
12171
+ /* harmony default export */ const segmentation_floodFill = (floodFill);
12172
+
12173
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/islandRemoval.js
12174
+
12175
+
12176
+
12177
+ /* harmony default export */ const islandRemoval = ({
12178
+ [enums_StrategyCallbacks.OnInteractionEnd]: (operationData) => {
12179
+ const { previewVoxelManager: previewVoxelManager, segmentationVoxelManager: segmentationVoxelManager, strategySpecificConfiguration, previewSegmentIndex, segmentIndex, } = operationData;
12180
+ if (!strategySpecificConfiguration.THRESHOLD || segmentIndex === null) {
12181
+ return;
12182
+ }
12183
+ const clickedPoints = previewVoxelManager.getPoints();
12184
+ if (!clickedPoints?.length) {
12185
+ return;
12186
+ }
12187
+ if (previewSegmentIndex === undefined) {
12188
+ return;
12189
+ }
12190
+ const boundsIJK = previewVoxelManager
12191
+ .getBoundsIJK()
12192
+ .map((bound, i) => [
12193
+ Math.min(bound[0], ...clickedPoints.map((point) => point[i])),
12194
+ Math.max(bound[1], ...clickedPoints.map((point) => point[i])),
12195
+ ]);
12196
+ if (boundsIJK.find((it) => it[0] < 0 || it[1] > 65535)) {
12197
+ return;
12198
+ }
12199
+ const floodedSet = new Set();
12200
+ const getter = (i, j, k) => {
12201
+ if (i < boundsIJK[0][0] ||
12202
+ i > boundsIJK[0][1] ||
12203
+ j < boundsIJK[1][0] ||
12204
+ j > boundsIJK[1][1] ||
12205
+ k < boundsIJK[2][0] ||
12206
+ k > boundsIJK[2][1]) {
12207
+ return -1;
12208
+ }
12209
+ const index = segmentationVoxelManager.toIndex([i, j, k]);
12210
+ if (floodedSet.has(index)) {
12211
+ return -2;
12212
+ }
12213
+ const oldVal = segmentationVoxelManager.getAtIndex(index);
12214
+ const isIn = oldVal === previewSegmentIndex || oldVal === segmentIndex ? 1 : 0;
12215
+ if (!isIn) {
12216
+ segmentationVoxelManager.addPoint(index);
12217
+ }
12218
+ return isIn;
12219
+ };
12220
+ let floodedCount = 0;
12221
+ const onFlood = (i, j, k) => {
12222
+ const index = segmentationVoxelManager.toIndex([i, j, k]);
12223
+ if (floodedSet.has(index)) {
12224
+ return;
12225
+ }
12226
+ previewVoxelManager.setAtIJK(i, j, k, previewSegmentIndex);
12227
+ floodedSet.add(index);
12228
+ floodedCount++;
12229
+ };
12230
+ clickedPoints.forEach((clickedPoint, index) => {
12231
+ if (getter(...clickedPoint) === 1) {
12232
+ segmentation_floodFill(getter, clickedPoint, {
12233
+ onFlood,
12234
+ diagonals: true,
12235
+ });
12236
+ }
12237
+ });
12238
+ let clearedCount = 0;
12239
+ let previewCount = 0;
12240
+ const callback = ({ index, pointIJK, value: trackValue }) => {
12241
+ const value = segmentationVoxelManager.getAtIndex(index);
12242
+ if (floodedSet.has(index)) {
12243
+ previewCount++;
12244
+ const newValue = trackValue === segmentIndex ? segmentIndex : previewSegmentIndex;
12245
+ previewVoxelManager.setAtIJKPoint(pointIJK, newValue);
12246
+ }
12247
+ else if (value === previewSegmentIndex) {
12248
+ clearedCount++;
12249
+ const newValue = trackValue ?? 0;
12250
+ previewVoxelManager.setAtIJKPoint(pointIJK, newValue);
12251
+ }
12252
+ };
12253
+ previewVoxelManager.forEach(callback, {});
12254
+ if (floodedCount - previewCount !== 0) {
12255
+ console.warn('There were flooded=', floodedCount, 'cleared=', clearedCount, 'preview count=', previewCount, 'not handled', floodedCount - previewCount);
12256
+ }
12257
+ const islandMap = new Set(segmentationVoxelManager.points || []);
12258
+ floodedSet.clear();
12259
+ for (const index of islandMap.keys()) {
12260
+ if (floodedSet.has(index)) {
12261
+ continue;
12262
+ }
12263
+ let isInternal = true;
12264
+ const internalSet = new Set();
12265
+ const onFloodInternal = (i, j, k) => {
12266
+ const floodIndex = previewVoxelManager.toIndex([i, j, k]);
12267
+ floodedSet.add(floodIndex);
12268
+ if ((boundsIJK[0][0] !== boundsIJK[0][1] &&
12269
+ (i === boundsIJK[0][0] || i === boundsIJK[0][1])) ||
12270
+ (boundsIJK[1][0] !== boundsIJK[1][1] &&
12271
+ (j === boundsIJK[1][0] || j === boundsIJK[1][1])) ||
12272
+ (boundsIJK[2][0] !== boundsIJK[2][1] &&
12273
+ (k === boundsIJK[2][0] || k === boundsIJK[2][1]))) {
12274
+ isInternal = false;
12275
+ }
12276
+ if (isInternal) {
12277
+ internalSet.add(floodIndex);
12278
+ }
12279
+ };
12280
+ const pointIJK = previewVoxelManager.toIJK(index);
12281
+ if (getter(...pointIJK) !== 0) {
12282
+ continue;
12283
+ }
12284
+ segmentation_floodFill(getter, pointIJK, {
12285
+ onFlood: onFloodInternal,
12286
+ diagonals: false,
12287
+ });
12288
+ if (isInternal) {
12289
+ for (const index of internalSet) {
12290
+ previewVoxelManager.setAtIndex(index, previewSegmentIndex);
12291
+ }
12292
+ }
12293
+ }
12294
+ triggerSegmentationDataModified(operationData.segmentationId, previewVoxelManager.getArrayOfSlices());
12295
+ },
12296
+ });
12297
+
12298
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/preview.js
12299
+
12300
+
12301
+
12302
+ /* harmony default export */ const preview = ({
12303
+ [enums_StrategyCallbacks.Preview]: function (operationData) {
12304
+ const { previewColors, strategySpecificConfiguration, enabledElement } = operationData;
12305
+ if (!previewColors || !strategySpecificConfiguration) {
12306
+ return;
12307
+ }
12308
+ if (operationData.preview) {
12309
+ delete operationData.preview;
12310
+ }
12311
+ delete strategySpecificConfiguration.centerSegmentIndex;
12312
+ this.onInteractionStart?.(enabledElement, operationData);
12313
+ const preview = this.fill(enabledElement, operationData);
12314
+ if (preview) {
12315
+ preview.isPreviewFromHover = true;
12316
+ operationData.preview = preview;
12317
+ this.onInteractionEnd?.(enabledElement, operationData);
12318
+ }
12319
+ return preview;
12320
+ },
12321
+ [enums_StrategyCallbacks.Initialize]: (operationData) => {
12322
+ const { toolGroupId, segmentIndex, segmentationRepresentationUID, previewSegmentIndex, previewColors, preview, } = operationData;
12323
+ if (previewColors === undefined) {
12324
+ return;
12325
+ }
12326
+ if (preview) {
12327
+ preview.previewVoxelManager.sourceVoxelManager =
12328
+ operationData.segmentationVoxelManager;
12329
+ operationData.previewVoxelManager = preview.previewVoxelManager;
12330
+ }
12331
+ if (segmentIndex === null || !previewSegmentIndex) {
12332
+ return;
12333
+ }
12334
+ const configColor = previewColors?.[segmentIndex];
12335
+ const segmentColor = getColorForSegmentIndex(toolGroupId, segmentationRepresentationUID, segmentIndex);
12336
+ if (!configColor && !segmentColor) {
12337
+ return;
12338
+ }
12339
+ const previewColor = configColor || segmentColor.map((it) => it * 0.9);
12340
+ setColorForSegmentIndex(toolGroupId, segmentationRepresentationUID, previewSegmentIndex, previewColor);
12341
+ },
12342
+ [enums_StrategyCallbacks.AcceptPreview]: (operationData) => {
12343
+ const { segmentationVoxelManager: segmentationVoxelManager, previewVoxelManager: previewVoxelManager, previewSegmentIndex, preview, } = operationData;
12344
+ if (previewSegmentIndex === undefined) {
12345
+ return;
12346
+ }
12347
+ const segmentIndex = preview?.segmentIndex ?? operationData.segmentIndex;
12348
+ const tracking = previewVoxelManager;
12349
+ if (!tracking || tracking.modifiedSlices.size === 0) {
12350
+ return;
12351
+ }
12352
+ const callback = ({ index }) => {
12353
+ const oldValue = segmentationVoxelManager.getAtIndex(index);
12354
+ if (oldValue === previewSegmentIndex) {
12355
+ segmentationVoxelManager.setAtIndex(index, segmentIndex);
12356
+ }
12357
+ };
12358
+ tracking.forEach(callback, {});
12359
+ triggerSegmentationDataModified(operationData.segmentationId, tracking.getArrayOfSlices());
12360
+ tracking.clear();
12361
+ },
12362
+ [enums_StrategyCallbacks.RejectPreview]: (operationData) => {
12363
+ const { previewVoxelManager: previewVoxelManager, segmentationVoxelManager: segmentationVoxelManager, } = operationData;
12364
+ if (previewVoxelManager.modifiedSlices.size === 0) {
12365
+ return;
12366
+ }
12367
+ const callback = ({ index, value }) => {
12368
+ segmentationVoxelManager.setAtIndex(index, value);
12369
+ };
12370
+ previewVoxelManager.forEach(callback);
12371
+ triggerSegmentationDataModified(operationData.segmentationId, previewVoxelManager.getArrayOfSlices());
12372
+ previewVoxelManager.clear();
12373
+ },
12374
+ });
12375
+
12376
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/regionFill.js
12377
+
12378
+
12379
+ /* harmony default export */ const regionFill = ({
12380
+ [enums_StrategyCallbacks.Fill]: (operationData) => {
12381
+ const { segmentsLocked, segmentationImageData, segmentationVoxelManager: segmentationVoxelManager, previewVoxelManager: previewVoxelManager, imageVoxelManager: imageVoxelManager, brushStrategy, centerIJK, } = operationData;
12382
+ const isWithinThreshold = brushStrategy.createIsInThreshold?.(operationData);
12383
+ const { setValue } = brushStrategy;
12384
+ const callback = isWithinThreshold
12385
+ ? (data) => {
12386
+ const { value, index } = data;
12387
+ if (segmentsLocked.includes(value) || !isWithinThreshold(index)) {
12388
+ return;
12389
+ }
12390
+ setValue(operationData, data);
12391
+ }
12392
+ : (data) => setValue(operationData, data);
12393
+ pointInShapeCallback(segmentationImageData, imageVoxelManager.isInObject, callback, segmentationVoxelManager.boundsIJK);
12394
+ previewVoxelManager.addPoint(centerIJK);
12395
+ },
12396
+ });
12397
+
12398
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/setValue.js
12399
+
12400
+ /* harmony default export */ const setValue = ({
12401
+ [enums_StrategyCallbacks.INTERNAL_setValue]: (operationData, { value, index }) => {
12402
+ const { segmentsLocked, segmentIndex, previewVoxelManager: previewVoxelManager, previewSegmentIndex, segmentationVoxelManager: segmentationVoxelManager, } = operationData;
12403
+ const existingValue = segmentationVoxelManager.getAtIndex(index);
12404
+ if (segmentIndex === null) {
12405
+ const oldValue = previewVoxelManager.getAtIndex(index);
12406
+ if (oldValue !== undefined) {
12407
+ previewVoxelManager.setAtIndex(index, oldValue);
12408
+ }
12409
+ return;
12410
+ }
12411
+ if (existingValue === segmentIndex || segmentsLocked.includes(value)) {
12412
+ return;
12413
+ }
12414
+ if (existingValue === previewSegmentIndex) {
12415
+ if (previewVoxelManager.getAtIndex(index) === undefined) {
12416
+ segmentationVoxelManager.setAtIndex(index, segmentIndex);
12417
+ }
12418
+ else {
12419
+ return;
12420
+ }
12421
+ }
12422
+ const useSegmentIndex = previewSegmentIndex ?? segmentIndex;
12423
+ previewVoxelManager.setAtIndex(index, useSegmentIndex);
12424
+ },
12425
+ });
12426
+
12427
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/threshold.js
12428
+
12429
+ /* harmony default export */ const threshold = ({
12430
+ [enums_StrategyCallbacks.CreateIsInThreshold]: (operationData) => {
12431
+ const { imageVoxelManager: imageVoxelManager, strategySpecificConfiguration, segmentIndex, } = operationData;
12432
+ if (!strategySpecificConfiguration || !segmentIndex) {
12433
+ return;
12434
+ }
12435
+ return (index) => {
12436
+ const { THRESHOLD, THRESHOLD_INSIDE_CIRCLE } = strategySpecificConfiguration;
12437
+ const voxelValue = imageVoxelManager.getAtIndex(index);
12438
+ const { threshold } = THRESHOLD || THRESHOLD_INSIDE_CIRCLE || {};
12439
+ if (!threshold?.length) {
12440
+ return true;
12441
+ }
12442
+ return threshold[0] <= voxelValue && voxelValue <= threshold[1];
12443
+ };
12444
+ },
12445
+ });
12446
+
12447
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/compositions/index.js
12448
+
12449
+
12450
+
12451
+
12452
+
12453
+
12454
+
12455
+
12456
+ /* harmony default export */ const compositions = ({
12457
+ determineSegmentIndex: determineSegmentIndex,
12458
+ dynamicThreshold: dynamicThreshold,
12459
+ erase: erase,
12460
+ islandRemoval: islandRemoval,
12461
+ preview: preview,
12462
+ regionFill: regionFill,
12463
+ setValue: setValue,
12464
+ threshold: threshold,
12465
+ });
11877
12466
 
11878
12467
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/utils/getStrategyData.js
11879
12468
 
11880
12469
 
12470
+ const { VoxelManager } = esm.utilities;
11881
12471
  function getStrategyData({ operationData, viewport }) {
11882
12472
  let segmentationImageData, segmentationScalarData, imageScalarData;
12473
+ let dimensions;
11883
12474
  if (isVolumeSegmentation(operationData)) {
11884
12475
  const { volumeId, referencedVolumeId } = operationData;
11885
12476
  const segmentationVolume = esm.cache.getVolume(volumeId);
@@ -11890,6 +12481,7 @@ function getStrategyData({ operationData, viewport }) {
11890
12481
  ({ imageData: segmentationImageData } = segmentationVolume);
11891
12482
  segmentationScalarData = segmentationVolume.getScalarData();
11892
12483
  imageScalarData = imageVolume.getScalarData();
12484
+ dimensions = imageVolume.dimensions;
11893
12485
  }
11894
12486
  else {
11895
12487
  const { imageIdReferenceMap, segmentationRepresentationUID } = operationData;
@@ -11907,134 +12499,232 @@ function getStrategyData({ operationData, viewport }) {
11907
12499
  segmentationScalarData = segmentationImage.getPixelData();
11908
12500
  const image = esm.cache.getImage(currentImageId);
11909
12501
  imageScalarData = image.getPixelData();
12502
+ dimensions = [image.columns, image.rows, 1];
11910
12503
  }
11911
12504
  return {
11912
12505
  segmentationImageData,
11913
12506
  segmentationScalarData,
12507
+ segmentationVoxelManager: VoxelManager.createVolumeVoxelManager(dimensions, segmentationScalarData),
11914
12508
  imageScalarData,
12509
+ imageVoxelManager: VoxelManager.createVolumeVoxelManager(dimensions, imageScalarData),
11915
12510
  };
11916
12511
  }
11917
12512
 
11918
12513
 
11919
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/fillSphere.js
12514
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/BrushStrategy.js
11920
12515
 
11921
12516
 
11922
12517
 
11923
12518
 
11924
12519
 
11925
12520
 
11926
- function fillSphere(enabledElement, operationData, _inside = true, threshold = false) {
11927
- const { viewport } = enabledElement;
11928
- const { segmentsLocked, segmentIndex, strategySpecificConfiguration, points, } = operationData;
11929
- const strategyData = getStrategyData({ operationData, viewport });
11930
- if (!strategyData) {
11931
- console.warn('No data found for fillSphere');
11932
- return;
11933
- }
11934
- const { imageScalarData, segmentationImageData, segmentationScalarData } = strategyData;
11935
- const scalarIndex = [];
11936
- let callback;
11937
- if (threshold) {
11938
- callback = ({ value, index }) => {
11939
- if (segmentsLocked.includes(value)) {
11940
- return;
12521
+ const { VoxelManager: BrushStrategy_VoxelManager } = esm.utilities;
12522
+ class BrushStrategy {
12523
+ constructor(name, ...initializers) {
12524
+ this._initialize = [];
12525
+ this._fill = [];
12526
+ this._onInteractionStart = [];
12527
+ this.fill = (enabledElement, operationData) => {
12528
+ const initializedData = this.initialize(enabledElement, operationData);
12529
+ const { strategySpecificConfiguration = {}, centerIJK } = initializedData;
12530
+ if (esm.utilities.isEqual(centerIJK, strategySpecificConfiguration.centerIJK)) {
12531
+ return operationData.preview;
12532
+ }
12533
+ else {
12534
+ strategySpecificConfiguration.centerIJK = centerIJK;
11941
12535
  }
11942
- if (utils_isWithinThreshold(index, imageScalarData, strategySpecificConfiguration)) {
11943
- segmentationScalarData[index] = segmentIndex;
11944
- scalarIndex.push(index);
12536
+ this._fill.forEach((func) => func(initializedData));
12537
+ const { segmentationVoxelManager, previewVoxelManager, previewSegmentIndex, } = initializedData;
12538
+ triggerSegmentationDataModified(initializedData.segmentationId, segmentationVoxelManager.getArrayOfSlices());
12539
+ if (!previewSegmentIndex || !previewVoxelManager.modifiedSlices.size) {
12540
+ return null;
11945
12541
  }
12542
+ return initializedData.preview || initializedData;
11946
12543
  };
11947
- }
11948
- else {
11949
- callback = ({ index, value }) => {
11950
- if (segmentsLocked.includes(value)) {
12544
+ this.onInteractionStart = (enabledElement, operationData) => {
12545
+ const { preview } = operationData;
12546
+ if (preview?.isPreviewFromHover) {
12547
+ preview.isPreviewFromHover = false;
11951
12548
  return;
11952
12549
  }
11953
- segmentationScalarData[index] = segmentIndex;
11954
- scalarIndex.push(index);
12550
+ const initializedData = this.initialize(enabledElement, operationData);
12551
+ this._onInteractionStart.forEach((func) => func.call(this, initializedData));
11955
12552
  };
11956
- }
11957
- pointInSurroundingSphereCallback(segmentationImageData, [points[0], points[1]], callback, viewport);
11958
- const dimensions = segmentationImageData.getDimensions();
11959
- let sliceArray;
11960
- if (isVolumeSegmentation(operationData)) {
11961
- const zMultiple = dimensions[0] * dimensions[1];
11962
- const minSlice = Math.floor(scalarIndex[0] / zMultiple);
11963
- const maxSlice = Math.floor(scalarIndex[scalarIndex.length - 1] / zMultiple);
11964
- sliceArray = Array.from({ length: maxSlice - minSlice + 1 }, (v, k) => k + minSlice);
11965
- triggerSegmentationDataModified(operationData.volumeId, sliceArray);
12553
+ this.configurationName = name;
12554
+ this.compositions = initializers;
12555
+ initializers.forEach((initializer) => {
12556
+ const result = typeof initializer === 'function' ? initializer() : initializer;
12557
+ if (!result) {
12558
+ return;
12559
+ }
12560
+ for (const key in result) {
12561
+ if (!BrushStrategy.childFunctions[key]) {
12562
+ throw new Error(`Didn't find ${key} as a brush strategy`);
12563
+ }
12564
+ BrushStrategy.childFunctions[key](this, result[key]);
12565
+ }
12566
+ });
12567
+ this.strategyFunction = (enabledElement, operationData) => this.fill(enabledElement, operationData);
12568
+ for (const key of Object.keys(BrushStrategy.childFunctions)) {
12569
+ this.strategyFunction[key] = this[key];
12570
+ }
12571
+ }
12572
+ static { this.COMPOSITIONS = compositions; }
12573
+ static { this.childFunctions = {
12574
+ [enums_StrategyCallbacks.OnInteractionStart]: addListMethod(enums_StrategyCallbacks.OnInteractionStart, enums_StrategyCallbacks.Initialize),
12575
+ [enums_StrategyCallbacks.OnInteractionEnd]: addListMethod(enums_StrategyCallbacks.OnInteractionEnd, enums_StrategyCallbacks.Initialize),
12576
+ [enums_StrategyCallbacks.Fill]: addListMethod(enums_StrategyCallbacks.Fill),
12577
+ [enums_StrategyCallbacks.Initialize]: addListMethod(enums_StrategyCallbacks.Initialize),
12578
+ [enums_StrategyCallbacks.CreateIsInThreshold]: addSingletonMethod(enums_StrategyCallbacks.CreateIsInThreshold),
12579
+ [enums_StrategyCallbacks.AcceptPreview]: addListMethod(enums_StrategyCallbacks.AcceptPreview, enums_StrategyCallbacks.Initialize),
12580
+ [enums_StrategyCallbacks.RejectPreview]: addListMethod(enums_StrategyCallbacks.RejectPreview, enums_StrategyCallbacks.Initialize),
12581
+ [enums_StrategyCallbacks.INTERNAL_setValue]: addSingletonMethod(enums_StrategyCallbacks.INTERNAL_setValue),
12582
+ [enums_StrategyCallbacks.Preview]: addSingletonMethod(enums_StrategyCallbacks.Preview, false),
12583
+ compositions: null,
12584
+ }; }
12585
+ initialize(enabledElement, operationData) {
12586
+ const { viewport } = enabledElement;
12587
+ const data = getStrategyData({ operationData, viewport });
12588
+ if (!data) {
12589
+ console.warn('No data found for BrushStrategy');
12590
+ return operationData.preview;
12591
+ }
12592
+ if (isVolumeSegmentation(operationData)) {
12593
+ const { referencedVolumeId, volumeId } = operationData;
12594
+ const imageVolume = esm.cache.getVolume(referencedVolumeId);
12595
+ const segmentation = esm.cache.getVolume(volumeId);
12596
+ if (!esm.utilities.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
12597
+ !esm.utilities.isEqual(segmentation.direction, imageVolume.direction)) {
12598
+ throw new Error('Only source data the same dimensions/size/orientation as the segmentation currently supported.');
12599
+ }
12600
+ }
12601
+ const { imageVoxelManager, segmentationVoxelManager, segmentationImageData, } = data;
12602
+ const previewVoxelManager = operationData.preview?.previewVoxelManager ||
12603
+ BrushStrategy_VoxelManager.createHistoryVoxelManager(segmentationVoxelManager);
12604
+ const previewEnabled = !!operationData.previewColors;
12605
+ const previewSegmentIndex = previewEnabled ? 255 : undefined;
12606
+ const initializedData = {
12607
+ previewSegmentIndex,
12608
+ ...operationData,
12609
+ enabledElement,
12610
+ imageVoxelManager,
12611
+ segmentationVoxelManager,
12612
+ segmentationImageData,
12613
+ previewVoxelManager,
12614
+ viewport,
12615
+ centerWorld: null,
12616
+ brushStrategy: this,
12617
+ };
12618
+ this._initialize.forEach((func) => func(initializedData));
12619
+ return initializedData;
11966
12620
  }
11967
12621
  }
11968
- function fillInsideSphere(enabledElement, operationData) {
11969
- fillSphere(enabledElement, operationData, true);
12622
+ function addListMethod(name, createInitialized) {
12623
+ const listName = `_${name}`;
12624
+ return (brushStrategy, func) => {
12625
+ brushStrategy[listName] ||= [];
12626
+ brushStrategy[listName].push(func);
12627
+ brushStrategy[name] ||= createInitialized
12628
+ ? (enabledElement, operationData) => {
12629
+ const initializedData = brushStrategy[createInitialized](enabledElement, operationData);
12630
+ brushStrategy[listName].forEach((func) => func.call(brushStrategy, initializedData));
12631
+ }
12632
+ : (operationData) => {
12633
+ brushStrategy[listName].forEach((func) => func.call(brushStrategy, operationData));
12634
+ };
12635
+ };
11970
12636
  }
11971
- function thresholdInsideSphere(enabledElement, operationData) {
11972
- if (isVolumeSegmentation(operationData)) {
11973
- const { referencedVolumeId, volumeId } = operationData;
11974
- const imageVolume = esm.cache.getVolume(referencedVolumeId);
11975
- const segmentation = esm.cache.getVolume(volumeId);
11976
- if (!esm.utilities.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
11977
- !esm.utilities.isEqual(segmentation.direction, imageVolume.direction)) {
11978
- throw new Error('Only source data the same dimensions/size/orientation as the segmentation currently supported.');
12637
+ function addSingletonMethod(name, isInitialized = true) {
12638
+ return (brushStrategy, func) => {
12639
+ if (brushStrategy[name]) {
12640
+ throw new Error(`The singleton method ${name} already exists`);
11979
12641
  }
11980
- }
11981
- fillSphere(enabledElement, operationData, true, true);
11982
- }
11983
- function fillOutsideSphere(enabledElement, operationData) {
11984
- fillSphere(enabledElement, operationData, false);
12642
+ brushStrategy[name] = isInitialized
12643
+ ? func
12644
+ : (enabledElement, operationData) => {
12645
+ operationData.enabledElement = enabledElement;
12646
+ return func.call(brushStrategy, operationData);
12647
+ };
12648
+ };
11985
12649
  }
11986
12650
 
11987
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/eraseSphere.js
12651
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/fillCircle.js
11988
12652
 
11989
- function eraseInsideSphere(enabledElement, operationData) {
11990
- const eraseOperationData = Object.assign({}, operationData, {
11991
- segmentIndex: 0,
11992
- });
11993
- fillInsideSphere(enabledElement, eraseOperationData);
11994
- }
11995
12653
 
11996
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/ellipse/pointInEllipse.js
11997
- function pointInEllipse(ellipse, pointLPS, inverts = {}) {
11998
- const { center, xRadius, yRadius, zRadius } = ellipse;
11999
- if (inverts.invXRadiusSq === undefined ||
12000
- inverts.invYRadiusSq === undefined ||
12001
- inverts.invZRadiusSq === undefined) {
12002
- inverts.invXRadiusSq = xRadius !== 0 ? 1 / xRadius ** 2 : 0;
12003
- inverts.invYRadiusSq = yRadius !== 0 ? 1 / yRadius ** 2 : 0;
12004
- inverts.invZRadiusSq = zRadius !== 0 ? 1 / zRadius ** 2 : 0;
12005
- }
12006
- let inside = 0;
12007
- const dx = pointLPS[0] - center[0];
12008
- inside += dx * dx * inverts.invXRadiusSq;
12009
- if (inside > 1) {
12010
- return false;
12011
- }
12012
- const dy = pointLPS[1] - center[1];
12013
- inside += dy * dy * inverts.invYRadiusSq;
12014
- if (inside > 1) {
12015
- return false;
12016
- }
12017
- const dz = pointLPS[2] - center[2];
12018
- inside += dz * dz * inverts.invZRadiusSq;
12019
- return inside <= 1;
12020
- }
12021
12654
 
12022
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/ellipse/getCanvasEllipseCorners.js
12023
- function getCanvasEllipseCorners(ellipseCanvasPoints) {
12024
- const [bottom, top, left, right] = ellipseCanvasPoints;
12025
- const topLeft = [left[0], top[1]];
12026
- const bottomRight = [right[0], bottom[1]];
12027
- return [topLeft, bottomRight];
12028
- }
12029
12655
 
12030
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/math/ellipse/index.js
12031
12656
 
12032
12657
 
12033
12658
 
12034
12659
 
12035
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/fillCircle.js
12660
+ const { transformWorldToIndex: fillCircle_transformWorldToIndex } = esm.utilities;
12661
+ const fillCircle_EPSILON = 1e-4;
12662
+ const nearOrZero = (testValue, nearValue) => Math.abs(testValue) < fillCircle_EPSILON || Math.abs(testValue - nearValue) < fillCircle_EPSILON;
12663
+ const initializeCircle = {
12664
+ [enums_StrategyCallbacks.Initialize]: (operationData) => {
12665
+ const { points, imageVoxelManager: imageVoxelManager, viewport, segmentationImageData, segmentationVoxelManager: segmentationVoxelManager, } = operationData;
12666
+ if (!points) {
12667
+ return;
12668
+ }
12669
+ const center = gl_matrix_esm/* vec3.fromValues */.R3.fromValues(0, 0, 0);
12670
+ points.forEach((point) => {
12671
+ gl_matrix_esm/* vec3.add */.R3.add(center, center, point);
12672
+ });
12673
+ gl_matrix_esm/* vec3.scale */.R3.scale(center, center, 1 / points.length);
12674
+ operationData.centerWorld = center;
12675
+ operationData.centerIJK = fillCircle_transformWorldToIndex(segmentationImageData, center);
12676
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
12677
+ const [topLeftCanvas, bottomRightCanvas] = getCanvasEllipseCorners(canvasCoordinates);
12678
+ const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
12679
+ const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
12680
+ const ellipsoidCornersIJK = [
12681
+ fillCircle_transformWorldToIndex(segmentationImageData, topLeftWorld),
12682
+ (fillCircle_transformWorldToIndex(segmentationImageData, bottomRightWorld)),
12683
+ ];
12684
+ segmentationVoxelManager.boundsIJK = boundingBox_getBoundingBoxAroundShape(ellipsoidCornersIJK, segmentationVoxelManager.dimensions);
12685
+ imageVoxelManager.isInObject = createPointInEllipse({
12686
+ topLeftWorld,
12687
+ bottomRightWorld,
12688
+ center,
12689
+ });
12690
+ },
12691
+ };
12692
+ function createPointInEllipse(worldInfo) {
12693
+ const { topLeftWorld, bottomRightWorld, center } = worldInfo;
12694
+ const xRadius = Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2;
12695
+ const yRadius = Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2;
12696
+ const zRadius = Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2;
12697
+ const radius = Math.max(xRadius, yRadius, zRadius);
12698
+ if (nearOrZero(xRadius, radius) &&
12699
+ nearOrZero(yRadius, radius) &&
12700
+ nearOrZero(zRadius, radius)) {
12701
+ const sphereObj = {
12702
+ center,
12703
+ radius,
12704
+ radius2: radius * radius,
12705
+ };
12706
+ return (pointLPS) => pointInSphere(sphereObj, pointLPS);
12707
+ }
12708
+ const ellipseObj = {
12709
+ center: center,
12710
+ xRadius,
12711
+ yRadius,
12712
+ zRadius,
12713
+ };
12714
+ const inverts = precalculatePointInEllipse(ellipseObj);
12715
+ const { precalculated } = inverts;
12716
+ return precalculated;
12717
+ }
12718
+ const CIRCLE_STRATEGY = new BrushStrategy('Circle', compositions.regionFill, compositions.setValue, initializeCircle, compositions.determineSegmentIndex, compositions.preview);
12719
+ const CIRCLE_THRESHOLD_STRATEGY = new BrushStrategy('CircleThreshold', compositions.regionFill, compositions.setValue, initializeCircle, compositions.determineSegmentIndex, compositions.dynamicThreshold, compositions.threshold, compositions.preview, compositions.islandRemoval);
12720
+ const fillInsideCircle = CIRCLE_STRATEGY.strategyFunction;
12721
+ const thresholdInsideCircle = CIRCLE_THRESHOLD_STRATEGY.strategyFunction;
12722
+ function fillOutsideCircle() {
12723
+ throw new Error('Not yet implemented');
12724
+ }
12036
12725
 
12037
12726
 
12727
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/fillSphere.js
12038
12728
 
12039
12729
 
12040
12730
 
@@ -12043,104 +12733,69 @@ function getCanvasEllipseCorners(ellipseCanvasPoints) {
12043
12733
 
12044
12734
 
12045
12735
 
12046
- const { transformWorldToIndex: fillCircle_transformWorldToIndex } = esm.utilities;
12047
- function fillCircle(enabledElement, operationData, threshold = false) {
12048
- const { points, segmentsLocked, segmentIndex, segmentationId, strategySpecificConfiguration, } = operationData;
12049
- const { viewport } = enabledElement;
12050
- const data = getStrategyData({ operationData, viewport });
12051
- if (!data) {
12052
- console.warn('No data found for fillCircle');
12053
- return;
12054
- }
12055
- const { imageScalarData, segmentationImageData, segmentationScalarData } = data;
12056
- const { ellipseObj, boundsIJK } = getEllipse(viewport, segmentationImageData, points);
12057
- const modifiedSlicesToUse = new Set();
12058
- let callback;
12059
- if (threshold) {
12060
- callback = ({ value, index, pointIJK }) => {
12061
- if (segmentsLocked.includes(value)) {
12062
- return;
12063
- }
12064
- if (utils_isWithinThreshold(index, imageScalarData, strategySpecificConfiguration)) {
12065
- segmentationScalarData[index] = segmentIndex;
12066
- modifiedSlicesToUse.add(pointIJK[2]);
12067
- }
12068
- };
12069
- }
12070
- else {
12071
- callback = ({ value, index, pointIJK }) => {
12072
- if (segmentsLocked.includes(value)) {
12073
- return;
12074
- }
12075
- segmentationScalarData[index] = segmentIndex;
12076
- modifiedSlicesToUse.add(pointIJK[2]);
12077
- };
12078
- }
12079
- pointInShapeCallback(segmentationImageData, (pointLPS) => pointInEllipse(ellipseObj, pointLPS, {
12080
- fast: true,
12081
- }), callback, boundsIJK);
12082
- const arrayOfSlices = Array.from(modifiedSlicesToUse);
12083
- triggerSegmentationDataModified(segmentationId, arrayOfSlices);
12084
- }
12085
- function fillInsideCircle(enabledElement, operationData) {
12086
- fillCircle(enabledElement, operationData, false);
12087
- }
12088
- function thresholdInsideCircle(enabledElement, operationData) {
12089
- if (isVolumeSegmentation(operationData)) {
12090
- const { referencedVolumeId, volumeId } = operationData;
12091
- const imageVolume = esm.cache.getVolume(referencedVolumeId);
12092
- const segmentation = esm.cache.getVolume(volumeId);
12093
- if (!esm.utilities.isEqual(segmentation.dimensions, imageVolume.dimensions) ||
12094
- !esm.utilities.isEqual(segmentation.direction, imageVolume.direction)) {
12095
- throw new Error('Only source data the same dimensions/size/orientation as the segmentation currently supported.');
12736
+ const { transformWorldToIndex: fillSphere_transformWorldToIndex } = esm.utilities;
12737
+ const sphereComposition = {
12738
+ [enums_StrategyCallbacks.Initialize]: (operationData) => {
12739
+ const { points, imageVoxelManager: imageVoxelManager, viewport, segmentationImageData, segmentationVoxelManager: segmentationVoxelManager, } = operationData;
12740
+ if (!points) {
12741
+ return;
12096
12742
  }
12097
- }
12098
- fillCircle(enabledElement, operationData, true);
12099
- }
12100
- function fillOutsideCircle(enabledElement, operationData) {
12101
- throw new Error('Not yet implemented');
12102
- }
12103
- function getCenter(points) {
12104
- const center = gl_matrix_esm/* vec3.fromValues */.R3.fromValues(0, 0, 0);
12105
- points.forEach((point) => {
12106
- gl_matrix_esm/* vec3.add */.R3.add(center, center, point);
12107
- });
12108
- gl_matrix_esm/* vec3.scale */.R3.scale(center, center, 1 / points.length);
12109
- return center;
12110
- }
12111
- function getEllipse(viewport, imageData, points) {
12112
- const center = getCenter(points);
12113
- const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
12114
- const dimensions = imageData.getDimensions();
12115
- const [topLeftCanvas, bottomRightCanvas] = getCanvasEllipseCorners(canvasCoordinates);
12116
- const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
12117
- const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
12118
- const ellipsoidCornersIJK = [
12119
- fillCircle_transformWorldToIndex(imageData, topLeftWorld),
12120
- fillCircle_transformWorldToIndex(imageData, bottomRightWorld),
12121
- ];
12122
- const boundsIJK = boundingBox_getBoundingBoxAroundShape(ellipsoidCornersIJK, dimensions);
12123
- if (boundsIJK.every(([min, max]) => min !== max)) {
12124
- throw new Error('Oblique segmentation tools are not supported yet');
12125
- }
12126
- const ellipseObj = {
12127
- center: center,
12128
- xRadius: Math.abs(topLeftWorld[0] - bottomRightWorld[0]) / 2,
12129
- yRadius: Math.abs(topLeftWorld[1] - bottomRightWorld[1]) / 2,
12130
- zRadius: Math.abs(topLeftWorld[2] - bottomRightWorld[2]) / 2,
12131
- };
12132
- return { ellipseObj, boundsIJK };
12743
+ const center = gl_matrix_esm/* vec3.fromValues */.R3.fromValues(0, 0, 0);
12744
+ points.forEach((point) => {
12745
+ gl_matrix_esm/* vec3.add */.R3.add(center, center, point);
12746
+ });
12747
+ gl_matrix_esm/* vec3.scale */.R3.scale(center, center, 1 / points.length);
12748
+ operationData.centerWorld = center;
12749
+ operationData.centerIJK = fillSphere_transformWorldToIndex(segmentationImageData, center);
12750
+ const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
12751
+ const [topLeftCanvas, bottomRightCanvas] = getCanvasEllipseCorners(canvasCoordinates);
12752
+ const topLeftWorld = viewport.canvasToWorld(topLeftCanvas);
12753
+ const bottomRightWorld = viewport.canvasToWorld(bottomRightCanvas);
12754
+ const diameters = topLeftWorld.map((left, index) => Math.abs(bottomRightWorld[index] - left));
12755
+ const radius = Math.max(...diameters) / 2;
12756
+ topLeftWorld.forEach((left, index) => {
12757
+ const right = bottomRightWorld[index];
12758
+ if (left === right) {
12759
+ topLeftWorld[index] = left - radius;
12760
+ bottomRightWorld[index] = left + radius;
12761
+ }
12762
+ });
12763
+ const ellipsoidCornersIJK = [
12764
+ fillSphere_transformWorldToIndex(segmentationImageData, topLeftWorld),
12765
+ (fillSphere_transformWorldToIndex(segmentationImageData, bottomRightWorld)),
12766
+ ];
12767
+ segmentationVoxelManager.boundsIJK = boundingBox_getBoundingBoxAroundShape(ellipsoidCornersIJK, segmentationVoxelManager.dimensions);
12768
+ imageVoxelManager.isInObject = createPointInEllipse({
12769
+ topLeftWorld,
12770
+ bottomRightWorld,
12771
+ center,
12772
+ });
12773
+ },
12774
+ };
12775
+ const SPHERE_STRATEGY = new BrushStrategy('Sphere', compositions.regionFill, compositions.setValue, sphereComposition, compositions.determineSegmentIndex, compositions.preview);
12776
+ const fillInsideSphere = SPHERE_STRATEGY.strategyFunction;
12777
+ const SPHERE_THRESHOLD_STRATEGY = new BrushStrategy('SphereThreshold', ...SPHERE_STRATEGY.compositions, compositions.dynamicThreshold, compositions.threshold, compositions.islandRemoval);
12778
+ const thresholdInsideSphere = SPHERE_THRESHOLD_STRATEGY.strategyFunction;
12779
+ function fillOutsideSphere() {
12780
+ throw new Error('fill outside sphere not implemented');
12133
12781
  }
12134
12782
 
12783
+
12784
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/eraseSphere.js
12785
+
12786
+
12787
+
12788
+ const ERASE_SPHERE_STRATEGY = new BrushStrategy('EraseSphere', compositions.erase, ...SPHERE_STRATEGY.compositions);
12789
+ const eraseInsideSphere = ERASE_SPHERE_STRATEGY.strategyFunction;
12790
+
12791
+
12135
12792
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/strategies/eraseCircle.js
12136
12793
 
12137
- function eraseInsideCircle(enabledElement, operationData) {
12138
- const eraseOperationData = {
12139
- ...operationData,
12140
- segmentIndex: 0,
12141
- };
12142
- fillInsideCircle(enabledElement, eraseOperationData);
12143
- }
12794
+
12795
+
12796
+ const ERASE_CIRCLE_STRATEGY = new BrushStrategy('EraseCircle', compositions.erase, ...CIRCLE_STRATEGY.compositions);
12797
+ const eraseInsideCircle = ERASE_CIRCLE_STRATEGY.strategyFunction;
12798
+
12144
12799
 
12145
12800
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/cursors/MouseCursor.js
12146
12801
  const DEFINED_CURSORS = Symbol('DefinedCursors');
@@ -12819,127 +13474,153 @@ class BrushTool extends base_BaseTool {
12819
13474
  THRESHOLD_INSIDE_SPHERE: thresholdInsideSphere,
12820
13475
  },
12821
13476
  strategySpecificConfiguration: {
12822
- THRESHOLD_INSIDE_CIRCLE: {
13477
+ THRESHOLD: {
12823
13478
  threshold: [-150, -70],
12824
13479
  },
12825
13480
  },
12826
13481
  defaultStrategy: 'FILL_INSIDE_CIRCLE',
12827
13482
  activeStrategy: 'FILL_INSIDE_CIRCLE',
12828
13483
  brushSize: 25,
13484
+ preview: {
13485
+ enabled: false,
13486
+ previewColors: {},
13487
+ previewTimeMs: 250,
13488
+ previewMoveDistance: 8,
13489
+ dragMoveDistance: 4,
13490
+ dragTimeMs: 500,
13491
+ },
13492
+ centerRadius: 2,
13493
+ actions: {
13494
+ [enums_StrategyCallbacks.AcceptPreview]: {
13495
+ method: enums_StrategyCallbacks.AcceptPreview,
13496
+ bindings: [
13497
+ {
13498
+ key: 'Enter',
13499
+ },
13500
+ ],
13501
+ },
13502
+ [enums_StrategyCallbacks.RejectPreview]: {
13503
+ method: enums_StrategyCallbacks.RejectPreview,
13504
+ bindings: [
13505
+ {
13506
+ key: 'Escape',
13507
+ },
13508
+ ],
13509
+ },
13510
+ },
12829
13511
  },
12830
13512
  }) {
12831
13513
  super(toolProps, defaultToolProps);
12832
- this.onSetToolPassive = () => {
13514
+ this._previewData = {
13515
+ preview: null,
13516
+ element: null,
13517
+ timerStart: 0,
13518
+ timer: null,
13519
+ startPoint: [NaN, NaN],
13520
+ isDrag: false,
13521
+ };
13522
+ this.onSetToolPassive = (evt) => {
12833
13523
  this.disableCursor();
12834
13524
  };
12835
13525
  this.onSetToolEnabled = () => {
12836
13526
  this.disableCursor();
12837
13527
  };
12838
- this.onSetToolDisabled = () => {
13528
+ this.onSetToolDisabled = (evt) => {
12839
13529
  this.disableCursor();
12840
13530
  };
12841
13531
  this.preMouseDownCallback = (evt) => {
12842
13532
  const eventData = evt.detail;
12843
13533
  const { element } = eventData;
12844
13534
  const enabledElement = (0,esm.getEnabledElement)(element);
12845
- const { viewport, renderingEngine } = enabledElement;
12846
- const toolGroupId = this.toolGroupId;
12847
- const activeSegmentationRepresentation = getActiveSegmentationRepresentation(toolGroupId);
12848
- if (!activeSegmentationRepresentation) {
12849
- throw new Error('No active segmentation detected, create one before using the brush tool');
12850
- }
12851
- const { segmentationId, type, segmentationRepresentationUID } = activeSegmentationRepresentation;
12852
- if (type === enums_SegmentationRepresentations.Contour) {
12853
- throw new Error('Not implemented yet');
12854
- }
12855
- const segmentsLocked = getLockedSegments(segmentationId);
12856
- const { representationData } = getSegmentation(segmentationId);
12857
- const labelmapData = representationData[enums_SegmentationRepresentations.Labelmap];
12858
- const viewportIdsToRender = [viewport.id];
12859
- if (isVolumeSegmentation(labelmapData)) {
12860
- const { volumeId } = representationData[type];
12861
- const actors = viewport.getActors();
12862
- const firstVolumeActorUID = actors[0].uid;
12863
- this._editData = {
12864
- volumeId,
12865
- referencedVolumeId: firstVolumeActorUID,
12866
- segmentsLocked,
12867
- segmentationRepresentationUID,
12868
- };
12869
- }
12870
- else {
12871
- const { imageIdReferenceMap } = labelmapData;
12872
- const currentImageId = viewport.getCurrentImageId();
12873
- if (!imageIdReferenceMap.get(currentImageId)) {
12874
- return;
12875
- }
12876
- if (this.configuration.activeStrategy.includes('SPHERE')) {
12877
- console.warn('Sphere manipulation is not supported for this stack of images yet');
12878
- return;
12879
- }
12880
- this._editData = {
12881
- imageIdReferenceMap,
12882
- segmentsLocked,
12883
- segmentationRepresentationUID,
12884
- };
12885
- }
13535
+ const { renderingEngine } = enabledElement;
13536
+ this._editData = this.createEditData(element);
12886
13537
  this._activateDraw(element);
12887
13538
  hideElementCursor(element);
12888
13539
  evt.preventDefault();
12889
- utilities_triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
13540
+ this._previewData.isDrag = false;
13541
+ this._previewData.timerStart = Date.now();
13542
+ utilities_triggerAnnotationRenderForViewportIds(renderingEngine, this._hoverData.viewportIdsToRender);
13543
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), enums_StrategyCallbacks.OnInteractionStart);
12890
13544
  return true;
12891
13545
  };
12892
13546
  this.mouseMoveCallback = (evt) => {
12893
13547
  if (this.mode === enums_ToolModes.Active) {
12894
13548
  this.updateCursor(evt);
13549
+ if (!this.configuration.preview.enabled) {
13550
+ return;
13551
+ }
13552
+ const { previewTimeMs, previewMoveDistance, dragMoveDistance } = this.configuration.preview;
13553
+ const { currentPoints, element } = evt.detail;
13554
+ const { canvas } = currentPoints;
13555
+ const { preview, startPoint, timer, timerStart, isDrag } = this._previewData;
13556
+ const delta = gl_matrix_esm/* vec2.distance */.K4.distance(canvas, startPoint);
13557
+ const time = Date.now() - timerStart;
13558
+ if (delta > previewMoveDistance ||
13559
+ (time > previewTimeMs && delta > dragMoveDistance)) {
13560
+ if (timer) {
13561
+ window.clearTimeout(timer);
13562
+ this._previewData.timer = null;
13563
+ }
13564
+ if (preview && !isDrag) {
13565
+ this.rejectPreview(element);
13566
+ }
13567
+ }
13568
+ if (!this._previewData.timer) {
13569
+ const timer = window.setTimeout(this.previewCallback, 250);
13570
+ Object.assign(this._previewData, {
13571
+ timerStart: Date.now(),
13572
+ timer,
13573
+ startPoint: canvas,
13574
+ element,
13575
+ });
13576
+ }
12895
13577
  }
12896
13578
  };
13579
+ this.previewCallback = () => {
13580
+ if (this._previewData.preview) {
13581
+ return;
13582
+ }
13583
+ this._previewData.timer = null;
13584
+ this._previewData.preview = this.applyActiveStrategyCallback((0,esm.getEnabledElement)(this._previewData.element), this.getOperationData(this._previewData.element), enums_StrategyCallbacks.Preview);
13585
+ };
12897
13586
  this._dragCallback = (evt) => {
12898
13587
  const eventData = evt.detail;
12899
- const { element } = eventData;
13588
+ const { element, currentPoints } = eventData;
12900
13589
  const enabledElement = (0,esm.getEnabledElement)(element);
12901
13590
  const { renderingEngine } = enabledElement;
12902
13591
  this.updateCursor(evt);
12903
- const { segmentIndex, segmentationId, segmentationRepresentationUID, brushCursor, viewportIdsToRender, } = this._hoverData;
12904
- const { data } = brushCursor;
12905
- const { viewPlaneNormal, viewUp } = brushCursor.metadata;
13592
+ const { viewportIdsToRender } = this._hoverData;
12906
13593
  utilities_triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
12907
- const operationData = {
12908
- ...this._editData,
12909
- points: data.handles.points,
12910
- segmentIndex,
12911
- viewPlaneNormal,
12912
- toolGroupId: this.toolGroupId,
12913
- segmentationId,
12914
- segmentationRepresentationUID,
12915
- viewUp,
12916
- strategySpecificConfiguration: this.configuration.strategySpecificConfiguration,
12917
- };
12918
- this.applyActiveStrategy(enabledElement, operationData);
13594
+ const delta = gl_matrix_esm/* vec2.distance */.K4.distance(currentPoints.canvas, this._previewData.startPoint);
13595
+ const { dragTimeMs, dragMoveDistance } = this.configuration.preview;
13596
+ if (!this._previewData.isDrag &&
13597
+ this._previewData.preview &&
13598
+ Date.now() - this._previewData.timerStart < dragTimeMs &&
13599
+ delta < dragMoveDistance) {
13600
+ return;
13601
+ }
13602
+ this._previewData.preview = this.applyActiveStrategy(enabledElement, this.getOperationData());
13603
+ this._previewData.element = element;
13604
+ this._previewData.timerStart = Date.now() + dragTimeMs;
13605
+ this._previewData.isDrag = true;
13606
+ this._previewData.startPoint = currentPoints.canvas;
12919
13607
  };
12920
13608
  this._endCallback = (evt) => {
12921
13609
  const eventData = evt.detail;
12922
13610
  const { element } = eventData;
12923
- const { segmentIndex, segmentationId, segmentationRepresentationUID, brushCursor, } = this._hoverData;
12924
- const { data } = brushCursor;
12925
- const { viewPlaneNormal, viewUp } = brushCursor.metadata;
13611
+ const enabledElement = (0,esm.getEnabledElement)(element);
13612
+ const operationData = this.getOperationData(element);
13613
+ if (!this._previewData.preview && !this._previewData.isDrag) {
13614
+ this.applyActiveStrategy(enabledElement, operationData);
13615
+ }
12926
13616
  this._deactivateDraw(element);
12927
13617
  resetElementCursor(element);
12928
- const enabledElement = (0,esm.getEnabledElement)(element);
12929
13618
  this.updateCursor(evt);
12930
- const operationData = {
12931
- points: data.handles.points,
12932
- ...this._editData,
12933
- segmentIndex,
12934
- viewPlaneNormal,
12935
- toolGroupId: this.toolGroupId,
12936
- segmentationId,
12937
- segmentationRepresentationUID,
12938
- viewUp,
12939
- strategySpecificConfiguration: this.configuration.strategySpecificConfiguration,
12940
- };
12941
13619
  this._editData = null;
12942
- this.applyActiveStrategy(enabledElement, operationData);
13620
+ this.applyActiveStrategyCallback(enabledElement, operationData, enums_StrategyCallbacks.OnInteractionEnd);
13621
+ if (!this._previewData.isDrag) {
13622
+ this.acceptPreview(element);
13623
+ }
12943
13624
  };
12944
13625
  this._activateDraw = (element) => {
12945
13626
  element.addEventListener(enums_Events.MOUSE_UP, this._endCallback);
@@ -12954,14 +13635,55 @@ class BrushTool extends base_BaseTool {
12954
13635
  }
12955
13636
  disableCursor() {
12956
13637
  this._hoverData = undefined;
13638
+ this.rejectPreview();
12957
13639
  }
12958
- updateCursor(evt) {
12959
- const eventData = evt.detail;
12960
- const { element } = eventData;
12961
- const { currentPoints } = eventData;
12962
- const centerCanvas = currentPoints.canvas;
13640
+ createEditData(element) {
12963
13641
  const enabledElement = (0,esm.getEnabledElement)(element);
12964
- const { renderingEngine, viewport } = enabledElement;
13642
+ const { viewport, renderingEngine } = enabledElement;
13643
+ const toolGroupId = this.toolGroupId;
13644
+ const activeSegmentationRepresentation = getActiveSegmentationRepresentation(toolGroupId);
13645
+ if (!activeSegmentationRepresentation) {
13646
+ throw new Error('No active segmentation detected, create one before using the brush tool');
13647
+ }
13648
+ const { segmentationId, type, segmentationRepresentationUID } = activeSegmentationRepresentation;
13649
+ if (type === enums_SegmentationRepresentations.Contour) {
13650
+ throw new Error('Not implemented yet');
13651
+ }
13652
+ const segmentsLocked = getLockedSegments(segmentationId);
13653
+ const { representationData } = getSegmentation(segmentationId);
13654
+ const labelmapData = representationData[enums_SegmentationRepresentations.Labelmap];
13655
+ const viewportIdsToRender = [viewport.id];
13656
+ if (isVolumeSegmentation(labelmapData)) {
13657
+ const { volumeId } = representationData[type];
13658
+ const actors = viewport.getActors();
13659
+ const firstVolumeActorUID = actors[0].uid;
13660
+ return {
13661
+ volumeId,
13662
+ referencedVolumeId: firstVolumeActorUID,
13663
+ segmentsLocked,
13664
+ segmentationRepresentationUID,
13665
+ };
13666
+ }
13667
+ else {
13668
+ const { imageIdReferenceMap } = labelmapData;
13669
+ const currentImageId = viewport.getCurrentImageId();
13670
+ if (!imageIdReferenceMap.get(currentImageId)) {
13671
+ return;
13672
+ }
13673
+ if (this.configuration.activeStrategy.includes('SPHERE')) {
13674
+ console.warn('Sphere manipulation is not supported for this stack of images yet');
13675
+ return;
13676
+ }
13677
+ return {
13678
+ imageIdReferenceMap,
13679
+ segmentsLocked,
13680
+ segmentationRepresentationUID,
13681
+ };
13682
+ }
13683
+ }
13684
+ createHoverData(element, centerCanvas) {
13685
+ const enabledElement = (0,esm.getEnabledElement)(element);
13686
+ const { viewport } = enabledElement;
12965
13687
  const camera = viewport.getCamera();
12966
13688
  const { viewPlaneNormal, viewUp } = camera;
12967
13689
  const toolGroupId = this.toolGroupId;
@@ -12985,7 +13707,7 @@ class BrushTool extends base_BaseTool {
12985
13707
  },
12986
13708
  data: {},
12987
13709
  };
12988
- this._hoverData = {
13710
+ return {
12989
13711
  brushCursor,
12990
13712
  centerCanvas,
12991
13713
  segmentIndex,
@@ -12994,8 +13716,37 @@ class BrushTool extends base_BaseTool {
12994
13716
  segmentColor,
12995
13717
  viewportIdsToRender,
12996
13718
  };
13719
+ }
13720
+ updateCursor(evt) {
13721
+ const eventData = evt.detail;
13722
+ const { element } = eventData;
13723
+ const { currentPoints } = eventData;
13724
+ const centerCanvas = currentPoints.canvas;
13725
+ this._hoverData = this.createHoverData(element, centerCanvas);
12997
13726
  this._calculateCursor(element, centerCanvas);
12998
- utilities_triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
13727
+ utilities_triggerAnnotationRenderForViewportIds((0,esm.getEnabledElement)(element).renderingEngine, this._hoverData.viewportIdsToRender);
13728
+ }
13729
+ getOperationData(element) {
13730
+ const editData = this._editData || this.createEditData(element);
13731
+ const { segmentIndex, segmentationId, segmentationRepresentationUID, brushCursor, } = this._hoverData || this.createHoverData(element);
13732
+ const { data, metadata = {} } = brushCursor || {};
13733
+ const { viewPlaneNormal, viewUp } = metadata;
13734
+ const operationData = {
13735
+ ...editData,
13736
+ points: data?.handles?.points,
13737
+ segmentIndex,
13738
+ previewColors: this.configuration.preview.enabled
13739
+ ? this.configuration.preview.previewColors
13740
+ : null,
13741
+ viewPlaneNormal,
13742
+ toolGroupId: this.toolGroupId,
13743
+ segmentationId,
13744
+ segmentationRepresentationUID,
13745
+ viewUp,
13746
+ strategySpecificConfiguration: this.configuration.strategySpecificConfiguration,
13747
+ preview: this._previewData?.preview,
13748
+ };
13749
+ return operationData;
12999
13750
  }
13000
13751
  _calculateCursor(element, centerCanvas) {
13001
13752
  const enabledElement = (0,esm.getEnabledElement)(element);
@@ -13034,6 +13785,24 @@ class BrushTool extends base_BaseTool {
13034
13785
  ];
13035
13786
  data.invalidated = false;
13036
13787
  }
13788
+ rejectPreview(element = this._previewData.element) {
13789
+ if (!element || !this._previewData.preview) {
13790
+ return;
13791
+ }
13792
+ const enabledElement = (0,esm.getEnabledElement)(element);
13793
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), enums_StrategyCallbacks.RejectPreview);
13794
+ this._previewData.preview = null;
13795
+ this._previewData.isDrag = false;
13796
+ }
13797
+ acceptPreview(element = this._previewData.element) {
13798
+ if (!element) {
13799
+ return;
13800
+ }
13801
+ const enabledElement = (0,esm.getEnabledElement)(element);
13802
+ this.applyActiveStrategyCallback(enabledElement, this.getOperationData(element), enums_StrategyCallbacks.AcceptPreview);
13803
+ this._previewData.isDrag = false;
13804
+ this._previewData.preview = null;
13805
+ }
13037
13806
  invalidateBrushCursor() {
13038
13807
  if (this._hoverData !== undefined) {
13039
13808
  const { data } = this._hoverData.brushCursor;
@@ -13076,6 +13845,13 @@ class BrushTool extends base_BaseTool {
13076
13845
  drawingSvg_drawCircle(svgDrawingHelper, annotationUID, circleUID, center, radius, {
13077
13846
  color,
13078
13847
  });
13848
+ const { centerRadius } = this.configuration;
13849
+ if (centerRadius >= 0) {
13850
+ const circleUID1 = '1';
13851
+ drawingSvg_drawCircle(svgDrawingHelper, annotationUID, circleUID1, center, 2, {
13852
+ color,
13853
+ });
13854
+ }
13079
13855
  }
13080
13856
  }
13081
13857
  BrushTool.toolName = 'Brush';
@@ -21536,8 +22312,7 @@ class EllipticalROITool extends base_AnnotationTool {
21536
22312
  const color = this.getStyle('color', styleSpecifier, annotation);
21537
22313
  const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
21538
22314
  const rotation = Math.abs(viewport.getRotation() - (data.initialRotation || 0));
21539
- let canvasCorners;
21540
- canvasCorners = (getCanvasEllipseCorners(canvasCoordinates));
22315
+ const canvasCorners = (getCanvasEllipseCorners(canvasCoordinates));
21541
22316
  const { centerPointRadius } = this.configuration;
21542
22317
  if (!data.cachedStats[targetId] ||
21543
22318
  data.cachedStats[targetId].areaUnit == null) {
@@ -27406,7 +28181,7 @@ KeyImageTool.toolName = 'KeyImage';
27406
28181
 
27407
28182
  const { transformWorldToIndex: fillRectangle_transformWorldToIndex } = esm.utilities;
27408
28183
  function fillRectangle(enabledElement, operationData, inside = true) {
27409
- const { points, segmentsLocked, segmentIndex, segmentationId, constraintFn } = operationData;
28184
+ const { points, segmentsLocked, segmentIndex, segmentationId } = operationData;
27410
28185
  const strategyData = getStrategyData({
27411
28186
  operationData,
27412
28187
  viewport: enabledElement.viewport,
@@ -27426,17 +28201,11 @@ function fillRectangle(enabledElement, operationData, inside = true) {
27426
28201
  });
27427
28202
  const boundsIJK = boundingBox_getBoundingBoxAroundShape(rectangleCornersIJK, segmentationImageData.getDimensions());
27428
28203
  const pointInRectangle = () => true;
27429
- const callback = ({ value, index, pointIJK }) => {
28204
+ const callback = ({ value, index }) => {
27430
28205
  if (segmentsLocked.includes(value)) {
27431
28206
  return;
27432
28207
  }
27433
- if (!constraintFn) {
27434
- segmentationScalarData[index] = segmentIndex;
27435
- return;
27436
- }
27437
- if (constraintFn(pointIJK)) {
27438
- segmentationScalarData[index] = segmentIndex;
27439
- }
28208
+ segmentationScalarData[index] = segmentIndex;
27440
28209
  };
27441
28210
  pointInShapeCallback(segmentationImageData, pointInRectangle, callback, boundsIJK);
27442
28211
  triggerSegmentationDataModified(segmentationId);
@@ -27696,12 +28465,14 @@ RectangleScissorsTool.toolName = 'RectangleScissor';
27696
28465
 
27697
28466
 
27698
28467
 
28468
+
27699
28469
  class CircleScissorsTool extends base_BaseTool {
27700
28470
  constructor(toolProps = {}, defaultToolProps = {
27701
28471
  supportedInteractionTypes: ['Mouse', 'Touch'],
27702
28472
  configuration: {
27703
28473
  strategies: {
27704
28474
  FILL_INSIDE: fillInsideCircle,
28475
+ ERASE_INSIDE: eraseInsideCircle,
27705
28476
  },
27706
28477
  defaultStrategy: 'FILL_INSIDE',
27707
28478
  activeStrategy: 'FILL_INSIDE',
@@ -27844,6 +28615,7 @@ class CircleScissorsTool extends base_BaseTool {
27844
28615
  points: data.handles.points,
27845
28616
  viewPlaneNormal,
27846
28617
  viewUp,
28618
+ strategySpecificConfiguration: {},
27847
28619
  };
27848
28620
  this.editData = null;
27849
28621
  this.isDrawing = false;
@@ -27916,12 +28688,14 @@ CircleScissorsTool.toolName = 'CircleScissor';
27916
28688
 
27917
28689
 
27918
28690
 
28691
+
27919
28692
  class SphereScissorsTool extends base_BaseTool {
27920
28693
  constructor(toolProps = {}, defaultToolProps = {
27921
28694
  supportedInteractionTypes: ['Mouse', 'Touch'],
27922
28695
  configuration: {
27923
28696
  strategies: {
27924
28697
  FILL_INSIDE: fillInsideSphere,
28698
+ ERASE_INSIDE: eraseInsideSphere,
27925
28699
  },
27926
28700
  defaultStrategy: 'FILL_INSIDE',
27927
28701
  activeStrategy: 'FILL_INSIDE',
@@ -27973,6 +28747,7 @@ class SphereScissorsTool extends base_BaseTool {
27973
28747
  centerCanvas: canvasPos,
27974
28748
  segmentationRepresentationUID,
27975
28749
  segmentIndex,
28750
+ segmentationId,
27976
28751
  segmentsLocked,
27977
28752
  segmentColor,
27978
28753
  toolGroupId,
@@ -28522,136 +29297,6 @@ class RectangleROIStartEndThresholdTool extends annotation_RectangleROITool {
28522
29297
  RectangleROIStartEndThresholdTool.toolName = 'RectangleROIStartEndThreshold';
28523
29298
  /* harmony default export */ const segmentation_RectangleROIStartEndThresholdTool = (RectangleROIStartEndThresholdTool);
28524
29299
 
28525
- ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/segmentation/floodFill.js
28526
- function floodFill(getter, seed, options = {}) {
28527
- const onFlood = options.onFlood;
28528
- const onBoundary = options.onBoundary;
28529
- const equals = options.equals || defaultEquals;
28530
- const diagonals = options.diagonals || false;
28531
- const startNode = get(seed);
28532
- const permutations = prunedPermutations();
28533
- const stack = [];
28534
- const flooded = [];
28535
- const visits = {};
28536
- const bounds = {};
28537
- stack.push({ currentArgs: seed });
28538
- while (stack.length > 0) {
28539
- flood(stack.pop());
28540
- }
28541
- return {
28542
- flooded,
28543
- boundaries: boundaries(),
28544
- };
28545
- function flood(job) {
28546
- const getArgs = job.currentArgs;
28547
- const prevArgs = job.previousArgs;
28548
- if (visited(getArgs)) {
28549
- return;
28550
- }
28551
- markAsVisited(getArgs);
28552
- if (member(getArgs)) {
28553
- markAsFlooded(getArgs);
28554
- pushAdjacent(getArgs);
28555
- }
28556
- else {
28557
- markAsBoundary(prevArgs);
28558
- }
28559
- }
28560
- function visited(key) {
28561
- return visits[key] === true;
28562
- }
28563
- function markAsVisited(key) {
28564
- visits[key] = true;
28565
- }
28566
- function member(getArgs) {
28567
- const node = safely(get, [getArgs]);
28568
- return safely(equals, [node, startNode]);
28569
- }
28570
- function markAsFlooded(getArgs) {
28571
- flooded.push(getArgs);
28572
- if (onFlood) {
28573
- onFlood(...getArgs);
28574
- }
28575
- }
28576
- function markAsBoundary(prevArgs) {
28577
- bounds[prevArgs] = prevArgs;
28578
- if (onBoundary) {
28579
- onBoundary(...prevArgs);
28580
- }
28581
- }
28582
- function pushAdjacent(getArgs) {
28583
- for (let i = 0; i < permutations.length; i += 1) {
28584
- const perm = permutations[i];
28585
- const nextArgs = getArgs.slice(0);
28586
- for (let j = 0; j < getArgs.length; j += 1) {
28587
- nextArgs[j] += perm[j];
28588
- }
28589
- stack.push({
28590
- currentArgs: nextArgs,
28591
- previousArgs: getArgs,
28592
- });
28593
- }
28594
- }
28595
- function get(getArgs) {
28596
- return getter(...getArgs);
28597
- }
28598
- function safely(f, args) {
28599
- try {
28600
- return f(...args);
28601
- }
28602
- catch (error) {
28603
- return;
28604
- }
28605
- }
28606
- function prunedPermutations() {
28607
- const permutations = permute(seed.length);
28608
- return permutations.filter(function (perm) {
28609
- const count = countNonZeroes(perm);
28610
- return count !== 0 && (count === 1 || diagonals);
28611
- });
28612
- }
28613
- function permute(length) {
28614
- const perms = [];
28615
- const permutation = function (string) {
28616
- return string.split('').map(function (c) {
28617
- return parseInt(c, 10) - 1;
28618
- });
28619
- };
28620
- for (let i = 0; i < Math.pow(3, length); i += 1) {
28621
- const string = lpad(i.toString(3), '0', length);
28622
- perms.push(permutation(string));
28623
- }
28624
- return perms;
28625
- }
28626
- function boundaries() {
28627
- const array = [];
28628
- for (const key in bounds) {
28629
- if (bounds[key] !== undefined) {
28630
- array.unshift(bounds[key]);
28631
- }
28632
- }
28633
- return array;
28634
- }
28635
- }
28636
- function defaultEquals(a, b) {
28637
- return a === b;
28638
- }
28639
- function countNonZeroes(array) {
28640
- let count = 0;
28641
- for (let i = 0; i < array.length; i += 1) {
28642
- if (array[i] !== 0) {
28643
- count += 1;
28644
- }
28645
- }
28646
- return count;
28647
- }
28648
- function lpad(string, character, length) {
28649
- const array = new Array(length + 1);
28650
- const pad = array.join(character);
28651
- return (pad + string).slice(-length);
28652
- }
28653
- /* harmony default export */ const segmentation_floodFill = (floodFill);
28654
-
28655
29300
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/segmentation/PaintFillTool.js
28656
29301
 
28657
29302
 
@@ -34380,15 +35025,21 @@ function getBrushSizeForToolGroup(toolGroupId, toolName) {
34380
35025
 
34381
35026
 
34382
35027
 
34383
- function setBrushThresholdForToolGroup(toolGroupId, threshold) {
35028
+ function setBrushThresholdForToolGroup(toolGroupId, threshold, otherArgs = { isDynamic: false }) {
34384
35029
  const toolGroup = ToolGroupManager_getToolGroup(toolGroupId);
34385
35030
  if (toolGroup === undefined) {
34386
35031
  return;
34387
35032
  }
34388
35033
  const brushBasedToolInstances = getBrushToolInstances(toolGroupId);
35034
+ const configuration = {
35035
+ ...otherArgs,
35036
+ ...(threshold !== undefined && { threshold }),
35037
+ };
34389
35038
  brushBasedToolInstances.forEach((tool) => {
34390
- tool.configuration.strategySpecificConfiguration.THRESHOLD_INSIDE_CIRCLE.threshold =
34391
- threshold;
35039
+ tool.configuration.strategySpecificConfiguration.THRESHOLD = {
35040
+ ...tool.configuration.strategySpecificConfiguration.THRESHOLD,
35041
+ ...configuration,
35042
+ };
34392
35043
  });
34393
35044
  const viewportsInfo = toolGroup.getViewportsInfo();
34394
35045
  if (!viewportsInfo.length) {
@@ -34413,8 +35064,8 @@ function getBrushThresholdForToolGroup(toolGroupId) {
34413
35064
  if (!brushToolInstance) {
34414
35065
  return;
34415
35066
  }
34416
- return brushToolInstance.configuration.strategySpecificConfiguration
34417
- .THRESHOLD_INSIDE_CIRCLE.threshold;
35067
+ return brushToolInstance.configuration.strategySpecificConfiguration.THRESHOLD
35068
+ .threshold;
34418
35069
  }
34419
35070
 
34420
35071
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/segmentation/thresholdSegmentationByRange.js
@@ -37187,28 +37838,71 @@ function getActiveToolForKeyboardEvent(evt) {
37187
37838
  for (let j = 0; j < toolGroupToolNames.length; j++) {
37188
37839
  const toolName = toolGroupToolNames[j];
37189
37840
  const toolOptions = toolGroup.toolOptions[toolName];
37841
+ if (toolOptions.mode !== getActiveToolForKeyboardEvent_Active) {
37842
+ continue;
37843
+ }
37190
37844
  const correctBinding = toolOptions.bindings.length &&
37191
37845
  toolOptions.bindings.some((binding) => binding.mouseButton === (mouseButton ?? defaultMousePrimary) &&
37192
37846
  binding.modifierKey === modifierKey);
37193
- if (toolOptions.mode === getActiveToolForKeyboardEvent_Active && correctBinding) {
37847
+ if (correctBinding) {
37194
37848
  return toolGroup.getToolInstance(toolName);
37195
37849
  }
37196
37850
  }
37197
37851
  }
37198
37852
 
37853
+ ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/eventDispatchers/shared/getToolsWithActionsForKeyboardEvents.js
37854
+
37855
+ function getToolsWithModesForKeyboardEvent(evt, toolModes) {
37856
+ const toolsWithActions = new Map();
37857
+ const { renderingEngineId, viewportId } = evt.detail;
37858
+ const toolGroup = ToolGroupManager_getToolGroupForViewport(viewportId, renderingEngineId);
37859
+ if (!toolGroup) {
37860
+ return toolsWithActions;
37861
+ }
37862
+ const toolGroupToolNames = Object.keys(toolGroup.toolOptions);
37863
+ const key = evt.detail.key;
37864
+ for (let j = 0; j < toolGroupToolNames.length; j++) {
37865
+ const toolName = toolGroupToolNames[j];
37866
+ const tool = toolGroup.getToolInstance(toolName);
37867
+ const actionsConfig = tool.configuration?.actions;
37868
+ if (!actionsConfig) {
37869
+ continue;
37870
+ }
37871
+ const actions = Object.values(actionsConfig);
37872
+ if (!actions?.length || !toolModes.includes(tool.mode)) {
37873
+ continue;
37874
+ }
37875
+ const action = actions.find((action) => action.bindings.some((binding) => binding.key === key));
37876
+ if (action) {
37877
+ toolsWithActions.set(tool, action);
37878
+ }
37879
+ }
37880
+ return toolsWithActions;
37881
+ }
37882
+
37199
37883
  ;// CONCATENATED MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/eventDispatchers/keyboardEventHandlers/keyDown.js
37200
37884
 
37201
37885
 
37886
+
37887
+
37202
37888
  function keyDown(evt) {
37203
37889
  const activeTool = getActiveToolForKeyboardEvent(evt);
37204
- if (!activeTool) {
37205
- return;
37890
+ if (activeTool) {
37891
+ const { renderingEngineId, viewportId } = evt.detail;
37892
+ const toolGroup = ToolGroupManager_getToolGroupForViewport(viewportId, renderingEngineId);
37893
+ const toolName = activeTool.getToolName();
37894
+ if (Object.keys(toolGroup.toolOptions).includes(toolName)) {
37895
+ toolGroup.setViewportsCursorByToolName(toolName);
37896
+ }
37206
37897
  }
37207
- const { renderingEngineId, viewportId } = evt.detail;
37208
- const toolGroup = ToolGroupManager_getToolGroupForViewport(viewportId, renderingEngineId);
37209
- const toolName = activeTool.getToolName();
37210
- if (Object.keys(toolGroup.toolOptions).includes(toolName)) {
37211
- toolGroup.setViewportsCursorByToolName(toolName);
37898
+ const activeToolsWithEventBinding = getToolsWithModesForKeyboardEvent(evt, [
37899
+ enums_ToolModes.Active,
37900
+ ]);
37901
+ if (activeToolsWithEventBinding?.size) {
37902
+ const { element } = evt.detail;
37903
+ for (const [key, value] of [...activeToolsWithEventBinding.entries()]) {
37904
+ key[value.method](element);
37905
+ }
37212
37906
  }
37213
37907
  }
37214
37908