-
Notifications
You must be signed in to change notification settings - Fork 5
/
propagation.go
113 lines (97 loc) · 3.09 KB
/
propagation.go
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
package main
import (
"time"
"github.com/divan/simulation/propagation"
"github.com/divan/three"
)
var (
BlinkedEdgeMaterial = NewBlinkedEdgeMaterial()
BlinkedNodeMaterial = NewBlinkedNodeMaterial()
)
// AnimatePropagation visualizes propagation of message based on plog.
func (w *WebGLScene) AnimatePropagation(plog *propagation.Log) {
w.rt.EnableRendering()
for i, ts := range plog.Timestamps {
duration := time.Duration(time.Duration(ts) * time.Millisecond)
nodes := plog.Nodes[i]
edges := plog.Links[i]
delay := time.Duration(w.blink) * time.Millisecond
fn := func() {
// blink nodes for this timestamp
for _, idx := range nodes {
node := w.nodes[idx]
w.BlinkNode(node)
go time.AfterFunc(delay, func() { w.UnblinkNode(node) })
}
// blink links for this timestamp
for _, idx := range edges {
edge := w.lines[idx]
w.BlinkEdge(edge)
go time.AfterFunc(delay, func() { w.UnblinkEdge(edge) })
}
}
go time.AfterFunc(duration, fn)
w.rt.EnableRendering() // prevent thorttler from enabling during long animations
}
}
// AnimateOneStep blinks permantently nodes and edges for the given step of plog.
// TODO(divan): "Animate-" is probably not the best name here, come up with something
// better (this function doesn't *animate* anything so far)
func (w *WebGLScene) AnimateOneStep(plog *propagation.Log, step int) {
nodes := plog.Nodes[step]
edges := plog.Links[step]
nodesToBlink := make(map[int]struct{})
for _, idx := range nodes {
nodesToBlink[idx] = struct{}{}
}
// blink nodes for this timestamp
for i, _ := range w.nodes {
node := w.nodes[i]
if _, ok := nodesToBlink[i]; ok {
w.BlinkNode(node)
} else {
w.UnblinkNode(node)
}
}
edgesToBlink := make(map[int]struct{})
for _, idx := range edges {
edgesToBlink[idx] = struct{}{}
}
for i, _ := range w.lines {
edge := w.lines[i]
if _, ok := edgesToBlink[i]; ok {
w.BlinkEdge(edge)
} else {
w.UnblinkEdge(edge)
}
}
}
// BlinkNode animates a single node blinking. Node specified by its idx.
// TODO(divan): consider renaming it to Highlight or something.
func (w *WebGLScene) BlinkNode(node *Mesh) {
node.Set("material", BlinkedNodeMaterial)
}
func (w *WebGLScene) UnblinkNode(node *Mesh) {
node.Object.Set("material", DefaultNodeMaterial)
}
// BlinkEdge animates a single edge blinking. Edge specified by its idx.
func (w *WebGLScene) BlinkEdge(edge *Line) {
edge.Set("material", BlinkedEdgeMaterial)
}
func (w *WebGLScene) UnblinkEdge(edge *Line) {
edge.Set("material", DefaultEdgeMaterial)
}
// NewBlinkedEdgeMaterial creates a new default material for the graph blinked edge lines.
func NewBlinkedEdgeMaterial() three.Material {
params := three.NewMaterialParameters()
params.Color = three.NewColorRGB(255, 0, 0)
params.Transparent = false
return three.NewLineBasicMaterial(params)
}
// NewBlinkedNodeMaterial creates a new default material for the graph blinked node.
func NewBlinkedNodeMaterial() three.Material {
params := three.NewMaterialParameters()
params.Color = three.NewColorRGB(255, 0, 0) // red
params.Transparent = false
return three.NewMeshPhongMaterial(params)
}