@cornerstonejs/adapters 1.51.5 → 1.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38144,6 +38144,164 @@ function applyPointsToPiecewiseFunction(points, range, pwf) {
38144
38144
  return rescaled;
38145
38145
  }
38146
38146
 
38147
+ let PointsManager$2 = class PointsManager {
38148
+ constructor(configuration = {}) {
38149
+ this._dimensions = 3;
38150
+ this._length = 0;
38151
+ this._byteSize = 4;
38152
+ this.growSize = 128;
38153
+ const {
38154
+ initialSize = 1024,
38155
+ dimensions = 3,
38156
+ growSize = 128
38157
+ } = configuration;
38158
+ const itemLength = initialSize * dimensions;
38159
+ this.growSize = growSize;
38160
+ this.array = new ArrayBuffer(itemLength * this._byteSize);
38161
+ this.data = new Float32Array(this.array);
38162
+ this._dimensions = dimensions;
38163
+ }
38164
+ forEach(func) {
38165
+ for (let i = 0; i < this._length; i++) {
38166
+ func(this.getPoint(i), i);
38167
+ }
38168
+ }
38169
+ get length() {
38170
+ return this._length;
38171
+ }
38172
+ get dimensions() {
38173
+ return this._dimensions;
38174
+ }
38175
+ get dimensionLength() {
38176
+ return this._length * this._dimensions;
38177
+ }
38178
+ getPoint(index) {
38179
+ if (index < 0) {
38180
+ index += this._length;
38181
+ }
38182
+ if (index < 0 || index >= this._length) {
38183
+ return;
38184
+ }
38185
+ const offset = this._dimensions * index;
38186
+ return this.data.subarray(offset, offset + this._dimensions);
38187
+ }
38188
+ getPointArray(index) {
38189
+ const array = [];
38190
+ if (index < 0) {
38191
+ index += this._length;
38192
+ }
38193
+ if (index < 0 || index >= this._length) {
38194
+ return;
38195
+ }
38196
+ const offset = this._dimensions * index;
38197
+ for (let i = 0; i < this._dimensions; i++) {
38198
+ array.push(this.data[i + offset]);
38199
+ }
38200
+ return array;
38201
+ }
38202
+ grow(additionalSize = 1, growSize = this.growSize) {
38203
+ if (this.dimensionLength + additionalSize * this._dimensions <= this.data.length) {
38204
+ return;
38205
+ }
38206
+ const newSize = this.data.length + growSize;
38207
+ const newArray = new ArrayBuffer(newSize * this._dimensions * this._byteSize);
38208
+ const newData = new Float32Array(newArray);
38209
+ newData.set(this.data);
38210
+ this.data = newData;
38211
+ this.array = newArray;
38212
+ }
38213
+ reverse() {
38214
+ const midLength = Math.floor(this._length / 2);
38215
+ for (let i = 0; i < midLength; i++) {
38216
+ const indexStart = i * this._dimensions;
38217
+ const indexEnd = (this._length - 1 - i) * this._dimensions;
38218
+ for (let dimension = 0; dimension < this._dimensions; dimension++) {
38219
+ const valueStart = this.data[indexStart + dimension];
38220
+ this.data[indexStart + dimension] = this.data[indexEnd + dimension];
38221
+ this.data[indexEnd + dimension] = valueStart;
38222
+ }
38223
+ }
38224
+ }
38225
+ push(point) {
38226
+ this.grow(1);
38227
+ const offset = this.length * this._dimensions;
38228
+ for (let i = 0; i < this._dimensions; i++) {
38229
+ this.data[i + offset] = point[i];
38230
+ }
38231
+ this._length++;
38232
+ }
38233
+ map(f) {
38234
+ const mapData = [];
38235
+ for (let i = 0; i < this._length; i++) {
38236
+ mapData.push(f(this.getPoint(i), i));
38237
+ }
38238
+ return mapData;
38239
+ }
38240
+ get points() {
38241
+ return this.map(p => p);
38242
+ }
38243
+ toXYZ() {
38244
+ const xyz = {
38245
+ x: [],
38246
+ y: []
38247
+ };
38248
+ if (this._dimensions >= 3) {
38249
+ xyz.z = [];
38250
+ }
38251
+ const {
38252
+ x,
38253
+ y,
38254
+ z
38255
+ } = xyz;
38256
+ this.forEach(p => {
38257
+ x.push(p[0]);
38258
+ y.push(p[1]);
38259
+ if (z) {
38260
+ z.push(p[2]);
38261
+ }
38262
+ });
38263
+ return xyz;
38264
+ }
38265
+ static fromXYZ({
38266
+ x,
38267
+ y,
38268
+ z
38269
+ }) {
38270
+ const array = PointsManager.create3(x.length);
38271
+ let offset = 0;
38272
+ for (let i = 0; i < x.length; i++) {
38273
+ array.data[offset++] = x[i];
38274
+ array.data[offset++] = y[i];
38275
+ array.data[offset++] = z ? z[i] : 0;
38276
+ }
38277
+ array._length = x.length;
38278
+ return array;
38279
+ }
38280
+ subselect(count = 10, offset = 0) {
38281
+ const selected = new PointsManager({
38282
+ initialSize: count,
38283
+ dimensions: this._dimensions
38284
+ });
38285
+ for (let i = 0; i < count; i++) {
38286
+ const index = (offset + Math.floor(this.length * i / count)) % this.length;
38287
+ selected.push(this.getPoint(index));
38288
+ }
38289
+ return selected;
38290
+ }
38291
+ static create3(initialSize = 128) {
38292
+ return new PointsManager({
38293
+ initialSize,
38294
+ dimensions: 3
38295
+ });
38296
+ }
38297
+ static create2(initialSize = 128) {
38298
+ return new PointsManager({
38299
+ initialSize,
38300
+ dimensions: 2
38301
+ });
38302
+ }
38303
+ };
38304
+
38147
38305
  const isMergeableObject = val => {
38148
38306
  const nonNullObject = val && typeof val === 'object';
38149
38307
  return nonNullObject && Object.prototype.toString.call(val) !== '[object RegExp]' && Object.prototype.toString.call(val) !== '[object Date]';
@@ -42216,6 +42374,7 @@ var colormap = /*#__PURE__*/Object.freeze({
42216
42374
 
42217
42375
  var utilities = /*#__PURE__*/Object.freeze({
42218
42376
  __proto__: null,
42377
+ PointsManager: PointsManager$2,
42219
42378
  ProgressiveIterator: ProgressiveIterator,
42220
42379
  VoxelManager: VoxelManager,
42221
42380
  actorIsA: actorIsA,
@@ -45160,7 +45319,9 @@ class StackViewport extends Viewport$1 {
45160
45319
  }
45161
45320
  const csImgFrame = this.csImage?.imageFrame;
45162
45321
  const imgFrame = image?.imageFrame;
45163
- if (csImgFrame?.photometricInterpretation !== imgFrame?.photometricInterpretation || this.csImage?.photometricInterpretation !== image?.photometricInterpretation) {
45322
+ const photometricInterpretation = csImgFrame?.photometricInterpretation || this.csImage?.photometricInterpretation;
45323
+ const newPhotometricInterpretation = imgFrame?.photometricInterpretation || image?.photometricInterpretation;
45324
+ if (photometricInterpretation !== newPhotometricInterpretation) {
45164
45325
  this.stackInvalidated = true;
45165
45326
  }
45166
45327
  this._setCSImage(image);
@@ -47039,6 +47200,7 @@ var ChangeTypes;
47039
47200
  ChangeTypes["StatsUpdated"] = "StatsUpdated";
47040
47201
  ChangeTypes["InitialSetup"] = "InitialSetup";
47041
47202
  ChangeTypes["Completed"] = "Completed";
47203
+ ChangeTypes["InterpolationUpdated"] = "InterpolationUpdated";
47042
47204
  })(ChangeTypes || (ChangeTypes = {}));
47043
47205
  var ChangeTypes$1 = ChangeTypes;
47044
47206
 
@@ -48208,6 +48370,100 @@ let AnnotationToPointData$1 = class AnnotationToPointData {
48208
48370
  AnnotationToPointData$1.register(RectangleROIStartEndThreshold$1);
48209
48371
  var AnnotationToPointData$2 = AnnotationToPointData$1;
48210
48372
 
48373
+ function getContourHolesDataWorld(annotation) {
48374
+ const childAnnotationUIDs = annotation.childAnnotationUIDs ?? [];
48375
+ return childAnnotationUIDs.map(uid => getAnnotation(uid).data.contour.polyline);
48376
+ }
48377
+
48378
+ function getContourHolesDataCanvas(annotation, viewport) {
48379
+ const worldHoleContours = getContourHolesDataWorld(annotation);
48380
+ const canvasHoleContours = [];
48381
+ worldHoleContours.forEach(worldHoleContour => {
48382
+ const numPoints = worldHoleContour.length;
48383
+ const canvasHoleContour = new Array(numPoints);
48384
+ for (let i = 0; i < numPoints; i++) {
48385
+ canvasHoleContour[i] = viewport.worldToCanvas(worldHoleContour[i]);
48386
+ }
48387
+ canvasHoleContours.push(canvasHoleContour);
48388
+ });
48389
+ return canvasHoleContours;
48390
+ }
48391
+
48392
+ function distanceToPointSquared(p1, p2) {
48393
+ if (p1.length !== p2.length) {
48394
+ throw Error('Both points should have the same dimensionality');
48395
+ }
48396
+ const [x1, y1, z1 = 0] = p1;
48397
+ const [x2, y2, z2 = 0] = p2;
48398
+ const dx = x2 - x1;
48399
+ const dy = y2 - y1;
48400
+ const dz = z2 - z1;
48401
+ return dx * dx + dy * dy + dz * dz;
48402
+ }
48403
+
48404
+ function getSignedArea(polyline) {
48405
+ const refPoint = polyline[0];
48406
+ let area = 0;
48407
+ for (let i = 0, len = polyline.length; i < len; i++) {
48408
+ const p1 = polyline[i];
48409
+ const p2Index = i === len - 1 ? 0 : i + 1;
48410
+ const p2 = polyline[p2Index];
48411
+ const aX = p1[0] - refPoint[0];
48412
+ const aY = p1[1] - refPoint[1];
48413
+ const bX = p2[0] - refPoint[0];
48414
+ const bY = p2[1] - refPoint[1];
48415
+ area += aX * bY - aY * bX;
48416
+ }
48417
+ area *= 0.5;
48418
+ return area;
48419
+ }
48420
+
48421
+ function getWindingDirection(polyline) {
48422
+ const signedArea = getSignedArea(polyline);
48423
+ return signedArea >= 0 ? 1 : -1;
48424
+ }
48425
+
48426
+ function updateContourPolyline(annotation, polylineData, transforms) {
48427
+ const {
48428
+ canvasToWorld
48429
+ } = transforms;
48430
+ const {
48431
+ data
48432
+ } = annotation;
48433
+ const {
48434
+ points: polyline,
48435
+ targetWindingDirection
48436
+ } = polylineData;
48437
+ let {
48438
+ closed
48439
+ } = polylineData;
48440
+ const numPoints = polyline.length;
48441
+ const polylineWorldPoints = new Array(numPoints);
48442
+ const currentWindingDirection = getWindingDirection(polyline);
48443
+ const parentAnnotation = getParentAnnotation(annotation);
48444
+ if (closed === undefined) {
48445
+ let currentClosedState = false;
48446
+ if (polyline.length > 3) {
48447
+ const lastToFirstDist = distanceToPointSquared(polyline[0], polyline[numPoints - 1]);
48448
+ currentClosedState = isEqual$2(0, lastToFirstDist);
48449
+ }
48450
+ closed = currentClosedState;
48451
+ }
48452
+ let windingDirection = parentAnnotation ? parentAnnotation.data.contour.windingDirection * -1 : targetWindingDirection;
48453
+ if (windingDirection === undefined) {
48454
+ windingDirection = currentWindingDirection;
48455
+ } else if (windingDirection !== currentWindingDirection) {
48456
+ polyline.reverse();
48457
+ }
48458
+ for (let i = 0; i < numPoints; i++) {
48459
+ polylineWorldPoints[i] = canvasToWorld(polyline[i]);
48460
+ }
48461
+ data.contour.polyline = polylineWorldPoints;
48462
+ data.contour.closed = closed;
48463
+ data.contour.windingDirection = windingDirection;
48464
+ invalidateAnnotation(annotation);
48465
+ }
48466
+
48211
48467
  function getInterpolationData(viewportData, filterParams = []) {
48212
48468
  const {
48213
48469
  viewport,
@@ -48231,7 +48487,9 @@ function getInterpolationData(viewportData, filterParams = []) {
48231
48487
  return value === x.value;
48232
48488
  });
48233
48489
  });
48234
- interpolationDatas.set(i, filteredInterpolatedAnnotations);
48490
+ if (filteredInterpolatedAnnotations.length) {
48491
+ interpolationDatas.set(i, filteredInterpolatedAnnotations);
48492
+ }
48235
48493
  }
48236
48494
  return interpolationDatas;
48237
48495
  }
@@ -48264,7 +48522,8 @@ function createPolylineToolData(polyline, handlePoints, referencedToolData) {
48264
48522
  });
48265
48523
  Object.assign(annotation.data, {
48266
48524
  handles: {
48267
- points: handlePoints || [],
48525
+ points: handlePoints.points || handlePoints || [],
48526
+ interpolationSources: handlePoints.sources,
48268
48527
  activeHandleIndex: null,
48269
48528
  textBox: {
48270
48529
  hasMoved: false,
@@ -48334,7 +48593,7 @@ function _getSlicePositionOfToolData(interpolationData, annotationUID) {
48334
48593
  }
48335
48594
  function _sliceNeedsInterpolating(interpolationData, sliceIndex) {
48336
48595
  const annotations = interpolationData.get(sliceIndex);
48337
- return !annotations || annotations.length === 1 && annotations[0].autoGenerated;
48596
+ return !annotations?.length || annotations.length === 1 && annotations[0].autoGenerated;
48338
48597
  }
48339
48598
  function _appendInterpolationList(contourPair, interpolationList, itemIndex) {
48340
48599
  const [startIndex] = contourPair;
@@ -48382,99 +48641,182 @@ function _getBoundingPair(sliceIndex, sliceRange, interpolationData) {
48382
48641
  return annotationPair;
48383
48642
  }
48384
48643
 
48385
- class PointsArray {
48386
- constructor(configuration = {}) {
48387
- this.dimensions = 3;
48388
- this.length = 0;
48389
- const {
48390
- initialSize = 1024,
48391
- dimensions = 3
48392
- } = configuration;
48393
- this.data = new Float32Array(initialSize * dimensions);
48394
- this.dimensions = dimensions;
48395
- }
48396
- forEach(func, point) {
48397
- for (let i = 0; i < this.length; i++) {
48398
- func(this.getPoint(i, point), i);
48399
- }
48400
- }
48401
- reverse() {
48402
- const midLength = Math.floor(this.length / 2);
48403
- for (let i = 0; i < midLength; i++) {
48404
- const indexStart = i * this.dimensions;
48405
- const indexEnd = (this.length - 1 - i) * this.dimensions;
48406
- for (let dimension = 0; dimension < this.dimensions; dimension++) {
48407
- const valueStart = this.data[indexStart + dimension];
48408
- this.data[indexStart + dimension] = this.data[indexEnd + dimension];
48409
- this.data[indexEnd + dimension] = valueStart;
48644
+ const {
48645
+ PointsManager: PointsManager$1
48646
+ } = utilities;
48647
+ function selectHandles(polyline, handleCount = 8) {
48648
+ const handles = PointsManager$1.create3(handleCount);
48649
+ handles.sources = [];
48650
+ const {
48651
+ sources: destPoints
48652
+ } = handles;
48653
+ const {
48654
+ length,
48655
+ sources: sourcePoints = []
48656
+ } = polyline;
48657
+ const distance = 6;
48658
+ if (length < distance * 3) {
48659
+ console.log('Adding subselect handles', handleCount, length);
48660
+ return polyline.subselect(handleCount);
48661
+ }
48662
+ const interval = Math.min(30, Math.floor(length / 3));
48663
+ sourcePoints.forEach(() => destPoints.push(PointsManager$1.create3(handleCount)));
48664
+ const dotValues = createDotValues(polyline, distance);
48665
+ const minimumRegions = findMinimumRegions(dotValues, handleCount);
48666
+ const indices = [];
48667
+ if (minimumRegions?.length > 2) {
48668
+ let lastHandle = -1;
48669
+ const thirdInterval = interval / 3;
48670
+ minimumRegions.forEach(region => {
48671
+ const [start,, end] = region;
48672
+ const midIndex = Math.ceil((start + end) / 2);
48673
+ if (end - lastHandle < thirdInterval) {
48674
+ return;
48675
+ }
48676
+ if (midIndex - start > 2 * thirdInterval) {
48677
+ addInterval(indices, lastHandle, start, interval, length);
48678
+ lastHandle = addInterval(indices, start, midIndex, interval, length);
48679
+ } else {
48680
+ lastHandle = addInterval(indices, lastHandle, midIndex, interval, length);
48681
+ }
48682
+ if (end - lastHandle > thirdInterval) {
48683
+ lastHandle = addInterval(indices, lastHandle, end, interval, length);
48410
48684
  }
48685
+ });
48686
+ const firstHandle = indices[0];
48687
+ const lastDistance = indexValue(firstHandle + length - lastHandle, length);
48688
+ if (lastDistance > 2 * thirdInterval) {
48689
+ addInterval(indices, lastHandle, firstHandle - thirdInterval, interval, length);
48411
48690
  }
48691
+ } else {
48692
+ const interval = Math.floor(length / handleCount);
48693
+ addInterval(indices, -1, length - interval, interval, length);
48412
48694
  }
48413
- map(f, factory) {
48414
- const mapData = [];
48415
- for (let i = 0; i < this.length; i++) {
48416
- mapData.push(f(this.getPoint(i, factory(i)), i));
48695
+ indices.forEach(index => {
48696
+ const point = polyline.getPointArray(index);
48697
+ handles.push(point);
48698
+ sourcePoints.forEach((source, destSourceIndex) => destPoints[destSourceIndex].push(source.getPoint(index)));
48699
+ });
48700
+ return handles;
48701
+ }
48702
+ function createDotValues(polyline, distance = 6) {
48703
+ const {
48704
+ length
48705
+ } = polyline;
48706
+ const prevVec3 = vec3.create();
48707
+ const nextVec3 = vec3.create();
48708
+ const dotValues = new Float32Array(length);
48709
+ for (let i = 0; i < length; i++) {
48710
+ const point = polyline.getPoint(i);
48711
+ const prevPoint = polyline.getPoint(i - distance);
48712
+ const nextPoint = polyline.getPoint((i + distance) % length);
48713
+ vec3.sub(prevVec3, point, prevPoint);
48714
+ vec3.sub(nextVec3, nextPoint, point);
48715
+ const dot = vec3.dot(prevVec3, nextVec3) / (vec3.len(prevVec3) * vec3.len(nextVec3));
48716
+ dotValues[i] = dot;
48717
+ }
48718
+ return dotValues;
48719
+ }
48720
+ function findMinimumRegions(dotValues, handleCount) {
48721
+ const {
48722
+ max,
48723
+ deviation
48724
+ } = getStats(dotValues);
48725
+ const {
48726
+ length
48727
+ } = dotValues;
48728
+ if (deviation < 0.01 || length < handleCount * 3) {
48729
+ return [0, Math.floor(length / 3), Math.floor(length * 2 / 3)];
48730
+ }
48731
+ const inflection = [];
48732
+ let pair = null;
48733
+ let minValue;
48734
+ let minIndex = 0;
48735
+ for (let i = 0; i < length; i++) {
48736
+ const dot = dotValues[i];
48737
+ if (dot < max - deviation) {
48738
+ if (pair) {
48739
+ pair[2] = i;
48740
+ if (dot < minValue) {
48741
+ minValue = dot;
48742
+ minIndex = i;
48743
+ }
48744
+ pair[1] = minIndex;
48745
+ } else {
48746
+ minValue = dot;
48747
+ minIndex = i;
48748
+ pair = [i, i, i];
48749
+ }
48750
+ } else {
48751
+ if (pair) {
48752
+ inflection.push(pair);
48753
+ pair = null;
48754
+ }
48417
48755
  }
48418
- return mapData;
48419
48756
  }
48420
- static fromXYZ({
48421
- x,
48422
- y,
48423
- z
48424
- }) {
48425
- const array = new PointsArray3({
48426
- initialSize: x.length
48427
- });
48428
- let offset = 0;
48429
- for (let i = 0; i < x.length; i++) {
48430
- array.data[offset++] = x[i];
48431
- array.data[offset++] = y[i];
48432
- array.data[offset++] = z[i];
48757
+ if (pair) {
48758
+ if (inflection[0][0] === 0) {
48759
+ inflection[0][0] = pair[0];
48760
+ } else {
48761
+ pair[1] = minIndex;
48762
+ pair[2] = length - 1;
48763
+ inflection.push(pair);
48433
48764
  }
48434
- array.length = x.length;
48435
- return array;
48436
48765
  }
48766
+ return inflection;
48437
48767
  }
48438
- class PointsArray3 extends PointsArray {
48439
- constructor(configuration = {}) {
48440
- super({
48441
- ...configuration,
48442
- dimensions: 3
48443
- });
48768
+ function addInterval(indices, start, finish, interval, length) {
48769
+ if (finish < start) {
48770
+ finish += length;
48444
48771
  }
48445
- forEach(func, point = vec3.create()) {
48446
- super.forEach(func, point);
48447
- }
48448
- getPoint(index, point = vec3.create()) {
48449
- if (index >= this.length) {
48450
- return;
48772
+ const distance = finish - start;
48773
+ const count = Math.ceil(distance / interval);
48774
+ if (count <= 0) {
48775
+ if (indices[indices.length - 1] !== finish) {
48776
+ indices.push(indexValue(finish, length));
48451
48777
  }
48452
- const index2 = index * 3;
48453
- point[0] = this.data[index2];
48454
- point[1] = this.data[index2 + 1];
48455
- point[2] = this.data[index2 + 2];
48456
- return point;
48778
+ return finish;
48457
48779
  }
48458
- get points() {
48459
- return this.map(point => point, () => vec3.create());
48780
+ for (let i = 1; i <= count; i++) {
48781
+ const index = indexValue(start + i * distance / count, length);
48782
+ indices.push(index);
48460
48783
  }
48461
- getXYZ() {
48462
- const x = [];
48463
- const y = [];
48464
- const z = [];
48465
- this.forEach(point => {
48466
- x.push(point[0]);
48467
- y.push(point[1]);
48468
- z.push(point[2]);
48469
- });
48470
- return {
48471
- x,
48472
- y,
48473
- z
48474
- };
48784
+ return indices[indices.length - 1];
48785
+ }
48786
+ function indexValue(v, length) {
48787
+ return (Math.round(v) + length) % length;
48788
+ }
48789
+ function getStats(dotValues) {
48790
+ const {
48791
+ length
48792
+ } = dotValues;
48793
+ let sum = 0;
48794
+ let min = Infinity;
48795
+ let max = -Infinity;
48796
+ let sumSq = 0;
48797
+ for (let i = 0; i < length; i++) {
48798
+ const dot = dotValues[i];
48799
+ sum += dot;
48800
+ min = Math.min(min, dot);
48801
+ max = Math.max(max, dot);
48802
+ }
48803
+ const mean = sum / length;
48804
+ for (let i = 0; i < length; i++) {
48805
+ const valueDiff = dotValues[i] - mean;
48806
+ sumSq += valueDiff * valueDiff;
48475
48807
  }
48808
+ return {
48809
+ mean,
48810
+ max,
48811
+ min,
48812
+ sumSq,
48813
+ deviation: Math.sqrt(sumSq / length)
48814
+ };
48476
48815
  }
48477
48816
 
48817
+ const {
48818
+ PointsManager
48819
+ } = utilities;
48478
48820
  const dP = 0.2;
48479
48821
  let interpolating = false;
48480
48822
  function interpolate(viewportData) {
@@ -48482,11 +48824,24 @@ function interpolate(viewportData) {
48482
48824
  return;
48483
48825
  }
48484
48826
  interpolating = true;
48485
- try {
48486
- startInterpolation(viewportData);
48487
- } finally {
48488
- interpolating = false;
48489
- }
48827
+ const {
48828
+ isInterpolationUpdate,
48829
+ annotation
48830
+ } = viewportData;
48831
+ queueMicrotask(() => {
48832
+ try {
48833
+ if (isInterpolationUpdate) {
48834
+ annotation.isInterpolationUpdate = true;
48835
+ annotation.autoGenerated = false;
48836
+ }
48837
+ startInterpolation(viewportData);
48838
+ } finally {
48839
+ interpolating = false;
48840
+ if (isInterpolationUpdate) {
48841
+ annotation.autoGenerated = true;
48842
+ }
48843
+ }
48844
+ });
48490
48845
  }
48491
48846
  function startInterpolation(viewportData) {
48492
48847
  const toolData = viewportData.annotation;
@@ -48526,6 +48881,8 @@ function _linearlyInterpolateBetween(indices, annotationPair, interpolationData,
48526
48881
  c1Interp,
48527
48882
  c2Interp
48528
48883
  } = _generateInterpolationContourPair(c1, c2);
48884
+ c1Interp.kIndex = annotationPair[0];
48885
+ c2Interp.kIndex = annotationPair[1];
48529
48886
  indices.forEach(function (index) {
48530
48887
  _linearlyInterpolateContour(c1Interp, c2Interp, index, annotationPair, interpolationData, c1.x.length > c2.x.length, eventData);
48531
48888
  });
@@ -48535,30 +48892,15 @@ function _linearlyInterpolateContour(c1Interp, c2Interp, sliceIndex, annotationP
48535
48892
  const zInterp = (sliceIndex - startIndex) / (endIndex - startIndex);
48536
48893
  const interpolated3DPoints = _generateInterpolatedOpenContour(c1Interp, c2Interp, zInterp, c1HasMoreNodes);
48537
48894
  const nearestAnnotation = interpolationData.get(annotationPair[zInterp > 0.5 ? 1 : 0])[0];
48538
- const handleCount = Math.round(Math.max(8, interpolationData.get(startIndex)[0].data.handles.points.length, interpolationData.get(endIndex)[0].data.handles.points.length, interpolated3DPoints.x.length / 50));
48539
- const handlePoints = _subselect(interpolated3DPoints, handleCount);
48895
+ const handlePoints = selectHandles(interpolated3DPoints);
48540
48896
  if (interpolationData.has(sliceIndex)) {
48541
48897
  _editInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, nearestAnnotation, eventData);
48542
48898
  } else {
48543
48899
  _addInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, nearestAnnotation, eventData);
48544
48900
  }
48545
48901
  }
48546
- function _subselect(points, count = 10) {
48547
- const handles = [];
48548
- const {
48549
- length
48550
- } = points.x;
48551
- if (!length) {
48552
- return handles;
48553
- }
48554
- for (let i = 0; i < count; i++) {
48555
- const handleIndex = Math.floor(length * i / count);
48556
- handles.push(vec3.fromValues(points.x[handleIndex], points.y[handleIndex], points.z[handleIndex]));
48557
- }
48558
- return handles;
48559
- }
48560
48902
  function _addInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, referencedToolData, eventData) {
48561
- const points = PointsArray.fromXYZ(interpolated3DPoints).points;
48903
+ const points = interpolated3DPoints.points;
48562
48904
  const {
48563
48905
  viewport
48564
48906
  } = eventData;
@@ -48569,7 +48911,7 @@ function _addInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex,
48569
48911
  interpolatedAnnotation.metadata.referencedImageId = targetId;
48570
48912
  interpolatedAnnotation.metadata.referencedSliceIndex = sliceIndex;
48571
48913
  addAnnotation(interpolatedAnnotation, viewport.element);
48572
- referencedToolData.postInterpolateAction?.(interpolatedAnnotation, referencedToolData);
48914
+ referencedToolData.onInterpolationComplete?.(interpolatedAnnotation, referencedToolData);
48573
48915
  }
48574
48916
  function _editInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex, referencedToolData, eventData) {
48575
48917
  const {
@@ -48589,26 +48931,37 @@ function _editInterpolatedContour(interpolated3DPoints, handlePoints, sliceIndex
48589
48931
  return;
48590
48932
  }
48591
48933
  const oldToolData = annotations[toolDataIndex];
48592
- const points = PointsArray.fromXYZ(interpolated3DPoints).points;
48934
+ const points = interpolated3DPoints.points;
48593
48935
  const interpolatedAnnotation = createPolylineToolData(points, handlePoints, oldToolData);
48594
48936
  interpolatedAnnotation.annotationUID = oldToolData.annotationUID;
48595
48937
  removeAnnotation(oldToolData.annotationUID);
48596
48938
  addAnnotation(interpolatedAnnotation, viewport.element);
48597
48939
  }
48598
48940
  function _generateInterpolatedOpenContour(c1ir, c2ir, zInterp, c1HasMoreNodes) {
48599
- const cInterp = {
48600
- x: [],
48601
- y: [],
48602
- z: []
48603
- };
48604
48941
  const indices = c1HasMoreNodes ? c1ir.I : c2ir.I;
48942
+ const c1 = PointsManager.fromXYZ(c1ir);
48943
+ const c2 = PointsManager.fromXYZ(c2ir);
48944
+ const {
48945
+ length
48946
+ } = c1;
48947
+ const cInterp = PointsManager.create3(length);
48948
+ const vecSubtract = vec3.create();
48949
+ const vecResult = vec3.create();
48950
+ const c1Source = PointsManager.create3(length);
48951
+ c1Source.kIndex = c1ir.kIndex;
48952
+ const c2Source = PointsManager.create3(length);
48953
+ c2Source.kIndex = c2ir.kIndex;
48605
48954
  for (let i = 0; i < c1ir.x.length; i++) {
48606
48955
  if (indices[i]) {
48607
- cInterp.x.push(c1ir.x[i] + (c2ir.x[i] - c1ir.x[i]) * zInterp);
48608
- cInterp.y.push(c1ir.y[i] + (c2ir.y[i] - c1ir.y[i]) * zInterp);
48609
- cInterp.z.push(c1ir.z[i] + (c2ir.z[i] - c1ir.z[i]) * zInterp);
48956
+ const c1point = c1.getPoint(i);
48957
+ const c2point = c2.getPoint(i);
48958
+ c1Source.push(c1point);
48959
+ c2Source.push(c2point);
48960
+ vec3.sub(vecSubtract, c2point, c1point);
48961
+ cInterp.push(vec3.scaleAndAdd(vecResult, c1point, vecSubtract, zInterp));
48610
48962
  }
48611
48963
  }
48964
+ cInterp.sources = [c1Source, c2Source];
48612
48965
  return cInterp;
48613
48966
  }
48614
48967
  function _generateInterpolationContourPair(c1, c2) {
@@ -48621,8 +48974,8 @@ function _generateInterpolationContourPair(c1, c2) {
48621
48974
  const numNodes2 = interpNodes + c1.x.length;
48622
48975
  const perim1Interp = _getInterpolatedPerim(numNodes1, cumPerim1Norm);
48623
48976
  const perim2Interp = _getInterpolatedPerim(numNodes2, cumPerim2Norm);
48624
- const perim1Ind = _getIndicatorArray(c1, numNodes1);
48625
- const perim2Ind = _getIndicatorArray(c2, numNodes2);
48977
+ const perim1Ind = _getIndicatorArray(numNodes1 - 2, c1.x.length);
48978
+ const perim2Ind = _getIndicatorArray(numNodes2 - 2, c2.x.length);
48626
48979
  const nodesPerSegment1 = _getNodesPerSegment(perim1Interp, perim1Ind);
48627
48980
  const nodesPerSegment2 = _getNodesPerSegment(perim2Interp, perim2Ind);
48628
48981
  const c1i = _getSuperSampledContour(c1, nodesPerSegment1);
@@ -48741,14 +49094,10 @@ function _getNodesPerSegment(perimInterp, perimInd) {
48741
49094
  }
48742
49095
  return nodesPerSegment;
48743
49096
  }
48744
- function _getIndicatorArray(contour, numNodes) {
48745
- const perimInd = [];
48746
- for (let i = 0; i < numNodes - 2; i++) {
48747
- perimInd.push(false);
48748
- }
48749
- for (let i = 0; i < contour.x.length; i++) {
48750
- perimInd.push(true);
48751
- }
49097
+ function _getIndicatorArray(numFalse, numTrue) {
49098
+ const perimInd = new Array(numFalse + numTrue);
49099
+ perimInd.fill(false, 0, numFalse);
49100
+ perimInd.fill(true, numFalse, numFalse + numTrue);
48752
49101
  return perimInd;
48753
49102
  }
48754
49103
  function _getInterpolatedPerim(numNodes, cumPerimNorm) {
@@ -48855,6 +49204,7 @@ function deleteRelatedAnnotations(viewportData) {
48855
49204
  const {
48856
49205
  uuidv4
48857
49206
  } = utilities;
49207
+ const ChangeTypesForInterpolation = [ChangeTypes$1.HandlesUpdated, ChangeTypes$1.InterpolationUpdated];
48858
49208
  class InterpolationManager {
48859
49209
  static {
48860
49210
  this.toolNames = [];
@@ -48868,7 +49218,8 @@ class InterpolationManager {
48868
49218
  const {
48869
49219
  toolNames,
48870
49220
  segmentationId,
48871
- segmentIndex
49221
+ segmentIndex,
49222
+ sliceIndex
48872
49223
  } = selector;
48873
49224
  for (const toolName of toolNames || InterpolationManager.toolNames) {
48874
49225
  const annotations = getAnnotations(toolName, annotationGroupSelector);
@@ -48878,7 +49229,8 @@ class InterpolationManager {
48878
49229
  for (const annotation of annotations) {
48879
49230
  const {
48880
49231
  data,
48881
- autoGenerated
49232
+ autoGenerated,
49233
+ metadata
48882
49234
  } = annotation;
48883
49235
  if (!autoGenerated) {
48884
49236
  continue;
@@ -48886,6 +49238,9 @@ class InterpolationManager {
48886
49238
  if (segmentIndex && segmentIndex !== data.segmentation.segmentIndex) {
48887
49239
  continue;
48888
49240
  }
49241
+ if (sliceIndex !== undefined && metadata && sliceIndex !== metadata.referencedSliceIndex) {
49242
+ continue;
49243
+ }
48889
49244
  if (segmentationId && segmentationId !== data.segmentation.segmentationId) {
48890
49245
  continue;
48891
49246
  }
@@ -48958,7 +49313,7 @@ class InterpolationManager {
48958
49313
  const {
48959
49314
  toolName
48960
49315
  } = annotation.metadata;
48961
- if (!this.toolNames.includes(toolName) || changeType !== ChangeTypes$1.HandlesUpdated) {
49316
+ if (!this.toolNames.includes(toolName) || !ChangeTypesForInterpolation.includes(changeType)) {
48962
49317
  return;
48963
49318
  }
48964
49319
  const viewport = getViewportForAnnotation(annotation);
@@ -48972,7 +49327,8 @@ class InterpolationManager {
48972
49327
  viewport,
48973
49328
  sliceData,
48974
49329
  annotation,
48975
- interpolationUID: annotation.interpolationUID
49330
+ interpolationUID: annotation.interpolationUID,
49331
+ isInterpolationUpdate: changeType === ChangeTypes$1.InterpolationUpdated
48976
49332
  };
48977
49333
  interpolate(viewportData);
48978
49334
  };
@@ -49070,8 +49426,11 @@ var index = /*#__PURE__*/Object.freeze({
49070
49426
  detectContourHoles: detectContourHoles,
49071
49427
  findHandlePolylineIndex: findHandlePolylineIndex,
49072
49428
  generateContourSetsFromLabelmap: generateContourSetsFromLabelmap$2,
49429
+ getContourHolesDataCanvas: getContourHolesDataCanvas,
49430
+ getContourHolesDataWorld: getContourHolesDataWorld,
49073
49431
  interpolation: index$1,
49074
- mergePoints: mergePoints
49432
+ mergePoints: mergePoints,
49433
+ updateContourPolyline: updateContourPolyline
49075
49434
  });
49076
49435
 
49077
49436
  const MODES = [ToolModes$1.Active, ToolModes$1.Passive, ToolModes$1.Enabled];
@@ -49159,6 +49518,9 @@ function getAnnotations(toolName, annotationGroupSelector) {
49159
49518
  const groupKey = manager.getGroupKey(annotationGroupSelector);
49160
49519
  return manager.getAnnotations(groupKey, toolName);
49161
49520
  }
49521
+ function getParentAnnotation(annotation) {
49522
+ return annotation.parentAnnotationUID ? getAnnotation(annotation.parentAnnotationUID) : undefined;
49523
+ }
49162
49524
  function addAnnotation(annotation, annotationGroupSelector) {
49163
49525
  if (!annotation.annotationUID) {
49164
49526
  annotation.annotationUID = uuidv4$1();
@@ -49183,6 +49545,7 @@ function removeAnnotation(annotationUID) {
49183
49545
  if (!annotation) {
49184
49546
  return;
49185
49547
  }
49548
+ annotation.childAnnotationUIDs?.forEach(childAnnotationUID => removeAnnotation(childAnnotationUID));
49186
49549
  manager.removeAnnotation(annotationUID);
49187
49550
  const eventType = Events$1.ANNOTATION_REMOVED;
49188
49551
  const eventDetail = {
@@ -49196,6 +49559,13 @@ function getAnnotation(annotationUID) {
49196
49559
  const annotation = manager.getAnnotation(annotationUID);
49197
49560
  return annotation;
49198
49561
  }
49562
+ function invalidateAnnotation(annotation) {
49563
+ let currAnnotation = annotation;
49564
+ while (currAnnotation) {
49565
+ currAnnotation.invalidated = true;
49566
+ currAnnotation = currAnnotation.parentAnnotationUID ? getAnnotation(currAnnotation.parentAnnotationUID) : undefined;
49567
+ }
49568
+ }
49199
49569
 
49200
49570
  function getPatientModule(imageId, metadataProvider) {
49201
49571
  var generalSeriesModule = metadataProvider.get("generalSeriesModule", imageId);