-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathAvalancheModel.js
60 lines (57 loc) · 2.1 KB
/
AvalancheModel.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import World from 'https://code.agentscript.org/src/World.js'
import Model from 'https://code.agentscript.org/src/Model.js'
import { mapzen as provider } from 'https://code.agentscript.org/src/TileData.js'
import { xyz2bbox } from 'https://code.agentscript.org/src/gis.js'
// Cody's Avalanche model
const pi = Math.PI
export default class AvalancheModel extends Model {
// ======================
constructor(worldOptions = World.defaultOptions(50)) {
super(worldOptions)
}
// data can be gis zxy or a DataSet
async startup() {
const z = 13,
x = 1555,
y = 3084
const bounds = xyz2bbox(x, y, z) // alta utah. USA
const elev = await provider.zxyToDataSet(z, x, y)
this.installDataSets(elev)
}
installDataSets(elevation) {
const { slope, aspect, dzdx, dzdy } = elevation.slopeAndAspect()
this.patches.importDataSet(aspect, 'aspect')
this.patches.importDataSet(slope, 'slope')
this.patches.importDataSet(dzdx, 'dzdx')
this.patches.importDataSet(dzdy, 'dzdy')
this.patches.importDataSet(elevation, 'elevation')
// for 3d
const elevationScaled = elevation.clone().scale(-10, 10)
this.patches.importDataSet(elevationScaled, 'z', true) // for drawing
}
setup() {
this.patches.ask(p => {
p.snowDepth = 1
})
}
step() {
// start new buffer
this.patches.ask(p => (p.nextSnow = p.snowDepth))
// drop snow
this.patches.ask(p => (p.nextSnow += +0.01))
// make avalanche
this.patches.ask(p => {
const maxSnowDepth = pi / p.slope
if (p.snowDepth > maxSnowDepth) {
//choose the 2 downhill neighbors to give snow to
const n = Math.min(2, p.neighbors.length)
p.neighbors
.minNOf(n, 'elevation')
.ask(p2 => (p2.nextSnow = p2.nextSnow + p.snowDepth / n))
p.nextSnow = 0
}
})
// swap buffer
this.patches.ask(p => (p.snowDepth = p.nextSnow))
}
}