Волны в антеннах
https://vk.com/pobeditelvp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
9.5 KiB
312 lines
9.5 KiB
<!-- 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" /> |
|
<label for="right_second" alt="">Вторая половина справа - другая среда</label> |
|
</p> |
|
|
|
<p> |
|
<input type="checkbox" id="generate" checked /> |
|
<label for="generate" alt="">Генерирование волны слева</label> |
|
</p> |
|
|
|
|
|
<p> |
|
<input type="checkbox" id="vel_graph_on" checked /> |
|
<label for="vel_graph_on" alt="">График скорости</label> |
|
<input type="range" id="vel_graph_scale_range" for="omega" name="volume" min="0" max="10000" value="300" |
|
oninput='document.getElementById("vel_graph_scale").value = document.getElementById("vel_graph_scale_range").value / 100;'> |
|
<input id = "vel_graph_scale" type="number" value="3.0" step=".1"/> |
|
<label for="vel_graph_scale" alt="">Маштаб</label> |
|
</p> |
|
|
|
<p> |
|
<input type="checkbox" id="force_graph_on" checked /> |
|
<label for="force_graph_on" alt="">График сил</label> |
|
<input type="range" id="force_graph_scale_range" for="omega" name="volume" min="0" max="10000" value="3000" |
|
oninput='document.getElementById("force_graph_scale").value = document.getElementById("force_graph_scale_range").value / 100;'> |
|
<input id = "force_graph_scale" type="number" value="30.0" step=".1"/> |
|
<label for="force_graph_scale" 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 |
|
|
|
vel_graph_on = False |
|
vel_graph_scale = 0.0 |
|
|
|
force_graph_on = False |
|
force_graph_scale = 0.0 |
|
|
|
y_scale = 0.3 |
|
|
|
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) |
|
|
|
style1 = 'blue' |
|
base_y = ym - (ym - y1) * y_scale * 1 |
|
DrawLine(x1, base_y, x2, base_y, lw, style1) |
|
|
|
base_y = ym - (ym - y1) * y_scale * (-1) |
|
DrawLine(x1, base_y, x2, base_y, lw, style1) |
|
|
|
|
|
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 |
|
|
|
global vel_graph_on |
|
global vel_graph_scale |
|
|
|
global force_graph_on |
|
global force_graph_scale |
|
|
|
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) |
|
|
|
vel_graph_on = document["vel_graph_on"].checked |
|
vel_graph_scale = float(document["vel_graph_scale"].value) |
|
force_graph_on = document["force_graph_on"].checked |
|
force_graph_scale = float(document["force_graph_scale"].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 vel_graph_on |
|
global vel_graph_scale |
|
|
|
global force_graph_on |
|
global force_graph_scale |
|
|
|
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' |
|
style_vel = 'green' |
|
style_force = 'red' |
|
line_width_scale = 4.0 |
|
|
|
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: |
|
force = 0.0 |
|
if i != max_step - 1: |
|
ac = acsel |
|
if right_second and i > max_step / 2: |
|
ac = acsel_second |
|
force = (y_values[i - 1] - y_values[i]) * ac + (y_values[i + 1] - y_values[i]) * ac |
|
vel_values[i] += force |
|
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) |
|
|
|
if vel_graph_on: |
|
base_y = ym - (ym - y1) * vel_graph_scale * vel_values[i] |
|
base_y_last = ym - (ym - y1) * vel_graph_scale * vel_values[i - 1] |
|
|
|
DrawLine(prev_x, base_y_last, cur_x, base_y, 1.0, style_vel) |
|
|
|
if force_graph_on: |
|
base_y = ym - (ym - y1) * force_graph_scale * force |
|
base_y_last = ym - (ym - y1) * force_graph_scale * force |
|
|
|
DrawLine(prev_x, base_y_last, cur_x, base_y, 1.0, style_force) |
|
|
|
|
|
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>
|
|
|