All files / packages/tools/src/utilities/math/polyline getClosestLineSegmentIntersection.ts

0% Statements 0/23
0% Branches 0/7
0% Functions 0/2
0% Lines 0/22

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                                                                                                                                                 
import { vec2 } from 'gl-matrix';
import type { Types } from '@cornerstonejs/core';
import areLineSegmentsIntersecting from './areLineSegmentsIntersecting';
 
/**
 * Checks whether the line (`p1`,`q1`) intersects any of the other lines in the
 * `points`, and returns the closest value.
 * @param points - Polyline points
 * @param p1 - Start point of the line segment
 * @param q1 - End point of the line segment
 * @param closed - Test the intersection against the line that connects the first to the last when closed
 * @returns The closest line segment from polyline that intersects the line segment [p1, q1]
 */
export default function getClosestLineSegmentIntersection(
  points: Types.Point2[],
  p1: Types.Point2,
  q1: Types.Point2,
  closed = true
): { segment: Types.Point2; distance: number } | undefined {
  let initialQ2Index;
  let p2Index;
 
  if (closed) {
    p2Index = points.length - 1;
    initialQ2Index = 0;
  } else {
    p2Index = 0;
    initialQ2Index = 1;
  }
 
  const intersections = [];
 
  for (let q2Index = initialQ2Index; q2Index < points.length; q2Index++) {
    const p2 = points[p2Index];
    const q2 = points[q2Index];
 
    if (areLineSegmentsIntersecting(p1, q1, p2, q2)) {
      intersections.push([p2Index, q2Index]);
    }
 
    p2Index = q2Index;
  }
 
  if (intersections.length === 0) {
    return;
  }
 
  // Find intersection closest to the start point
  const distances = [];
 
  intersections.forEach((intersection) => {
    const intersectionPoints = [
      points[intersection[0]],
      points[intersection[1]],
    ];
 
    const midpoint = [
      (intersectionPoints[0][0] + intersectionPoints[1][0]) / 2,
      (intersectionPoints[0][1] + intersectionPoints[1][1]) / 2,
    ];
 
    distances.push(vec2.distance(<vec2>midpoint, p1));
  });
 
  const minDistance = Math.min(...distances);
  const indexOfMinDistance = distances.indexOf(minDistance);
 
  return {
    segment: intersections[indexOfMinDistance],
    distance: minDistance,
  };
}