Skip to content

Instantly share code, notes, and snippets.

@steveruizok
Last active May 13, 2022 06:28
Show Gist options
  • Save steveruizok/4bd2341417ae707e67a36e4ef0089194 to your computer and use it in GitHub Desktop.
Save steveruizok/4bd2341417ae707e67a36e4ef0089194 to your computer and use it in GitHub Desktop.
Get outer tangents of two circles.
function getOuterTangents(
x0: number,
y0: number,
r0: number,
x1: number,
y1: number,
r1: number
) {
const dx = x1 - x0,
dy = y1 - y0,
dist = Math.hypot(dx, dy)
// Circles are overlapping, no tangents
if (dist < Math.abs(r1 - r0)) return
const a0 = Math.atan2(dy, dx),
a1 = Math.acos((r0 - r1) / dist)
return [
x0 + r0 * Math.cos(a0 + a1),
y0 + r0 * Math.sin(a0 + a1),
x1 + r1 * Math.cos(a0 + a1),
y1 + r1 * Math.sin(a0 + a1),
x0 + r0 * Math.cos(a0 - a1),
y0 + r0 * Math.sin(a0 - a1),
x1 + r1 * Math.cos(a0 - a1),
y1 + r1 * Math.sin(a0 - a1),
]
}
/**
* Get the outer tangents of two circles. This better preserves the positions of the four tangents.
*
* @example
* t0______t1 t3______t2
* (A) -> (B) (B) <- (A)
* t2 ‾‾‾‾‾t3 t1 ‾‾‾‾‾t0
*
* @param A The first circle.
* @param rA The first radius.
* @param B The second circle.
* @param rB The second radius.
* @returns The outer tangents of the circles.
*/
export function getCircleOuterTangents(
A: VecLike,
r0: number,
B: VecLike,
r1: number
): Vec2dModel[] {
const gamma = Math.atan((A.y - B.y) / (B.x - A.x))
const beta = Math.sin((r1 - r0) / Math.hypot(A.y - B.y, A.x - B.x))
let result = [
{
x: A.x + r0 * Math.cos(TAU - (gamma - beta)),
y: A.y + r0 * Math.sin(TAU - (gamma - beta)),
},
{
x: B.x + r1 * Math.cos(TAU - (gamma - beta)),
y: B.y + r1 * Math.sin(TAU - (gamma - beta)),
},
{
x: A.x + r0 * Math.cos(-(TAU + (gamma + beta))),
y: A.y + r0 * Math.sin(-(TAU + (gamma + beta))),
},
{
x: B.x + r1 * Math.cos(-(TAU + (gamma + beta))),
y: B.y + r1 * Math.sin(-(TAU + (gamma + beta))),
},
]
if (A.x <= B.x) {
result = result.concat(result.splice(0, 2))
}
return result
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment