Текущая версия |
Ваш текст |
Строка 23: |
Строка 23: |
| | | |
| == Визуализация на языке JavaScript == | | == Визуализация на языке JavaScript == |
− | | + | [http://tm.spbstu.ru/%D0%9D%D0%B5%D0%BB%D0%B8%D0%BD%D0%B5%D0%B9%D0%BD%D1%8B%D0%B5_%D0%BA%D0%BE%D0%BB%D0%B5%D0%B1%D0%B0%D0%BD%D0%B8%D1%8F_%D0%B3%D1%80%D1%83%D0%B7%D0%B0_%D1%81_%D0%B2%D1%8B%D0%BD%D1%83%D0%B6%D0%B4%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%D1%81%D0%B8%D0%BB%D0%BE%D0%B9_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0 Просмотреть] |
− | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Kiselev/Spring/Springs.html |width=800 |height=800 |border=0 }}
| |
| | | |
| Скачать программу: [[Медиа:SpringNoLine.rar|SpringNoLine.rar]] | | Скачать программу: [[Медиа:SpringNoLine.rar|SpringNoLine.rar]] |
− |
| |
− | '''Текст программы на языке JavaScript (разработчик [[Киселев Павел]]):''' <div class="mw-collapsible-content">
| |
− | Файл '''"Spring.js"'''
| |
− | <syntaxhighlight lang="javascript" 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 m0 = 1; // масштаб массы
| |
− | var T0 = 1; // масштаб времени (период колебаний исходной системы)
| |
− | var t = 0;
| |
− | var k0 = 2 * Pi / T0; // масштаб частоты
| |
− | var C0 = m0 * k0 * k0; // масштаб жесткости
| |
− | var B0 = 2 * m0 * k0; // масштаб вязкости
| |
− | var omega = 10;
| |
− |
| |
− | // *** Задание физических параметров ***
| |
− | var F = 80;
| |
− | var m = 1 * m0; // масса
| |
− | var C = 1 * C0; // жесткость
| |
− | var C1 = 1 * C0; // жесткость1
| |
− | var B = .1 * B0; // вязкость
| |
− |
| |
− | 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_C1.value = (C / C0).toFixed(1); number_C1.value = (C / C0).toFixed(1);
| |
− | slider_B.value = (B / B0).toFixed(1); number_B.value = (B / B0).toFixed(1);
| |
− | slider_F.value = (F / 40).toFixed(1); number_F.value = (F / 40).toFixed(1);
| |
− |
| |
− | // *** Задание вычислительных параметров ***
| |
− |
| |
− | var fps = 300; // frames per second - число кадров в секунду (качечтво отображения)
| |
− | var spf = 100; // steps per frame - число шагов интегрирования между кадрами
| |
− | var dt = 0.05 * T0 / fps; // шаг интегрирования (качество расчета)
| |
− | var steps = 0; // количество шагов интегрирования
| |
− |
| |
− | function setM(new_m) {m = new_m * m0;}
| |
− | function setC(new_C) {C = new_C * C0;}
| |
− | function setC1(new_C1) {C1 = new_C1 * C0 * 0.067;}
| |
− | function setB(new_B) {B = new_B * B0;}
| |
− | function setF(new_F) {F = new_F * 40;}
| |
− |
| |
− | 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_C1.oninput = function() {number_C1.value = slider_C1.value; setC1(slider_C1.value);};
| |
− | number_C1.oninput = function() {slider_C1.value = number_C1.value; setC1(number_C1.value);};
| |
− | slider_B.oninput = function() {number_B.value = slider_B.value; setB(slider_B.value);};
| |
− | number_B.oninput = function() {slider_B.value = number_B.value; setB(number_B.value);};
| |
− | slider_F.oninput = function() {number_F.value = slider_F.value; setF(slider_F.value);};
| |
− | number_F.oninput = function() {slider_F.value = number_F.value; setF(number_F.value);};
| |
− |
| |
− | var count = true; // проводить ли расчет системы
| |
− | var v = 0; // скорость тела
| |
− |
| |
− | var rw = canvas.width / 30;
| |
− | var rh = canvas.height / 1.5;
| |
− | var x0 = 15 * rw - rw / 2;
| |
− | var y0 = rh / 1.33 - rh / 2;
| |
− |
| |
− | // параметры пружины
| |
− | var coil = 10; // количество витков
| |
− | var startX = 0; // закрепление пружины
| |
− |
| |
− | // создаем прямоугольник-грузик
| |
− | var rect = {
| |
− | x: x0, width: rw,
| |
− | y: y0, height: rh,
| |
− | fill: "rgba(0, 0, 255, 1)" // цвет
| |
− | };
| |
− |
| |
− | // захват прямоугольника мышью
| |
− | var mx_; // буфер позиции мыши (для расчета скорости при отпускании шара)
| |
− | document.onmousedown = function(e) { // функция при нажатии клавиши мыши
| |
− | var m = mouseCoords(e); // получаем расчетные координаты курсора мыши
| |
− |
| |
− | var x = rect.x;
| |
− | var xw = rect.x + rect.width;
| |
− | var y = rect.y;
| |
− | var yh = rect.y + rect.height;
| |
− | if (x <= m.x && xw >= m.x && y <= m.y && yh >= m.y) {
| |
− | if (e.which == 1) { // нажата левая клавиша мыши
| |
− | rect.xPlus = rect.x - m.x; // сдвиг курсора относительно грузика по x
| |
− | rect.yPlus = rect.y - m.y; // сдвиг курсора относительно грузика по y
| |
− | mx_ = m.x;
| |
− | count = false;
| |
− | document.onmousemove = mouseMove; // пока клавиша нажата - работает функция перемещения
| |
− | }
| |
− | }
| |
− | };
| |
− |
| |
− | document.onmouseup = function(e) { // функция при отпускании клавиши мыши
| |
− | document.onmousemove = null; // когда клавиша отпущена - функции перемещения нету
| |
− | count = true;
| |
− | };
| |
− |
| |
− | function mouseMove(e) { // функция при перемещении мыши, работает только с зажатой ЛКМ
| |
− | var m = mouseCoords(e); // получаем расчетные координаты курсора мыши
| |
− | rect.x = m.x + rect.xPlus;
| |
− | // v = 6.0 * (m.x - mx_) / dt / fps; // сохранение инерции
| |
− | v = 0;
| |
− | mx_ = m.x;
| |
− | }
| |
− |
| |
− | function mouseCoords(e) { // функция возвращает расчетные координаты курсора мыши
| |
− | var m = [];
| |
− | var rect = canvas.getBoundingClientRect();
| |
− | m.x = (e.clientX - rect.left);
| |
− | m.y = (e.clientY - rect.top);
| |
− | return m;
| |
− | }
| |
− |
| |
− | // график
| |
− | var vGraph = new TM_graph( // определить график
| |
− | "#vGraph", // на html-элементе #vGraph
| |
− | 250, // сколько шагов по оси "x" отображается
| |
− | -1, 1, 0.2); // мин. значение оси Y, макс. значение оси Y, шаг по оси Y
| |
− |
| |
− | function control() {
| |
− | calculate();
| |
− | draw();
| |
− | requestAnimationFrame(control);
| |
− | }
| |
− | control();
| |
− | // setInterval(control, 1000 / fps); // Запуск системы
| |
− |
| |
− | function calculate() {
| |
− | if (!count) return;
| |
− | for (var s=1; s<=spf; s++) {
| |
− | var f = -B*v - C * (rect.x - x0) - C1*Math.pow(rect.x - x0,3)+2*F*Math.sin(t);
| |
− | v += f / m * dt;
| |
− | //console.log(f);
| |
− | rect.x += v * dt;
| |
− | t+= dt;
| |
− | steps++;
| |
− | if (steps % 80 == 0) vGraph.graphIter(steps, (rect.x-x0)/canvas.width*2); // подать данные на график
| |
− | }
| |
− |
| |
− | }
| |
− |
| |
− | function draw() {
| |
− | ctx.clearRect(0, 0, w, h);
| |
− | draw_spring(startX, rect.x, h/2, 10, 50);
| |
− | ctx.fillStyle = "#0000ff";
| |
− | ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
| |
− | }
| |
− |
| |
− |
| |
− | 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();
| |
− | }
| |
− | }
| |
− | }
| |