-
Notifications
You must be signed in to change notification settings - Fork 7
/
trajectories.js
113 lines (98 loc) · 2.49 KB
/
trajectories.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
"use strict"
module.exports = StateTrajectories
var bsearch = require("binary-search-bounds")
var hermite = require("cubic-hermite")
function createId() {
return (Math.random() * (1<<10))|0
}
function State(x, v, t, event) {
this.x = x
this.v = v
this.t = t
this.event = event
}
function StateTrajectories() {
this.counter = 0
this.id = createId() << 20
this.particles = {}
this.numIters = 25
}
var proto = StateTrajectories.prototype
proto.createParticle = function(id, x, v, t) {
console.log("created", Date.now())
if(!id) {
id = this.id + (this.counter++)
}
this.particles[id] = [ new State(x, v, t, "create") ]
return id
}
proto.moveParticle = function(id, x, v, t) {
this.particles[id].push(new State(x, v, t))
}
proto.destroyParticle = function(id, x, v, t) {
this.particles[id].push(new State(x, v, t, "destroy"))
}
function testState(a, t) {
return a.t - t
}
function getState(trajectory, t) {
var idx = bsearch.le(trajectory, t, testState)
if(idx < 0) {
return new State(trajectory[0].x.slice(), trajectory[0].v.slice(), trajectory[0].t, "create")
}
if(idx === trajectory.length - 1) {
var a = trajectory[idx]
if("destroy" === a.event) {
return new State(trajectory[idx].x.slice(), [0,0], trajectory[0].t, "destroy")
}
var dt = t - a.t
var nx = [a.x[0] + a.v[0] * dt, a.x[1] + a.v[1] * dt]
return new State(nx, a.v.slice(), t)
}
var a = trajectory[idx]
var b = trajectory[idx+1]
var dt = (t - a.t) / (b.t - a.t)
return new State(
hermite(a.x, a.v, b.x, b.v, dt),
hermite.derivative(a.x, a.v, b.x, b.v, dt),
t)
}
proto.getParticle = function(id, t) {
if(id in this.particles) {
return getState(this.particles[id], t)
}
return null
}
proto.getState = function(lpf) {
var t0 = lpf(0, 0)
var states = {}
for(var id in this.particles) {
var trajectory = this.particles[id]
var s = getState(trajectory, t0), t
for(var i=0; i<this.numIters; ++i) {
var t = lpf(s.x[0], s.x[1])
s = getState(trajectory, t)
if(Math.abs(s.t - t) < 0.05) {
break
}
}
if(s.event === "create") {
if(t < s.t) {
continue
}
}
if(s.event === "destroy") {
if(s.t < t) {
continue
}
}
states[id] = s
}
return states
}
proto.listen = function(events) {
var state = this
events.on("create", this.createParticle.bind(this))
events.on("move", this.moveParticle.bind(this))
events.on("destroy", this.destroyParticle.bind(this))
}