Поперечные волны в струне — различия между версиями
Материал из 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
Виртуальная лаборатория > Динамика взаимодействия частиц произвольной формыСодержание
Курсовой проект по механике дискретных сред
- разработчик Богданов Дмитрий
- руководитель Кузькин Виталий
Цель проекта
Разработка программы моделирующая колебания струны
Математическая модель
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 }