Current section
Files
Jump to
Current section
Files
lib/topo/line_ring.ex
defmodule Topo.LineRing do
@moduledoc false
alias Topo.PointRing
alias Topo.Util
@spec intersects?(list, list) :: boolean
def intersects?(ring, line) do
Util.any_edge_pair_not?(ring, line, :disjoint) || contains?(ring, line)
end
@spec contains?(list, list) :: boolean
def contains?(ring, line) do
(PointRing.any_point?(ring, line, :interior) || any_midpoint_interior?(ring, line)) &&
!PointRing.any_point?(ring, line, :disjoint) &&
!any_segment?(ring, line, :interior)
end
defp any_midpoint_interior?(_, [_]), do: false
defp any_midpoint_interior?(a, [b1, b2 | rest]) do
PointRing.relate(a, Util.midpoint(b1, b2)) == :interior ||
any_midpoint_interior?(a, [b2 | rest])
end
defp any_segment?(_, [_], _), do: false
defp any_segment?(a, [b1, b2 | rest], relation) do
any_ring_segment?(a, b1, b2, relation) || any_segment?(a, [b2 | rest], relation)
end
defp any_ring_segment?([_], _, _, _), do: false
defp any_ring_segment?([a1, a2 | rest], b1, b2, relation) do
SegSeg.intersection(a1, a2, b1, b2, epsilon: Util.epsilon()) |> elem(1) == relation ||
any_ring_segment?([a2 | rest], b1, b2, relation)
end
@spec none_contain_line?(list, list) :: boolean
def none_contain_line?(rings, line) do
!Enum.any?(rings, fn ring ->
!Util.any_edge_pair_not?(ring, line, :disjoint) && contains?(ring, line)
end)
end
@spec line_exterior_to_all?(list, list) :: boolean
def line_exterior_to_all?(rings, line) do
Enum.all?(rings, fn ring ->
!Util.any_edge_pair?(ring, line, :interior) && PointRing.any_point?(ring, line, :disjoint)
end)
end
end