Skip to content

sky_view_factor: horizon angle ignores cell size, wrong by factor of cell_size #1407

@brendancol

Description

@brendancol

Describe the bug

sky_view_factor computes horizon angles using ray distance in cells rather than ground units. The kernels (_svf_cpu and _svf_gpu in xrspatial/sky_view_factor.py) compute:

dz = elev - center
dist = float(r)            # r is the ray step index, in cells
elev_angle = atan2(dz, dist)

dz is in elevation units (typically meters); dist is in cells. For any DEM whose cell size is not 1.0 in the same unit as elevation, the ratio is wrong by a factor of cell_size.

Concrete example

A 30 m SRTM tile with cell size 30 m and a neighbor 30 m higher should give a horizon angle of atan(30/30) = 45°. The current code computes atan(30/1) ≈ 88°, which collapses SVF toward 0 even on gentle terrain.

For an aerial photogrammetry DEM at 0.5 m cell size with a neighbor 1 m above, the true angle is atan(1/0.5) ≈ 63.4°. The current code returns atan(1/1) = 45°.

Expected behavior

Read cell size from the DataArray (via get_dataarray_resolution from xrspatial.utils) and compute true ground distance per ray step:

ground_dx = r * dx * cellsize_x
ground_dy = r * dy * cellsize_y
dist = sqrt(ground_dx**2 + ground_dy**2)

Allow callers to pass explicit cellsize_x / cellsize_y overrides for cases where the DataArray lacks usable coordinates.

Why existing tests miss this

test_known_svf_simple_ramp uses cell size 0.5 with a z = x ramp but only asserts 0.5 < svf < 1.0. Both the buggy 45° angle and the correct 63.4° angle satisfy that band, so the bug slips through.

Scope

  • _svf_cpu (CPU kernel)
  • _svf_gpu (CUDA kernel)
  • _run_numpy, _run_cupy, _run_dask_numpy, _run_dask_cupy
  • Public sky_view_factor() API
  • Tests covering non-unit cell size and anisotropic cell size

Categories: Cat 4 (missing projection / cell-size correction)
Severity: HIGH

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions