Поперечные волны в струне

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
Виртуальная лаборатория > Динамика взаимодействия частиц произвольной формы
Движение струны, со скоростью 1200 кадров в секунду

Курсовой проект по механике дискретных сред

Цель проекта

Разработка программы моделирующая колебания струны


Решение

[math] m \ddot r=\sum -k \Delta r - B \dot r [/math]

r = r(x,y)
m - масса одной частицы
k - жесткость пружины
B - вязкость

Обе конца пружины закреплены

Результаты




Скачать архив

Текст программы на языке JavaScript (разработчик Александров Сергей):

Файл "Test.js" function Main_Spring(canvas, slider_g, text_g, slider_nu, text_nu, slider_A, text_A, sinbutton) { var canvas, ctx, w, h, world, lineBody, lineBody1, mouseConstraint, s, s1; // переменные: канвас, содержимое канваса, ширина и высота канваса, создание "мира" p2, парвая и левая "стена", закрепление мыши, пружины для связи со стенами var scaleX = 50, scaleY = -50; //масштаб var circleBody2 = new Array(); //массив шариков var circleShape2 = new Array(); //массив форм шариков var ss = new Array();//массив пружин var num = 100; //общее кол-во частиц var k = 250; // жесткость пружин var B = 4; // вязкость var R = 0.05; //радиус шаров var dx = 0.01; // начальная длина пружин var g = 0; // сила тяжести var dtt = 0; // время для колебаний по sin var LA = 2; // смещение по вертикали для sin var dt = 0.03; // "скорость" для sin var sw = 0; // переключатель для кнопок

// Инициализируем канвал и действия маши canvas = document.getElementById("myCanvas");

   w = canvas.width;
   h = canvas.height;
   ctx = canvas.getContext("2d");
   ctx.lineWidth = 0.05;

canvas.addEventListener("mousedown", doMouseDown, false); canvas.addEventListener("mousemove", doMouseMove, false); canvas.addEventListener("mouseup", doMouseUp, false);

// Ползунки и текстовые поля this.setSlider_g = function(new_g){g = new_g; world.gravity[1] = -g;}; this.setSlider_nu = function(new_nu){dt = new_nu/10;}; this.setSlider_A = function(new_A){LA = new_A*4;}; this.setSlider_B = function(new_B){B = new_B*12; s.damping = B; s1.damping = B; for (var i = 0; i < num-1; i++){ss[i].damping = B;}; for (var j = 0; j < num; j++){circleBody2[j].damping=B/24;};};

slider_g.min = 0; slider_g.max = 1;

   slider_g.step = 0.10;
   slider_g.value = g;
   text_g.value = g.toFixed(1);

slider_A.min = 0; slider_A.max = 1;

   slider_A.step = 0.10;
   slider_A.value = LA/4;
   text_A.value = (LA/4).toFixed(1);


slider_B.min = 0; slider_B.max = 1;

   slider_B.step = 0.10;
   slider_B.value = B/12;
   text_B.value = (B/12).toFixed(1);

slider_nu.min = 0; slider_nu.max = 1;

   slider_nu.step = 0.10;
   slider_nu.value = dt*10;          // начальное значение ползунка должно задаваться после min и max
   text_nu.value = (dt*10).toFixed(1);
     init();
     animate();

// Функция "переключения" кнопок this.sw = function(a)

	{

if (a==-1) sw = a; else sw += a; }

// Функция движения левой границы по Sin function FSin() { sinbutton.value = "Стоп"; sw = 1; dtt+=dt; s.localAnchorB[0] = 4-LA * (Math.sin(dtt)/2); return 0; }

function Stop() { sw = 0; sinbutton.value = "Sin"; }

// Функция сброса function Reset() { if (sinbutton.value != "Sin") sinbutton.value = "Sin"; dtt = 0; sw = 0; world.clear(); init();

}

// Функция создания всех объектов

     function init(){
       

// Создание мира p2

       world = new p2.World();

world.gravity[1] = -g; world.solver.iterations = 10; world.solver.frictionIterations = 0;

// Создаем левую границу lineShape = new p2.Line({ length: 6 });

       lineBody = new p2.Body({
         position: [-6,-4],
         angle: Math.PI/2 
       });
       lineBody.addShape(lineShape, [0,0], Math.PI );
       world.addBody(lineBody);

// Создаем правую границу lineShape1 = new p2.Line({ length: 6 });

       lineBody1 = new p2.Body({
         position: [6,-4],
         angle: Math.PI/2 
       });
       lineBody1.addShape(lineShape1, [0,0], Math.PI );
       world.addBody(lineBody1);

// Создаем все шарики for (var i = 0; i < num; i++) { circleShape2[i] = new p2.Circle({ radius: R }); circleBody2[i] = new p2.Body({ mass:0.5, position:[(-6 + (12*(i+1)/(num+1))) ,0] , angularDamping:0, damping:B/24}); circleBody2[i].addShape(circleShape2[i]); world.addBody(circleBody2[i]); };

//Создаем пружину для связи с левой границей s = new p2.LinearSpring(circleBody2[0], lineBody, {

               restLength : dx,
               stiffness : k,

damping : B,

               localAnchorB : [4,0],
           });
       world.addSpring(s);

