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
05fcb6f5be
commit
a774e98350
1 changed files with 29 additions and 0 deletions
|
|
@ -129,6 +129,7 @@ defmodule Microwaveprop.Terrain.Viewshed do
|
|||
{:exit, _} -> nil
|
||||
end)
|
||||
|> Enum.reject(&is_nil/1)
|
||||
|> smooth_boundary(lat, lon)
|
||||
|
||||
%{origin: %{lat: lat, lon: lon}, boundary: boundary}
|
||||
end
|
||||
|
|
@ -180,6 +181,34 @@ defmodule Microwaveprop.Terrain.Viewshed do
|
|||
Application.get_env(:microwaveprop, :srtm_tiles_dir, Path.expand("~/srtm/tiles"))
|
||||
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
|
||||
Enum.find_index(interior, & &1.obstructed)
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue