Current section

Files

Jump to
geocalc lib geocalc.ex
Raw

lib/geocalc.ex

defmodule Geocalc do
@earth_radius 6_371_000
@moduledoc """
Calculate distance, bearing and more between Latitude/Longitude points.
"""
@doc """
Calculates distance between 2 points.
Return distance in meters.
## Example
iex> berlin = [52.5075419, 13.4251364]
iex> paris = [48.8588589, 2.3475569]
iex> Geocalc.distance_between(berlin, paris)
878327.4291149472
iex> Geocalc.distance_between(paris, berlin)
878327.4291149472
"""
def distance_between([point_1_lat, point_1_lng], [point_2_lat, point_2_lng]) do
point_1_lat_rad = radian(point_1_lat)
point_2_lat_rad = radian(point_2_lat)
diff_lat = radian(point_2_lat - point_1_lat)
diff_lng = radian(point_2_lng - point_1_lng)
a = :math.sin(diff_lat / 2) * :math.sin(diff_lat / 2) + :math.cos(point_1_lat_rad) * :math.cos(point_2_lat_rad) * :math.sin(diff_lng / 2) * :math.sin(diff_lng / 2)
c = 2 * :math.atan2(:math.sqrt(a), :math.sqrt(1 - a))
@earth_radius * c
end
@doc """
Calculates bearing.
Return degrees from the range -180°..180°.
## Example
iex> berlin = [52.5075419, 13.4251364]
iex> paris = [48.8588589, 2.3475569]
iex> london = [51.5286416, -0.1015987]
iex> Geocalc.bearing(berlin, paris)
15.113303075326261
iex> Geocalc.bearing(paris, berlin)
82.85424470451336
iex> Geocalc.bearing(paris, london)
-110.99076100695387
"""
def bearing([point_1_lat, point_1_lng], [point_2_lat, point_2_lng]) do
y = :math.sin(point_2_lng - point_1_lng) * :math.cos(point_2_lat)
x = :math.cos(point_1_lat) * :math.sin(point_2_lat) - :math.sin(point_1_lat) * :math.cos(point_2_lat) * :math.cos(point_2_lng - point_1_lng)
degrees(:math.atan2(y, x))
end
defp radian(lat_or_lng) do
lat_or_lng * :math.pi / 180
end
defp degrees(radians) do
radians * 180 / :math.pi
end
end