@cornerstonejs/adapters 1.63.5 → 1.64.1

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.
@@ -36033,7 +36033,7 @@ function loadAndCacheImage(imageId, options = {
36033
36033
  return imageLoadObject.promise;
36034
36034
  }
36035
36035
 
36036
- const VIEWPORT_ELEMENT = 'viewport-element';
36036
+ const VIEWPORT_ELEMENT$1 = 'viewport-element';
36037
36037
  const CANVAS_CSS_CLASS = 'cornerstone-canvas';
36038
36038
  function createCanvas(element) {
36039
36039
  const canvas = document.createElement('canvas');
@@ -36049,13 +36049,13 @@ function createViewportElement(element) {
36049
36049
  div.style.position = 'relative';
36050
36050
  div.style.width = '100%';
36051
36051
  div.style.height = '100%';
36052
- div.classList.add(VIEWPORT_ELEMENT);
36052
+ div.classList.add(VIEWPORT_ELEMENT$1);
36053
36053
  element.appendChild(div);
36054
36054
  return div;
36055
36055
  }
36056
36056
  function getOrCreateCanvas(element) {
36057
36057
  const canvasSelector = `canvas.${CANVAS_CSS_CLASS}`;
36058
- const viewportElement = `div.${VIEWPORT_ELEMENT}`;
36058
+ const viewportElement = `div.${VIEWPORT_ELEMENT$1}`;
36059
36059
  const internalDiv = element.querySelector(viewportElement) || createViewportElement(element);
36060
36060
  return internalDiv.querySelector(canvasSelector) || createCanvas(internalDiv);
36061
36061
  }
@@ -48803,6 +48803,238 @@ function getSegmentation(segmentationId) {
48803
48803
  return segmentationStateManager.getSegmentation(segmentationId);
48804
48804
  }
48805
48805
 
48806
+ const VIEWPORT_ELEMENT = 'viewport-element';
48807
+ function getSvgDrawingHelper(element) {
48808
+ const enabledElement = getEnabledElement(element);
48809
+ const {
48810
+ viewportId,
48811
+ renderingEngineId
48812
+ } = enabledElement;
48813
+ const canvasHash = `${viewportId}:${renderingEngineId}`;
48814
+ const svgLayerElement = _getSvgLayer(element);
48815
+ Object.keys(state.svgNodeCache[canvasHash]).forEach(cacheKey => {
48816
+ state.svgNodeCache[canvasHash][cacheKey].touched = false;
48817
+ });
48818
+ return {
48819
+ svgLayerElement: svgLayerElement,
48820
+ svgNodeCacheForCanvas: state.svgNodeCache,
48821
+ getSvgNode: getSvgNode.bind(this, canvasHash),
48822
+ appendNode: appendNode.bind(this, svgLayerElement, canvasHash),
48823
+ setNodeTouched: setNodeTouched.bind(this, canvasHash),
48824
+ clearUntouched: clearUntouched.bind(this, svgLayerElement, canvasHash)
48825
+ };
48826
+ }
48827
+ function _getSvgLayer(element) {
48828
+ const viewportElement = `.${VIEWPORT_ELEMENT}`;
48829
+ const internalDivElement = element.querySelector(viewportElement);
48830
+ const svgLayer = internalDivElement.querySelector(':scope > .svg-layer');
48831
+ return svgLayer;
48832
+ }
48833
+ function getSvgNode(canvasHash, cacheKey) {
48834
+ if (!state.svgNodeCache[canvasHash]) {
48835
+ return;
48836
+ }
48837
+ if (state.svgNodeCache[canvasHash][cacheKey]) {
48838
+ return state.svgNodeCache[canvasHash][cacheKey].domRef;
48839
+ }
48840
+ }
48841
+ function appendNode(svgLayerElement, canvasHash, svgNode, cacheKey) {
48842
+ if (!state.svgNodeCache[canvasHash]) {
48843
+ return null;
48844
+ }
48845
+ state.svgNodeCache[canvasHash][cacheKey] = {
48846
+ touched: true,
48847
+ domRef: svgNode
48848
+ };
48849
+ svgLayerElement.appendChild(svgNode);
48850
+ }
48851
+ function setNodeTouched(canvasHash, cacheKey) {
48852
+ if (!state.svgNodeCache[canvasHash]) {
48853
+ return;
48854
+ }
48855
+ if (state.svgNodeCache[canvasHash][cacheKey]) {
48856
+ state.svgNodeCache[canvasHash][cacheKey].touched = true;
48857
+ }
48858
+ }
48859
+ function clearUntouched(svgLayerElement, canvasHash) {
48860
+ if (!state.svgNodeCache[canvasHash]) {
48861
+ return;
48862
+ }
48863
+ Object.keys(state.svgNodeCache[canvasHash]).forEach(cacheKey => {
48864
+ const cacheEntry = state.svgNodeCache[canvasHash][cacheKey];
48865
+ if (!cacheEntry.touched && cacheEntry.domRef) {
48866
+ svgLayerElement.removeChild(cacheEntry.domRef);
48867
+ delete state.svgNodeCache[canvasHash][cacheKey];
48868
+ }
48869
+ });
48870
+ }
48871
+
48872
+ function draw(element, fn) {
48873
+ const svgDrawingHelper = getSvgDrawingHelper(element);
48874
+ fn(svgDrawingHelper);
48875
+ svgDrawingHelper.clearUntouched();
48876
+ }
48877
+
48878
+ function getToolsWithModesForElement(element, modesFilter) {
48879
+ const enabledElement = getEnabledElement(element);
48880
+ const {
48881
+ renderingEngineId,
48882
+ viewportId
48883
+ } = enabledElement;
48884
+ const toolGroup = getToolGroupForViewport(viewportId, renderingEngineId);
48885
+ if (!toolGroup) {
48886
+ return [];
48887
+ }
48888
+ const enabledTools = [];
48889
+ const toolGroupToolNames = Object.keys(toolGroup.toolOptions);
48890
+ for (let j = 0; j < toolGroupToolNames.length; j++) {
48891
+ const toolName = toolGroupToolNames[j];
48892
+ const toolOptions = toolGroup.toolOptions[toolName];
48893
+ if (!toolOptions) {
48894
+ continue;
48895
+ }
48896
+ if (modesFilter.includes(toolOptions.mode)) {
48897
+ const toolInstance = toolGroup.getToolInstance(toolName);
48898
+ enabledTools.push(toolInstance);
48899
+ }
48900
+ }
48901
+ return enabledTools;
48902
+ }
48903
+
48904
+ const {
48905
+ Active: Active$1,
48906
+ Passive: Passive$1,
48907
+ Enabled: Enabled$1
48908
+ } = ToolModes$1;
48909
+ class AnnotationRenderingEngine {
48910
+ constructor() {
48911
+ this._needsRender = new Set();
48912
+ this._animationFrameSet = false;
48913
+ this._animationFrameHandle = null;
48914
+ this._renderFlaggedViewports = () => {
48915
+ this._throwIfDestroyed();
48916
+ const elements = Array.from(this._viewportElements.values());
48917
+ for (let i = 0; i < elements.length; i++) {
48918
+ const element = elements[i];
48919
+ if (this._needsRender.has(element)) {
48920
+ this._triggerRender(element);
48921
+ this._needsRender.delete(element);
48922
+ if (this._needsRender.size === 0) {
48923
+ break;
48924
+ }
48925
+ }
48926
+ }
48927
+ this._animationFrameSet = false;
48928
+ this._animationFrameHandle = null;
48929
+ this._render();
48930
+ };
48931
+ this._viewportElements = new Map();
48932
+ }
48933
+ addViewportElement(viewportId, element) {
48934
+ this._viewportElements.set(viewportId, element);
48935
+ }
48936
+ removeViewportElement(viewportId, element) {
48937
+ this._viewportElements.delete(viewportId);
48938
+ this._needsRender.delete(element);
48939
+ this._reset();
48940
+ }
48941
+ renderViewport(element) {
48942
+ this._setViewportsToBeRenderedNextFrame([element]);
48943
+ }
48944
+ _throwIfDestroyed() {
48945
+ if (this.hasBeenDestroyed) {
48946
+ throw new Error('this.destroy() has been manually called to free up memory, can not longer use this instance. Instead make a new one.');
48947
+ }
48948
+ }
48949
+ _setAllViewportsToBeRenderedNextFrame() {
48950
+ const elements = [...this._viewportElements.values()];
48951
+ elements.forEach(element => {
48952
+ this._needsRender.add(element);
48953
+ });
48954
+ this._renderFlaggedViewports();
48955
+ }
48956
+ _setViewportsToBeRenderedNextFrame(elements) {
48957
+ const elementsEnabled = [...this._viewportElements.values()];
48958
+ elements.forEach(element => {
48959
+ if (elementsEnabled.indexOf(element) !== -1) {
48960
+ this._needsRender.add(element);
48961
+ }
48962
+ });
48963
+ this._render();
48964
+ }
48965
+ _render() {
48966
+ if (this._needsRender.size > 0 && this._animationFrameSet === false) {
48967
+ this._animationFrameHandle = window.requestAnimationFrame(this._renderFlaggedViewports);
48968
+ this._animationFrameSet = true;
48969
+ }
48970
+ }
48971
+ _triggerRender(element) {
48972
+ const enabledElement = getEnabledElement(element);
48973
+ if (!enabledElement) {
48974
+ console.warn('Element has been disabled');
48975
+ return;
48976
+ }
48977
+ const renderingEngine = getRenderingEngine(enabledElement.renderingEngineId);
48978
+ if (!renderingEngine) {
48979
+ console.warn('rendering Engine has been destroyed');
48980
+ return;
48981
+ }
48982
+ const enabledTools = getToolsWithModesForElement(element, [Active$1, Passive$1, Enabled$1]);
48983
+ const {
48984
+ renderingEngineId,
48985
+ viewportId
48986
+ } = enabledElement;
48987
+ const eventDetail = {
48988
+ element,
48989
+ renderingEngineId,
48990
+ viewportId
48991
+ };
48992
+ draw(element, svgDrawingHelper => {
48993
+ let anyRendered = false;
48994
+ const handleDrawSvg = tool => {
48995
+ if (tool.renderAnnotation) {
48996
+ const rendered = tool.renderAnnotation(enabledElement, svgDrawingHelper);
48997
+ anyRendered = anyRendered || rendered;
48998
+ }
48999
+ };
49000
+ enabledTools.forEach(handleDrawSvg);
49001
+ if (anyRendered) {
49002
+ triggerEvent(element, Events$1.ANNOTATION_RENDERED, {
49003
+ ...eventDetail
49004
+ });
49005
+ }
49006
+ });
49007
+ }
49008
+ _reset() {
49009
+ window.cancelAnimationFrame(this._animationFrameHandle);
49010
+ this._needsRender.clear();
49011
+ this._animationFrameSet = false;
49012
+ this._animationFrameHandle = null;
49013
+ this._setAllViewportsToBeRenderedNextFrame();
49014
+ }
49015
+ }
49016
+ const annotationRenderingEngine = new AnnotationRenderingEngine();
49017
+ function triggerAnnotationRender(element) {
49018
+ annotationRenderingEngine.renderViewport(element);
49019
+ }
49020
+
49021
+ function triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender) {
49022
+ if (!viewportIdsToRender.length || !renderingEngine) {
49023
+ return;
49024
+ }
49025
+ viewportIdsToRender.forEach(viewportId => {
49026
+ const viewport = renderingEngine.getViewport(viewportId);
49027
+ if (!viewport) {
49028
+ console.warn(`Viewport not available for ${viewportId}`);
49029
+ return;
49030
+ }
49031
+ const {
49032
+ element
49033
+ } = viewport;
49034
+ triggerAnnotationRender(element);
49035
+ });
49036
+ }
49037
+
48806
49038
  const {
48807
49039
  isEqual: isEqual$1
48808
49040
  } = utilities;
@@ -49739,7 +49971,7 @@ function updateContourPolyline(annotation, polylineData, transforms, options) {
49739
49971
  invalidateAnnotation(annotation);
49740
49972
  }
49741
49973
 
49742
- const DEFAULT_CONTOUR_SEG_TOOLNAME = 'PlanarFreehandContourSegmentationTool';
49974
+ const DEFAULT_CONTOUR_SEG_TOOLNAME$1 = 'PlanarFreehandContourSegmentationTool';
49743
49975
  function getInterpolationData(viewportData, filterParams = []) {
49744
49976
  const {
49745
49977
  viewport,
@@ -49753,8 +49985,8 @@ function getInterpolationData(viewportData, filterParams = []) {
49753
49985
  } = annotation.metadata;
49754
49986
  const testToolName = originalToolName || toolName;
49755
49987
  const annotations = (getAnnotations(testToolName, viewport.element) || []).filter(annotation => !annotation.metadata.originalToolName || annotation.metadata.originalToolName === testToolName);
49756
- if (testToolName !== DEFAULT_CONTOUR_SEG_TOOLNAME) {
49757
- const modifiedAnnotations = getAnnotations(DEFAULT_CONTOUR_SEG_TOOLNAME, viewport.element);
49988
+ if (testToolName !== DEFAULT_CONTOUR_SEG_TOOLNAME$1) {
49989
+ const modifiedAnnotations = getAnnotations(DEFAULT_CONTOUR_SEG_TOOLNAME$1, viewport.element);
49758
49990
  if (modifiedAnnotations?.length) {
49759
49991
  modifiedAnnotations.forEach(annotation => {
49760
49992
  const {
@@ -49816,7 +50048,8 @@ function createPolylineToolData(polyline, handlePoints, referencedToolData) {
49816
50048
  autoGenerated: true,
49817
50049
  annotationUID: undefined,
49818
50050
  cachedStats: {},
49819
- childAnnotationUIDs: []
50051
+ childAnnotationUIDs: [],
50052
+ parentAnnotationUID: undefined
49820
50053
  });
49821
50054
  Object.assign(annotation.data, {
49822
50055
  handles: {
@@ -49835,8 +50068,8 @@ function createPolylineToolData(polyline, handlePoints, referencedToolData) {
49835
50068
  }
49836
50069
  },
49837
50070
  contour: {
49838
- polyline,
49839
- closed: true
50071
+ ...referencedToolData.data.contour,
50072
+ polyline
49840
50073
  }
49841
50074
  });
49842
50075
  return annotation;
@@ -49956,11 +50189,11 @@ function selectHandles(polyline, handleCount = 12) {
49956
50189
  length,
49957
50190
  sources: sourcePoints = []
49958
50191
  } = polyline;
49959
- const distance = 6;
50192
+ const distance = 5;
49960
50193
  if (length < distance * 3) {
49961
50194
  return polyline.subselect(handleCount);
49962
50195
  }
49963
- const interval = Math.floor(Math.max(2 * length / handleCount, distance * 5));
50196
+ const interval = Math.floor(Math.max(2 * length / handleCount, distance * 2));
49964
50197
  sourcePoints.forEach(() => destPoints.push(PointsManager$1.create3(handleCount)));
49965
50198
  const dotValues = createDotValues(polyline, distance);
49966
50199
  const minimumRegions = findMinimumRegions(dotValues, handleCount);
@@ -50115,6 +50348,214 @@ function getStats(dotValues) {
50115
50348
  };
50116
50349
  }
50117
50350
 
50351
+ function updateChildInterpolationUID(annotation) {
50352
+ const {
50353
+ parentAnnotationUID,
50354
+ annotationUID
50355
+ } = annotation;
50356
+ if (!parentAnnotationUID) {
50357
+ return annotation.interpolationUID;
50358
+ }
50359
+ const parentAnnotation = getAnnotation(parentAnnotationUID);
50360
+ const {
50361
+ interpolationUID
50362
+ } = parentAnnotation;
50363
+ const index = parentAnnotation.childAnnotationUIDs.indexOf(annotationUID);
50364
+ annotation.interpolationUID = `${interpolationUID}-${index}`;
50365
+ return annotation.interpolationUID;
50366
+ }
50367
+
50368
+ function filterViewportsWithFrameOfReferenceUID(viewports, FrameOfReferenceUID) {
50369
+ const numViewports = viewports.length;
50370
+ const viewportsWithFrameOfReferenceUID = [];
50371
+ for (let vp = 0; vp < numViewports; vp++) {
50372
+ const viewport = viewports[vp];
50373
+ if (viewport.getFrameOfReferenceUID() === FrameOfReferenceUID) {
50374
+ viewportsWithFrameOfReferenceUID.push(viewport);
50375
+ }
50376
+ }
50377
+ return viewportsWithFrameOfReferenceUID;
50378
+ }
50379
+
50380
+ const {
50381
+ Active,
50382
+ Passive,
50383
+ Enabled
50384
+ } = ToolModes$1;
50385
+ function filterViewportsWithToolEnabled(viewports, toolName) {
50386
+ const numViewports = viewports.length;
50387
+ const viewportsWithToolEnabled = [];
50388
+ for (let vp = 0; vp < numViewports; vp++) {
50389
+ const viewport = viewports[vp];
50390
+ const toolGroup = getToolGroupForViewport(viewport.id, viewport.renderingEngineId);
50391
+ if (!toolGroup) {
50392
+ continue;
50393
+ }
50394
+ const hasTool = _toolGroupHasActiveEnabledOrPassiveTool(toolGroup, toolName);
50395
+ if (hasTool) {
50396
+ viewportsWithToolEnabled.push(viewport);
50397
+ }
50398
+ }
50399
+ return viewportsWithToolEnabled;
50400
+ }
50401
+ function _toolGroupHasActiveEnabledOrPassiveTool(toolGroup, toolName) {
50402
+ const {
50403
+ toolOptions
50404
+ } = toolGroup;
50405
+ const tool = toolOptions[toolName];
50406
+ if (!tool) {
50407
+ return false;
50408
+ }
50409
+ const toolMode = tool.mode;
50410
+ return toolMode === Active || toolMode === Passive || toolMode === Enabled;
50411
+ }
50412
+
50413
+ function filterViewportsWithParallelNormals(viewports, camera, EPS = 0.999) {
50414
+ return viewports.filter(viewport => {
50415
+ const vpCamera = viewport.getCamera();
50416
+ const isParallel = Math.abs(vec3.dot(vpCamera.viewPlaneNormal, camera.viewPlaneNormal)) > EPS;
50417
+ return isParallel;
50418
+ });
50419
+ }
50420
+
50421
+ function getViewportIdsWithToolToRender(element, toolName, requireParallelNormals = true) {
50422
+ const enabledElement = getEnabledElement(element);
50423
+ const {
50424
+ renderingEngine,
50425
+ FrameOfReferenceUID
50426
+ } = enabledElement;
50427
+ let viewports = renderingEngine.getViewports();
50428
+ viewports = filterViewportsWithFrameOfReferenceUID(viewports, FrameOfReferenceUID);
50429
+ viewports = filterViewportsWithToolEnabled(viewports, toolName);
50430
+ const viewport = renderingEngine.getViewport(enabledElement.viewportId);
50431
+ if (requireParallelNormals) {
50432
+ viewports = filterViewportsWithParallelNormals(viewports, viewport.getCamera());
50433
+ }
50434
+ const viewportIds = viewports.map(vp => vp.id);
50435
+ return viewportIds;
50436
+ }
50437
+
50438
+ function addContourSegmentationAnnotation(annotation) {
50439
+ if (annotation.parentAnnotationUID) {
50440
+ return;
50441
+ }
50442
+ if (!annotation.data.segmentation) {
50443
+ throw new Error('addContourSegmentationAnnotation: annotation does not have a segmentation data');
50444
+ }
50445
+ const {
50446
+ segmentationId,
50447
+ segmentIndex
50448
+ } = annotation.data.segmentation;
50449
+ const segmentation = getSegmentation(segmentationId);
50450
+ if (!segmentation.representationData.CONTOUR) {
50451
+ segmentation.representationData.CONTOUR = {
50452
+ annotationUIDsMap: new Map()
50453
+ };
50454
+ }
50455
+ const {
50456
+ annotationUIDsMap
50457
+ } = segmentation.representationData.CONTOUR;
50458
+ let annotationsUIDsSet = annotationUIDsMap.get(segmentIndex);
50459
+ if (!annotationsUIDsSet) {
50460
+ annotationsUIDsSet = new Set();
50461
+ annotationUIDsMap.set(segmentIndex, annotationsUIDsSet);
50462
+ }
50463
+ annotationUIDsMap.set(segmentIndex, annotationsUIDsSet.add(annotation.annotationUID));
50464
+ }
50465
+
50466
+ function removeContourSegmentationAnnotation(annotation) {
50467
+ if (!annotation.data.segmentation) {
50468
+ throw new Error('removeContourSegmentationAnnotation: annotation does not have a segmentation data');
50469
+ }
50470
+ const {
50471
+ segmentationId,
50472
+ segmentIndex
50473
+ } = annotation.data.segmentation;
50474
+ const segmentation = getSegmentation(segmentationId);
50475
+ const {
50476
+ annotationUIDsMap
50477
+ } = segmentation?.representationData.CONTOUR || {};
50478
+ const annotationsUIDsSet = annotationUIDsMap?.get(segmentIndex);
50479
+ if (!annotationsUIDsSet) {
50480
+ return;
50481
+ }
50482
+ annotationsUIDsSet.delete(annotation.annotationUID);
50483
+ if (!annotationsUIDsSet.size) {
50484
+ annotationUIDsMap.delete(segmentIndex);
50485
+ }
50486
+ }
50487
+
50488
+ var index$1 = /*#__PURE__*/Object.freeze({
50489
+ __proto__: null,
50490
+ InterpolationManager: InterpolationManager
50491
+ });
50492
+
50493
+ const {
50494
+ isEqual
50495
+ } = utilities;
50496
+ function findHandlePolylineIndex(annotation, handleIndex) {
50497
+ const {
50498
+ polyline
50499
+ } = annotation.data.contour;
50500
+ const {
50501
+ points
50502
+ } = annotation.data.handles;
50503
+ const {
50504
+ length
50505
+ } = points;
50506
+ if (handleIndex === length) {
50507
+ return polyline.length;
50508
+ }
50509
+ if (handleIndex < 0) {
50510
+ handleIndex = (handleIndex + length) % length;
50511
+ }
50512
+ if (handleIndex === 0) {
50513
+ return 0;
50514
+ }
50515
+ const handle = points[handleIndex];
50516
+ const index = polyline.findIndex(point => isEqual(handle, point));
50517
+ if (index !== -1) {
50518
+ return index;
50519
+ }
50520
+ let closestDistance = Infinity;
50521
+ return polyline.reduce((closestIndex, point, testIndex) => {
50522
+ const distance = vec3.squaredDistance(point, handle);
50523
+ if (distance < closestDistance) {
50524
+ closestDistance = distance;
50525
+ return testIndex;
50526
+ }
50527
+ return closestIndex;
50528
+ }, -1);
50529
+ }
50530
+
50531
+ const DEFAULT_CONTOUR_SEG_TOOLNAME = 'PlanarFreehandContourSegmentationTool';
50532
+ function createPolylineHole(viewport, targetAnnotation, holeAnnotation) {
50533
+ const {
50534
+ windingDirection: targetWindingDirection
50535
+ } = targetAnnotation.data.contour;
50536
+ const {
50537
+ windingDirection: holeWindingDirection
50538
+ } = holeAnnotation.data.contour;
50539
+ if (targetWindingDirection === holeWindingDirection) {
50540
+ holeAnnotation.data.contour.polyline.reverse();
50541
+ holeAnnotation.data.contour.windingDirection = targetWindingDirection * -1;
50542
+ }
50543
+ addChildAnnotation(targetAnnotation, holeAnnotation);
50544
+ removeContourSegmentationAnnotation(holeAnnotation);
50545
+ const {
50546
+ element
50547
+ } = viewport;
50548
+ const enabledElement = getEnabledElement(element);
50549
+ const {
50550
+ renderingEngine
50551
+ } = enabledElement;
50552
+ const updatedToolNames = new Set([DEFAULT_CONTOUR_SEG_TOOLNAME, targetAnnotation.metadata.toolName, holeAnnotation.metadata.toolName]);
50553
+ for (const toolName of updatedToolNames.values()) {
50554
+ const viewportIdsToRender = getViewportIdsWithToolToRender(element, toolName);
50555
+ triggerAnnotationRenderForViewportIds(renderingEngine, viewportIdsToRender);
50556
+ }
50557
+ }
50558
+
50118
50559
  const {
50119
50560
  PointsManager
50120
50561
  } = utilities;
@@ -50142,7 +50583,10 @@ function interpolate(viewportData) {
50142
50583
  });
50143
50584
  }
50144
50585
  function startInterpolation(viewportData) {
50145
- const toolData = viewportData.annotation;
50586
+ const {
50587
+ annotation: toolData
50588
+ } = viewportData;
50589
+ updateChildInterpolationUID(toolData);
50146
50590
  const {
50147
50591
  interpolationData,
50148
50592
  interpolationList
@@ -50176,8 +50620,10 @@ function startInterpolation(viewportData) {
50176
50620
  }
50177
50621
  }
50178
50622
  function _linearlyInterpolateBetween(indices, annotationPair, interpolationData, eventData) {
50179
- const c1 = _generateClosedContour(interpolationData.get(annotationPair[0])[0].data.contour.polyline);
50180
- const c2 = _generateClosedContour(interpolationData.get(annotationPair[1])[0].data.contour.polyline);
50623
+ const annotation0 = interpolationData.get(annotationPair[0])[0];
50624
+ const annotation1 = interpolationData.get(annotationPair[1])[0];
50625
+ const c1 = _generateClosedContour(annotation0.data.contour.polyline);
50626
+ const c2 = _generateClosedContour(annotation1.data.contour.polyline);
50181
50627
  const {
50182
50628
  c1Interp,
50183
50629
  c2Interp
@@ -50191,8 +50637,10 @@ function _linearlyInterpolateBetween(indices, annotationPair, interpolationData,
50191
50637
  function _linearlyInterpolateContour(c1Interp, c2Interp, sliceIndex, annotationPair, interpolationData, c1HasMoreNodes, eventData) {
50192
50638
  const [startIndex, endIndex] = annotationPair;
50193
50639
  const zInterp = (sliceIndex - startIndex) / (endIndex - startIndex);
50640
+ const annotation0 = interpolationData.get(startIndex)[0];
50641
+ const annotation1 = interpolationData.get(endIndex)[0];
50194
50642
  const interpolated3DPoints = _generateInterpolatedOpenContour(c1Interp, c2Interp, zInterp, c1HasMoreNodes);
50195
- const nearestAnnotation = interpolationData.get(annotationPair[zInterp > 0.5 ? 1 : 0])[0];
50643
+ const nearestAnnotation = zInterp > 0.5 ? annotation1 : annotation0;
50196
50644
  const handlePoints = selectHandles(interpolated3DPoints);
50197
50645
  if (interpolationData.has(sliceIndex)) {
50198
50646
  _editInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, nearestAnnotation, eventData);
@@ -50213,30 +50661,35 @@ function _addInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex,
50213
50661
  interpolatedAnnotation.metadata.sliceIndex = sliceIndex;
50214
50662
  addAnnotation(interpolatedAnnotation, viewport.element);
50215
50663
  referencedToolData.onInterpolationComplete?.(interpolatedAnnotation, referencedToolData);
50664
+ const {
50665
+ parentAnnotationUID
50666
+ } = referencedToolData;
50667
+ if (parentAnnotationUID) {
50668
+ const parentReferenced = getAnnotation(parentAnnotationUID);
50669
+ const parentAnnotation = _findExistingAnnotation(parentReferenced, sliceIndex, eventData);
50670
+ createPolylineHole(viewport, parentAnnotation, interpolatedAnnotation);
50671
+ }
50216
50672
  }
50217
- function _editInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, referencedToolData, eventData) {
50673
+ function _findExistingAnnotation(referencedToolData, sliceIndex, eventData) {
50218
50674
  const {
50219
50675
  viewport
50220
50676
  } = eventData;
50221
50677
  const annotations = getAnnotations(referencedToolData.metadata.toolName, viewport.element);
50222
- let toolDataIndex;
50223
50678
  for (let i = 0; i < annotations.length; i++) {
50224
50679
  const annotation = annotations[i];
50225
50680
  if (annotation.interpolationUID === referencedToolData.interpolationUID && annotation.metadata.sliceIndex === sliceIndex) {
50226
- toolDataIndex = i;
50227
- break;
50681
+ return annotation;
50228
50682
  }
50229
50683
  }
50230
- if (toolDataIndex === undefined) {
50231
- console.warn('Unable to find referenced slice index in the tool data', sliceIndex, annotations);
50232
- return;
50233
- }
50234
- const oldToolData = annotations[toolDataIndex];
50684
+ }
50685
+ function _editInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, referencedToolData, eventData) {
50686
+ const oldAnnotationData = _findExistingAnnotation(referencedToolData, sliceIndex, eventData);
50235
50687
  const points = interpolated3DPoints.points;
50236
- const interpolatedAnnotation = createPolylineToolData(points, handlePoints, oldToolData);
50237
- interpolatedAnnotation.annotationUID = oldToolData.annotationUID;
50238
- removeAnnotation(oldToolData.annotationUID);
50239
- addAnnotation(interpolatedAnnotation, viewport.element);
50688
+ const interpolatedAnnotation = createPolylineToolData(points, handlePoints, oldAnnotationData);
50689
+ Object.assign(oldAnnotationData, {
50690
+ metadata: interpolatedAnnotation.metadata,
50691
+ data: interpolatedAnnotation.data
50692
+ });
50240
50693
  }
50241
50694
  function _generateInterpolatedOpenContour(c1ir, c2ir, zInterp, c1HasMoreNodes) {
50242
50695
  const indices = c1HasMoreNodes ? c1ir.I : c2ir.I;
@@ -50502,31 +50955,6 @@ function deleteRelatedAnnotations(viewportData) {
50502
50955
  }
50503
50956
  }
50504
50957
 
50505
- function addContourSegmentationAnnotation(annotation) {
50506
- if (!annotation.data.segmentation) {
50507
- throw new Error('addContourSegmentationAnnotation: annotation does not have a segmentation data');
50508
- }
50509
- const {
50510
- segmentationId,
50511
- segmentIndex
50512
- } = annotation.data.segmentation;
50513
- const segmentation = getSegmentation(segmentationId);
50514
- if (!segmentation.representationData.CONTOUR) {
50515
- segmentation.representationData.CONTOUR = {
50516
- annotationUIDsMap: new Map()
50517
- };
50518
- }
50519
- const {
50520
- annotationUIDsMap
50521
- } = segmentation.representationData.CONTOUR;
50522
- let annotationsUIDsSet = annotationUIDsMap.get(segmentIndex);
50523
- if (!annotationsUIDsSet) {
50524
- annotationsUIDsSet = new Set();
50525
- annotationUIDsMap.set(segmentIndex, annotationsUIDsSet);
50526
- }
50527
- annotationUIDsMap.set(segmentIndex, annotationsUIDsSet.add(annotation.annotationUID));
50528
- }
50529
-
50530
50958
  const {
50531
50959
  uuidv4
50532
50960
  } = utilities;
@@ -50720,49 +51148,6 @@ function acceptAutogeneratedInterpolations(annotationGroupSelector, selector) {
50720
51148
  InterpolationManager.acceptAutoGenerated(annotationGroupSelector, selector);
50721
51149
  }
50722
51150
 
50723
- var index$1 = /*#__PURE__*/Object.freeze({
50724
- __proto__: null,
50725
- InterpolationManager: InterpolationManager
50726
- });
50727
-
50728
- const {
50729
- isEqual
50730
- } = utilities;
50731
- function findHandlePolylineIndex(annotation, handleIndex) {
50732
- const {
50733
- polyline
50734
- } = annotation.data.contour;
50735
- const {
50736
- points
50737
- } = annotation.data.handles;
50738
- const {
50739
- length
50740
- } = points;
50741
- if (handleIndex === length) {
50742
- return polyline.length;
50743
- }
50744
- if (handleIndex < 0) {
50745
- handleIndex = (handleIndex + length) % length;
50746
- }
50747
- if (handleIndex === 0) {
50748
- return 0;
50749
- }
50750
- const handle = points[handleIndex];
50751
- const index = polyline.findIndex(point => isEqual(handle, point));
50752
- if (index !== -1) {
50753
- return index;
50754
- }
50755
- let closestDistance = Infinity;
50756
- return polyline.reduce((closestIndex, point, testIndex) => {
50757
- const distance = vec3.squaredDistance(point, handle);
50758
- if (distance < closestDistance) {
50759
- closestDistance = distance;
50760
- return testIndex;
50761
- }
50762
- return closestIndex;
50763
- }, -1);
50764
- }
50765
-
50766
51151
  var index = /*#__PURE__*/Object.freeze({
50767
51152
  __proto__: null,
50768
51153
  AnnotationToPointData: AnnotationToPointData$2,
@@ -50779,6 +51164,21 @@ var index = /*#__PURE__*/Object.freeze({
50779
51164
  updateContourPolyline: updateContourPolyline
50780
51165
  });
50781
51166
 
51167
+ function getToolGroupForViewport(viewportId, renderingEngineId) {
51168
+ if (!renderingEngineId) {
51169
+ renderingEngineId = getRenderingEngines().find(re => re.getViewports().find(vp => vp.id === viewportId))?.id;
51170
+ }
51171
+ const toolGroupFilteredByIds = state.toolGroups.filter(tg => tg.viewportsInfo.some(vp => vp.renderingEngineId === renderingEngineId && (!vp.viewportId || vp.viewportId === viewportId)));
51172
+ if (!toolGroupFilteredByIds.length) {
51173
+ return;
51174
+ }
51175
+ if (toolGroupFilteredByIds.length > 1) {
51176
+ throw new Error(`Multiple tool groups found for renderingEngineId: ${renderingEngineId} and viewportId: ${viewportId}. You should only
51177
+ have one tool group per viewport in a renderingEngine.`);
51178
+ }
51179
+ return toolGroupFilteredByIds[0];
51180
+ }
51181
+
50782
51182
  const MODES = [ToolModes$1.Active, ToolModes$1.Passive, ToolModes$1.Enabled];
50783
51183
  function getToolGroupsWithToolName(toolName) {
50784
51184
  return state.toolGroups.filter(({
@@ -50864,6 +51264,36 @@ function getAnnotations(toolName, annotationGroupSelector) {
50864
51264
  const groupKey = manager.getGroupKey(annotationGroupSelector);
50865
51265
  return manager.getAnnotations(groupKey, toolName);
50866
51266
  }
51267
+ function clearParentAnnotation(annotation) {
51268
+ const {
51269
+ annotationUID: childUID,
51270
+ parentAnnotationUID
51271
+ } = annotation;
51272
+ if (!parentAnnotationUID) {
51273
+ return;
51274
+ }
51275
+ const parentAnnotation = getAnnotation(parentAnnotationUID);
51276
+ const childUIDIndex = parentAnnotation.childAnnotationUIDs.indexOf(childUID);
51277
+ parentAnnotation.childAnnotationUIDs.splice(childUIDIndex, 1);
51278
+ annotation.parentAnnotationUID = undefined;
51279
+ }
51280
+ function addChildAnnotation(parentAnnotation, childAnnotation) {
51281
+ const {
51282
+ annotationUID: parentUID
51283
+ } = parentAnnotation;
51284
+ const {
51285
+ annotationUID: childUID
51286
+ } = childAnnotation;
51287
+ clearParentAnnotation(childAnnotation);
51288
+ if (!parentAnnotation.childAnnotationUIDs) {
51289
+ parentAnnotation.childAnnotationUIDs = [];
51290
+ }
51291
+ if (parentAnnotation.childAnnotationUIDs.includes(childUID)) {
51292
+ return;
51293
+ }
51294
+ parentAnnotation.childAnnotationUIDs.push(childUID);
51295
+ childAnnotation.parentAnnotationUID = parentUID;
51296
+ }
50867
51297
  function getParentAnnotation(annotation) {
50868
51298
  return annotation.parentAnnotationUID ? getAnnotation(annotation.parentAnnotationUID) : undefined;
50869
51299
  }