It would be nice to have a ray tracing component or hittest method. Posting Joseph's code here for reference.
const Intersection = {
ofLines: function (ptA, ptB, ptC, ptD, lineSegmentOnly) {
if ((ptA.x === ptB.x && ptA.y === ptB.y) || (ptC.x === ptD.x && ptC.y === ptD.y)) {
return null;
}
const denominator = ((ptD.y - ptC.y) * (ptB.x - ptA.x) - (ptD.x - ptC.x) * (ptB.y - ptA.y));
// Lines are parallel
if (denominator === 0) {
return null;
}
const ua = ((ptD.x - ptC.x) * (ptA.y - ptC.y) - (ptD.y - ptC.y) * (ptA.x - ptC.x)) / denominator;
// Check if the intersection point is within the bounds of the line segments if required
if (lineSegmentOnly) {
const ub = ((ptB.x - ptA.x) * (ptA.y - ptC.y) - (ptB.y - ptA.y) * (ptA.x - ptC.x)) / denominator;
if (ua < 0 || ua > 1 || ub < 0 || ub > 1) {
return null;
}
}
// Return an object with the x and y coordinates of the intersection
const x = ptA.x + ua * (ptB.x - ptA.x);
const y = ptA.y + ua * (ptB.y - ptA.y);
return {x, y};
},
ofRectAndExitingRay: function (ptA, ptB, rect) {
const lineLen = Math.sqrt((ptB.x - ptA.x) ** 2 + (ptB.y - ptA.y) ** 2);
// 1.42 ensures the minimum value necessary to reach outside the rect (just exceeds hypotenuse)
const rayLen = Math.max(rect.width, rect.height) * 1.42;
const extendX = (ptB.x - ptA.x) / lineLen * rayLen;
const extendY = (ptB.y - ptA.y) / lineLen * rayLen;
const farPt = {x: ptA.x + extendX, y: ptA.y + extendY};
// Define the bounding box to test
const rectCornerPts = [
{x: 0, y: 0},
{x: rect.width, y: 0},
{x: rect.width, y: rect.height},
{x: 0, y: rect.height}
];
let intersectionPt = null;
for (let i = 1; i <= rectCornerPts.length && intersectionPt == null; ++i) {
const edgePtA = rectCornerPts[i - 1];
const edgePtB = rectCornerPts[i % rectCornerPts.length];
intersectionPt = this.ofLines(ptA, farPt, edgePtA, edgePtB, true);
}
return intersectionPt;
}
}