Created
July 22, 2024 12:25
-
-
Save lostPixels/191c13206bd93b8fed386fe05012432a to your computer and use it in GitHub Desktop.
Calculate ray and circle reflection points
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Calculates whether a ray intersects a circle. If it does, it returns the intersection point, the angle of reflection, and the distance from the origin of the ray. | |
* @param {Object} origin {x, y} | |
* @param {Number} angle | |
* @param {Object} circle {x, y, r} | |
* @returns {Object} {x, y, angle, dist} | null | |
* | |
*/ | |
const rayCircleIntersection = (origin, angle, circle) => { | |
let x1 = origin.x; | |
let y1 = origin.y; | |
let x2 = origin.x + cos(angle); | |
let y2 = origin.y + sin(angle); | |
let cx = circle.x; | |
let cy = circle.y; | |
let r = circle.r / 4; | |
let dx = x2 - x1; | |
let dy = y2 - y1; | |
let fx = x1 - cx; | |
let fy = y1 - cy; | |
let a = dx * dx + dy * dy; | |
let b = 2 * (fx * dx + fy * dy); | |
let c = fx * fx + fy * fy - r * r; | |
let discriminant = b * b - 4 * a * c; | |
if (discriminant >= 0) { | |
discriminant = sqrt(discriminant); | |
let t1 = (-b - discriminant) / (2 * a); | |
let t2 = (-b + discriminant) / (2 * a); | |
//console.log(t1, t2) | |
//if (t1 >= 0 && t1 <= 1) { | |
if (t1 >= 0 && t2 <= 1) { | |
let intersectionPoint = { | |
x: x1 + t1 * dx, | |
y: y1 + t1 * dy | |
}; | |
let normal = { | |
x: (intersectionPoint.x - cx) / r, | |
y: (intersectionPoint.y - cy) / r | |
}; | |
let incidentAngle = atan2(dy, dx); | |
let reflectionAngle = 2 * atan2(normal.y, normal.x) - incidentAngle + PI; | |
//console.log('incident', incidentAngle) | |
return { | |
x: intersectionPoint.x, | |
y: intersectionPoint.y, | |
angle: reflectionAngle, | |
dist: dist(origin.x, origin.y, intersectionPoint.x, intersectionPoint.y) | |
}; | |
} | |
else if (t1 <= 0 && t2 >= 1) { | |
let intersectionPoint = { | |
x: x1 + t2 * dx, | |
y: y1 + t2 * dy | |
}; | |
let normal = { | |
x: (intersectionPoint.x - cx) / r, | |
y: (intersectionPoint.y - cy) / r | |
}; | |
let incidentAngle = atan2(dy, dx); | |
let reflectionAngle = 2 * atan2(normal.y, normal.x) - incidentAngle; | |
console.log('incident', incidentAngle) | |
return { | |
x: intersectionPoint.x, | |
y: intersectionPoint.y, | |
angle: reflectionAngle, | |
dist: dist(origin.x, origin.y, intersectionPoint.x, intersectionPoint.y) | |
}; | |
} | |
} | |
return null; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment