Skip to content

Instantly share code, notes, and snippets.

@zkessin
Created March 9, 2023 22:42
Show Gist options
  • Save zkessin/5ff0734a6f39f354c2639374e002dce7 to your computer and use it in GitHub Desktop.
Save zkessin/5ff0734a6f39f354c2639374e002dce7 to your computer and use it in GitHub Desktop.
defmodule LineCircleIntersection do
@type point() :: {number, number}
@spec intersection([point()], point(), number()) :: [point()] | nil
def intersection([{x1, y1}, {x2, y2}], {cx, cy}, r) when is_number(r) do
dx = x2 - x1
dy = y2 - y1
dr = :math.sqrt(dx * dx + dy * dy)
matrix = x1 * y2 - x2 * y1
discriminant = square(r) * square(dr) - square(matrix)
if discriminant < 0 do
nil
else
x_1 = (matrix * dy + sign(dy) * dx * :math.sqrt(discriminant)) / (dr * dr)
x_2 = (matrix * dy - sign(dy) * dx * :math.sqrt(discriminant)) / (dr * dr)
y_1 = (-matrix * dx + abs(dy) * :math.sqrt(discriminant)) / (dr * dr)
y_2 = (-matrix * dx - abs(dy) * :math.sqrt(discriminant)) / (dr * dr)
[{x_1 + cx, y_1 + cy}, {x_2 + cx, y_2 + cy}]
end
end
defp square(x), do: x * x
defp sign(x) do
if x < 0 do
-1
else
1
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment