Поперечные волны в струне — различия между версиями

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
(Математическая модель=)
Строка 10: Строка 10:
 
Разработка программы моделирующая колебания струны
 
Разработка программы моделирующая колебания струны
 
    
 
    
==Математическая модель===  
+
===Математическая модель===  
 
<math> m \ddot r_i= -k \Delta r_i - B \dot r_i  </math><br />
 
<math> m \ddot r_i= -k \Delta r_i - B \dot r_i  </math><br />
 
  r = r(x,y)<br />
 
  r = r(x,y)<br />

Версия 14:48, 9 января 2016

Виртуальная лаборатория > Динамика взаимодействия частиц произвольной формы
Движение струны, со скоростью 1200 кадров в секунду

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

Цель проекта

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

Математическая модель

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

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

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


Результаты




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

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

Файл "Test.js"

  1 function Main_Spring(canvas, slider_g, text_g, slider_nu, text_nu, slider_A, text_A, sinbutton) {
  2 	var canvas, ctx, w, h, world, lineBody, lineBody1, mouseConstraint, s, s1; // переменные: канвас, содержимое канваса, ширина и высота канваса, создание "мира" p2, парвая и левая "стена", закрепление мыши, пружины для связи со стенами 
  3 	var scaleX = 50, scaleY = -50; //масштаб
  4 	var circleBody2 = new Array(); //массив шариков
  5 	var circleShape2 = new Array(); //массив форм шариков
  6 	var ss = new Array();//массив пружин
  7 	var num = 100; //общее кол-во частиц
  8 	var k = 250; // жесткость пружин
  9 	var B = 4; // вязкость
 10 	var R = 0.05; //радиус шаров
 11 	var dx = 0.01; // начальная длина пружин
 12 	var g = 0; // сила тяжести
 13 	var dtt = 0; // время для колебаний по sin
 14 	var LA = 2; // смещение по вертикали для sin
 15 	var dt = 0.03; // "скорость" для sin
 16 	var sw = 0; // переключатель для кнопок
 17 	
 18 	// Инициализируем канвал и действия маши 
 19 	canvas = document.getElementById("myCanvas");
 20     w = canvas.width;
 21     h = canvas.height;
 22     ctx = canvas.getContext("2d");
 23     ctx.lineWidth = 0.05;
 24 	canvas.addEventListener("mousedown", doMouseDown, false);
 25 	canvas.addEventListener("mousemove", doMouseMove, false);
 26 	canvas.addEventListener("mouseup", doMouseUp, false);
 27 	
 28 	// Ползунки и текстовые поля	
 29 	this.setSlider_g = function(new_g){g = new_g; world.gravity[1] = -g;};
 30 	this.setSlider_nu = function(new_nu){dt = new_nu/10;};
 31 	this.setSlider_A = function(new_A){LA = new_A*4;};
 32 	this.setSlider_B = function(new_B){B = new_B*12; s.damping = B; s1.damping = B; 
 33 	for (var i = 0; i < num-1; i++){ss[i].damping = B;};
 34 	for (var j = 0; j < num; j++){circleBody2[j].damping=B/24;};};
 35 	
 36 	slider_g.min = 0;               slider_g.max = 1;
 37     slider_g.step = 0.10;
 38     slider_g.value = g;
 39     text_g.value = g.toFixed(1);
 40 	
 41 	slider_A.min = 0;               slider_A.max = 1;
 42     slider_A.step = 0.10;
 43     slider_A.value = LA/4;
 44     text_A.value = (LA/4).toFixed(1);
 45 	
 46 		
 47 	slider_B.min = 0;               slider_B.max = 1;
 48     slider_B.step = 0.10;
 49     slider_B.value = B/12;
 50     text_B.value = (B/12).toFixed(1);
 51 	
 52 	slider_nu.min = 0;               slider_nu.max = 1;
 53     slider_nu.step = 0.10;
 54     slider_nu.value = dt*10;          // начальное значение ползунка должно задаваться после min и max
 55     text_nu.value = (dt*10).toFixed(1);
 56 
 57       init();
 58       animate();
 59 	  
 60 	// Функция "переключения" кнопок 
 61 	this.sw = function(a)
 62  	{
 63 		if (a==-1) sw = a;
 64 			else		
 65 				sw += a;
 66 	}
 67 	
 68 	// Функция движения левой границы по Sin 
 69 	function FSin()
 70 	{
 71 		sinbutton.value = "Стоп";
 72 		sw = 1;
 73 		dtt+=dt;
 74 		s.localAnchorB[0] = 4-LA * (Math.sin(dtt)/2);
 75 		return 0;
 76 	}
 77 	
 78 	function Stop()
 79 	{
 80 		sw = 0;
 81 		sinbutton.value = "Sin";
 82 	}
 83 	
 84 	// Функция сброса 
 85 	function Reset()
 86 	{
 87 		if (sinbutton.value != "Sin") sinbutton.value = "Sin";
 88 		dtt = 0;
 89 		sw = 0;
 90 		world.clear();
 91 		init();
 92 
 93 	}
 94 	
 95 	// Функция создания всех объектов 
 96       function init(){
 97         
 98 		// Создание мира p2
 99         world = new p2.World();
100 		world.gravity[1] = -g;
101 		world.solver.iterations = 10;
102 		world.solver.frictionIterations = 0;
103 
104 		// Создаем левую границу
105 		lineShape = new p2.Line({ length: 6 });
106         lineBody = new p2.Body({
107           position: [-6,-4],
108           angle: Math.PI/2 
109         });
110         lineBody.addShape(lineShape, [0,0], Math.PI );
111         world.addBody(lineBody);
112 		
113 		// Создаем правую границу
114 		lineShape1 = new p2.Line({ length: 6 });
115         lineBody1 = new p2.Body({
116           position: [6,-4],
117           angle: Math.PI/2 
118         });
119         lineBody1.addShape(lineShape1, [0,0], Math.PI );
120         world.addBody(lineBody1);
121 
122 		// Создаем все шарики
123 		for (var i = 0; i < num; i++)
124 		{
125 			circleShape2[i] = new p2.Circle({ radius: R });
126 			circleBody2[i] = new p2.Body({ mass:0.5, position:[(-6 + (12*(i+1)/(num+1))) ,0] , angularDamping:0, damping:B/24});
127 			circleBody2[i].addShape(circleShape2[i]);
128 			world.addBody(circleBody2[i]);
129 		};
130 		
131 		//Создаем пружину для связи с левой границей
132 		s = new p2.LinearSpring(circleBody2[0], lineBody, {
133                 restLength : dx,
134                 stiffness : k,
135 				damping : B,
136                 localAnchorB : [4,0],
137             });
138         world.addSpring(s);
139 		
140 		// Создаем пружину для связи с правой границей
141 		s1 = new p2.LinearSpring(circleBody2[num-1], lineBody1, {
142                 restLength : dx,
143                 stiffness : k,
144 				damping : B,
145                 localAnchorB : [4,0],
146             });
147         world.addSpring(s1);
148 		
149 		// Создаем пружины для связи шариков вместе
150 		for (var i = 0; i < num-1; i++)
151 		{
152 			ss[i] = new p2.LinearSpring(circleBody2[i], circleBody2[i+1], {
153                 restLength : dx,
154                 stiffness : k,
155 				damping : B,
156                 localAnchorA : [0,0],
157                 localAnchorB : [0,0],
158             });
159 			world.addSpring(ss[i]);
160 		}; 
161 		
162 		//Отключаем взаимодействие между пружинами и между шариками
163 		for (var i = 0; i < num-1; i++)
164 		{
165 			for (var j = i; j < num-1; j++)
166 			{
167 				world.disableBodyCollision(ss[i], ss[j]);
168 			}
169 		};
170 		
171 		for (var i = 0; i < num; i++)
172 		{
173 			for (var j = i; j < num; j++)
174 			{
175 				world.disableBodyCollision(circleBody2[i], circleBody2[j]);
176 				world.disableBodyCollision(circleBody2[i], lineBody1);
177 				world.disableBodyCollision(circleBody2[i], lineBody);
178 			}
179 		};
180 		
181 		// Создаем объект для мыши
182         mouseBody = new p2.Body();
183         world.addBody(mouseBody);
184 		
185       }
186 	  
187 	  // Функция нажатия мыши вниз 
188 	  function doMouseDown(event){
189           var position = getPhysicsCoord(event);
190           circleBody2.forEach(function(item, i, circleBody2)
191 		  {
192 		  var hitBodies = world.hitTest(position, [item]);
193           if(hitBodies.length){
194             mouseBody.position[0] = position[0];
195             mouseBody.position[1] = position[1];
196            mouseConstraint = new p2.LockConstraint(mouseBody, item);
197             world.addConstraint(mouseConstraint);
198 		  }
199           });
200         }
201 		
202 		// Функция перемещения мыши 
203 		  function doMouseMove(event){
204           var position = getPhysicsCoord(event);
205           mouseBody.position[0] = position[0];
206           mouseBody.position[1] = position[1];
207         }
208 		
209 		// Функция отпуская клавиши мыши 
210         function doMouseUp(event){
211           world.removeConstraint(mouseConstraint);
212         }  
213 
214 		// Перевод координат мыши в текущие координаты 
215 	    function getPhysicsCoord(mouseEvent){
216           var rect = canvas.getBoundingClientRect();
217           var x = mouseEvent.clientX - rect.left;
218           var y = mouseEvent.clientY - rect.top;
219           x = (x - w / 2) / scaleX;
220           y = (y - h / 2) / scaleY;
221 
222           return [x, y];
223 		}
224 	  
225 	  // Функция рисования всех шаров 
226 	  function drawAllCircle(){
227 		for (var i = 0; i < num; i++)
228 		{
229 		ctx.beginPath();
230         var x1 = circleBody2[i].position[0],
231             y1 = circleBody2[i].position[1],
232             radius1 = circleShape2[i].radius;
233         ctx.arc(x1,y1,radius1,0,2*Math.PI);
234 		ctx.fill();
235 		ctx.stroke();
236 		}
237 		ctx.strokeStyle = "black";
238       }
239 		
240 	// Рисуем пол
241       function drawPlane(){
242         ctx.moveTo(-w, -4);
243         ctx.lineTo( w, -4);
244 		ctx.strokeStyle = "black";
245         ctx.stroke();
246       }
247 	  
248 	  // Рисуем правую стену
249 	  function drawRL(){
250         ctx.beginPath();
251         var x = lineBody.position[0],
252             y = lineBody.position[1];
253         ctx.moveTo(x, -y);
254         ctx.lineTo(x, y);
255         ctx.strokeStyle = "black";
256 		ctx.stroke();
257       }
258 	  
259 	  
260 	  // Рисуем левую стену
261 	  function drawLL(){
262         ctx.beginPath();
263         var x = lineBody1.position[0],
264             y = lineBody1.position[1];
265         ctx.moveTo(x, -y);
266         ctx.lineTo(x, y);
267 		ctx.strokeStyle = "black";
268         ctx.stroke();
269       }
270 	  
271 	  // Рисуем все пружины
272 	  function drawAllSpring(){
273 		for (var i = 0; i < num-1; i++)
274 		{
275 		ctx.beginPath();
276         var x = circleBody2[i].position[0],
277             y = circleBody2[i].position[1];
278 		var x1 = circleBody2[i+1].position[0],
279             y1 = circleBody2[i+1].position[1];
280             ctx.moveTo(x, y);
281 			ctx.lineTo(x1, y1);
282 		ctx.strokeStyle = "black";
283         ctx.stroke();
284 		}
285       }
286 	  
287 	  // Рисуем пружину для связи первого шарика со стеной
288 	  function draw1S(){
289 		ctx.beginPath();
290         var x = circleBody2[0].position[0],
291             y = circleBody2[0].position[1];
292 		ctx.moveTo(-6, (s.localAnchorB[0]-4));
293         ctx.lineTo(x, y);
294         ctx.strokeStyle = "black";
295 		ctx.stroke();
296       }
297 	  
298 	  // Рисуем пружину для связи последнего шарика со стеной
299 	  function draw2S(){
300         ctx.beginPath();
301         var x = circleBody2[num-1].position[0],
302             y = circleBody2[num-1].position[1];
303         ctx.moveTo(6, 0);
304         ctx.lineTo(x, y);
305         ctx.strokeStyle = "black";
306 		ctx.stroke();
307       }
308 	  
309       function render(){
310         ctx.clearRect(0,0,w,h);
311         ctx.save();
312         ctx.translate(w/2, h/2);  // Переводим начало в центр
313         ctx.scale(50, -50);       //Зумируем канвас
314         // Рисуем все тела на канвасе
315 		drawAllCircle();
316         drawRL();
317 		drawLL();
318 		drawPlane();
319 		drawAllSpring();
320 		draw1S();
321 		draw2S();
322         ctx.restore();
323       }
324 
325       function animate(){
326         requestAnimationFrame(animate);
327 		if (sw == 1) FSin();
328 		if (sw == 2) Stop();
329 		if (sw == -1) Reset();
330         world.step(1/60);
331         render();
332       }
333 	  
334 }