Smooth viewshed boundary to remove SRTM elevation spikes
Apply 5-point circular moving average to reach_km values before rendering the boundary polygon. Eliminates sharp spikes caused by isolated terrain anomalies in SRTM data.
This commit is contained in:
parent
114f25a461
commit
d1e42dd8a0
1 changed files with 29 additions and 0 deletions
|
|
@ -129,6 +129,7 @@ defmodule Microwaveprop.Terrain.Viewshed do
|
||||||
{:exit, _} -> nil
|
{:exit, _} -> nil
|
||||||
end)
|
end)
|
||||||
|> Enum.reject(&is_nil/1)
|
|> Enum.reject(&is_nil/1)
|
||||||
|
|> smooth_boundary(lat, lon)
|
||||||
|
|
||||||
%{origin: %{lat: lat, lon: lon}, boundary: boundary}
|
%{origin: %{lat: lat, lon: lon}, boundary: boundary}
|
||||||
end
|
end
|
||||||
|
|
@ -180,6 +181,34 @@ defmodule Microwaveprop.Terrain.Viewshed do
|
||||||
Application.get_env(:microwaveprop, :srtm_tiles_dir, Path.expand("~/srtm/tiles"))
|
Application.get_env(:microwaveprop, :srtm_tiles_dir, Path.expand("~/srtm/tiles"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Smooth reach_km values with a circular moving average to remove spikes
|
||||||
|
# from SRTM elevation artifacts, then recompute boundary lat/lon.
|
||||||
|
defp smooth_boundary(points, _origin_lat, _origin_lon) when length(points) < 5, do: points
|
||||||
|
|
||||||
|
defp smooth_boundary(points, origin_lat, origin_lon) do
|
||||||
|
reaches = Enum.map(points, & &1.reach_km)
|
||||||
|
n = length(reaches)
|
||||||
|
arr = :array.from_list(reaches)
|
||||||
|
half = 2
|
||||||
|
|
||||||
|
smoothed_reaches =
|
||||||
|
Enum.map(0..(n - 1), fn i ->
|
||||||
|
window =
|
||||||
|
for offset <- -half..half do
|
||||||
|
:array.get(rem(i + offset + n, n), arr)
|
||||||
|
end
|
||||||
|
|
||||||
|
Enum.sum(window) / length(window)
|
||||||
|
end)
|
||||||
|
|
||||||
|
points
|
||||||
|
|> Enum.zip(smoothed_reaches)
|
||||||
|
|> Enum.map(fn {pt, reach} ->
|
||||||
|
{lat, lon} = destination_point(origin_lat, origin_lon, pt.bearing, reach)
|
||||||
|
%{pt | reach_km: reach, lat: lat, lon: lon}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defp find_first_obstructed_index(interior) do
|
defp find_first_obstructed_index(interior) do
|
||||||
Enum.find_index(interior, & &1.obstructed)
|
Enum.find_index(interior, & &1.obstructed)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue