Packages

Geometry library for determining spatial relationships between geometries

Current section

Files

Jump to
topo lib topo util.ex
Raw

lib/topo/util.ex

defmodule Topo.Util do
@moduledoc false
@type point :: {number, number}
@spec cross(point, point, point) :: number
def cross({ax, ay}, {bx, by}, {cx, cy}) do
{ax - cx, ay - cy}
|> Vector.cross({bx - cx, by - cy})
|> Vector.component(:z)
end
@spec collinear?(point, point, point) :: boolean
def collinear?(a, b, c) do
cross(a, b, c) == 0
end
@spec between?(point, point, point) :: boolean
def between?({ax, ay}, {bx, by}, {px, py})
when ax == bx and ay == by and (px != ax and py != ay),
do: false
def between?({ax, ay}, {bx, by}, {_, py}) when ax == bx and ay != by,
do: (ay <= py && py <= by) || (ay >= py && py >= by)
def between?({ax, _}, {bx, _}, {px, _}), do: (ax <= px && px <= bx) || (ax >= px && px >= bx)
@spec assert_no_collinear(list) :: list
def assert_no_collinear([a, b, c | rest]) do
if collinear?(a, c, b) && between?(a, c, b) do
assert_no_collinear([a, c | rest])
else
[a] ++ assert_no_collinear([b, c | rest])
end
end
def assert_no_collinear(ring), do: ring
@spec midpoint(point, point) :: point
def midpoint(a, b) do
Vector.divide(Vector.add(a, b), 2)
end
@spec any_edge_pair_not?(list, list, atom) :: boolean
def any_edge_pair_not?(a, b, rel) do
do_any_edge_pair?(a, b, fn a1, a2, b1, b2 ->
elem(SegSeg.intersection(a1, a2, b1, b2), 1) != rel
end)
end
@spec any_edge_pair?(list, list, atom) :: boolean
def any_edge_pair?(a, b, rel) do
do_any_edge_pair?(a, b, fn a1, a2, b1, b2 ->
elem(SegSeg.intersection(a1, a2, b1, b2), 1) == rel
end)
end
@spec do_any_edge_pair?(list, list, function) :: boolean
defp do_any_edge_pair?(_, [_], _), do: false
defp do_any_edge_pair?(a, [b1, b2 | rest], fun) do
any_edge?(a, [b1, b2], fun) || do_any_edge_pair?(a, [b2 | rest], fun)
end
@spec any_edge?(list, list, function) :: boolean
defp any_edge?([_], _, _), do: false
defp any_edge?([a1, a2 | rest], [b1, b2], fun) do
fun.(a1, a2, b1, b2) || any_edge?([a2 | rest], [b1, b2], fun)
end
end