-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrandom_walk.html
More file actions
316 lines (264 loc) · 8.77 KB
/
random_walk.html
File metadata and controls
316 lines (264 loc) · 8.77 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
<!DOCTYPE html>
<html>
<!--
Random Walk
16-Dec-2023 Martin Bridge Created
-->
<!-- TODO:
User choice for dx, dt, line width, final point dot, max iterations
pop-up for input parameters
more contrast between consecutive colors (hue)
-->
<head>
<link href="main.css" media="all" rel="stylesheet" type="text/css" />
<link href="buttons.css" media="all" rel="stylesheet" type="text/css" />
<style>
#canvContainer {
width: 100%;
text-align: center;
}
#myCanvas {
display: inline;
}
#actionpanel {
display: flex;
column-gap: 20px;
/* row-gap: 99px; */
background-color: #333;
padding: 10px;
margin-bottom: 10px;
}
#inputpanel {
display: grid;
grid-template-columns: 65% 35%;
column-gap: 5px;
row-gap: 5px;
vertical-align: middle;
align-items: center;
/* width: 450px; */
}
#textpanel {
display: inline;
margin-left: 30px;
padding: 5px;
background-color: #202020;
}
button {
width: 100%;
margin: 5px;
}
</style>
<script>delta_t
var canvas;
var canvasContext;
const bg_color = '#111111';
var origin_canv_x, origin_canv_y;
const canv_margin = 0;
// Current and previous coordinates
var x = 0, y = 0;
var x_old = 0, y_old = 0;
// Main loop variables
var step_num = 0;
var timer;
var running = true;
// User input parameters
var max_steps = 500000;
var delta_t; // Time step
var dx, dy; // Step sizes equal dx and dy for now
var dot_size; // Tile or circle size
var half_dot_size; // Half dot size (for offset and radius
var line_width; // Line width plot
var final_point_only; // Show final point (instead of plotting whole walk)
var plot_type; // Plot type: line. tile or circle
// Get element from css selector
const el = (sel, par) => (par || document).querySelector(sel);
function get_params() {
// Assign input parameters from HTML to global variables
max_steps = parseInt(el('#max_iter').value);
delta_t = parseInt(el('#delta_t').value);
dx = parseInt(el('#step_size').value);
dy = dx;
dot_size = parseInt(el('#dot_size').value);
half_dot_size = (dot_size == 1) ? 1 : Math.floor(dot_size / 2);
line_width = parseInt(el('#line_width').value);
fade = el('#fade').checked;
final_point_only = el('#final_point').checked;
plot_type = el('input[name="plot_type"]:checked').value;
}
function random_color () {
// Random between mn and mx
rn = (mn, mx) => Math.ceil(mn + Math.random() * (mx - mn));
h = rn(0, 360);
s = rn(50, 100);
l = rn(50, 66);
return `hsl(${h}, ${s}%, ${l}%)`;
}
function canvas_circle(x, y) {
ctx.beginPath();
if (half_dot_size == 1) { // Radius 1
ctx.fillRect(x, y, 1, 1);
} else {
ctx.arc(x, y, half_dot_size, 0, 2 * Math.PI);
}
ctx.fill();
}
function canvas_tile(x, y) {
// Offset by half tile size
ctx.fillRect(x - half_dot_size, y - half_dot_size, dot_size, dot_size);
}
function canvas_line(x1, y1, x2, y2) {
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function get_step() {
const pf = 0.333; // p(move forward)
const pb = 0.333; // p(move back)
// p(no move) = 1 -pf -pb
var r = Math.random();
if (r <= pb) {
return -1;
} else if (r > 1 - pf) {
return 1;
} else {
return 0;
}
}
function walk() {
if (running) {
// Get next step
var xstep = get_step();
var ystep = get_step();
// console.log(`step = (${xstep},${ystep})`);
x += xstep * dx;
y += ystep * dy;
el("#stepnum").innerHTML = step_num;
// Reached the edge? Start again with a new color
// Or exceeded max iterations
if ((final_point_only) && (step_num >= max_steps)) {
// Plot the end point of the random walk
ctx.fillStyle = "white";
canvas_circle(x, y);
}
if ((x > canvas.width) || (x < 0) || (y > canvas.height) || (y < 0) || (step_num >= max_steps)) {
x = Math.floor(canvas.width / 2)
y = Math.floor(canvas.height / 2)
x_old = x;
y_old = y;
// Fade out the older plots
if (fade) {
ctx.fillStyle = "hsla(0, 0%, 0%, 0.1)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
ctx.fillStyle = random_color();
ctx.strokeStyle = random_color();
step_num = 0;
}
if (!final_point_only) {
if (plot_type == "tile") {
canvas_tile(x, y);
}
else if (plot_type == "circle") {
canvas_circle(x, y);
}
else {
canvas_line(x_old, y_old, x, y);
}
}
x_old = x;
y_old = y
step_num++;
if (delta_t == 0) {
timer2 = requestAnimationFrame(walk);
}
}
}
function play_pause() {
running = !running;
}
function start_animation() {
console.log("START");
step_num = 0;
// In case we have already been running...
if (timer != 0) {
clearInterval(timer);
timer = 0;
}
canvContainer = el('#canvContainer');
canvas = el('#myCanvas');
ctx = canvas.getContext('2d');
sz = Math.min()
canvas.width = canvContainer.clientWidth;
canvas.height = window.innerHeight -140; // Kludge to cater for scroll bar :=)
get_params();
// Origin of real world origin on canvas
origin_canv_x = canvas.width / 2 - canv_margin;
origin_canv_y = canvas.height - canv_margin;
ctx.fillStyle = bg_color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// first point - centre of canvas to ensure it's inside the triangle
x = Math.floor(canvas.width / 2)
y = Math.floor(canvas.height / 2)
x_old = x;
y_old = y;
line_color = random_color();
// Set canvas styles for inital walk
ctx.fillStyle = random_color();
ctx.strokeStyle = random_color();
ctx.lineWidth = line_width;
ctx.lineCap = "round";
running = true;
timer = setInterval(walk, delta_t);
}
</script>
</head>
<body>
<div id="actionpanel">
<div id="inputpanel">
<label for="max_iter">Max steps</label>
<input id="max_iter" size="8" value="200" pattern="[0-9]+">
<label for="delta_t">Δt (ms)</label>
<input id="delta_t" size="8" value="10">
<label for="step_size">Δx (pixels)</label>
<input id="step_size" size="8" value="15" required pattern="[0-9]+">
<label for="dot_size">Tile/Dot size (pixels)</label>
<input id="dot_size" size="8" value="14" required pattern="[0-9]+">
<label for="line_width">Line width (pixels)</label>
<input id="line_width" size="8" value="1" required pattern="[0-9]+">
<label for="fade">Fade previous paths?</label>
<input id="fade" type="checkbox">
<label for="final_point">Plot <em>only</em> last point?</label>
<input id="final_point" type="checkbox">
<div>Display Type: </div>
<div>
<input type="radio" id="line" name="plot_type" value="line">
<label for="line">Lines</label>
<br/>
<input type="radio" id="tile" name="plot_type" value="tile" checked="true">
<label for="tile">Tiles</label>
<br/>
<input type="radio" id="circle" name="plot_type" value="circle" >
<label for="circle">Circles</label>
</div>
</div>
<div id="buttonpanel">
<button id="start_btn" onclick="start_animation()">Go</button>
<br/>
<button id="pause_btn" onclick="play_pause()">Pause / Continue</button>
<br/>
<button id="settings_btn" onclick="popup_settings()">Settings</button>
<br/>
<span id="step">Step: <span id="stepnum"></span></span>
</div>
<div id="textpanel">
<h2>Random Walk</h2>
<p>Random walk in 2 dimensions.</p>
<p>Martin Bridge, 2023</p>
</div>
</div>
<div id="canvContainer" data-popup="#infotable">
<canvas id="myCanvas"></canvas>
</div>
</body>
</html>