defmodule RayCasting do @moduledoc """ A Ray Casting algorithm for Elixir. This module contains the Application that you can use to perform solutions for some problems like: - To know if a coordinate exists inside a polygon - To know if a coordinate exists outside a polygon """ @doc """ Ray Casting """ def rayCasting(path, point) do crossings = 0 {x, _y} = Enum.map_reduce(path, 0, fn _item, acc -> a = Enum.at(path, acc) b = Enum.at(path, acc + 1) if (a == List.last(path)) do b = Enum.at(path, 0) end if rayCrossesSegment(point, a, b) do crossings = crossings + 1 end acc = acc + 1 {crossings, acc} end) crossings = List.last(x) rem(crossings, 2) == 1 end defp rayCrossesSegment(point, a, b) do px = point.lng py = point.lat ax = a.lng ay = a.lat bx = b.lng by = b.lat if (ay > by) do ax = b.lng ay = b.lat bx = a.lng by = a.lat end if (px < 0), do: px = px + 360 if (ax < 0), do: ax = ax + 360 if (bx < 0), do: bx = bx + 360 if (py == ay || py == by), do: py = py + 0.00000001 if (ax != bx) do red = ((by - ay) / (bx - ax)) else red = Infinity end if (ax != px) do blue = ((py - ay) / (px - ax)) else blue = Infinity end cond do ((py > by || py < ay) || (px > max(ax, bx))) -> false (px < min(ax, bx)) -> true blue >= red -> true true -> true end end end