Алексей Безбородов
2 years ago
2 changed files with 246 additions and 7 deletions
@ -0,0 +1,243 @@ |
|||||||
|
<!-- Copyright 2023 by Alexei Bezborodov <AlexeiBv+mirocod_wave_simulate@narod.ru> --> |
||||||
|
<!-- public domain --> |
||||||
|
|
||||||
|
<html lang="ru"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>Симуляция волн</title> |
||||||
|
|
||||||
|
<!-- |
||||||
|
Загрузка скриптов из интернета |
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js"></script> |
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython_stdlib.js"></script> |
||||||
|
--> |
||||||
|
|
||||||
|
<!-- |
||||||
|
Загрузка скриптов из локальной папки (рядом с файлом html) |
||||||
|
--> |
||||||
|
<script type="text/javascript" src="brython.min.js"></script> |
||||||
|
<script type="text/javascript" src="brython_stdlib.js"></script> |
||||||
|
|
||||||
|
|
||||||
|
</head> |
||||||
|
|
||||||
|
<body onload="brython()"> |
||||||
|
|
||||||
|
<details open> |
||||||
|
<summary>Расчётные данные</summary> |
||||||
|
<div> |
||||||
|
<p> |
||||||
|
<input type="range" id="max_step_range" for="max_step" name="volume" min="10" max="1000" value="20" |
||||||
|
oninput='document.getElementById("max_step").value = document.getElementById("max_step_range").value;'> |
||||||
|
<input id = "max_step" type="number" value="20" step="1" |
||||||
|
oninput='recalculate();'/> |
||||||
|
<label for="max_step" alt="Количество расчётных точек на всю длину среды">Точек расчёта</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="checkbox" id="right_second" checked /> |
||||||
|
<label for="right_second" alt="">Вторая половина справа - другая среда</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="checkbox" id="generate" checked /> |
||||||
|
<label for="generate" alt="">Генерирование волны слева</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="range" id="length_range" for="omega" name="volume" min="0" max="200" value="50" |
||||||
|
oninput='document.getElementById("length").value = document.getElementById("length_range").value / 100;'> |
||||||
|
<input id = "length" type="number" value="0.5" step=".01"/> |
||||||
|
<label for="length" alt="">Длина волны</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="range" id="omega_range" for="omega" name="volume" min="-1000" max="1000" value="10" |
||||||
|
oninput='document.getElementById("omega").value = document.getElementById("omega_range").value / 100;'> |
||||||
|
<input id = "omega" type="number" value="0.1" step=".01"/> |
||||||
|
<label for="omega" alt="">Шаг фазы</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="range" id="acsel_range" for="omega" name="volume" min="0" max="1000" value="2" |
||||||
|
oninput='document.getElementById("acsel").value = document.getElementById("acsel_range").value / 100;'> |
||||||
|
<input id = "acsel" type="number" value="0.02" step=".01"/> |
||||||
|
<label for="acsel" alt="">Ускрение слева</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="range" id="acsel_second_range" for="omega" name="volume" min="0" max="1000" value="1" |
||||||
|
oninput='document.getElementById("acsel_second").value = document.getElementById("acsel_second_range").value / 100;'> |
||||||
|
<input id = "acsel_second" type="number" value="0.001" step=".01"/> |
||||||
|
<label for="acsel_second" alt="">Ускрение справа</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
<p> |
||||||
|
<input type="range" id="trenie_range" for="omega" name="volume" min="-0" max="1000" value="980" |
||||||
|
oninput='document.getElementById("trenie").value = document.getElementById("trenie_range").value / 100;'> |
||||||
|
<input id = "trenie" type="number" value="0.98" step=".01"/> |
||||||
|
<label for="trenie" alt="">Трение</label> |
||||||
|
</p> |
||||||
|
|
||||||
|
|
||||||
|
<button id="reload">Загрузить</button> |
||||||
|
</div> |
||||||
|
</details> |
||||||
|
|
||||||
|
<h1 class="text-center">Графики волн</h1> |
||||||
|
<canvas id="draw-board" width="1024" height="500"></canvas> |
||||||
|
|
||||||
|
<script type="text/python"> |
||||||
|
|
||||||
|
from browser import document, html, window |
||||||
|
import random, math |
||||||
|
|
||||||
|
canvas = document["draw-board"] |
||||||
|
ctx = canvas.getContext("2d") |
||||||
|
|
||||||
|
x_border = 10 |
||||||
|
y_border = 10 |
||||||
|
|
||||||
|
max_step = 0 |
||||||
|
|
||||||
|
generate = False |
||||||
|
right_second = False |
||||||
|
|
||||||
|
length = 0.0 |
||||||
|
omega = 0.0 |
||||||
|
delta_omega = 0.0 |
||||||
|
|
||||||
|
trenie = 0.0 |
||||||
|
acsel = 0.0 |
||||||
|
acsel_second = 0.0 |
||||||
|
|
||||||
|
y_values = [] |
||||||
|
vel_values = [] |
||||||
|
|
||||||
|
# Чёрный экран |
||||||
|
def DrawBlackScreen(): |
||||||
|
ctx.fillStyle = "black" |
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height) |
||||||
|
|
||||||
|
def DrawLine(x1, y1, x2, y2, lineWidth, style): |
||||||
|
ctx.strokeStyle = style |
||||||
|
ctx.lineWidth = lineWidth |
||||||
|
ctx.beginPath() |
||||||
|
ctx.moveTo(x1, y1) |
||||||
|
ctx.lineTo(x2, y2) |
||||||
|
ctx.stroke() |
||||||
|
return |
||||||
|
|
||||||
|
def DrawAxesScreen(): |
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height) |
||||||
|
x1 = x_border |
||||||
|
x2 = canvas.width - x1 |
||||||
|
y1 = y_border |
||||||
|
y2 = canvas.height - y1 |
||||||
|
ym = canvas.height/2 |
||||||
|
style = 'red' |
||||||
|
lw = 2 |
||||||
|
DrawLine(x1, ym, x2, ym, lw, style) |
||||||
|
DrawLine(x1, y1, x1, y2, lw, style) |
||||||
|
DrawLine(x2, y1, x2, y2, lw, style) |
||||||
|
|
||||||
|
def base_func(length, omega): |
||||||
|
return math.sin(length * omega) |
||||||
|
|
||||||
|
def reload(): |
||||||
|
global max_step |
||||||
|
global y_values |
||||||
|
global vel_values |
||||||
|
global generate |
||||||
|
global right_second |
||||||
|
global length |
||||||
|
global delta_omega |
||||||
|
global trenie |
||||||
|
global acsel |
||||||
|
global acsel_second |
||||||
|
|
||||||
|
max_step = int(document["max_step"].value) |
||||||
|
y_values = [0.0] * max_step |
||||||
|
vel_values = [0.0] * max_step |
||||||
|
|
||||||
|
generate = document["generate"].checked |
||||||
|
right_second = document["right_second"].checked |
||||||
|
|
||||||
|
length = float(document["length"].value) |
||||||
|
delta_omega = float(document["omega"].value) |
||||||
|
trenie = float(document["trenie"].value) |
||||||
|
acsel = float(document["acsel"].value) |
||||||
|
acsel_second = float(document["acsel_second"].value) |
||||||
|
|
||||||
|
def recalculate(): |
||||||
|
global max_step |
||||||
|
global y_values |
||||||
|
global vel_values |
||||||
|
global generate |
||||||
|
global right_second |
||||||
|
global length |
||||||
|
global delta_omega |
||||||
|
global trenie |
||||||
|
global acsel |
||||||
|
global acsel_second |
||||||
|
|
||||||
|
global omega |
||||||
|
|
||||||
|
DrawBlackScreen() |
||||||
|
DrawAxesScreen() |
||||||
|
|
||||||
|
pi = math.pi |
||||||
|
|
||||||
|
x1 = x_border |
||||||
|
x2 = canvas.width - x1 |
||||||
|
y1 = y_border |
||||||
|
y2 = canvas.height - y1 |
||||||
|
ym = canvas.height/2 |
||||||
|
style = 'white' |
||||||
|
line_width_scale = 4.0 |
||||||
|
y_scale = 0.3 |
||||||
|
|
||||||
|
cur_x = 0 |
||||||
|
prev_x = cur_x |
||||||
|
|
||||||
|
omega += delta_omega |
||||||
|
|
||||||
|
for i in range(max_step): |
||||||
|
cur_x = x1 + (x2 - x1) * i / max_step |
||||||
|
|
||||||
|
if i == 0 and generate: |
||||||
|
y_values[i] = base_func(length, omega) |
||||||
|
vel_values[i] = 0.0 |
||||||
|
else: |
||||||
|
if i != max_step - 1: |
||||||
|
ac = acsel |
||||||
|
if right_second and i > max_step / 2: |
||||||
|
ac = acsel_second |
||||||
|
vel_values[i] += (y_values[i - 1] - y_values[i]) * ac + (y_values[i + 1] - y_values[i]) * ac |
||||||
|
vel_values[i] *= trenie |
||||||
|
y_values[i] += vel_values[i] |
||||||
|
base_y = ym - (ym - y1) * y_scale * y_values[i] |
||||||
|
base_y_last = ym - (ym - y1) * y_scale * y_values[i - 1] |
||||||
|
|
||||||
|
DrawLine(prev_x, base_y_last, cur_x, base_y, 1.0 * line_width_scale, style) |
||||||
|
|
||||||
|
prev_x = cur_x |
||||||
|
|
||||||
|
def recalculate_event(): |
||||||
|
recalculate() |
||||||
|
|
||||||
|
def reload_event(event): |
||||||
|
reload() |
||||||
|
|
||||||
|
reload() |
||||||
|
|
||||||
|
document["reload"].bind("click", reload_event) |
||||||
|
|
||||||
|
game_loop = window.setInterval(recalculate_event, 1000/20) |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
</body> |
||||||
|
|
||||||
|
</html> |
Loading…
Reference in new issue