@ohif/app 3.13.0-beta.63 → 3.13.0-beta.65

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 (33) hide show
  1. package/dist/{2851.bundle.82a96cdcc6fc18c73030.js → 2851.bundle.ffc5656f20a4159d591d.js} +12 -5
  2. package/dist/{7166.bundle.775a8ac234701c028acf.js → 7166.bundle.bd50b3917b5ee6166971.js} +134 -7
  3. package/dist/{7537.bundle.1726a7f7a4c378296085.js → 7537.bundle.889ba5f2707418c6fd88.js} +1 -1
  4. package/dist/{9039.bundle.7afa93b103c3b26d4855.js → 9039.bundle.f72736f47fedeff521e2.js} +123 -47
  5. package/dist/{9205.bundle.315c3b56464a7590235a.js → 9205.bundle.ed7bce8436a7a431955e.js} +122 -47
  6. package/dist/{9567.bundle.be350438bed4e656f278.js → 9567.bundle.ff782480a4c66e306027.js} +438 -85
  7. package/dist/{app.bundle.ea477c22ff095b97d6a0.js → app.bundle.9e45525b479dad4d8113.js} +8 -3
  8. package/dist/{compute.bundle.a41ec0ba4f935200ab93.js → compute.bundle.b7c2ea55f1a69f4a736b.js} +1 -1
  9. package/dist/index.html +1 -1
  10. package/dist/{polySeg.bundle.be57af5b834dd833a418.js → polySeg.bundle.e1f6f05d81ea1352bef3.js} +1 -1
  11. package/dist/sw.js +1 -1
  12. package/package.json +21 -21
  13. /package/dist/{1459.bundle.b6eb8878f677bf92be9f.js → 1459.bundle.b76252d4cbc3588eba65.js} +0 -0
  14. /package/dist/{1933.bundle.727252ef4ef9ee3200b7.js → 1933.bundle.10e823bd588169da5894.js} +0 -0
  15. /package/dist/{2018.bundle.ecd9564ec338f828ceed.js → 2018.bundle.a2960b28da742a90207e.js} +0 -0
  16. /package/dist/{213.bundle.4eef2eee1a2d128ae809.js → 213.bundle.33ca5d29734d9e99a676.js} +0 -0
  17. /package/dist/{2424.bundle.2fd7e2572807b314ea54.js → 2424.bundle.31d8e6bdf23d51886680.js} +0 -0
  18. /package/dist/{3138.bundle.e58b8a8dc3733e27fcb5.js → 3138.bundle.2fd53c9e63b1aea321ac.js} +0 -0
  19. /package/dist/{3461.bundle.c9f965b0ecc3e76030a1.js → 3461.bundle.b50d8125ecc168f22da3.js} +0 -0
  20. /package/dist/{4507.bundle.b3e80ce6bbb20bdf43d5.js → 4507.bundle.061dfcf4609ef7aa8ede.js} +0 -0
  21. /package/dist/{4819.bundle.9e663daa60622566dc01.js → 4819.bundle.ac518de1987ad93304c8.js} +0 -0
  22. /package/dist/{5015.bundle.45c90a114408bed47e06.js → 5015.bundle.46f8b754a318286c18ad.js} +0 -0
  23. /package/dist/{5028.bundle.03fefb86628d2b93d535.js → 5028.bundle.608de6dde0d0af9e2b3e.js} +0 -0
  24. /package/dist/{5457.bundle.4e46bd724396818ecbf8.js → 5457.bundle.449b35dfd1134c977985.js} +0 -0
  25. /package/dist/{5485.bundle.274b8b176f3763a5f3b4.js → 5485.bundle.c59e61ecef95882924d1.js} +0 -0
  26. /package/dist/{6027.bundle.b6d8247b432dde4707ab.js → 6027.bundle.ea6f6e5bbb336cdb2796.js} +0 -0
  27. /package/dist/{7639.bundle.a71fb464ab990cae6fa8.js → 7639.bundle.04596df767fc6b0003a3.js} +0 -0
  28. /package/dist/{8305.bundle.063949071f42e6c9e286.js → 8305.bundle.a9764cd29cfa5bc6fd79.js} +0 -0
  29. /package/dist/{8499.bundle.eb055feb83a541941371.js → 8499.bundle.4a7f127900cf03af4e49.js} +0 -0
  30. /package/dist/{85.bundle.c41b0b4c4ed19791ce23.js → 85.bundle.e122f01517ddea1e3af0.js} +0 -0
  31. /package/dist/{8558.bundle.e212dfb2a24db4516420.js → 8558.bundle.522dbc153f443298deaa.js} +0 -0
  32. /package/dist/{8583.bundle.1fbf8dfd991f207857af.js → 8583.bundle.bd1d92122c5ebfb867fc.js} +0 -0
  33. /package/dist/{9927.bundle.827f6df9ac73bb635517.js → 9927.bundle.21cdba4cf5309feb8b7d.js} +0 -0
