Skip to content

Commit 8ae9961

Browse files
authored
Fix inverted decay and off-by-one in bump spread (#1102) (#1103)
_finish_bump had two bugs: 1. d2/s gave more height to farther pixels (inverted). Changed to (s-d2)/s so adjacent pixels get the most contribution. 2. range(x-spread, x+spread) missed the last pixel. Changed to x+spread+1 for both axes.
1 parent 0d4bb18 commit 8ae9961

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

xrspatial/bump.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ def _finish_bump(width, height, locs, heights, spread):
2929
z = heights[i]
3030
out[y, x] = out[y, x] + z
3131
if s > 0:
32-
for nx in range(max(x - spread, 0), min(x + spread, width)):
33-
for ny in range(max(y - spread, 0), min(y + spread, height)):
32+
for nx in range(max(x - spread, 0), min(x + spread + 1, width)):
33+
for ny in range(max(y - spread, 0), min(y + spread + 1, height)):
3434
d2 = (nx - x) * (nx - x) + (ny - y) * (ny - y)
3535
if d2 <= s:
36-
out[ny, nx] = out[ny, nx] + (out[y, x] * (d2 / s))
36+
out[ny, nx] = out[ny, nx] + (out[y, x] * ((s - d2) / s))
3737
return out
3838

3939

xrspatial/tests/test_bump.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,46 @@ def test_bump_agg_infers_shape():
136136
np.random.seed(42)
137137
result2 = bump(width=25, height=15)
138138
np.testing.assert_array_equal(result.values, result2.values)
139+
140+
141+
def test_bump_decay_strongest_at_center_1102():
142+
"""Pixels adjacent to center should be taller than pixels far from center.
143+
144+
Regression test for #1102: decay formula was inverted (d2/s instead
145+
of (s-d2)/s), giving more height to farther pixels.
146+
"""
147+
from xrspatial.bump import _finish_bump
148+
149+
locs = np.array([[5, 5]], dtype=np.uint16)
150+
heights = np.array([10.0])
151+
out = _finish_bump(11, 11, locs, heights, spread=3)
152+
153+
center = out[5, 5]
154+
adjacent = out[5, 6] # 1 pixel away
155+
far = out[5, 8] # 3 pixels away (edge of spread)
156+
157+
assert center > adjacent > 0, f"center={center}, adjacent={adjacent}"
158+
assert adjacent > far, f"adjacent={adjacent}, far={far}"
159+
160+
161+
def test_bump_spread_reaches_both_sides_1102():
162+
"""Spread should reach pixels on both sides of center.
163+
164+
Regression test for #1102: range upper bound excluded x+spread pixel,
165+
making the bump one pixel short on the positive side.
166+
"""
167+
from xrspatial.bump import _finish_bump
168+
169+
locs = np.array([[5, 5]], dtype=np.uint16)
170+
heights = np.array([10.0])
171+
out = _finish_bump(11, 11, locs, heights, spread=3)
172+
173+
# Pixels 1 step away on BOTH sides should be reached
174+
assert out[5, 4] > 0, "left-1 should be > 0"
175+
assert out[5, 6] > 0, "right-1 should be > 0"
176+
assert out[4, 5] > 0, "up-1 should be > 0"
177+
assert out[6, 5] > 0, "down-1 should be > 0"
178+
179+
# Pixels well outside spread should be 0
180+
assert out[5, 9] == 0, "well outside spread should be 0"
181+
assert out[0, 0] == 0, "corner should be 0"

0 commit comments

Comments
 (0)