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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 2225x 2225x 2225x 2225x 2225x 2225x 2225x 2225x 2225x 2225x 2223x 2x 2x 2x 8x 8x 4x 4x | import type { Types } from '@cornerstonejs/core';
// ATTENTION: this is an internal function and it should not be added to "polyline"
// namespace.
//
// TODO: there is a similar function in math.lineSegment.intersectLine but we
// need to investigate why it is 6x slower than this one when thousands of
// intersections are calculated. Also that one may return [NaN, NaN] for
// collinear points.
/**
* Checks whether the line (`p1`,`q1`) intersects the line (`p2`,`q2`) via an
* orientation algorithm.
*
* Credit and details: geeksforgeeks.org/check-if-two-given-line-segments-intersect/
*
* @param p1 - Start point of line segment 1
* @param q1 - End point of line segment 1
* @param p2 - Start point of line segment 2
* @param q2 - End point of line segment 2
* @returns True if the line segments intersect or false otherwise
*/
export default function areLineSegmentsIntersecting(
p1: Types.Point2,
q1: Types.Point2,
p2: Types.Point2,
q2: Types.Point2
): boolean {
let result = false;
// Line 1 AABB
const line1MinX = p1[0] < q1[0] ? p1[0] : q1[0];
const line1MinY = p1[1] < q1[1] ? p1[1] : q1[1];
const line1MaxX = p1[0] > q1[0] ? p1[0] : q1[0];
const line1MaxY = p1[1] > q1[1] ? p1[1] : q1[1];
// Line 2 AABB
const line2MinX = p2[0] < q2[0] ? p2[0] : q2[0];
const line2MinY = p2[1] < q2[1] ? p2[1] : q2[1];
const line2MaxX = p2[0] > q2[0] ? p2[0] : q2[0];
const line2MaxY = p2[1] > q2[1] ? p2[1] : q2[1];
// If AABBs do not intersect it is impossible for the lines to intersect.
// Checking AABB before doing any math makes it run ~12% faster.
if (
line1MinX > line2MaxX ||
line1MaxX < line2MinX ||
line1MinY > line2MaxY ||
line1MaxY < line2MinY
) {
return false;
}
const orient = [
orientation(p1, q1, p2),
orientation(p1, q1, q2),
orientation(p2, q2, p1),
orientation(p2, q2, q1),
];
// General Case
Eif (orient[0] !== orient[1] && orient[2] !== orient[3]) {
return true;
}
// Special Cases
if (orient[0] === 0 && onSegment(p1, p2, q1)) {
// If p1, q1 and p2 are colinear and p2 lies on segment p1q1
result = true;
} else if (orient[1] === 0 && onSegment(p1, q2, q1)) {
// If p1, q1 and p2 are colinear and q2 lies on segment p1q1
result = true;
} else if (orient[2] === 0 && onSegment(p2, p1, q2)) {
// If p2, q2 and p1 are colinear and p1 lies on segment p2q2
result = true;
} else if (orient[3] === 0 && onSegment(p2, q1, q2)) {
// If p2, q2 and q1 are colinear and q1 lies on segment p2q2
result = true;
}
return result;
}
/**
* Checks the orientation of 3 points, returns a 0, 1 or 2 based on
* the orientation of the points.
*/
function orientation(
p: Types.Point2,
q: Types.Point2,
r: Types.Point2
): number {
// Take the cross product between vectors PQ and QR
const orientationValue =
(q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);
if (orientationValue === 0) {
return 0; // Colinear
}
return orientationValue > 0 ? 1 : 2;
}
/**
* Checks if point `q` lies on the segment (`p`,`r`).
*/
function onSegment(p: Types.Point2, q: Types.Point2, r: Types.Point2): boolean {
if (
q[0] <= Math.max(p[0], r[0]) &&
q[0] >= Math.min(p[0], r[0]) &&
q[1] <= Math.max(p[1], r[1]) &&
q[1] >= Math.min(p[1], r[1])
) {
return true;
}
return false;
}
|