Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lostPixels/191c13206bd93b8fed386fe05012432a to your computer and use it in GitHub Desktop.
Save lostPixels/191c13206bd93b8fed386fe05012432a to your computer and use it in GitHub Desktop.
Calculate ray and circle reflection points
/**
* 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