Skip to content

Fix horizon angle calculation for distant terrain #75

Open
rafaqz wants to merge 3 commits into
Deltares:mainfrom
rafaqz:restrict_bad_horizon_angles
Open

Fix horizon angle calculation for distant terrain #75
rafaqz wants to merge 3 commits into
Deltares:mainfrom
rafaqz:restrict_bad_horizon_angles

Conversation

@rafaqz
Copy link
Copy Markdown
Contributor

@rafaqz rafaqz commented May 29, 2026

I messed up the algorithm a bit.

The sweep used (prev_elev - elev) / dist against only the immediate predecessor cell, with max_tan accumulated across the entire ray. So:

  1. Distant peaks invisible
  2. Visible stripes from the max_tan accumulation

The fix walks every visible cell back along the ray at each position and divides by the actual distance (k * dist). NaN cells reset the visible_start index so terrain past a NaN is hidden. Allocation-free; O(N²) per ray.

Also adds a small check to block multiple of 8 e.g. 24 angles slipping through that could erroneously work previously.

@evetion
Copy link
Copy Markdown
Member

evetion commented May 29, 2026

I thought this algorithm was missing something, good to fix this. Can you also take a look at #64?

@rafaqz
Copy link
Copy Markdown
Contributor Author

rafaqz commented May 29, 2026

Yep will take a look. I need it anyway

@evetion
Copy link
Copy Markdown
Member

evetion commented May 29, 2026

Why would NaN block the horizon? That is assuming it is Inf (instead of -Inf before). Could we make it configurable?

Also, seeing my old reply in previous PR #59 (comment), I would love to re-use these kernels to calculate a viewshed, which is 99% the same, it's just changing the output to a bool. Any thoughts on such a refactor? I rather not duplicate kernels, but not sure if adding an if/else for a different output (type) is wise here.

Comment thread src/horizon.jl
max_tan = max(max_tan, tan_angle)
tan_angle = (prev_elev - elev_pos) / (k * dist)
if tan_angle > max_tan
max_tan = tan_angle
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding out[r, c] = True here would give you a viewshed.

@rafaqz
Copy link
Copy Markdown
Contributor Author

rafaqz commented May 29, 2026

Re NaN: I wondered that too. What is the height of NaN. You could assume zero is more often accurate? (the sea often missing). We can make it a keyword.

We can totally share the kernel, just type it with a struct and the if/else will compile away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants