Added: Initial world generation tool
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package thermal
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestConeIsCutToRepose is the property the whole hillslope story rests on: after enough passes nothing may
|
||||
// stand steeper than the angle of repose. A cone is the worst case, because every cell on it is steep.
|
||||
func TestConeIsCutToRepose(t *testing.T) {
|
||||
const (
|
||||
w, h = 101, 101
|
||||
cellM = 10.0
|
||||
deg = 33.0
|
||||
)
|
||||
talus := TalusFromDegrees(deg)
|
||||
field := make([]float32, w*h)
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
// A steep cone: 60 m of fall per 10 m cell at the flanks, far beyond repose.
|
||||
d := math.Hypot(float64(x-w/2), float64(y-h/2))
|
||||
field[y*w+x] = float32(math.Max(0, 600-6*d*cellM))
|
||||
}
|
||||
}
|
||||
before := maxSlope(field, w, h, cellM)
|
||||
scratch := make([]float32, w*h)
|
||||
|
||||
volBefore := sum(field)
|
||||
Apply(field, w, h, cellM, talus, 400, nil, scratch)
|
||||
volAfter := sum(field)
|
||||
|
||||
after := maxSlope(field, w, h, cellM)
|
||||
t.Logf("max slope %.1f deg -> %.1f deg (repose %.1f)", degOf(before), degOf(after), deg)
|
||||
if degOf(after) > deg+2 {
|
||||
t.Errorf("after 400 passes the steepest slope is %.1f deg, want no more than %.1f", degOf(after), deg+2)
|
||||
}
|
||||
if rel := math.Abs(volAfter-volBefore) / volBefore; rel > 1e-4 {
|
||||
t.Errorf("mass changed by %.4f%%; thermal weathering must conserve it", rel*100)
|
||||
}
|
||||
}
|
||||
|
||||
func sum(a []float32) float64 {
|
||||
var s float64
|
||||
for _, v := range a {
|
||||
s += float64(v)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func degOf(slope float64) float64 { return math.Atan(slope) * 180 / math.Pi }
|
||||
|
||||
func maxSlope(a []float32, w, h int, cellM float64) float64 {
|
||||
worst := 0.0
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
i := y*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(a[i]-a[ny*w+nx]) / d; s > worst {
|
||||
worst = s
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return worst
|
||||
}
|
||||
Reference in New Issue
Block a user