@@ -7329,8 +7329,14 @@ function configureViewportForLayerAddition(params) {
7329
7329
 
7330
7330
  // If a viewport type was already set do not reset it.
7331
7331
  if (!viewport.viewportOptions.viewportType) {
7332
- // Special handling for overlay display sets
7333
- if (requestedLayerDisplaySet.isOverlayDisplaySet) {
7332
+ // If the live Cornerstone viewport is already orthographic (volume), keep it as
7333
+ // 'volume'. Prevents accidentally downgrading a volume viewport to 'stack' when
7334
+ // viewportOptions arrives without a viewportType (e.g. from the HP overlay path).
7335
+ const csViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
7336
+ if (csViewport?.type === 'orthographic') {
7337
+ viewport.viewportOptions.viewportType = 'volume';
7338
+ // Special handling for overlay display sets
7339
+ } else if (requestedLayerDisplaySet.isOverlayDisplaySet) {
7334
7340
  // Do not force volume for SEG and RTSTRUCT if it and all the current display sets are for the same display set
7335
7341
  const isSameDisplaySet = currentDisplaySetUIDs.every(uid => {
7336
7342
  const currentDisplaySet = displaySetService.getDisplaySetByUID(uid);
@@ -7386,7 +7392,8 @@ function configureViewportForLayerRemoval(params) {
7386
7392
  if (!viewport.viewportOptions) {
7387
7393
  viewport.viewportOptions = {};
7388
7394
  }
7389
- viewport.viewportOptions.viewportType = 'volume';
7395
+ const csViewportOrthographic = cornerstoneViewportService.getCornerstoneViewport(viewportId)?.type === 'orthographic';
7396
+ viewport.viewportOptions.viewportType = csViewportOrthographic ? 'volume' : 'stack';
7390
7397
 
7391
7398
  // orientation
7392
7399
  if (!viewport.viewportOptions.orientation) {
@@ -10607,8 +10614,8 @@ function AboutModalDefault() {
10607
10614
  name
10608
10615
  } = (0,browser_detect_es5/* default */.A)();
10609
10616
  const browser = `${name[0].toUpperCase()}${name.substr(1)} ${version}`;
10610
- const versionNumber = "3.13.0-beta.63";
10611
- const commitHash = "f3cca21e49729fbf4bab85aa1de64b9dcfebd0ce";
10617
+ const versionNumber = "3.13.0-beta.65";
10618
+ const commitHash = "62620afb9b7d8d0302584f125704509d65ae6a2d";
10612
10619
  const [main, beta] = versionNumber.split('-');
10613
10620
  return /*#__PURE__*/react.createElement(ui_next_src/* AboutModal */.VTU, {
10614
10621
  className: "w-[400px]"
@@ -9950,6 +9950,51 @@ function generateSegmentationCSVReport(segmentationData, info) {
9950
9950
  });
9951
9951
  }
9952
9952
  ;// ../../../extensions/cornerstone/src/utils/hydrationUtils.ts
9953
+ /**
9954
+ * After SEG hydration we must refresh every viewport that shows the referenced volume so
9955
+ * presentations (including segmentation) apply to all MPR/3D tiles. Hanging-protocol matching
9956
+ * can return only the active viewport when protocol definitions omit viewportId (e.g. 3D four-up)
9957
+ * or when layout state diverges from the protocol; this merges in all grid panes that already
9958
+ * list that volume in `displaySetInstanceUIDs`.
9959
+ *
9960
+ * Only exact displaySetInstanceUID matches are used (no Frame-of-Reference inference): sibling
9961
+ * MPR planes must already share the same referenced volume UID in grid state, or HP matching
9962
+ * must list them; otherwise forcing a different UID onto a volume viewport can leave it blank.
9963
+ */
9964
+ function mergeVolumeSharingViewports(hangingProtocolUpdates, volumeUid, viewports) {
9965
+ if (!volumeUid) {
9966
+ return hangingProtocolUpdates ?? [];
9967
+ }
9968
+ const byId = new Map();
9969
+ const add = (viewportId, uids) => {
9970
+ if (!viewportId) {
9971
+ return;
9972
+ }
9973
+ byId.set(viewportId, {
9974
+ viewportId,
9975
+ displaySetInstanceUIDs: uids
9976
+ });
9977
+ };
9978
+ if (Array.isArray(hangingProtocolUpdates)) {
9979
+ for (const entry of hangingProtocolUpdates) {
9980
+ const vid = entry.viewportId ?? entry.viewportOptions?.viewportId;
9981
+ if (vid) {
9982
+ add(vid, entry.displaySetInstanceUIDs?.length ? entry.displaySetInstanceUIDs : [volumeUid]);
9983
+ }
9984
+ }
9985
+ }
9986
+ viewports.forEach(vp => {
9987
+ const uids = vp.displaySetInstanceUIDs || [];
9988
+ if (uids.includes(volumeUid)) {
9989
+ add(vp.viewportId, [volumeUid]);
9990
+ }
9991
+ });
9992
+ const merged = Array.from(byId.values());
9993
+ if (merged.length === 0 && Array.isArray(hangingProtocolUpdates) && hangingProtocolUpdates.length > 0) {
9994
+ return hangingProtocolUpdates;
9995
+ }
9996
+ return merged;
9997
+ }
9953
9998
  function getUpdatedViewportsForSegmentation({
9954
9999
  viewportId,
9955
10000
  servicesManager,
@@ -9960,7 +10005,8 @@ function getUpdatedViewportsForSegmentation({
9960
10005
  viewportGridService
9961
10006
  } = servicesManager.services;
9962
10007
  const {
9963
- isHangingProtocolLayout
10008
+ isHangingProtocolLayout,
10009
+ viewports
9964
10010
  } = viewportGridService.getState();
9965
10011
  const viewport = getTargetViewport({
9966
10012
  viewportId,
@@ -9968,7 +10014,10 @@ function getUpdatedViewportsForSegmentation({
9968
10014
  });
9969
10015
  const targetViewportId = viewport.viewportOptions.viewportId;
9970
10016
  const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(targetViewportId, displaySetInstanceUIDs[0], isHangingProtocolLayout);
9971
- return updatedViewports;
10017
+ if (updatedViewports == null) {
10018
+ return updatedViewports;
10019
+ }
10020
+ return mergeVolumeSharingViewports(updatedViewports, displaySetInstanceUIDs[0], viewports);
9972
10021
  }
9973
10022
  const getTargetViewport = ({
9974
10023
  viewportId,
@@ -12572,6 +12621,15 @@ function commandsModule({
12572
12621
  servicesManager,
12573
12622
  displaySetInstanceUIDs
12574
12623
  });
12624
+ if (!updatedViewports?.length) {
12625
+ return;
12626
+ }
12627
+ updatedViewports.forEach(({
12628
+ viewportId: csViewportId
12629
+ }) => {
12630
+ const csViewport = cornerstoneViewportService.getCornerstoneViewport(csViewportId);
12631
+ csViewport?.setNeedsRender?.();
12632
+ });
12575
12633
  actions.setDisplaySetsForViewports({
12576
12634
  viewportsToUpdate: updatedViewports.map(viewport => ({
12577
12635
  viewportId: viewport.viewportId,
@@ -21503,6 +21561,32 @@ const CornerstoneViewportService_EVENTS = {
21503
21561
  };
21504
21562
  const MIN_STACK_VIEWPORTS_TO_ENQUEUE_RESIZE = 12;
21505
21563
  const MIN_VOLUME_VIEWPORTS_TO_ENQUEUE_RESIZE = 6;
21564
+ function getVolumeActorReferencedIds(viewport) {
21565
+ const actors = viewport.getActors?.() ?? [];
21566
+ return actors.filter(ac => ac.actor?.getClassName?.() === 'vtkVolume').map(ac => ac.referencedId).filter(Boolean);
21567
+ }
21568
+ function volumeIdPrefixesMatch(existingIds, prefixLen, targetIds) {
21569
+ if (prefixLen > targetIds.length) {
21570
+ return false;
21571
+ }
21572
+ for (let i = 0; i < prefixLen; i++) {
21573
+ if (existingIds[i] !== targetIds[i]) {
21574
+ return false;
21575
+ }
21576
+ }
21577
+ return true;
21578
+ }
21579
+
21580
+ /**
21581
+ * Returns true when the viewport type matches a volume-based presentation (ORTHOGRAPHIC or VOLUME_3D).
21582
+ */
21583
+ function viewportMatchesDesiredVolumePresentation(viewport, desiredViewportInfo) {
21584
+ const desiredType = desiredViewportInfo.getViewportType();
21585
+ if (viewport.type !== desiredType) {
21586
+ return false;
21587
+ }
21588
+ return desiredType === esm.Enums.ViewportType.ORTHOGRAPHIC || desiredType === esm.Enums.ViewportType.VOLUME_3D;
21589
+ }
21506
21590
  const WITH_NAVIGATION = {
21507
21591
  withNavigation: true,
21508
21592
  withOrientation: false
@@ -22508,7 +22592,33 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22508
22592
  }
22509
22593
  });
22510
22594
  }
22511
- await viewport.setVolumes(volumeInputArray);
22595
+ const baseVolumeInputs = filteredVolumeInputArray.map(({
22596
+ volumeInput
22597
+ }) => volumeInput);
22598
+ const nextBaseVolumeIds = baseVolumeInputs.map(v => v.volumeId);
22599
+ const existingVolumeIds = getVolumeActorReferencedIds(viewport);
22600
+ let skippedIdenticalBaseVolumes = false;
22601
+ if (baseVolumeInputs.length) {
22602
+ const singleBaseViewport = nextBaseVolumeIds.length === 1;
22603
+
22604
+ // Only skip setVolumes() when the viewport type already matches the desired OHIF type
22605
+ // (ORTHOGRAPHIC / VOLUME_3D); otherwise a stack → MPR switch with the same volumeId
22606
+ // would incorrectly skip rebuilding the viewport.
22607
+ if (singleBaseViewport && existingVolumeIds.length >= nextBaseVolumeIds.length && volumeIdPrefixesMatch(existingVolumeIds, nextBaseVolumeIds.length, nextBaseVolumeIds) && viewportMatchesDesiredVolumePresentation(viewport, viewportInfo)) {
22608
+ // Same primary volume already loaded (e.g. labelmap / extra actors after it) — avoid
22609
+ // setVolumes(), which tears down all actors and blanks MPR during SEG hydrate.
22610
+ skippedIdenticalBaseVolumes = true;
22611
+ } else if (existingVolumeIds.length && nextBaseVolumeIds.length > existingVolumeIds.length && volumeIdPrefixesMatch(existingVolumeIds, existingVolumeIds.length, nextBaseVolumeIds) && typeof viewport.addVolumes === 'function') {
22612
+ const toAdd = baseVolumeInputs.slice(existingVolumeIds.length);
22613
+ if (toAdd.length) {
22614
+ await viewport.addVolumes(toAdd);
22615
+ }
22616
+ } else {
22617
+ await viewport.setVolumes(baseVolumeInputs);
22618
+ }
22619
+ } else if (volumeInputArray.length) {
22620
+ await viewport.setVolumes(volumeInputArray);
22621
+ }
22512
22622
  await this._addOverlayRepresentations(overlayProcessingResults);
22513
22623
  viewport.render();
22514
22624
  volumesProperties.forEach(({
@@ -22521,7 +22631,10 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22521
22631
  });
22522
22632
  });
22523
22633
  this.setPresentations(viewport.id, presentations);
22524
- if (!presentations.positionPresentation) {
22634
+ // Presentations apply segmentation (hydrated labelmap etc.) after the render above — redraw so
22635
+ // every orthographic/3D tile shows the updated scene (fixes MPR siblings blank after SEG hydrate).
22636
+ viewport.render();
22637
+ if (!presentations.positionPresentation && !skippedIdenticalBaseVolumes) {
22525
22638
  const imageIndex = this._getInitialImageIndexForViewport(viewportInfo);
22526
22639
  if (imageIndex !== undefined) {
22527
22640
  esm.utilities.jumpToSlice(viewport.element, {
@@ -26815,20 +26928,34 @@ const _getSegmentationPresentationId = ({
26815
26928
  if (!viewport?.viewportOptions || !viewport.displaySetInstanceUIDs?.length) {
26816
26929
  return;
26817
26930
  }
26931
+ const {
26932
+ displaySetService
26933
+ } = servicesManager.services;
26818
26934
  const {
26819
26935
  displaySetInstanceUIDs,
26820
26936
  viewportOptions
26821
26937
  } = viewport;
26938
+
26939
+ // Match keys used by updateStoredSegmentationPresentation (referenced volume only).
26940
+ // Including overlay UIDs (e.g. SEG) produced ids like "MR&SEG" while the store
26941
+ // entry is under "MR", so hydrated segmentations never applied and viewports could mis-render.
26942
+ const nonOverlayUIDs = displaySetInstanceUIDs.filter(uid => {
26943
+ const ds = displaySetService.getDisplaySetByUID(uid);
26944
+ return ds && !ds.isOverlayDisplaySet;
26945
+ });
26946
+ if (!nonOverlayUIDs.length) {
26947
+ return;
26948
+ }
26822
26949
  let orientation = viewportOptions.orientation;
26823
26950
  if (!orientation) {
26824
26951
  // Calculate orientation from the viewport sample image
26825
- const displaySet = servicesManager.services.displaySetService.getDisplaySetByUID(displaySetInstanceUIDs[0]);
26826
- const sampleImage = displaySet.images?.[0];
26952
+ const displaySet = displaySetService.getDisplaySetByUID(nonOverlayUIDs[0]);
26953
+ const sampleImage = displaySet?.images?.[0];
26827
26954
  const imageOrientationPatient = sampleImage?.ImageOrientationPatient;
26828
26955
  orientation = getViewportOrientationFromImageOrientationPatient(imageOrientationPatient);
26829
26956
  }
26830
26957
  const segmentationPresentationArr = [];
26831
- segmentationPresentationArr.push(...displaySetInstanceUIDs);
26958
+ segmentationPresentationArr.push(...nonOverlayUIDs);
26832
26959
 
26833
26960
  // Uncomment if unique indexing is needed
26834
26961
  // addUniqueIndex(
@@ -36341,7 +36341,7 @@ function uuidv4() {
36341
36341
 
36342
36342
  "use strict";
36343
36343
  /* unused harmony export version */
36344
- const version = '4.21.7';
36344
+ const version = '4.22.3';
36345
36345
 
36346
36346
 
36347
36347
  /***/ },
@@ -7309,7 +7309,7 @@ var COLOR_LUT = __webpack_require__(93952);
7309
7309
 
7310
7310
 
7311
7311
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/version.js
7312
- const version = '4.21.7';
7312
+ const version = '4.22.3';
7313
7313
 
7314
7314
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/synchronizers/callbacks/cameraSyncCallback.js
7315
7315
  /* unused harmony import specifier */ var cameraSyncCallback_getRenderingEngine;
@@ -11343,6 +11343,8 @@ var SphereSource = __webpack_require__(73435);
11343
11343
  var Plane = __webpack_require__(49794);
11344
11344
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/volumeCropping/index.js + 8 modules
11345
11345
  var volumeCropping = __webpack_require__(88380);
11346
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/interactionDragCoordinator.js
11347
+ var interactionDragCoordinator = __webpack_require__(51970);
11346
11348
  ;// ../../../node_modules/@cornerstonejs/tools/dist/esm/tools/VolumeCroppingTool.js
11347
11349
 
11348
11350
 
@@ -11357,6 +11359,7 @@ var volumeCropping = __webpack_require__(88380);
11357
11359
 
11358
11360
 
11359
11361
 
11362
+
11360
11363
  class VolumeCroppingTool extends base/* BaseTool */.oS {
11361
11364
  constructor(toolProps = {}, defaultToolProps = {
11362
11365
  configuration: {
@@ -11387,6 +11390,7 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11387
11390
  this.originalClippingPlanes = [];
11388
11391
  this.draggingSphereIndex = null;
11389
11392
  this.rotatePlanesOnDrag = false;
11393
+ this.suppressPlaneRotationForCurrentDrag = false;
11390
11394
  this.cornerDragOffset = null;
11391
11395
  this.faceDragOffset = null;
11392
11396
  this.volumeDirectionVectors = null;
@@ -11409,8 +11413,11 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11409
11413
  const { element } = eventDetail;
11410
11414
  const enabledElement = (0,esm.getEnabledElement)(element);
11411
11415
  const { viewport } = enabledElement;
11412
- const actorEntry = viewport.getDefaultActor();
11413
- const actor = actorEntry.actor;
11416
+ this.suppressPlaneRotationForCurrentDrag = (0,interactionDragCoordinator/* isDragOwnedBy */.lq)(viewport.id, 'orientation-controller');
11417
+ const actor = this._getVolumeActor(viewport);
11418
+ if (!actor) {
11419
+ return false;
11420
+ }
11414
11421
  const mapper = actor.getMapper();
11415
11422
  const mouseCanvas = [
11416
11423
  evt.detail.currentPoints.canvas[0],
@@ -11481,6 +11488,7 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11481
11488
  this.draggingSphereIndex = null;
11482
11489
  this.cornerDragOffset = null;
11483
11490
  this.faceDragOffset = null;
11491
+ this.suppressPlaneRotationForCurrentDrag = false;
11484
11492
  viewport.render();
11485
11493
  this._hasResolutionChanged = false;
11486
11494
  };
@@ -11638,12 +11646,12 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11638
11646
  if (!viewport) {
11639
11647
  return;
11640
11648
  }
11641
- const volumeActors = viewport.getActors();
11642
- if (!volumeActors || volumeActors.length === 0) {
11649
+ const volumeActor = this._getVolumeActor(viewport);
11650
+ if (!volumeActor) {
11643
11651
  console.warn('VolumeCroppingTool: No volume actors found in the viewport.');
11644
11652
  return;
11645
11653
  }
11646
- const imageData = volumeActors[0].actor.getMapper().getInputData();
11654
+ const imageData = volumeActor.getMapper().getInputData();
11647
11655
  if (!imageData) {
11648
11656
  console.warn('VolumeCroppingTool: No image data found for volume actor.');
11649
11657
  return;
@@ -11765,9 +11773,7 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
11765
11773
  this.edgeLines[uid] = { actor, source, key1, key2 };
11766
11774
  }
11767
11775
  });
11768
- const mapper = viewport
11769
- .getDefaultActor()
11770
- .actor.getMapper();
11776
+ const mapper = volumeActor.getMapper();
11771
11777
  mapper.addClippingPlane(planeXMin);
11772
11778
  mapper.addClippingPlane(planeXMax);
11773
11779
  mapper.addClippingPlane(planeYMin);
@@ -12114,6 +12120,23 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12114
12120
  getHandlesVisible() {
12115
12121
  return this.configuration.showHandles;
12116
12122
  }
12123
+ setHandleRadius(radius) {
12124
+ this.configuration.sphereRadius = radius;
12125
+ this.sphereStates.forEach((state) => {
12126
+ if (state?.sphereSource?.setRadius) {
12127
+ state.sphereSource.setRadius(radius);
12128
+ state.sphereSource.modified();
12129
+ }
12130
+ });
12131
+ const viewportsInfo = this._getViewportsInfo();
12132
+ const [viewport3D] = viewportsInfo;
12133
+ if (!viewport3D) {
12134
+ return;
12135
+ }
12136
+ const renderingEngine = (0,esm.getRenderingEngine)(viewport3D.renderingEngineId);
12137
+ const viewport = renderingEngine?.getViewport(viewport3D.viewportId);
12138
+ viewport?.render();
12139
+ }
12117
12140
  getClippingPlanesVisible() {
12118
12141
  return this.configuration.showClippingPlanes;
12119
12142
  }
@@ -12149,7 +12172,8 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12149
12172
  }
12150
12173
  else {
12151
12174
  const shiftKey = evt.detail.event?.shiftKey ?? false;
12152
- if (this.rotatePlanesOnDrag === true || shiftKey) {
12175
+ if ((this.rotatePlanesOnDrag === true || shiftKey) &&
12176
+ !this.suppressPlaneRotationForCurrentDrag) {
12153
12177
  this._rotateClippingPlanes(evt);
12154
12178
  return;
12155
12179
  }
@@ -12207,9 +12231,11 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12207
12231
  }
12208
12232
  }
12209
12233
  _updateClippingPlanes(viewport) {
12210
- const actorEntry = viewport.getDefaultActor();
12211
- const actor = actorEntry.actor;
12212
- const mapper = actor.getMapper();
12234
+ const actor = this._getVolumeActor(viewport);
12235
+ const mapper = this._getVolumeMapper(viewport);
12236
+ if (!actor || !mapper) {
12237
+ return;
12238
+ }
12213
12239
  const matrix = actor.getMatrix();
12214
12240
  if (!this.configuration.showClippingPlanes) {
12215
12241
  mapper.removeAllClippingPlanes();
@@ -12346,7 +12372,10 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12346
12372
  }
12347
12373
  _getVolumeActor(viewport) {
12348
12374
  const vp = viewport || this._getViewport();
12349
- return vp?.getDefaultActor()?.actor;
12375
+ return vp
12376
+ ?.getActors?.()
12377
+ ?.find((entry) => entry.actor?.getClassName?.() === 'vtkVolume')
12378
+ ?.actor;
12350
12379
  }
12351
12380
  _getVolumeMapper(viewport) {
12352
12381
  const actor = this._getVolumeActor(viewport);
@@ -12363,7 +12392,10 @@ class VolumeCroppingTool extends base/* BaseTool */.oS {
12363
12392
  }
12364
12393
  }
12365
12394
  _updateClippingPlanesFromFaceSpheres(viewport) {
12366
- const mapper = viewport.getDefaultActor().actor.getMapper();
12395
+ const mapper = this._getVolumeMapper(viewport);
12396
+ if (!mapper) {
12397
+ return;
12398
+ }
12367
12399
  this.originalClippingPlanes[volumeCropping.PLANEINDEX.XMIN].origin = [
12368
12400
  ...this.sphereStates[volumeCropping.SPHEREINDEX.XMIN].point,
12369
12401
  ];
@@ -16081,7 +16113,7 @@ class MagnifyTool extends base/* BaseTool */.oS {
16081
16113
  const { viewport } = enabledElement;
16082
16114
  const { element } = viewport;
16083
16115
  const viewportProperties = viewport.getProperties();
16084
- const { rotation: originalViewportRotation } = viewport.getViewPresentation();
16116
+ const { rotation: originalViewportRotation, flipHorizontal: originalViewportFlipHorizontal, flipVertical: originalViewportFlipVertical, } = viewport.getViewPresentation();
16085
16117
  const { canvas: canvasPos, world: worldPos } = currentPoints;
16086
16118
  let magnifyToolElement;
16087
16119
  magnifyToolElement = element.querySelector('.magnifyTool');
@@ -16112,6 +16144,8 @@ class MagnifyTool extends base/* BaseTool */.oS {
16112
16144
  magnifyViewport.setProperties(viewportProperties);
16113
16145
  magnifyViewport.setViewPresentation({
16114
16146
  rotation: originalViewportRotation,
16147
+ flipHorizontal: originalViewportFlipHorizontal,
16148
+ flipVertical: originalViewportFlipVertical,
16115
16149
  });
16116
16150
  const { parallelScale } = viewport.getCamera();
16117
16151
  const { focalPoint, position, viewPlaneNormal } = magnifyViewport.getCamera();
@@ -17134,6 +17168,7 @@ class AdvancedMagnifyViewport {
17134
17168
  _syncViewportsCameras(sourceViewport, magnifyViewport) {
17135
17169
  const worldPos = sourceViewport.canvasToWorld(this.position);
17136
17170
  const parallelScale = this._convertZoomFactorToParallelScale(sourceViewport, magnifyViewport, this.zoomFactor);
17171
+ const { flipHorizontal, flipVertical } = sourceViewport.getCamera();
17137
17172
  const { focalPoint, position, viewPlaneNormal } = magnifyViewport.getCamera();
17138
17173
  const distance = Math.sqrt(Math.pow(focalPoint[0] - position[0], 2) +
17139
17174
  Math.pow(focalPoint[1] - position[1], 2) +
@@ -17152,6 +17187,8 @@ class AdvancedMagnifyViewport {
17152
17187
  parallelScale,
17153
17188
  focalPoint: updatedFocalPoint,
17154
17189
  position: updatedPosition,
17190
+ flipHorizontal,
17191
+ flipVertical,
17155
17192
  });
17156
17193
  }
17157
17194
  _syncStackViewports(sourceViewport, magnifyViewport) {
@@ -29447,12 +29484,19 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29447
29484
  showEdgeFaces: true,
29448
29485
  showCornerFaces: true,
29449
29486
  keepOrientationUp: true,
29487
+ highlightColor: [255, 255, 255],
29488
+ edgeColor: [200, 200, 200],
29489
+ cornerColor: [150, 150, 150],
29490
+ restingAmbient: 1.0,
29491
+ hoverAmbient: 1.0,
29450
29492
  },
29451
29493
  }) {
29452
29494
  super(toolProps, defaultToolProps);
29453
29495
  this.widget = new OrientationControllerWidget/* vtkOrientationControllerWidget */.C();
29454
29496
  this.resizeObservers = new Map();
29455
29497
  this.cameraHandlers = new Map();
29498
+ this.animationFrameHandles = new Map();
29499
+ this.animationTokens = new Map();
29456
29500
  this._getViewportsInfo = () => {
29457
29501
  const viewports = (0,ToolGroupManager.getToolGroup)(this.toolGroupId)?.viewportsInfo;
29458
29502
  return viewports || [];
@@ -29546,6 +29590,7 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29546
29590
  }
29547
29591
  const volumeViewport = viewport;
29548
29592
  this.widget.positionActors(volumeViewport, actors, this.getPositionConfig());
29593
+ this.widget.syncOverlayViewport(viewportId, volumeViewport);
29549
29594
  viewport.render();
29550
29595
  };
29551
29596
  }
@@ -29611,6 +29656,9 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29611
29656
  this.resizeObservers.forEach((observer) => observer.disconnect());
29612
29657
  this.resizeObservers.clear();
29613
29658
  this.cameraHandlers.clear();
29659
+ this.animationFrameHandles.forEach((handle) => cancelAnimationFrame(handle));
29660
+ this.animationFrameHandles.clear();
29661
+ this.animationTokens.clear();
29614
29662
  }
29615
29663
  createAnnotatedRhombActor() {
29616
29664
  const faceColors = this.getFaceColors();
@@ -29621,9 +29669,17 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29621
29669
  opacity: this.configuration.opacity ?? 1.0,
29622
29670
  showEdgeFaces: this.configuration.showEdgeFaces !== false,
29623
29671
  showCornerFaces: this.configuration.showCornerFaces !== false,
29672
+ highlightColor: this.configuration.highlightColor ?? [255, 255, 255],
29673
+ edgeColor: this.configuration.edgeColor ?? [200, 200, 200],
29674
+ cornerColor: this.configuration.cornerColor ?? [150, 150, 150],
29675
+ restingAmbient: this.configuration.restingAmbient ?? 1.0,
29676
+ hoverAmbient: this.configuration.hoverAmbient ?? 1.0,
29624
29677
  });
29625
29678
  }
29626
29679
  addMarkerToViewport(viewportId, renderingEngineId) {
29680
+ if (this.widget.getActors(viewportId)) {
29681
+ return;
29682
+ }
29627
29683
  const enabledElement = (0,esm.getEnabledElementByIds)(viewportId, renderingEngineId);
29628
29684
  if (!enabledElement) {
29629
29685
  console.warn('OrientationControllerTool: No enabled element found');
@@ -29664,8 +29720,8 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29664
29720
  }
29665
29721
  },
29666
29722
  onFaceHover: (result) => {
29667
- if (result && result.actorIndex !== 0) {
29668
- this.widget.highlightFace(result.pickedActor, result.cellId, volumeViewport, false);
29723
+ if (result) {
29724
+ this.widget.highlightFace(result.pickedActor, result.cellId, volumeViewport, result.actorIndex === 0);
29669
29725
  }
29670
29726
  else {
29671
29727
  this.widget.clearHighlight();
@@ -29704,6 +29760,14 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29704
29760
  viewport.render();
29705
29761
  }
29706
29762
  animateCameraToOrientation(viewport, targetViewPlaneNormal, targetViewUp) {
29763
+ const viewportId = viewport.id;
29764
+ const existingHandle = this.animationFrameHandles.get(viewportId);
29765
+ if (existingHandle !== undefined) {
29766
+ cancelAnimationFrame(existingHandle);
29767
+ this.animationFrameHandles.delete(viewportId);
29768
+ }
29769
+ const nextToken = (this.animationTokens.get(viewportId) ?? 0) + 1;
29770
+ this.animationTokens.set(viewportId, nextToken);
29707
29771
  const keepOrientationUp = this.configuration.keepOrientationUp !== false;
29708
29772
  const renderer = viewport.getRenderer();
29709
29773
  const camera = renderer.getActiveCamera();
@@ -29715,34 +29779,33 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29715
29779
  gl_matrix_esm/* vec3.cross */.eR.cross(startRight, startUp, startForward);
29716
29780
  gl_matrix_esm/* vec3.normalize */.eR.normalize(startRight, startRight);
29717
29781
  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);
29782
+ const targetForward = gl_matrix_esm/* vec3.normalize */.eR.normalize(gl_matrix_esm/* vec3.create */.eR.create(), targetViewPlaneNormal);
29718
29783
  let targetUp;
29719
29784
  if (keepOrientationUp) {
29720
29785
  targetUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(targetViewUp[0], targetViewUp[1], targetViewUp[2]);
29721
29786
  }
29722
29787
  else {
29723
- const currentUp = gl_matrix_esm/* vec3.normalize */.eR.normalize(gl_matrix_esm/* vec3.create */.eR.create(), startUp);
29724
- const normalizedForward = gl_matrix_esm/* vec3.create */.eR.create();
29725
- gl_matrix_esm/* vec3.normalize */.eR.normalize(normalizedForward, targetViewPlaneNormal);
29726
- const dot = gl_matrix_esm/* vec3.dot */.eR.dot(currentUp, normalizedForward);
29788
+ const currentFwd = gl_matrix_esm/* vec3.normalize */.eR.normalize(gl_matrix_esm/* vec3.create */.eR.create(), startForward);
29789
+ const rotQuat = gl_matrix_esm/* quat.create */.Yu.create();
29790
+ gl_matrix_esm/* quat.rotationTo */.Yu.rotationTo(rotQuat, currentFwd, targetForward);
29727
29791
  targetUp = gl_matrix_esm/* vec3.create */.eR.create();
29728
- gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(targetUp, currentUp, normalizedForward, -dot);
29792
+ gl_matrix_esm/* vec3.transformQuat */.eR.transformQuat(targetUp, startUp, rotQuat);
29729
29793
  gl_matrix_esm/* vec3.normalize */.eR.normalize(targetUp, targetUp);
29730
- if (gl_matrix_esm/* vec3.length */.eR.length(targetUp) < 0.001) {
29731
- if (Math.abs(normalizedForward[2]) < 0.9) {
29732
- targetUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(0, 0, 1);
29733
- }
29734
- else {
29735
- targetUp = gl_matrix_esm/* vec3.fromValues */.eR.fromValues(0, 1, 0);
29736
- }
29737
- const dot2 = gl_matrix_esm/* vec3.dot */.eR.dot(targetUp, normalizedForward);
29738
- gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(targetUp, targetUp, normalizedForward, -dot2);
29739
- gl_matrix_esm/* vec3.normalize */.eR.normalize(targetUp, targetUp);
29740
- }
29741
29794
  }
29795
+ const upDotForward = gl_matrix_esm/* vec3.dot */.eR.dot(targetUp, targetForward);
29796
+ gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(targetUp, targetUp, targetForward, -upDotForward);
29797
+ if (gl_matrix_esm/* vec3.length */.eR.length(targetUp) < 0.0001) {
29798
+ targetUp = gl_matrix_esm/* vec3.clone */.eR.clone(startUp);
29799
+ const fallbackDot = gl_matrix_esm/* vec3.dot */.eR.dot(targetUp, targetForward);
29800
+ gl_matrix_esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(targetUp, targetUp, targetForward, -fallbackDot);
29801
+ }
29802
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(targetUp, targetUp);
29742
29803
  const targetRight = gl_matrix_esm/* vec3.create */.eR.create();
29743
- gl_matrix_esm/* vec3.cross */.eR.cross(targetRight, targetUp, targetViewPlaneNormal);
29804
+ gl_matrix_esm/* vec3.cross */.eR.cross(targetRight, targetUp, targetForward);
29744
29805
  gl_matrix_esm/* vec3.normalize */.eR.normalize(targetRight, targetRight);
29745
- 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);
29806
+ gl_matrix_esm/* vec3.cross */.eR.cross(targetUp, targetForward, targetRight);
29807
+ gl_matrix_esm/* vec3.normalize */.eR.normalize(targetUp, targetUp);
29808
+ const targetMatrix = gl_matrix_esm/* mat4.fromValues */.pB.fromValues(targetRight[0], targetRight[1], targetRight[2], 0, targetUp[0], targetUp[1], targetUp[2], 0, targetForward[0], targetForward[1], targetForward[2], 0, 0, 0, 0, 1);
29746
29809
  const startQuat = gl_matrix_esm/* mat4.getRotation */.pB.getRotation(gl_matrix_esm/* quat.create */.Yu.create(), startMatrix);
29747
29810
  const targetQuat = gl_matrix_esm/* mat4.getRotation */.pB.getRotation(gl_matrix_esm/* quat.create */.Yu.create(), targetMatrix);
29748
29811
  let dotProduct = gl_matrix_esm/* quat.dot */.Yu.dot(startQuat, targetQuat);
@@ -29754,13 +29817,21 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29754
29817
  if (dotProduct > threshold) {
29755
29818
  return;
29756
29819
  }
29757
- const steps = 10;
29758
29820
  const duration = 150;
29759
- const stepDuration = duration / steps;
29760
- let currentStep = 0;
29761
- const animate = () => {
29762
- currentStep++;
29763
- const t = currentStep / steps;
29821
+ const animationStart = performance.now();
29822
+ const finalNormal = [
29823
+ targetForward[0],
29824
+ targetForward[1],
29825
+ targetForward[2],
29826
+ ];
29827
+ const finalUp = [targetUp[0], targetUp[1], targetUp[2]];
29828
+ const animate = (now) => {
29829
+ if (this.animationTokens.get(viewportId) !== nextToken) {
29830
+ return;
29831
+ }
29832
+ const elapsed = now - animationStart;
29833
+ const t = Math.min(1, elapsed / duration);
29834
+ const isLastStep = t >= 1;
29764
29835
  const easedT = t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
29765
29836
  const interpolatedQuat = gl_matrix_esm/* quat.create */.Yu.create();
29766
29837
  gl_matrix_esm/* quat.slerp */.Yu.slerp(interpolatedQuat, startQuat, targetQuat, easedT);
@@ -29769,16 +29840,21 @@ class OrientationControllerTool extends base/* BaseTool */.oS {
29769
29840
  const interpolatedForward = interpolatedMatrix.slice(8, 11);
29770
29841
  const interpolatedUp = interpolatedMatrix.slice(4, 7);
29771
29842
  viewport.setCamera({
29772
- viewPlaneNormal: interpolatedForward,
29773
- viewUp: interpolatedUp,
29843
+ viewPlaneNormal: isLastStep ? finalNormal : interpolatedForward,
29844
+ viewUp: isLastStep ? finalUp : interpolatedUp,
29774
29845
  });
29775
29846
  viewport.resetCamera(ANIMATE_RESET_CAMERA_OPTIONS);
29776
29847
  viewport.render();
29777
- if (currentStep < steps) {
29778
- setTimeout(animate, stepDuration);
29848
+ if (!isLastStep) {
29849
+ const handle = requestAnimationFrame(animate);
29850
+ this.animationFrameHandles.set(viewportId, handle);
29851
+ }
29852
+ else {
29853
+ this.animationFrameHandles.delete(viewportId);
29779
29854
  }
29780
29855
  };
29781
- animate();
29856
+ const handle = requestAnimationFrame(animate);
29857
+ this.animationFrameHandles.set(viewportId, handle);
29782
29858
  }
29783
29859
  }
29784
29860
  /* harmony default export */ const tools_OrientationControllerTool = ((/* unused pure expression or super */ null && (OrientationControllerTool)));