// Создаем пружину для связи с правой границей s1 = new p2.LinearSpring(circleBody2[num-1], lineBody1, {

               restLength : dx,
               stiffness : k,

damping : B,

               localAnchorB : [4,0],
           });
       world.addSpring(s1);

// Создаем пружины для связи шариков вместе for (var i = 0; i < num-1; i++) { ss[i] = new p2.LinearSpring(circleBody2[i], circleBody2[i+1], {

               restLength : dx,
               stiffness : k,

damping : B,

               localAnchorA : [0,0],
               localAnchorB : [0,0],
           });

world.addSpring(ss[i]); };

//Отключаем взаимодействие между пружинами и между шариками for (var i = 0; i < num-1; i++) { for (var j = i; j < num-1; j++) { world.disableBodyCollision(ss[i], ss[j]); } };

for (var i = 0; i < num; i++) { for (var j = i; j < num; j++) { world.disableBodyCollision(circleBody2[i], circleBody2[j]); world.disableBodyCollision(circleBody2[i], lineBody1); world.disableBodyCollision(circleBody2[i], lineBody); } };

// Создаем объект для мыши

       mouseBody = new p2.Body();
       world.addBody(mouseBody);
     }

// Функция нажатия мыши вниз function doMouseDown(event){

         var position = getPhysicsCoord(event);
         circleBody2.forEach(function(item, i, circleBody2)

{ var hitBodies = world.hitTest(position, [item]);

         if(hitBodies.length){
           mouseBody.position[0] = position[0];
           mouseBody.position[1] = position[1];
          mouseConstraint = new p2.LockConstraint(mouseBody, item);
           world.addConstraint(mouseConstraint);

}

         });
       }

// Функция перемещения мыши function doMouseMove(event){

         var position = getPhysicsCoord(event);
         mouseBody.position[0] = position[0];
         mouseBody.position[1] = position[1];
       }

// Функция отпуская клавиши мыши

       function doMouseUp(event){
         world.removeConstraint(mouseConstraint);
       }  

// Перевод координат мыши в текущие координаты function getPhysicsCoord(mouseEvent){

         var rect = canvas.getBoundingClientRect();
         var x = mouseEvent.clientX - rect.left;
         var y = mouseEvent.clientY - rect.top;
         x = (x - w / 2) / scaleX;
         y = (y - h / 2) / scaleY;
         return [x, y];

}

// Функция рисования всех шаров function drawAllCircle(){ for (var i = 0; i < num; i++) { ctx.beginPath();

       var x1 = circleBody2[i].position[0],
           y1 = circleBody2[i].position[1],
           radius1 = circleShape2[i].radius;
       ctx.arc(x1,y1,radius1,0,2*Math.PI);

ctx.fill(); ctx.stroke(); } ctx.strokeStyle = "black";

     }

// Рисуем пол

     function drawPlane(){
       ctx.moveTo(-w, -4);
       ctx.lineTo( w, -4);

ctx.strokeStyle = "black";

       ctx.stroke();
     }

// Рисуем правую стену function drawRL(){

       ctx.beginPath();
       var x = lineBody.position[0],
           y = lineBody.position[1];
       ctx.moveTo(x, -y);
       ctx.lineTo(x, y);
       ctx.strokeStyle = "black";

ctx.stroke();

     }


// Рисуем левую стену function drawLL(){

       ctx.beginPath();
       var x = lineBody1.position[0],
           y = lineBody1.position[1];
       ctx.moveTo(x, -y);
       ctx.lineTo(x, y);

ctx.strokeStyle = "black";

       ctx.stroke();
     }

// Рисуем все пружины function drawAllSpring(){ for (var i = 0; i < num-1; i++) { ctx.beginPath();

       var x = circleBody2[i].position[0],
           y = circleBody2[i].position[1];

var x1 = circleBody2[i+1].position[0],

           y1 = circleBody2[i+1].position[1];
           ctx.moveTo(x, y);

ctx.lineTo(x1, y1); ctx.strokeStyle = "black";

       ctx.stroke();

}

     }

// Рисуем пружину для связи первого шарика со стеной function draw1S(){ ctx.beginPath();

       var x = circleBody2[0].position[0],
           y = circleBody2[0].position[1];

ctx.moveTo(-6, (s.localAnchorB[0]-4));

       ctx.lineTo(x, y);
       ctx.strokeStyle = "black";

ctx.stroke();

     }

// Рисуем пружину для связи последнего шарика со стеной function draw2S(){

       ctx.beginPath();
       var x = circleBody2[num-1].position[0],
           y = circleBody2[num-1].position[1];
       ctx.moveTo(6, 0);
       ctx.lineTo(x, y);
       ctx.strokeStyle = "black";

ctx.stroke();

     }
     function render(){
       ctx.clearRect(0,0,w,h);
       ctx.save();
       ctx.translate(w/2, h/2);  // Переводим начало в центр
       ctx.scale(50, -50);       //Зумируем канвас
       // Рисуем все тела на канвасе

drawAllCircle();

       drawRL();

drawLL(); drawPlane(); drawAllSpring(); draw1S(); draw2S();

       ctx.restore();
     }
     function animate(){
       requestAnimationFrame(animate);

if (sw == 1) FSin(); if (sw == 2) Stop(); if (sw == -1) Reset();

       world.step(1/60);
       render();
     }

}

</syntaxhighlight>