All files / packages/tools/src/utilities/planarFreehandROITool/interpolation interpolateSegmentPoints.ts

0% Statements 0/25
0% Branches 0/11
0% Functions 0/2
0% Lines 0/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91                                                                                                                                                                                     
import { Types } from '@cornerstonejs/core';
import { interpolatePoints } from './algorithms/bspline';
 
/**
 * Returns a list of uniform distributed values. This list contains the max amount of values which has at least a minimum distance between two consecutive values.
 * minDistributionDistance means the min distance between two consecutive distributed values.
 * Closed interval contains the min/max values.
 *
 * Formula for reference
 * For given {x ∈ R | x ≥ 0} and {minDis ∈ R | minDis ≥ 0}, ∃ D(x) where D(x) ≥ a and D(x) ≤ b  =>
 *         |
 * D(x)  = |                  (b - a)
 *         |  round( ------------------------ * x  )   + a
 *         |                (b - a + 1)
 *         |        round( -----------  )
 *         |                 minDis
 */
function getContinuousUniformDistributionValues(
  minDistributionDistance: number,
  closedInterval: [number, number]
): number[] {
  const result = [];
  const [intervalIni, intervalEnd] = closedInterval;
 
  const intervalSize = intervalEnd - intervalIni + 1;
  const intensity = Math.floor(intervalSize / minDistributionDistance);
 
  let x = 0;
  let continuosDistributionValue =
    Math.round(((intervalSize - 1) / (intensity - 1)) * x) + intervalIni;
 
  while (continuosDistributionValue <= intervalEnd) {
    result.push(continuosDistributionValue);
    x++;
    continuosDistributionValue =
      Math.round(((intervalSize - 1) / (intensity - 1)) * x) + intervalIni;
  }
 
  return result;
}
 
/**
 * Interpolates a segment of points from iniIndex until endIndex.
 * The process of interpolation considers the param knotsRatioPercentage as being the percentage of points from Segment that are likely to be considered.
 * By default it uses b-spline algorithm.
 * The result total of points is equal to original points.
 */
export default function interpolateSegmentPoints(
  points: (Types.Point2 | Types.Point3)[],
  iniIndex: number,
  endIndex: number,
  knotsRatioPercentage: number
): (Types.Point2 | Types.Point3)[] {
  const segmentSize = endIndex - iniIndex + 1;
 
  const amountOfKnots =
    Math.floor((knotsRatioPercentage / 100) * segmentSize) ?? 1;
  const minKnotDistance = Math.floor(segmentSize / amountOfKnots) ?? 1;
 
  if (isNaN(segmentSize) || !segmentSize || !minKnotDistance) {
    return points;
  }
 
  // segment should be at least the double of desired minKnot distance. This will ensure at there will enough knots to interpolate.
  if (segmentSize / minKnotDistance < 2) {
    return points;
  }
 
  const interpolationIniIndex = Math.max(0, iniIndex);
  const interpolationEndIndex = Math.min(points.length - 1, endIndex);
  const segmentPointsUnchangedBeg = points.slice(0, interpolationIniIndex);
 
  const segmentPointsUnchangedEnd = points.slice(
    interpolationEndIndex + 1,
    points.length
  );
 
  const knotsIndexes = getContinuousUniformDistributionValues(minKnotDistance, [
    interpolationIniIndex,
    interpolationEndIndex,
  ]);
 
  const interpolatedPoints = interpolatePoints(points, knotsIndexes);
 
  return [
    ...segmentPointsUnchangedBeg,
    ...interpolatedPoints,
    ...segmentPointsUnchangedEnd,
  ];
}