51 lines
1.2 KiB
Go
51 lines
1.2 KiB
Go
package fluvial
|
|
|
|
import (
|
|
"math"
|
|
"testing"
|
|
)
|
|
|
|
// TestClampToReposeCutsACone is the smallest possible check on the constraint: a cone far steeper than the
|
|
// repose angle must come back at or under it.
|
|
func TestClampToReposeCutsACone(t *testing.T) {
|
|
const (
|
|
w, h = 81, 81
|
|
cellM = 10.0
|
|
talus = 0.4 // about 22 degrees
|
|
)
|
|
base := make([]bool, w*h)
|
|
field := make([]float32, w*h)
|
|
for y := 0; y < h; y++ {
|
|
for x := 0; x < w; x++ {
|
|
d := math.Hypot(float64(x-w/2), float64(y-h/2)) * cellM
|
|
field[y*w+x] = float32(math.Max(0, 800-2.0*d)) // slope 2.0, five times repose
|
|
}
|
|
}
|
|
g := NewGrid(w, h, cellM, base)
|
|
g.SetElevationRange(-100, 2000)
|
|
removed := g.ClampToRepose(field, talus)
|
|
|
|
worst := 0.0
|
|
for y := 0; y < h; y++ {
|
|
for x := 0; x < w; x++ {
|
|
for k := 0; k < 8; k++ {
|
|
nx, ny := x+dx8[k], y+dy8[k]
|
|
if nx < 0 || ny < 0 || nx >= w || ny >= h {
|
|
continue
|
|
}
|
|
d := cellM
|
|
if dx8[k] != 0 && dy8[k] != 0 {
|
|
d = cellM * math.Sqrt2
|
|
}
|
|
if s := float64(field[y*w+x]-field[ny*w+nx]) / d; s > worst {
|
|
worst = s
|
|
}
|
|
}
|
|
}
|
|
}
|
|
t.Logf("removed %.2f m mean; steepest slope now %.3f (repose %.3f)", removed, worst, talus)
|
|
if worst > talus*1.02 {
|
|
t.Errorf("steepest slope %.3f exceeds repose %.3f", worst, talus)
|
|
}
|
|
}
|