Два математических маятника, связанных пружиной — различия между версиями
Vaan007 (обсуждение | вклад) |
Vaan007 (обсуждение | вклад) |
||
(не показано 17 промежуточных версий 5 участников) | |||
Строка 1: | Строка 1: | ||
[[Виртуальная лаборатория]]>[[Два математических маятника, связанных пружиной]] <HR> | [[Виртуальная лаборатория]]>[[Два математических маятника, связанных пружиной]] <HR> | ||
− | '''Что собой представляет система'''<br /> | + | '''Что собой представляет система '''<br /> |
− | Два математических маятника, | + | Два математических маятника, связанные пружиной, совершают малые колебания. Упругое звено служит неким инструментом для "перекачки" энергии с одного маятника на другой. |
− | '''Постановка задачи'''<br /> | + | '''Постановка задачи'''<br /> Демонстрируются малые колебания математических маятников одинаковой длинны <math>{l}</math> и массы <math>{m}</math>. Пружина жесткости <math>{C}</math> закреплена по центру стержней математических маятников. При отклонении первого маятника на малый угол <math>\varphi_{0}</math> под действием пружины происходит возбуждение колебаний второго маятника, а колебания первого затухают. Затем происходит обратный процесс. |
[[Файл: TwoMayaWithSpring.jpg|300px|Два связанных математических маятника]] | [[Файл: TwoMayaWithSpring.jpg|300px|Два связанных математических маятника]] | ||
Строка 10: | Строка 10: | ||
'''Основные уравнения'''<br /> | '''Основные уравнения'''<br /> | ||
+ | ::<math> | ||
+ | \left\{ | ||
+ | \begin{array}{ll} | ||
+ | \varphi_{1}= \varphi_{0}\cdot\cos(\frac{({k}_{1} + {k}_{2})} {2} \cdot{t}) \cdot \cos(\frac{({k}_{2} - {k}_{1})} {2} \cdot{t})\\ | ||
+ | \displaystyle \varphi_{2}= \varphi_{0}\cdot\sin(\frac{({k}_{1} + {k}_{2})} {2} \cdot{t})\cdot\sin(\frac{({k}_{2} - {k}_{1})} {2} \cdot{t})\\ | ||
+ | \end{array} | ||
+ | \right. | ||
+ | </math> | ||
+ | <br /> | ||
− | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/ | + | где <math>{k}_{1}=\sqrt\frac{{g}}{l}</math> и <math>{k}_{2}=\sqrt{\frac{{g}}{l} + \frac{{2Cd^2}}{ml^2}}</math> |
+ | <br /> | ||
+ | |||
+ | <math>\varphi_{1},\varphi_{2}</math> - обобщенные координаты | ||
+ | <br /> | ||
+ | <math>\varphi_{0}</math> - начальный угол отклонения | ||
+ | <br /> | ||
+ | <math>{g}</math> - гравитационная постоянная | ||
+ | <br /> | ||
+ | <math>{l}</math> - длина маятников | ||
+ | <br /> | ||
+ | <math>{m}</math> - масса маятников | ||
+ | <br /> | ||
+ | <math>{C}</math> - жесткость пружины | ||
+ | <br /> | ||
+ | <math>{d}</math> - положение пружины на стержне | ||
+ | <br /> | ||
+ | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Alexandrov_S_D/TwoMaya.html |width=950 |height=730 |border=0 }} | ||
+ | <br /> | ||
+ | Скачать программу [[Медиа:NewTwoMaya.rar|TwoMaya.rar]]. | ||
+ | <br /> | ||
+ | <br /> | ||
+ | |||
+ | <div class="mw-collapsible mw-collapsed" style="width:100%" > | ||
+ | '''Текст программы на языке JavaScript (разработчик [[Александров Сергей]]):''' <div class="mw-collapsible-content"> | ||
+ | Файл '''"TwoMaya.js"''' | ||
+ | <syntaxhighlight lang="javascript" line start="1" enclose="div"> | ||
+ | window.addEventListener("load", Main_Spring, true); | ||
+ | function Main_Spring() { | ||
+ | |||
+ | // *** Некие исходные данные *** | ||
+ | |||
+ | var canvas = spring_canvas; | ||
+ | canvas.onselectstart = function () {return false;}; // запрет выделения canvas | ||
+ | var ctx = canvas.getContext("2d"); // на ctx происходит рисование | ||
+ | var w = canvas.width; // ширина окна в расчетных координатах | ||
+ | var h = canvas.height; // высота окна в расчетных координатах | ||
+ | |||
+ | var Pi = 3.1415926; // число "пи" | ||
+ | var g = 9.8; // гравитационная постоянная | ||
+ | |||
+ | var T0 = 0.01; // масштаб времени (период колебаний исходной системы) | ||
+ | var k0 = 2 * Pi / T0; // масштаб частоты | ||
+ | |||
+ | |||
+ | |||
+ | var m0 = 1; // масштаб массы маятника | ||
+ | var l0 = 2; // масштаб длины маятника | ||
+ | var fiZero0 = 1; // масштаб начального угла отклонения | ||
+ | var d0 = 1; // масштаб местоположения пружины на маятнике | ||
+ | var C0 = 1; // масштаб жесткости пружины | ||
+ | |||
+ | var count = true; // проводить ли расчет системы | ||
+ | var v = 0; // скорость тела | ||
+ | var t = 0; | ||
+ | var f_1 = 0.1; // угл отклонения первого маятника от положения равновесия | ||
+ | var f_2 = 0.1; // угл отклонения второго маятника от положения равновесия | ||
+ | var q = 10; // маштабирующий коэффициент отклонения маятника | ||
+ | |||
+ | // параметры полученные из размеров холста | ||
+ | var rw = canvas.width / 100; var rh = canvas.height / 4; | ||
+ | //var x0 = (15 * rw - rw / 2); var y0 = (rh / 1.33 - rh / 2) * 10; | ||
+ | var x0 = canvas.width/5; | ||
+ | var y0 = canvas.height/8; | ||
+ | var rad0 = 15; | ||
+ | |||
+ | // параметры пружины | ||
+ | var coil = 10; // количество витков | ||
+ | var startX = 500; // закрепление пружины | ||
+ | |||
+ | |||
+ | // *** Задание вычислительных параметров *** | ||
+ | |||
+ | var fps = 60; // frames per second - число кадров в секунду (качечтво отображения) | ||
+ | var spf = 10; // steps per frame - число шагов интегрирования между кадрами | ||
+ | var dt = 50 * T0 / fps; // шаг интегрирования (качество расчета) | ||
+ | var steps = 0; // количество шагов интегрирования | ||
+ | |||
+ | |||
+ | // *** Задание физических параметров *** | ||
+ | |||
+ | var m = 1 * m0; // масса маятника | ||
+ | var C = 0.3 * C0; // жесткость пружины | ||
+ | var l = 8 * l0; // длина маятников | ||
+ | var fiZero = 0.3 * fiZero0; // начальное отклонение первого маятника | ||
+ | var d = l/2 * d0; // местоположение пружины на маятнике | ||
+ | var hole = canvas.width/2 + 50; // расстояние между закреплениями маятников по Х | ||
+ | var bound_x = x0; // координаты закрепления первого маятника по Х | ||
+ | var bound_y = 10; // координаты закрепления первого маятника по У | ||
+ | |||
+ | slider_m.value = (m / m0).toFixed(1); number_m.value = (m / m0).toFixed(1); | ||
+ | slider_C.value = (C / C0).toFixed(1); number_C.value = (C / C0).toFixed(1); | ||
+ | slider_l.value = (l / l0).toFixed(1); number_l.value = (l / l0).toFixed(1); | ||
+ | slider_fiZero.value = (fiZero / fiZero0).toFixed(1); number_fiZero.value = (fiZero / fiZero0).toFixed(1); | ||
+ | slider_spf.value = (spf).toFixed(1); number_spf.value = (spf).toFixed(1); | ||
+ | |||
+ | // *** Установка слайдеров для переменных величин *** | ||
+ | |||
+ | function setM(new_m) {m = new_m * m0;} | ||
+ | function setC(new_C) {C = new_C * C0;} | ||
+ | function setL(new_l) {l = new_l * l0;} | ||
+ | function setFiZero(new_fiZero) {fiZero = new_fiZero * fiZero0;} | ||
+ | function setSpf(new_spf) {spf = new_spf;} | ||
+ | |||
+ | slider_m.oninput = function() {number_m.value = slider_m.value; setM(slider_m.value);}; | ||
+ | number_m.oninput = function() {slider_m.value = number_m.value; setM(number_m.value);}; | ||
+ | |||
+ | slider_C.oninput = function() {number_C.value = slider_C.value; setC(slider_C.value);}; | ||
+ | number_C.oninput = function() {slider_C.value = number_C.value; setC(number_C.value);}; | ||
+ | |||
+ | slider_l.oninput = function() {number_l.value = slider_l.value; setL(slider_l.value);}; | ||
+ | number_l.oninput = function() {slider_l.value = number_l.value; setL(number_l.value);}; | ||
+ | |||
+ | slider_fiZero.oninput = function() {number_fiZero.value = slider_fiZero.value; setFiZero(slider_fiZero.value);}; | ||
+ | number_fiZero.oninput = function() {slider_fiZero.value = number_fiZero.value; setFiZero(number_fiZero.value);}; | ||
+ | |||
+ | slider_spf.oninput = function() {number_spf.value = slider_spf.value; setSpf(slider_spf.value);}; | ||
+ | number_spf.oninput = function() {slider_spf.value = number_spf.value; setSpf(number_spf.value);}; | ||
+ | |||
+ | |||
+ | // Параметры первого круга-грузика | ||
+ | var circ1 = { | ||
+ | x: x0, | ||
+ | y: y0, | ||
+ | rad: rad0, | ||
+ | fill: "rgba(0, 0, 255, 1)" | ||
+ | }; | ||
+ | |||
+ | // Параметры второго круга-грузика | ||
+ | var circ2 = { | ||
+ | x: x0+hole, | ||
+ | y: y0, | ||
+ | rad: rad0, | ||
+ | fill: "rgba(0, 255, 0, 1)" | ||
+ | }; | ||
+ | |||
+ | // *** Функция обеспечивающая "жизнь" маятников с пружиной *** | ||
+ | |||
+ | function control() { | ||
+ | calculate(); | ||
+ | draw(); | ||
+ | requestAnimationFrame(control); | ||
+ | |||
+ | } | ||
+ | control(); | ||
+ | |||
+ | // график | ||
+ | var vGraph1 = new TM_graph( // определить график | ||
+ | "#vGraph1", // на html-элементе #vGraph | ||
+ | 250, // сколько шагов по оси "x" отображается | ||
+ | -1, 1, 0.1); // мин. значение оси Y, макс. значение оси Y, шаг по оси Y | ||
+ | |||
+ | var vGraph2 = new TM_graph( // определить график | ||
+ | "#vGraph2", // на html-элементе #vGraph | ||
+ | 250, // сколько шагов по оси "x" отображается | ||
+ | -1, 1, 0.1); // мин. значение оси Y, макс. значение оси Y, шаг по оси Y | ||
+ | |||
+ | |||
+ | |||
+ | // *** Функция расчетов координат *** | ||
+ | |||
+ | function calculate() { | ||
+ | |||
+ | //if (!count) return; | ||
+ | |||
+ | for (var s=1; s<=spf; s++) { | ||
+ | |||
+ | var k1 = Math.sqrt(g/l); // коэффициент первой пружины | ||
+ | var k2 = Math.sqrt(g/l + (2 * C * Math.pow(d,2))/m/(Math.pow(l,2))); // коэффициент второй пружины | ||
+ | |||
+ | t += dt; | ||
+ | |||
+ | f_1 = fiZero * Math.cos((k1 + k2)/2 * t) * Math.cos((k1 - k2)/2 * t); // закон изменения угла отклонения первого маятника от положения равновесия | ||
+ | f_2 = fiZero * Math.sin((k1 + k2)/2 * t) * Math.sin((k2 - k1)/2 * t); // закон изменения угла отклонения второго маятника от положения равновесия | ||
+ | |||
+ | |||
+ | // изменение координат первого грузика | ||
+ | circ1.x = (x0 + l * Math.sin(f_1) * q); | ||
+ | circ1.y = 100 + (y0 + l * Math.cos(f_1) * q); | ||
+ | |||
+ | // изменение координат второго грузика | ||
+ | circ2.x = (x0 + hole + l * Math.sin(f_2) * q); | ||
+ | circ2.y = 100 + (y0 + l * Math.cos(f_2) * q); | ||
+ | |||
+ | |||
+ | steps++; | ||
+ | if (steps % 80 == 0) { | ||
+ | vGraph1.graphIter(steps, (f_1)) | ||
+ | vGraph2.graphIter(steps, (f_2))}; // подать данные на график | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | // *** Функция рисования объектов *** | ||
+ | |||
+ | function draw() { | ||
+ | |||
+ | ctx.clearRect(0, 0, w, h); | ||
+ | |||
+ | |||
+ | //!!! пружина | ||
+ | /* draw_spring( | ||
+ | 100, // х-координата начала пружины | ||
+ | 400, // х-координата конца пружины | ||
+ | 300, // у-координата пружины | ||
+ | 6, // количество витков пружины | ||
+ | 100 // высота изгиба пружины (чем меньше, тем больше пружина похожа на линию) | ||
+ | ); */ | ||
+ | |||
+ | // Пружина соединяющая два маятника | ||
+ | draw_spring((circ1.x - x0)/2 + x0, (circ2.x - x0 - hole)/2 + x0 + hole , (circ1.y + y0/2)/2 , 10, 30); | ||
+ | |||
+ | |||
+ | // Стержень первого маятника | ||
+ | ctx.lineWidth = 6; | ||
+ | ctx.strokeStyle = "#e1974d"; | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(circ1.x, circ1.y); | ||
+ | ctx.lineTo(x0, y0 - bound_y); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | // Стержень второго маятника | ||
+ | ctx.lineWidth = 6; | ||
+ | ctx.strokeStyle = "#e1974d"; | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(circ2.x, circ2.y); | ||
+ | ctx.lineTo(x0 + hole,y0 - bound_y); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | // Круглый грузик первого маятника | ||
+ | ctx.beginPath(); | ||
+ | ctx.arc(circ1.x, circ1.y, rad0, 0, 2 * Math.PI, false); | ||
+ | ctx.fillStyle = 'red'; | ||
+ | ctx.fill(); | ||
+ | ctx.lineWidth = 7; | ||
+ | ctx.strokeStyle = '#003300'; | ||
+ | ctx.stroke(); | ||
+ | |||
+ | // Круглый грузик второго маятника | ||
+ | ctx.beginPath(); | ||
+ | ctx.arc(circ2.x, circ2.y, rad0, 0, 2 * Math.PI, false); | ||
+ | ctx.fillStyle = 'blue'; | ||
+ | ctx.fill(); | ||
+ | ctx.lineWidth = 7; | ||
+ | ctx.strokeStyle = '#003300'; | ||
+ | ctx.stroke(); | ||
+ | |||
+ | // Рисование закрепления первого маятника | ||
+ | ctx.lineWidth = 6; | ||
+ | ctx.strokeStyle = "#7394cb"; | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(x0-20, y0 - bound_y); | ||
+ | ctx.lineTo(x0+20, y0 - bound_y); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | // Рисование закрепления второго маятника | ||
+ | ctx.lineWidth = 6; | ||
+ | ctx.strokeStyle = "#7394cb"; | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(x0-20 + hole, y0 - bound_y); | ||
+ | ctx.lineTo(x0+20 + hole, y0 - bound_y); | ||
+ | ctx.stroke(); | ||
+ | } | ||
+ | |||
+ | // *** Функция рисования пружины *** | ||
+ | |||
+ | function draw_spring(x_start, x_end, y, n, h) { | ||
+ | ctx.lineWidth = 2; | ||
+ | ctx.strokeStyle = "#7394cb"; | ||
+ | var L = x_end - x_start; | ||
+ | for (var i = 0; i < n; i++) { | ||
+ | var x_st = x_start + L / n * i; | ||
+ | var x_end = x_start + L / n * (i + 1); | ||
+ | var l = x_end - x_st; | ||
+ | ctx.beginPath(); | ||
+ | ctx.bezierCurveTo(x_st, y, x_st + l / 4, y + h, x_st + l / 2, y); | ||
+ | ctx.bezierCurveTo(x_st + l / 2, y, x_st + 3 * l / 4, y - h, x_st + l, y); | ||
+ | ctx.stroke(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | </div> | ||
+ | </div> | ||
+ | |||
+ | [[Category: Виртуальная лаборатория]] | ||
+ | [[Category: Программирование]] | ||
+ | [[Category: JavaScript]] |
Текущая версия на 20:12, 4 сентября 2016
Виртуальная лаборатория>Два математических маятника, связанных пружинойЧто собой представляет система
Два математических маятника, связанные пружиной, совершают малые колебания. Упругое звено служит неким инструментом для "перекачки" энергии с одного маятника на другой.
Постановка задачи
Демонстрируются малые колебания математических маятников одинаковой длинны и массы . Пружина жесткости закреплена по центру стержней математических маятников. При отклонении первого маятника на малый угол под действием пружины происходит возбуждение колебаний второго маятника, а колебания первого затухают. Затем происходит обратный процесс.
Основные уравнения
где
- начальный угол отклонения
- гравитационная постоянная
- длина маятников
- масса маятников
- жесткость пружины
- положение пружины на стержне
Скачать программу TwoMaya.rar.
Файл "TwoMaya.js"
1 window.addEventListener("load", Main_Spring, true);
2 function Main_Spring() {
3
4 // *** Некие исходные данные ***
5
6 var canvas = spring_canvas;
7 canvas.onselectstart = function () {return false;}; // запрет выделения canvas
8 var ctx = canvas.getContext("2d"); // на ctx происходит рисование
9 var w = canvas.width; // ширина окна в расчетных координатах
10 var h = canvas.height; // высота окна в расчетных координатах
11
12 var Pi = 3.1415926; // число "пи"
13 var g = 9.8; // гравитационная постоянная
14
15 var T0 = 0.01; // масштаб времени (период колебаний исходной системы)
16 var k0 = 2 * Pi / T0; // масштаб частоты
17
18
19
20 var m0 = 1; // масштаб массы маятника
21 var l0 = 2; // масштаб длины маятника
22 var fiZero0 = 1; // масштаб начального угла отклонения
23 var d0 = 1; // масштаб местоположения пружины на маятнике
24 var C0 = 1; // масштаб жесткости пружины
25
26 var count = true; // проводить ли расчет системы
27 var v = 0; // скорость тела
28 var t = 0;
29 var f_1 = 0.1; // угл отклонения первого маятника от положения равновесия
30 var f_2 = 0.1; // угл отклонения второго маятника от положения равновесия
31 var q = 10; // маштабирующий коэффициент отклонения маятника
32
33 // параметры полученные из размеров холста
34 var rw = canvas.width / 100; var rh = canvas.height / 4;
35 //var x0 = (15 * rw - rw / 2); var y0 = (rh / 1.33 - rh / 2) * 10;
36 var x0 = canvas.width/5;
37 var y0 = canvas.height/8;
38 var rad0 = 15;
39
40 // параметры пружины
41 var coil = 10; // количество витков
42 var startX = 500; // закрепление пружины
43
44
45 // *** Задание вычислительных параметров ***
46
47 var fps = 60; // frames per second - число кадров в секунду (качечтво отображения)
48 var spf = 10; // steps per frame - число шагов интегрирования между кадрами
49 var dt = 50 * T0 / fps; // шаг интегрирования (качество расчета)
50 var steps = 0; // количество шагов интегрирования
51
52
53 // *** Задание физических параметров ***
54
55 var m = 1 * m0; // масса маятника
56 var C = 0.3 * C0; // жесткость пружины
57 var l = 8 * l0; // длина маятников
58 var fiZero = 0.3 * fiZero0; // начальное отклонение первого маятника
59 var d = l/2 * d0; // местоположение пружины на маятнике
60 var hole = canvas.width/2 + 50; // расстояние между закреплениями маятников по Х
61 var bound_x = x0; // координаты закрепления первого маятника по Х
62 var bound_y = 10; // координаты закрепления первого маятника по У
63
64 slider_m.value = (m / m0).toFixed(1); number_m.value = (m / m0).toFixed(1);
65 slider_C.value = (C / C0).toFixed(1); number_C.value = (C / C0).toFixed(1);
66 slider_l.value = (l / l0).toFixed(1); number_l.value = (l / l0).toFixed(1);
67 slider_fiZero.value = (fiZero / fiZero0).toFixed(1); number_fiZero.value = (fiZero / fiZero0).toFixed(1);
68 slider_spf.value = (spf).toFixed(1); number_spf.value = (spf).toFixed(1);
69
70 // *** Установка слайдеров для переменных величин ***
71
72 function setM(new_m) {m = new_m * m0;}
73 function setC(new_C) {C = new_C * C0;}
74 function setL(new_l) {l = new_l * l0;}
75 function setFiZero(new_fiZero) {fiZero = new_fiZero * fiZero0;}
76 function setSpf(new_spf) {spf = new_spf;}
77
78 slider_m.oninput = function() {number_m.value = slider_m.value; setM(slider_m.value);};
79 number_m.oninput = function() {slider_m.value = number_m.value; setM(number_m.value);};
80
81 slider_C.oninput = function() {number_C.value = slider_C.value; setC(slider_C.value);};
82 number_C.oninput = function() {slider_C.value = number_C.value; setC(number_C.value);};
83
84 slider_l.oninput = function() {number_l.value = slider_l.value; setL(slider_l.value);};
85 number_l.oninput = function() {slider_l.value = number_l.value; setL(number_l.value);};
86
87 slider_fiZero.oninput = function() {number_fiZero.value = slider_fiZero.value; setFiZero(slider_fiZero.value);};
88 number_fiZero.oninput = function() {slider_fiZero.value = number_fiZero.value; setFiZero(number_fiZero.value);};
89
90 slider_spf.oninput = function() {number_spf.value = slider_spf.value; setSpf(slider_spf.value);};
91 number_spf.oninput = function() {slider_spf.value = number_spf.value; setSpf(number_spf.value);};
92
93
94 // Параметры первого круга-грузика
95 var circ1 = {
96 x: x0,
97 y: y0,
98 rad: rad0,
99 fill: "rgba(0, 0, 255, 1)"
100 };
101
102 // Параметры второго круга-грузика
103 var circ2 = {
104 x: x0+hole,
105 y: y0,
106 rad: rad0,
107 fill: "rgba(0, 255, 0, 1)"
108 };
109
110 // *** Функция обеспечивающая "жизнь" маятников с пружиной ***
111
112 function control() {
113 calculate();
114 draw();
115 requestAnimationFrame(control);
116
117 }
118 control();
119
120 // график
121 var vGraph1 = new TM_graph( // определить график
122 "#vGraph1", // на html-элементе #vGraph
123 250, // сколько шагов по оси "x" отображается
124 -1, 1, 0.1); // мин. значение оси Y, макс. значение оси Y, шаг по оси Y
125
126 var vGraph2 = new TM_graph( // определить график
127 "#vGraph2", // на html-элементе #vGraph
128 250, // сколько шагов по оси "x" отображается
129 -1, 1, 0.1); // мин. значение оси Y, макс. значение оси Y, шаг по оси Y
130
131
132
133 // *** Функция расчетов координат ***
134
135 function calculate() {
136
137 //if (!count) return;
138
139 for (var s=1; s<=spf; s++) {
140
141 var k1 = Math.sqrt(g/l); // коэффициент первой пружины
142 var k2 = Math.sqrt(g/l + (2 * C * Math.pow(d,2))/m/(Math.pow(l,2))); // коэффициент второй пружины
143
144 t += dt;
145
146 f_1 = fiZero * Math.cos((k1 + k2)/2 * t) * Math.cos((k1 - k2)/2 * t); // закон изменения угла отклонения первого маятника от положения равновесия
147 f_2 = fiZero * Math.sin((k1 + k2)/2 * t) * Math.sin((k2 - k1)/2 * t); // закон изменения угла отклонения второго маятника от положения равновесия
148
149
150 // изменение координат первого грузика
151 circ1.x = (x0 + l * Math.sin(f_1) * q);
152 circ1.y = 100 + (y0 + l * Math.cos(f_1) * q);
153
154 // изменение координат второго грузика
155 circ2.x = (x0 + hole + l * Math.sin(f_2) * q);
156 circ2.y = 100 + (y0 + l * Math.cos(f_2) * q);
157
158
159 steps++;
160 if (steps % 80 == 0) {
161 vGraph1.graphIter(steps, (f_1))
162 vGraph2.graphIter(steps, (f_2))}; // подать данные на график
163 }
164
165 }
166
167 // *** Функция рисования объектов ***
168
169 function draw() {
170
171 ctx.clearRect(0, 0, w, h);
172
173
174 //!!! пружина
175 /* draw_spring(
176 100, // х-координата начала пружины
177 400, // х-координата конца пружины
178 300, // у-координата пружины
179 6, // количество витков пружины
180 100 // высота изгиба пружины (чем меньше, тем больше пружина похожа на линию)
181 ); */
182
183 // Пружина соединяющая два маятника
184 draw_spring((circ1.x - x0)/2 + x0, (circ2.x - x0 - hole)/2 + x0 + hole , (circ1.y + y0/2)/2 , 10, 30);
185
186
187 // Стержень первого маятника
188 ctx.lineWidth = 6;
189 ctx.strokeStyle = "#e1974d";
190 ctx.beginPath();
191 ctx.moveTo(circ1.x, circ1.y);
192 ctx.lineTo(x0, y0 - bound_y);
193 ctx.stroke();
194
195 // Стержень второго маятника
196 ctx.lineWidth = 6;
197 ctx.strokeStyle = "#e1974d";
198 ctx.beginPath();
199 ctx.moveTo(circ2.x, circ2.y);
200 ctx.lineTo(x0 + hole,y0 - bound_y);
201 ctx.stroke();
202
203 // Круглый грузик первого маятника
204 ctx.beginPath();
205 ctx.arc(circ1.x, circ1.y, rad0, 0, 2 * Math.PI, false);
206 ctx.fillStyle = 'red';
207 ctx.fill();
208 ctx.lineWidth = 7;
209 ctx.strokeStyle = '#003300';
210 ctx.stroke();
211
212 // Круглый грузик второго маятника
213 ctx.beginPath();
214 ctx.arc(circ2.x, circ2.y, rad0, 0, 2 * Math.PI, false);
215 ctx.fillStyle = 'blue';
216 ctx.fill();
217 ctx.lineWidth = 7;
218 ctx.strokeStyle = '#003300';
219 ctx.stroke();
220
221 // Рисование закрепления первого маятника
222 ctx.lineWidth = 6;
223 ctx.strokeStyle = "#7394cb";
224 ctx.beginPath();
225 ctx.moveTo(x0-20, y0 - bound_y);
226 ctx.lineTo(x0+20, y0 - bound_y);
227 ctx.stroke();
228
229 // Рисование закрепления второго маятника
230 ctx.lineWidth = 6;
231 ctx.strokeStyle = "#7394cb";
232 ctx.beginPath();
233 ctx.moveTo(x0-20 + hole, y0 - bound_y);
234 ctx.lineTo(x0+20 + hole, y0 - bound_y);
235 ctx.stroke();
236 }
237
238 // *** Функция рисования пружины ***
239
240 function draw_spring(x_start, x_end, y, n, h) {
241 ctx.lineWidth = 2;
242 ctx.strokeStyle = "#7394cb";
243 var L = x_end - x_start;
244 for (var i = 0; i < n; i++) {
245 var x_st = x_start + L / n * i;
246 var x_end = x_start + L / n * (i + 1);
247 var l = x_end - x_st;
248 ctx.beginPath();
249 ctx.bezierCurveTo(x_st, y, x_st + l / 4, y + h, x_st + l / 2, y);
250 ctx.bezierCurveTo(x_st + l / 2, y, x_st + 3 * l / 4, y - h, x_st + l, y);
251 ctx.stroke();
252 }
253 }
254 }