Skip to content

Instantly share code, notes, and snippets.

@zkessin
Created March 9, 2023 22:44
Show Gist options
  • Save zkessin/2f1f35c032406d41e332261afff7c01e to your computer and use it in GitHub Desktop.
Save zkessin/2f1f35c032406d41e332261afff7c01e to your computer and use it in GitHub Desktop.
defmodule LineCircle 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
test "sholder" do
a = {3575.2, 2526.5}
b = {2567.2, 2526.5}
center = {2600.24, 2601.4}
radius = 52 * 72
assert [p1, p2] = LineCircle.intersection([a, b], center, radius)|> IO.inspect()
assert y(p1) == 2526.5
# Y == 2127.9 here
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment