In this post we take a look at a small interactive animation made using p5* graphic library for JavaScript, that shows pressure waves generated by a point travelling at different speeds relative to the speed of sound in the medium. You can select the Mach number using the slider and see the resulting effect.
The code
In this post I’m not getting into detail about how JavaScript or p5* work, but you can think of JavaScript as the C++ for web development. In fact, the syntax is very similar to C/C++, so if you know any of these languages you can start programming in JavaScript relatively easily. You don’t need any specific environment to execute the JS scripts, they are executed directly in your favorite browser. Without further delays, here goes the code:
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
<div id="simple-sketch-holder" style="position: relative"></div>
<script src="https://cdn.jsdelivr.net/npm/p5@1.0.0/lib/p5.js"></script>
<script>
let waves = [];
let next;
let speed;
let mSlider;
let checkbox;
let angle;
let mach;
function setup() {
let canvasDiv = document.getElementById('simple-sketch-holder');
let width = canvasDiv.offsetWidth;
canvas = createCanvas(width, 400);
canvas.parent('simple-sketch-holder');
mSlider = createSlider(0, 200, 0);
mSlider.position(40, 20);
mSlider.style('width', '80px');
mSlider.parent('simple-sketch-holder');
checkbox = createCheckbox('', false);
checkbox.parent('simple-sketch-holder');
checkbox.position(215,20);
speed = 0.4;
next = 0;
}
function draw() {
background(200);
if (millis() > next) {
// Add new particle
waves.push(new Wave());
// Schedule next circle
next = millis() + 500;
}
// Draw all paths
for( let i = 0; i < waves.length; i++) {
waves[i].update();
waves[i].display();
if(waves[i].lifespan <= 0){
waves.splice(i,1);
}
}
mach = mSlider.value()/100;
noStroke();
fill(0);
text('Mach', mSlider.x + mSlider.width + 20, 35);
text(mach, mSlider.x + mSlider.width + 55, 35);
if(mach >= 1){
angle = degrees(asin(1/mach));
checkbox.removeAttribute('disabled');
if(checkbox.checked()){
text(nf(angle,0,2), mSlider.x + mSlider.width + 185, 35);
}
}
else{
checkbox.attribute('disabled', '');
noStroke();
fill(150);
if(checkbox.checked()){
text('-', mSlider.x + mSlider.width + 185, 35);
}
}
text('Mach angle', mSlider.x + mSlider.width + 115, 35);
}
class Wave {
constructor() {
this.x = width/4;
this.y = height/2;
this.diameter = 0;
this.lifespan = 255;
}
update() {
this.diameter += speed*2;
this.lifespan -= 0.5;
this.x = this.x + speed * mSlider.value()/100;
}
display() {
stroke(0, this.lifespan);
fill(0,0);
ellipse(this.x, this.y, this.diameter, this.diameter);
}
}
</script>