diff --git a/lib/microwaveprop/rover/elevation.ex b/lib/microwaveprop/rover/elevation.ex new file mode 100644 index 00000000..ff4ee8fd --- /dev/null +++ b/lib/microwaveprop/rover/elevation.ex @@ -0,0 +1,23 @@ +defmodule Microwaveprop.Rover.Elevation do + @moduledoc """ + Bulk SRTM elevation lookup for a list of `{lat, lon}` points. + + Wraps `Microwaveprop.Terrain.Srtm.lookup/3`, which already opens and + reads each tile per call. Cells whose tile is missing or whose value + is the SRTM void sentinel are mapped to `nil`. + """ + + alias Microwaveprop.Terrain.Srtm + + @spec lookup_many([{float(), float()}]) :: %{{float(), float()} => integer() | nil} + def lookup_many(points) when is_list(points) do + tiles_dir = Application.get_env(:microwaveprop, :srtm_tiles_dir, "/data/srtm") + + Map.new(points, fn {lat, lon} = key -> + case Srtm.lookup(lat, lon, tiles_dir) do + {:ok, elev} -> {key, elev} + {:error, _} -> {key, nil} + end + end) + end +end diff --git a/test/microwaveprop/rover/elevation_test.exs b/test/microwaveprop/rover/elevation_test.exs new file mode 100644 index 00000000..6f0ac200 --- /dev/null +++ b/test/microwaveprop/rover/elevation_test.exs @@ -0,0 +1,41 @@ +defmodule Microwaveprop.Rover.ElevationTest do + use ExUnit.Case, async: false + + alias Microwaveprop.Rover.Elevation + + setup do + tmp = Path.join(System.tmp_dir!(), "rover_elev_#{System.unique_integer([:positive])}") + File.mkdir_p!(tmp) + prev = Application.get_env(:microwaveprop, :srtm_tiles_dir) + Application.put_env(:microwaveprop, :srtm_tiles_dir, tmp) + + on_exit(fn -> + File.rm_rf!(tmp) + + if prev do + Application.put_env(:microwaveprop, :srtm_tiles_dir, prev) + else + Application.delete_env(:microwaveprop, :srtm_tiles_dir) + end + end) + + :ok + end + + describe "lookup_many/1" do + test "returns map keyed by {lat, lon}, nil values when no tiles available" do + points = [{33.0, -96.0}, {30.0, -97.0}] + result = Elevation.lookup_many(points) + + assert is_map(result) + assert Map.has_key?(result, {33.0, -96.0}) + assert Map.has_key?(result, {30.0, -97.0}) + assert result[{33.0, -96.0}] == nil + assert result[{30.0, -97.0}] == nil + end + + test "empty list returns empty map" do + assert Elevation.lookup_many([]) == %{} + end + end +end