Current section
Files
Jump to
Current section
Files
lib/geomeasure/extent.ex
defmodule GeoMeasure.Extent do
@moduledoc false
alias GeoMeasure.Utils
@spec calculate_extent([{number, number}]) :: {number, number, number, number}
def calculate_extent(coords) do
coords
|> Enum.reduce({nil, nil, nil, nil}, fn {x, y}, {min_x, max_x, min_y, max_y} ->
Utils.tuple_not_nil!({x, y})
{
min_x |> min_or_init(x),
max_x |> max_or_init(x),
min_y |> min_or_init(y),
max_y |> max_or_init(y)
}
end)
end
@spec calculate_extent_3d([{number, number, number}]) ::
{number, number, number, number, number, number}
def calculate_extent_3d(coords) do
coords
|> Enum.reduce({nil, nil, nil, nil, nil, nil}, fn {x, y, z},
{min_x, max_x, min_y, max_y, min_z, max_z} ->
Utils.tuple_not_nil!({x, y, z})
{
min_x |> min_or_init(x),
max_x |> max_or_init(x),
min_y |> min_or_init(y),
max_y |> max_or_init(y),
min_z |> min_or_init(z),
max_z |> max_or_init(z)
}
end)
end
@spec min_or_init(nil, number) :: number | nil
defp min_or_init(nil, val), do: val
@spec min_or_init(number, number) :: number
defp min_or_init(current, val), do: min(current, val)
@spec max_or_init(nil, number) :: number | nil
defp max_or_init(nil, val), do: val
@spec max_or_init(number, number) :: number
defp max_or_init(current, val), do: max(current, val)
@doc """
Calculates the extent coordinates of a Geo struct.
"""
@doc since: "0.0.1"
@spec calculate(Geo.LineString.t()) :: {number, number, number, number}
def calculate(%Geo.LineString{coordinates: coords}) do
calculate_extent(coords)
end
@spec calculate(Geo.LineStringM.t()) :: {number, number, number, number}
def calculate(%Geo.LineStringM{coordinates: coords}) do
coords
|> Utils.remove_m_values()
|> calculate_extent()
end
@spec calculate(Geo.LineStringZ.t()) :: {number, number, number, number, number, number}
def calculate(%Geo.LineStringZ{coordinates: coords}) do
calculate_extent_3d(coords)
end
@spec calculate(Geo.LineStringZM.t()) :: {number, number, number, number, number, number}
def calculate(%Geo.LineStringZM{coordinates: coords}) do
coords
|> Utils.remove_m_values()
|> calculate_extent_3d()
end
@spec calculate(Geo.Polygon.t()) :: {number, number, number, number}
def calculate(%Geo.Polygon{coordinates: coords}) do
coords
|> hd()
|> tl()
|> calculate_extent()
end
@spec calculate(Geo.PolygonZ.t()) :: {number, number, number, number, number, number}
def calculate(%Geo.PolygonZ{coordinates: coords}) do
coords
|> hd()
|> tl()
|> calculate_extent_3d()
end
end