Grid layers: add HeightMap-based procedural generation methods
TileLayer (closes #200): - apply_threshold(source, range, tile): Set tile index where heightmap value is in range - apply_ranges(source, ranges): Apply multiple tile assignments in one pass ColorLayer (closes #201): - apply_threshold(source, range, color): Set fixed color where value is in range - apply_gradient(source, range, color_low, color_high): Interpolate colors based on value - apply_ranges(source, ranges): Apply multiple color assignments (fixed or gradient) All methods return self for chaining. HeightMap size must match layer dimensions. Later ranges override earlier ones if overlapping. Cells not matching any range are unchanged. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b7c5262abf
commit
a4b1ab7d68
4 changed files with 1165 additions and 0 deletions
320
tests/unit/test_colorlayer_heightmap.py
Normal file
320
tests/unit/test_colorlayer_heightmap.py
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Unit tests for ColorLayer HeightMap methods (#201)
|
||||
|
||||
Tests ColorLayer.apply_threshold(), apply_gradient(), and apply_ranges() methods.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import mcrfpy
|
||||
|
||||
|
||||
def test_apply_threshold_basic():
|
||||
"""apply_threshold sets colors in range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
layer.fill((0, 0, 0, 0)) # Clear all
|
||||
|
||||
# Apply threshold - all cells should get blue
|
||||
result = layer.apply_threshold(hmap, (0.4, 0.6), (0, 0, 255))
|
||||
|
||||
# Verify result is the layer (chaining)
|
||||
assert result is layer, "apply_threshold should return self"
|
||||
|
||||
# Verify color was set
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 0 and c.g == 0 and c.b == 255, f"Expected (0, 0, 255), got ({c.r}, {c.g}, {c.b})"
|
||||
print("PASS: test_apply_threshold_basic")
|
||||
|
||||
|
||||
def test_apply_threshold_with_alpha():
|
||||
"""apply_threshold handles RGBA colors"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
layer.apply_threshold(hmap, (0.0, 1.0), (100, 150, 200, 128))
|
||||
|
||||
c = layer.at(5, 5)
|
||||
assert c.r == 100 and c.g == 150 and c.b == 200 and c.a == 128, \
|
||||
f"Expected (100, 150, 200, 128), got ({c.r}, {c.g}, {c.b}, {c.a})"
|
||||
print("PASS: test_apply_threshold_with_alpha")
|
||||
|
||||
|
||||
def test_apply_threshold_preserves_outside():
|
||||
"""apply_threshold doesn't modify cells outside range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
layer.fill((255, 0, 0)) # Fill with red
|
||||
|
||||
# Apply threshold for range that doesn't include 0.5
|
||||
layer.apply_threshold(hmap, (0.6, 1.0), (0, 0, 255))
|
||||
|
||||
# Should still be red
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 255 and c.g == 0 and c.b == 0, \
|
||||
f"Expected red, got ({c.r}, {c.g}, {c.b})"
|
||||
print("PASS: test_apply_threshold_preserves_outside")
|
||||
|
||||
|
||||
def test_apply_threshold_with_color_object():
|
||||
"""apply_threshold accepts Color objects"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
color = mcrfpy.Color(50, 100, 150)
|
||||
layer.apply_threshold(hmap, (0.0, 1.0), color)
|
||||
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 50 and c.g == 100 and c.b == 150
|
||||
print("PASS: test_apply_threshold_with_color_object")
|
||||
|
||||
|
||||
def test_apply_threshold_size_mismatch():
|
||||
"""apply_threshold rejects mismatched HeightMap size"""
|
||||
hmap = mcrfpy.HeightMap((5, 5)) # Different size
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
try:
|
||||
layer.apply_threshold(hmap, (0.0, 1.0), (255, 0, 0))
|
||||
print("FAIL: test_apply_threshold_size_mismatch - should have raised ValueError")
|
||||
sys.exit(1)
|
||||
except ValueError as e:
|
||||
assert "size" in str(e).lower()
|
||||
|
||||
print("PASS: test_apply_threshold_size_mismatch")
|
||||
|
||||
|
||||
def test_apply_gradient_basic():
|
||||
"""apply_gradient interpolates colors"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
# Apply gradient from black to white
|
||||
result = layer.apply_gradient(hmap, (0.0, 1.0), (0, 0, 0), (255, 255, 255))
|
||||
|
||||
assert result is layer, "apply_gradient should return self"
|
||||
|
||||
# At 0.5 in range [0,1], should be gray (~127-128)
|
||||
c = layer.at(0, 0)
|
||||
assert 120 < c.r < 135, f"Expected ~127, got r={c.r}"
|
||||
assert 120 < c.g < 135, f"Expected ~127, got g={c.g}"
|
||||
assert 120 < c.b < 135, f"Expected ~127, got b={c.b}"
|
||||
print("PASS: test_apply_gradient_basic")
|
||||
|
||||
|
||||
def test_apply_gradient_full_range():
|
||||
"""apply_gradient at range endpoints"""
|
||||
# Test at minimum of range
|
||||
hmap_low = mcrfpy.HeightMap((10, 10), fill=0.0)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
layer.apply_gradient(hmap_low, (0.0, 1.0), (100, 0, 0), (200, 255, 0))
|
||||
|
||||
c = layer.at(0, 0)
|
||||
# At t=0.0, should be color_low
|
||||
assert c.r == 100 and c.g == 0 and c.b == 0, \
|
||||
f"Expected (100, 0, 0), got ({c.r}, {c.g}, {c.b})"
|
||||
|
||||
# Test at maximum of range
|
||||
hmap_high = mcrfpy.HeightMap((10, 10), fill=1.0)
|
||||
layer.apply_gradient(hmap_high, (0.0, 1.0), (100, 0, 0), (200, 255, 0))
|
||||
|
||||
c = layer.at(0, 0)
|
||||
# At t=1.0, should be color_high
|
||||
assert c.r == 200 and c.g == 255 and c.b == 0, \
|
||||
f"Expected (200, 255, 0), got ({c.r}, {c.g}, {c.b})"
|
||||
|
||||
print("PASS: test_apply_gradient_full_range")
|
||||
|
||||
|
||||
def test_apply_gradient_preserves_outside():
|
||||
"""apply_gradient doesn't modify cells outside range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
layer.fill((255, 0, 0)) # Fill with red
|
||||
|
||||
# Apply gradient for range that doesn't include 0.5
|
||||
layer.apply_gradient(hmap, (0.6, 1.0), (0, 0, 0), (255, 255, 255))
|
||||
|
||||
# Should still be red
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 255 and c.g == 0 and c.b == 0
|
||||
print("PASS: test_apply_gradient_preserves_outside")
|
||||
|
||||
|
||||
def test_apply_ranges_fixed_colors():
|
||||
"""apply_ranges with fixed colors"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
layer.fill((0, 0, 0))
|
||||
|
||||
result = layer.apply_ranges(hmap, [
|
||||
((0.0, 0.3), (255, 0, 0)), # Red, won't match
|
||||
((0.3, 0.7), (0, 255, 0)), # Green, will match
|
||||
((0.7, 1.0), (0, 0, 255)), # Blue, won't match
|
||||
])
|
||||
|
||||
assert result is layer, "apply_ranges should return self"
|
||||
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 0 and c.g == 255 and c.b == 0, \
|
||||
f"Expected green, got ({c.r}, {c.g}, {c.b})"
|
||||
print("PASS: test_apply_ranges_fixed_colors")
|
||||
|
||||
|
||||
def test_apply_ranges_gradient():
|
||||
"""apply_ranges with gradient specification"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
# Gradient from (0,0,0) to (255,255,255) over range [0,1]
|
||||
# At value 0.5, should be ~(127,127,127)
|
||||
layer.apply_ranges(hmap, [
|
||||
((0.0, 1.0), ((0, 0, 0), (255, 255, 255))), # Gradient
|
||||
])
|
||||
|
||||
c = layer.at(0, 0)
|
||||
assert 120 < c.r < 135, f"Expected ~127, got r={c.r}"
|
||||
print("PASS: test_apply_ranges_gradient")
|
||||
|
||||
|
||||
def test_apply_ranges_mixed():
|
||||
"""apply_ranges with mixed fixed and gradient entries"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
layer.fill((0, 0, 0))
|
||||
|
||||
# Test mixed: gradient that includes 0.5
|
||||
layer.apply_ranges(hmap, [
|
||||
((0.0, 0.3), (255, 0, 0)), # Fixed red
|
||||
((0.3, 0.7), ((50, 50, 50), (200, 200, 200))), # Gradient gray
|
||||
])
|
||||
|
||||
# 0.5 is at midpoint of [0.3, 0.7] range, so t = 0.5
|
||||
# Expected: 50 + (200-50)*0.5 = 125
|
||||
c = layer.at(0, 0)
|
||||
assert 120 < c.r < 130, f"Expected ~125, got r={c.r}"
|
||||
print("PASS: test_apply_ranges_mixed")
|
||||
|
||||
|
||||
def test_apply_ranges_later_wins():
|
||||
"""apply_ranges: later ranges override earlier ones"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
layer.apply_ranges(hmap, [
|
||||
((0.0, 1.0), (255, 0, 0)), # Red, matches everything
|
||||
((0.4, 0.6), (0, 255, 0)), # Green, also matches 0.5
|
||||
])
|
||||
|
||||
# Green should win (later entry)
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 0 and c.g == 255 and c.b == 0
|
||||
print("PASS: test_apply_ranges_later_wins")
|
||||
|
||||
|
||||
def test_apply_ranges_no_match_unchanged():
|
||||
"""apply_ranges leaves unmatched cells unchanged"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
layer.fill((128, 128, 128)) # Gray marker
|
||||
|
||||
layer.apply_ranges(hmap, [
|
||||
((0.0, 0.2), (255, 0, 0)),
|
||||
((0.8, 1.0), (0, 0, 255)),
|
||||
])
|
||||
|
||||
# Should still be gray
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 128 and c.g == 128 and c.b == 128
|
||||
print("PASS: test_apply_ranges_no_match_unchanged")
|
||||
|
||||
|
||||
def test_apply_threshold_invalid_range():
|
||||
"""apply_threshold rejects min > max"""
|
||||
hmap = mcrfpy.HeightMap((10, 10))
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
try:
|
||||
layer.apply_threshold(hmap, (1.0, 0.0), (255, 0, 0))
|
||||
print("FAIL: test_apply_threshold_invalid_range - should have raised ValueError")
|
||||
sys.exit(1)
|
||||
except ValueError as e:
|
||||
assert "min" in str(e).lower()
|
||||
|
||||
print("PASS: test_apply_threshold_invalid_range")
|
||||
|
||||
|
||||
def test_apply_gradient_narrow_range():
|
||||
"""apply_gradient handles narrow value ranges correctly"""
|
||||
# Use a value exactly at the range
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('color', z_index=0)
|
||||
|
||||
# Apply gradient over exact value (min == max)
|
||||
layer.apply_gradient(hmap, (0.5, 0.5), (0, 0, 0), (255, 255, 255))
|
||||
|
||||
# When range_span is 0, t should be 0, so color_low
|
||||
c = layer.at(0, 0)
|
||||
assert c.r == 0 and c.g == 0 and c.b == 0, \
|
||||
f"Expected black at zero-width range, got ({c.r}, {c.g}, {c.b})"
|
||||
print("PASS: test_apply_gradient_narrow_range")
|
||||
|
||||
|
||||
def run_all_tests():
|
||||
"""Run all tests"""
|
||||
print("Running ColorLayer HeightMap method tests (#201)...")
|
||||
print()
|
||||
|
||||
test_apply_threshold_basic()
|
||||
test_apply_threshold_with_alpha()
|
||||
test_apply_threshold_preserves_outside()
|
||||
test_apply_threshold_with_color_object()
|
||||
test_apply_threshold_size_mismatch()
|
||||
test_apply_gradient_basic()
|
||||
test_apply_gradient_full_range()
|
||||
test_apply_gradient_preserves_outside()
|
||||
test_apply_ranges_fixed_colors()
|
||||
test_apply_ranges_gradient()
|
||||
test_apply_ranges_mixed()
|
||||
test_apply_ranges_later_wins()
|
||||
test_apply_ranges_no_match_unchanged()
|
||||
test_apply_threshold_invalid_range()
|
||||
test_apply_gradient_narrow_range()
|
||||
|
||||
print()
|
||||
print("All ColorLayer HeightMap method tests PASSED!")
|
||||
|
||||
|
||||
# Run tests directly
|
||||
run_all_tests()
|
||||
sys.exit(0)
|
||||
229
tests/unit/test_tilelayer_heightmap.py
Normal file
229
tests/unit/test_tilelayer_heightmap.py
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Unit tests for TileLayer HeightMap methods (#200)
|
||||
|
||||
Tests TileLayer.apply_threshold() and TileLayer.apply_ranges() methods.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import mcrfpy
|
||||
|
||||
|
||||
def test_apply_threshold_basic():
|
||||
"""apply_threshold sets tiles in range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
# Create a grid and get a tile layer
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(-1) # Clear all tiles
|
||||
|
||||
# Apply threshold - all cells should get tile 5
|
||||
result = layer.apply_threshold(hmap, (0.4, 0.6), 5)
|
||||
|
||||
# Verify result is the layer (chaining)
|
||||
assert result is layer, "apply_threshold should return self"
|
||||
|
||||
# Verify tiles were set
|
||||
assert layer.at(0, 0) == 5, f"Expected tile 5, got {layer.at(0, 0)}"
|
||||
assert layer.at(5, 5) == 5, f"Expected tile 5, got {layer.at(5, 5)}"
|
||||
print("PASS: test_apply_threshold_basic")
|
||||
|
||||
|
||||
def test_apply_threshold_partial():
|
||||
"""apply_threshold only affects cells in range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10))
|
||||
# Fill with different values in different areas
|
||||
hmap.fill(0.0) # Start with 0
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(-1)
|
||||
|
||||
# Apply threshold for range that doesn't match (0.5-1.0 when values are 0.0)
|
||||
layer.apply_threshold(hmap, (0.5, 1.0), 10)
|
||||
|
||||
# Should still be -1 since 0.0 is not in [0.5, 1.0]
|
||||
assert layer.at(0, 0) == -1, f"Expected -1, got {layer.at(0, 0)}"
|
||||
print("PASS: test_apply_threshold_partial")
|
||||
|
||||
|
||||
def test_apply_threshold_preserves_outside():
|
||||
"""apply_threshold doesn't modify cells outside range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(99) # Fill with marker value
|
||||
|
||||
# Apply threshold for range that doesn't include 0.5
|
||||
layer.apply_threshold(hmap, (0.6, 1.0), 10)
|
||||
|
||||
# Should still be 99
|
||||
assert layer.at(0, 0) == 99, f"Expected 99, got {layer.at(0, 0)}"
|
||||
print("PASS: test_apply_threshold_preserves_outside")
|
||||
|
||||
|
||||
def test_apply_threshold_invalid_range():
|
||||
"""apply_threshold rejects min > max"""
|
||||
hmap = mcrfpy.HeightMap((10, 10))
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
|
||||
try:
|
||||
layer.apply_threshold(hmap, (1.0, 0.0), 5) # min > max
|
||||
print("FAIL: test_apply_threshold_invalid_range - should have raised ValueError")
|
||||
sys.exit(1)
|
||||
except ValueError as e:
|
||||
assert "min" in str(e).lower()
|
||||
|
||||
print("PASS: test_apply_threshold_invalid_range")
|
||||
|
||||
|
||||
def test_apply_threshold_size_mismatch():
|
||||
"""apply_threshold rejects mismatched HeightMap size"""
|
||||
hmap = mcrfpy.HeightMap((5, 5)) # Different size
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
|
||||
try:
|
||||
layer.apply_threshold(hmap, (0.0, 1.0), 5)
|
||||
print("FAIL: test_apply_threshold_size_mismatch - should have raised ValueError")
|
||||
sys.exit(1)
|
||||
except ValueError as e:
|
||||
assert "size" in str(e).lower()
|
||||
|
||||
print("PASS: test_apply_threshold_size_mismatch")
|
||||
|
||||
|
||||
def test_apply_ranges_basic():
|
||||
"""apply_ranges sets multiple tile ranges"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(-1)
|
||||
|
||||
# Apply ranges - 0.5 falls in the second range
|
||||
result = layer.apply_ranges(hmap, [
|
||||
((0.0, 0.3), 1), # Won't match
|
||||
((0.3, 0.7), 2), # Will match (0.5 is in here)
|
||||
((0.7, 1.0), 3), # Won't match
|
||||
])
|
||||
|
||||
assert result is layer, "apply_ranges should return self"
|
||||
assert layer.at(0, 0) == 2, f"Expected tile 2, got {layer.at(0, 0)}"
|
||||
print("PASS: test_apply_ranges_basic")
|
||||
|
||||
|
||||
def test_apply_ranges_later_wins():
|
||||
"""apply_ranges: later ranges override earlier ones"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(-1)
|
||||
|
||||
# Apply overlapping ranges - later should win
|
||||
layer.apply_ranges(hmap, [
|
||||
((0.0, 1.0), 10), # Matches everything
|
||||
((0.4, 0.6), 20), # Also matches 0.5, comes later
|
||||
])
|
||||
|
||||
# Later range (20) should win
|
||||
assert layer.at(0, 0) == 20, f"Expected tile 20, got {layer.at(0, 0)}"
|
||||
print("PASS: test_apply_ranges_later_wins")
|
||||
|
||||
|
||||
def test_apply_ranges_no_match_unchanged():
|
||||
"""apply_ranges leaves unmatched cells unchanged"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(99)
|
||||
|
||||
# Apply ranges that don't match 0.5
|
||||
layer.apply_ranges(hmap, [
|
||||
((0.0, 0.2), 1),
|
||||
((0.8, 1.0), 2),
|
||||
])
|
||||
|
||||
# Should still be 99
|
||||
assert layer.at(0, 0) == 99, f"Expected 99, got {layer.at(0, 0)}"
|
||||
print("PASS: test_apply_ranges_no_match_unchanged")
|
||||
|
||||
|
||||
def test_apply_ranges_invalid_format():
|
||||
"""apply_ranges rejects invalid range format"""
|
||||
hmap = mcrfpy.HeightMap((10, 10))
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
|
||||
# Missing tile index
|
||||
try:
|
||||
layer.apply_ranges(hmap, [((0.0, 1.0),)]) # Tuple with only one element
|
||||
print("FAIL: test_apply_ranges_invalid_format - should have raised TypeError")
|
||||
sys.exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
print("PASS: test_apply_ranges_invalid_format")
|
||||
|
||||
|
||||
def test_apply_threshold_boundary():
|
||||
"""apply_threshold includes boundary values"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(-1)
|
||||
|
||||
# Range includes 0.5 exactly
|
||||
layer.apply_threshold(hmap, (0.5, 0.5), 7)
|
||||
|
||||
assert layer.at(0, 0) == 7, f"Expected 7, got {layer.at(0, 0)}"
|
||||
print("PASS: test_apply_threshold_boundary")
|
||||
|
||||
|
||||
def test_apply_threshold_accepts_list():
|
||||
"""apply_threshold accepts list as range"""
|
||||
hmap = mcrfpy.HeightMap((10, 10), fill=0.5)
|
||||
|
||||
grid = mcrfpy.Grid(grid_size=(10, 10))
|
||||
layer = grid.add_layer('tile', z_index=0)
|
||||
layer.fill(-1)
|
||||
|
||||
# Use list instead of tuple
|
||||
layer.apply_threshold(hmap, [0.4, 0.6], 5)
|
||||
|
||||
assert layer.at(0, 0) == 5
|
||||
print("PASS: test_apply_threshold_accepts_list")
|
||||
|
||||
|
||||
def run_all_tests():
|
||||
"""Run all tests"""
|
||||
print("Running TileLayer HeightMap method tests (#200)...")
|
||||
print()
|
||||
|
||||
test_apply_threshold_basic()
|
||||
test_apply_threshold_partial()
|
||||
test_apply_threshold_preserves_outside()
|
||||
test_apply_threshold_invalid_range()
|
||||
test_apply_threshold_size_mismatch()
|
||||
test_apply_ranges_basic()
|
||||
test_apply_ranges_later_wins()
|
||||
test_apply_ranges_no_match_unchanged()
|
||||
test_apply_ranges_invalid_format()
|
||||
test_apply_threshold_boundary()
|
||||
test_apply_threshold_accepts_list()
|
||||
|
||||
print()
|
||||
print("All TileLayer HeightMap method tests PASSED!")
|
||||
|
||||
|
||||
# Run tests directly
|
||||
run_all_tests()
|
||||
sys.exit(0)
|
||||
Loading…
Add table
Add a link
Reference in a new issue