-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathRoadsModel.js
89 lines (78 loc) · 2.85 KB
/
RoadsModel.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import * as util from 'https://code.agentscript.org/src/utils.js'
import Model from '../src/Model.js'
import { lineStringsToLinks } from 'https://code.agentscript.org/src/geojson.js'
// import santafeRoads from './data/santafe14roads.json' with { type: 'json' }
import santafeRoads from './data/santaferoads.json' with { type: 'json' }
// import * as gis from '../src/gis.js'
export default class RoadsModel extends Model {
network
numDrivers = 100 // 25
speed = 0.05
speedDelta = 0.05
constructor(worldOptions = { bbox: santafeRoads, patchesWidth: 201 }) {
super(worldOptions)
this.checkOptions(worldOptions)
}
checkOptions(options) {
if (!(options.bbox && options.bbox.type === 'FeatureCollection')) {
throw Error('RoadsModel: worldOptions.bbox must be geojson object')
}
}
setup() {
this.turtleBreeds('intersections nodes drivers')
// REMIND: this fails! this.nodes.setDefault('atEdge', 'clamp')
this.turtles.setDefault('atEdge', 'clamp')
this.network = lineStringsToLinks(
this, // model
this.world.bbox,
this.world.geojson
)
console.log('network', this.network)
this.turtles.ask(t => {
if (!this.world.isOnWorld(t.x, t.y)) {
console.log('t offworld', t.x, t.y)
t.die()
}
})
this.turtles.ask(t => {
if (t.links.length === 0) {
console.log('t no links', t.id)
t.die()
}
})
this.turtles.ask(t => {
this.nodes.setBreed(t)
if (t.links.length > 2) this.intersections.setBreed(t)
})
util.repeat(this.numDrivers, () => {
const node = this.nodes.oneOf()
node.hatch(1, this.drivers, driver => {
driver.fromNode = node
driver.toNode = node.linkNeighbors().oneOf()
driver.face(driver.toNode)
driver.speed = this.speed + util.randomFloat(this.speedDelta)
})
})
}
step() {
this.drivers.ask(driver => {
const moveBy = Math.min(
driver.speed,
driver.distance(driver.toNode)
)
driver.face(driver.toNode)
driver.forward(moveBy)
// if moveBy was driver.distance, change to/from nodes
if (moveBy < driver.speed) {
const lastFromNode = driver.fromNode
driver.fromNode = driver.toNode
if (driver.toNode.links.length === 1) {
driver.toNode = lastFromNode
} else {
const neighbors = driver.toNode.linkNeighbors()
driver.toNode = neighbors.otherOneOf(lastFromNode)
}
}
})
}
}