All files / packages/tools/src/utilities/polyData utils.ts

0% Statements 0/39
0% Branches 0/10
0% Functions 0/6
0% Lines 0/37

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                                                                                                                                                                                   
import vtkPolyData from '@kitware/vtk.js/Common/DataModel/PolyData';
import type { Types } from '@cornerstonejs/core';
import { vec3 } from 'gl-matrix';
 
/**
 * Gets a point from an array of numbers given its index
 * @param points - array of number, each point defined by three consecutive numbers
 * @param idx - index of the point to retrieve
 * @returns
 */
export function getPoint(points, idx): Types.Point3 {
  const idx3 = idx * 3;
  if (idx3 < points.length) {
    return vec3.fromValues(
      points[idx3],
      points[idx3 + 1],
      points[idx3 + 2]
    ) as Types.Point3;
  }
}
 
/**
 * Extract contour point sets from the outline of a poly data actor
 * @param polyData - vtk polyData
 * @returns
 */
export function getPolyDataPointIndexes(polyData: vtkPolyData) {
  const linesData = polyData.getLines().getData();
  let idx = 0;
  const lineSegments = new Map<number, number[]>();
 
  // Populate lineSegments map
  while (idx < linesData.length) {
    const segmentSize = linesData[idx++];
    const segment = [];
    for (let i = 0; i < segmentSize; i++) {
      segment.push(linesData[idx + i]);
    }
    lineSegments.set(segment[0], segment);
    idx += segmentSize;
  }
 
  const contours = [];
 
  // Function to find an available starting point
  const findStartingPoint = (map) => {
    for (const [key, value] of map.entries()) {
      if (value !== undefined) {
        return key;
      }
    }
    return -1;
  };
 
  // Build contours
  let startPoint = findStartingPoint(lineSegments);
  while (startPoint !== -1) {
    const contour = [startPoint];
    while (lineSegments.has(startPoint)) {
      const nextPoint = lineSegments.get(startPoint)[1];
      if (lineSegments.has(nextPoint)) {
        contour.push(nextPoint);
      }
      lineSegments.delete(startPoint);
      startPoint = nextPoint;
    }
    contours.push(contour);
    startPoint = findStartingPoint(lineSegments);
  }
 
  return contours.length ? contours : undefined;
}
 
/**
 * Extract contour points from a poly data object
 * @param polyData - vtk polyData
 * @returns
 */
export function getPolyDataPoints(polyData: vtkPolyData) {
  const contoursIndexes = getPolyDataPointIndexes(polyData);
  if (!contoursIndexes) {
    return;
  }
 
  const rawPointsData = polyData.getPoints().getData();
  return contoursIndexes.map((contourIndexes) =>
    contourIndexes.map((index) => getPoint(rawPointsData, index))
  );
}