Skip to content

Instantly share code, notes, and snippets.

@whatisaphone
Created December 27, 2018 13:44
Show Gist options
  • Save whatisaphone/3c179a548427d19831b81b0f867bba5d to your computer and use it in GitHub Desktop.
Save whatisaphone/3c179a548427d19831b81b0f867bba5d to your computer and use it in GitHub Desktop.
circle_point_tangents
/// Returns the two points on a circle that form a tangent with the given point.
///
/// If the point is inside the circle, returns `None`.
pub fn circle_point_tangents(
center: Point2<f32>,
radius: f32,
point: Point2<f32>,
) -> Option<[Point2<f32>; 2]> {
// I'm so glad the internet exists
// http://www.ambrsoft.com/TrigoCalc/Circles2/CirclePoint/CirclePointDistance.htm
let a = center.x;
let b = center.y;
let r = radius;
let xp = point.x;
let yp = point.y;
let xpm = r * (yp - b) * ((xp - a).powi(2) + (yp - b).powi(2) - r.powi(2)).sqrt();
let x1 = (r.powi(2) * (xp - a) + xpm) / ((xp - a).powi(2) + (yp - b).powi(2)) + a;
let x2 = (r.powi(2) * (xp - a) - xpm) / ((xp - a).powi(2) + (yp - b).powi(2)) + a;
let ymp = r * (xp - a) * ((xp - a).powi(2) + (yp - b).powi(2) - r.powi(2)).sqrt();
let y1 = (r.powi(2) * (yp - b) - ymp) / ((xp - a).powi(2) + (yp - b).powi(2)) + b;
let y2 = (r.powi(2) * (yp - b) + ymp) / ((xp - a).powi(2) + (yp - b).powi(2)) + b;
if x1.is_nan() {
None
} else {
Some([Point2::new(x1, y1), Point2::new(x2, y2)])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment