Skip to content

Commit ca1b4ab

Browse files
committed
Return all-NaN from HPA* when a segment cannot be refined (#3631)
A failed refinement used to return the partially written path image, so an unreachable goal produced a finite cost trail that dead-ends mid-grid while every other search path returns all NaN for no-path. Return a fresh all-NaN surface instead.
1 parent b9ba8a8 commit ca1b4ab

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

xrspatial/pathfinding.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,11 @@ def _hpa_star_search(surface_data, friction_data, start_py, start_px,
520520
local_gy = g_py - min_row
521521
local_gx = g_px - min_col
522522
if sub_path is None or not np.isfinite(sub_path[local_gy, local_gx]):
523-
return path_img # partial result
523+
# Refinement could not connect this segment even at the
524+
# largest radius. Return all-NaN ("no path found") rather
525+
# than a partial cost trail that dead-ends mid-grid, matching
526+
# the no-path contract of the other search paths.
527+
return np.full((h, w), np.nan, dtype=np.float64)
524528

525529
seg_goal_cost = sub_path[local_gy, local_gx]
526530
sh, sw = sub_path.shape

xrspatial/tests/test_pathfinding.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,29 @@ def test_hpa_star_correctness():
699699
assert (r, c) != (np.nan, np.nan)
700700

701701

702+
def test_hpa_star_unreachable_goal_all_nan():
703+
"""HPA* returns all-NaN when no path exists, not a partial trail.
704+
705+
The coarse grid sees blocks containing a thin NaN wall as passable
706+
(each block still has valid cells), so the coarse route crosses the
707+
wall and refinement fails. The output must follow the no-path
708+
contract (all NaN) instead of keeping the already-refined segments.
709+
"""
710+
H = W = 200
711+
data = np.ones((H, W))
712+
data[:, 100] = np.nan # complete wall: goal unreachable
713+
714+
dy, dx, dd = _neighborhood_structure(1.0, 1.0, 8)
715+
barriers = np.array([], dtype=np.float64)
716+
717+
path_img = _hpa_star_search(
718+
data, None, 0, 0, 199, 199,
719+
barriers, dy, dx, dd,
720+
1.0, False, 1.0, 1.0, H, W)
721+
722+
assert not np.isfinite(path_img).any()
723+
724+
702725
def test_auto_radius_selection():
703726
"""When mocked low memory, auto-radius kicks in and finds path."""
704727
data = np.ones((20, 20))

0 commit comments

Comments
 (0)