A ray fired from a fixed origin toward the mouse. The mirror line is placed on the right with a random orientation. At the hit point the surface normal is perpendicular to the line, and the reflection is the same d − 2(d·n)n as for the circle.
See also: Reflect a line off a circle — same reflection formula, different surface; Line-segment intersection — same ray/segment math.
// 1. Ray-segment intersection
// ray: P + t * D, t >= 0
// segment: A + u * S, S = B - A, u in [0, 1]
denom = D.x * S.y - D.y * S.x
if (denom == 0) return null // parallel
t = ((A.x - P.x) * S.y - (A.y - P.y) * S.x) / denom
u = ((A.x - P.x) * D.y - (A.y - P.y) * D.x) / denom
if (t < 0 || u < 0 || u > 1) return null
hit = P + D * t
// 2. Reflect direction about the line's normal
tangent = normalize(S)
n = (-tangent.y, tangent.x) // perpendicular
reflected = D - n * (2 * (D . n))
const ox = 20, oy = 150 // ray origin
const dx = mouseX - ox
const dy = mouseY - oy
// (ax, ay) -> (bx, by) is the mirror line, placed at a random angle on the right
const sx = bx - ax
const sy = by - ay
const denom = dx * sy - dy * sx
if (denom !== 0) {
const t = ((ax - ox) * sy - (ay - oy) * sx) / denom
const u = ((ax - ox) * dy - (ay - oy) * dx) / denom
if (t > 0 && u >= 0 && u <= 1) {
const hx = ox + dx * t
const hy = oy + dy * t
// perpendicular to the line, normalised
const lx = bx - ax, ly = by - ay
const llen = Math.sqrt(lx * lx + ly * ly)
const nx = -ly / llen
const ny = lx / llen
const dDotN = dx * nx + dy * ny
const rdx = dx - 2 * dDotN * nx
const rdy = dy - 2 * dDotN * ny
}
}