|
|
Строка 1: |
Строка 1: |
− | Визуализация 3D-задачи по статике на JavaScript
| |
| | | |
− | Исполнитель: [[Андреева Полина]]
| |
− |
| |
− | Группа 23604/1 Кафедра Теоретической механики
| |
− |
| |
− | ==Формулировка задачи==
| |
− | [[File:8.14(1).png]]
| |
− |
| |
− |
| |
− | [[File:8.14.png]]
| |
− |
| |
− | ==Решение задачи==
| |
− | {{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/Andreeva/statica/Polks.html |width=1000 |height=830 |border=0 }}
| |
− |
| |
− |
| |
− | <div class="mw-collapsible mw-collapsed" style="width:100%" >
| |
− | <syntaxhighlight lang="javascript" line start="1" enclose="div">
| |
− |
| |
− | <!DOCTYPE html>
| |
− | <html>
| |
− | <head>
| |
− | <title> Задача из Мещерского </title>
| |
− | <script src = "http://tm.spbstu.ru/htmlets/Andreeva/statica/three.js">
| |
− | </script>
| |
− | <script src = "http://tm.spbstu.ru/htmlets/Andreeva/statica/stats.min.js">
| |
− | </script>
| |
− | <script src = "http://tm.spbstu.ru/htmlets/Andreeva/statica/OrbitControls.js" >
| |
− | </script>
| |
− | <script src = "http://tm.spbstu.ru/htmlets/Andreeva/statica/dat.gui.js">
| |
− | </script>
| |
− | <style>
| |
− | body
| |
− | {
| |
− | margin:0;
| |
− | overflow:hidden;
| |
− | }
| |
− | </style>
| |
− | </head>
| |
− | <body>
| |
− |
| |
− | <div id = "WebGL"> </div>
| |
− | <div id = "Stats-output"> </div>
| |
− |
| |
− | <script>
| |
− |
| |
− | var renderer,scene,camera,plane,stats,al,controls,c1,c2,c3,line1,line2,arrowFt,arr1_1,arr1_2,arr1_3,arr1_t,arr2,arr2_1,arr2_2,arr2_t,arr3,arr3_1,arr3_3,arr3_t;
| |
− |
| |
− | ///// ЗАДАНИЕ ПАРАМЕТРОВ, УКАЗАННЫХ В ЗАДАЧЕ /////
| |
− |
| |
− | var P=20;
| |
− | var rV=2;
| |
− | var LV=30;
| |
− | var radiusSegment=150;
| |
− | var heightSegment=150;
| |
− | var radiusToppalki=0.5;
| |
− | var L=LV+10;
| |
− | var heightpalkivertical=20;
| |
− | var LH=5;
| |
− | var LL=5;
| |
− | var A = Math.PI/6;
| |
− | var lengthTHREAD=30;
| |
− | var R=10;
| |
− | var segments=50;
| |
− | var radiusp=3;
| |
− | var stats;
| |
− | var ambiColor="#0c0c0c";
| |
− | var ambientLight;
| |
− | var step=0;
| |
− | var cylindergeom;
| |
− | var palka1geom;
| |
− | var palka2geom;
| |
− | var palka4geom;
| |
− | var diskgeom ;
| |
− | var boxQg;
| |
− | var diskpgeom;
| |
− | var boxPg;
| |
− | var control;
| |
− | var controls;
| |
− | //var thetastart= 0;
| |
− | //var thetalength= 2*Math.PI;
| |
− |
| |
− | function init()
| |
− | {
| |
− | scene = new THREE.Scene(); // создаем сцену
| |
− | camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000); // создаем камеру
| |
− | renderer = new THREE.WebGLRenderer();
| |
− | renderer.setClearColor(0xEEEEEE, 1);
| |
− | renderer.setSize(window.innerWidth, window.innerHeight);
| |
− | renderer.shadowMap.enabled = true;
| |
− |
| |
− | var axes = new THREE.AxisHelper(20); // создаем координатные оси
| |
− | scene.add(axes);
| |
− |
| |
− | control = new THREE.OrbitControls(camera,renderer.domElement);
| |
− |
| |
− | controls = new function() // создаем переключатели, позволяющие изменять входные параметры
| |
− | {
| |
− | this.lengthH = 5; //расстояние между диском концом вала
| |
− | this.LengthL = 5; //расстояние до веса Q
| |
− | this.lengthVAL = 30; // длина вала
| |
− | this.radiusVAL = 2; //радиус вала
| |
− | this.radius = 10; //радиус диска
| |
− | this.weightP = 2;//вес P
| |
− | this.alpha = Math.PI/6; //угол
| |
− | this.displayForces = true;
| |
− | }
| |
− |
| |
− | controls1=new function()
| |
− | {
| |
− | this.Xa='0'; // вывод полученных в ходе решения задачи значений
| |
− | this.Xb='0';
| |
− | this.Zb='0';
| |
− | this.Za='0';
| |
− | this.Q='0';
| |
− |
| |
− | }
| |
− |
| |
− | var gui = new dat.GUI(); // позволяем менять каждый из параметров в определенном диапазоне, в случае изменения вызываем функцию, перестраивающую выводимую на экран картинку
| |
− | gui.add(controls, 'lengthH',0,50).onChange(ReDraw);
| |
− | gui.add(controls, 'lengthVAL',30,60).onChange(ReDraw);
| |
− | gui.add(controls, 'LengthL',5,LV+5).onChange(ReDraw);
| |
− | gui.add(controls, 'radiusVAL',0.1,3).onChange(ReDraw);
| |
− | gui.add(controls, 'radius',1,30).onChange(ReDraw);
| |
− | gui.add(controls, 'weightP',0,20).onChange(ReDraw);
| |
− | gui.add(controls, 'alpha',0,Math.PI/2).onChange(ReDraw)
| |
− | gui.add(controls, 'displayForces').onChange(Change); // параметр, определяющий вариант отображения задачи (с отображением сил и без отображения)
| |
− | gui.add(controls1, 'Xa').listen();
| |
− | gui.add(controls1, 'Xb').listen();
| |
− | gui.add(controls1, 'Za').listen();
| |
− | gui.add(controls1, 'Zb').listen();
| |
− | gui.add(controls1, 'Q').listen();
| |
− |
| |
− |
| |
− | AmbientLight=new THREE.AmbientLight(ambiColor);
| |
− | scene.add(ambientLight);
| |
− | document.getElementById("WebGL").appendChild(renderer.domElement);
| |
− | camera.position.x = 0;
| |
− | camera.position.y = 0;
| |
− | camera.position.z = 100;
| |
− | camera.lookAt(0,0,0);
| |
− | spotLight=new THREE.SpotLight(0xffffff);
| |
− | spotLight.position.set(90,-45,-90);
| |
− | scene.add(spotLight);
| |
− |
| |
− | stats = initStats();
| |
− | Draw();
| |
− | renderScene();
| |
− | window.addEventListener('resize',onResize,false);
| |
− | }
| |
− |
| |
− | /////
| |
− |
| |
− | function Change() // функция, меняющая вариант отображения задачи
| |
− | {
| |
− | if (controls.displayForces == true) // если требуется отображение сил
| |
− | {VisionTrue();}
| |
− | if (controls.displayForces == false) // если не требуется отображение сил
| |
− | {VisionFalse();}
| |
− | }
| |
− |
| |
− | function VisionTrue() // функция, рисующая задачу с отображением сил
| |
− | {
| |
− | ReDraw();
| |
− | }
| |
− |
| |
− | function VisionFalse() // общая картинка задача без отображения сил
| |
− | {
| |
− | ReDraw();
| |
− | cylinder.opacity = 1
| |
− | palka1.opacity = 1
| |
− | palka2.opacity = 1
| |
− | palka3.opacity = 1
| |
− | palka4.opacity = 1
| |
− | disk.opacity = 1
| |
− | disk2.opacity = 1
| |
− | diskp.opacity = 1
| |
− | diskp2.opacity = 1
| |
− | boxP.opacity = 1
| |
− | boxQ.opacity = 1
| |
− | boxPvec.visible = false; // убираем векторы, отображающие силы
| |
− | boxQvec.visible = false;
| |
− | XBvec.visible = false;
| |
− | XAvec.visible = false;
| |
− | ZBvec.visible = false;
| |
− | ZAvec.visible = false;
| |
− |
| |
− | renderScene();
| |
− | }
| |
− |
| |
− |
| |
− | function ReDraw() // функция, перерисовывающая всю картинку
| |
− | {
| |
− | scene.remove(cylinder); // удаляем ранее созданные объекты
| |
− | scene.remove(palka1);
| |
− | scene.remove(palka2);
| |
− | scene.remove(palka3);
| |
− | scene.remove(palka4);
| |
− | scene.remove(disk);
| |
− | scene.remove(disk2);
| |
− | scene.remove(diskp);
| |
− | scene.remove(diskp2);
| |
− | scene.remove(boxP);
| |
− | scene.remove(boxQ);
| |
− |
| |
− |
| |
− | LH = controls.lengthH; // меняем значения параметров на те, что ввел пользователь
| |
− | LV = controls.lengthVAL;
| |
− | LL = controls.LengthL;
| |
− | L = controls.lengthVAL+10;
| |
− | rV = controls.radiusVAL;
| |
− | R = controls.radius;
| |
− | P=controls.weightP;
| |
− | A=controls.alpha;
| |
− | Draw();
| |
− | }
| |
− |
| |
− | function Draw()
| |
− | {
| |
− | Q=P*R/rV;
| |
− | Q2 = P*R/rV;
| |
− | controls1.Q= Q2; // вывод решения на экран
| |
− |
| |
− | vectXb =P*Math.cos(A)*LH/((L));
| |
− | controls1.Xb= vectXb;
| |
− |
| |
− | vectXa = P*Math.cos(A) + vectXb;
| |
− | controls1.Xa= vectXa;
| |
− |
| |
− | vectP = P;
| |
− | controls1.P1= vectP;
| |
− |
| |
− | vectZb = Q*LL/(L) - P*Math.sin(A)*LH/(L);
| |
− | controls1.Zb= vectZb;
| |
− |
| |
− | vectZa = Q+ P*Math.sin(A)-vectZb;
| |
− | controls1.Za= vectZa;
| |
− | ///// СОЗДАНИЕ всех ТЕЛ /////
| |
− |
| |
− | cylindergeom = new THREE.CylinderGeometry (rV, rV, LV, radiusSegment, heightSegment); // задаем геометрию вала
| |
− | cylindermaterial = new THREE.MeshLambertMaterial( { opacity:1, color: 0xDAA520,transparent:true } ); // задаем материал 1-ого тела
| |
− | cylinder = new THREE.Mesh(cylindergeom,cylindermaterial); // создаем тело с заданными геометрией и материалом
| |
− | cylinder.rotation.z = 1.57; // смещаем его центр из точки (0,0,0)
| |
− | scene.add(cylinder); // добавляем тело в сцену
| |
− |
| |
− | palka1geom = new THREE.CylinderGeometry (radiusToppalki, radiusToppalki, L, radiusSegment, heightSegment); // задаем геометрию вала
| |
− | palka1material = new THREE.MeshLambertMaterial( { opacity:1, color: 0xDAA520,transparent:true } ); // задаем материал 1-ого тела
| |
− | palka1 = new THREE.Mesh(palka1geom,palka1material); // создаем тело с заданными геометрией и материалом
| |
− | palka1.rotation.z = 1.57; // смещаем его центр из точки (0,0,0)
| |
− | scene.add(palka1); // добавляем тело в сцену
| |
− |
| |
− | palka2geom = new THREE.CylinderGeometry (radiusToppalki, radiusToppalki, heightpalkivertical, radiusSegment, heightSegment); // задаем геометрию вала
| |
− | palka2 = new THREE.Mesh(palka2geom,palka1material); // создаем тело с заданными геометрией и материалом
| |
− | palka2.position.x = L/2 - radiusToppalki ; // смещаем его центр из точки (0,0,0)
| |
− | palka2.position.y = -heightpalkivertical/2;
| |
− | scene.add(palka2);
| |
− |
| |
− | palka3 = new THREE.Mesh(palka2geom,palka1material); // создаем тело с заданными геометрией и материалом
| |
− | palka3.position.x = - L/2 + radiusToppalki ; // смещаем его центр из точки (0,0,0)
| |
− | palka3.position.y = -heightpalkivertical/2;
| |
− | scene.add(palka3);
| |
− |
| |
− | palka4geom = new THREE.CylinderGeometry (radiusToppalki, radiusToppalki, LH, radiusSegment, heightSegment); // задаем геометрию вала
| |
− | palka4 = new THREE.Mesh(palka4geom,palka1material); // создаем тело с заданными геометрией и материалом
| |
− | palka4.position.x = - L/2 -LH/2 ; // смещаем его центр из точки (0,0,0)
| |
− | palka4.rotation.z = 1.57;
| |
− | scene.add(palka4);
| |
− |
| |
− | diskgeom = new THREE.CircleGeometry(R,segments);//рисуем плоскость кольцо
| |
− | diskmaterial = new THREE.MeshBasicMaterial( {opacity:1, color: 0xCD853F, transparent: true}); // задаем материал
| |
− | disk = new THREE.Mesh(diskgeom,diskmaterial); // создаем тело с заданными геометрией и материалом
| |
− | disk.position.x = -L/2 - LH ; // смещаем его центр из точки (0,0,0)
| |
− | disk.rotation.y=Math.PI/2;
| |
− | //disk.position.x = ;
| |
− | scene.add(disk); // добавляем тело в сцену
| |
− |
| |
− |
| |
− | disk2 = new THREE.Mesh(diskgeom,diskmaterial); // создаем тело с заданными геометрией и материалом
| |
− | disk2.position.x = -L/2 -LH ; // смещаем его центр из точки (0,0,0)
| |
− | disk2.rotation.y=-Math.PI/2;
| |
− | //disk.position.x = ;
| |
− | scene.add(disk2);
| |
− |
| |
− | boxQg = new THREE.BoxGeometry (2, 2, 2); // задаем геометрию третьего тела (правое)
| |
− | boxm = new THREE.MeshBasicMaterial( {opacity:1, color: 0xFFDEAD, transparent: true}); // задаем материал
| |
− | boxQ = new THREE.Mesh(boxQg, boxm); // создаем тело с заданными геометрией и материалом
| |
− | boxQ.position.x = -L/2+LL; // смещаем его центр из точки (0,0,0)
| |
− | boxQ.position.y = -rV-10;
| |
− | boxQ.position.z = rV;
| |
− | scene.add(boxQ); // добавляем тело в сцену
| |
− |
| |
− |
| |
− | diskpgeom = new THREE.CircleGeometry(radiusp,segments);//рисуем плоскость кольцо
| |
− | diskp = new THREE.Mesh(diskpgeom,diskmaterial); // создаем тело с заданными геометрией и материалом
| |
− | diskp.position.x = -L/2 - LH ; // смещаем его центр из точки (0,0,0)
| |
− | diskp.rotation.y=Math.PI/2;
| |
− | diskp.position.z = R*Math.sin(A)+lengthTHREAD*Math.cos(A) - Math.sin(A) * radiusp ;
| |
− | diskp.position.y = R*Math.cos(A) - lengthTHREAD*Math.sin(A) - Math.cos(A)*radiusp;
| |
− | scene.add(diskp); // добавляем тело в сцену
| |
− |
| |
− |
| |
− | diskp2 = new THREE.Mesh(diskpgeom,diskmaterial); // создаем тело с заданными геометрией и материалом
| |
− | diskp2.position.x = -L/2 - LH ; // смещаем его центр из точки (0,0,0)
| |
− | diskp2.rotation.y=-Math.PI/2;
| |
− | diskp2.position.z = R*Math.sin(A)+lengthTHREAD*Math.cos(A) - Math.sin(A) * radiusp ;
| |
− | diskp2.position.y = R*Math.cos(A) - lengthTHREAD*Math.sin(A) - Math.cos(A)*radiusp;
| |
− | scene.add(diskp2);
| |
− |
| |
− | boxPg = new THREE.BoxGeometry (2, 2, 2); // задаем геометрию третьего тела (правое)
| |
− | boxP = new THREE.Mesh(boxPg, boxm);
| |
− | boxP.position.x = -L/2 - LH; // смещаем его центр из точки (0,0,0)
| |
− | boxP.position.z = diskp.position.z + radiusp;
| |
− | boxP.position.y = diskp.position.y - radiusp - 5;
| |
− | scene.add(boxP); // добавляем тело в сцену
| |
− |
| |
− |
| |
− | ///// СОЗДАНИЕ НИТЕЙ, СОЕДИНЯЮЩИХ ТЕЛА /////
| |
− |
| |
− |
| |
− |
| |
− | lg1 = new THREE.Geometry(); // создаем новую геометрию, предназначенную для изображения линии
| |
− | lg1.vertices.push(
| |
− | new THREE.Vector3(0,0,0), // задаем координату начала
| |
− | new THREE.Vector3(0,-boxQ.position.y,0) // задаем координату конца
| |
− | );
| |
− | lm = new THREE.LineBasicMaterial({color: 0xA0522D}); // задаем материал
| |
− | line1 = new THREE.Line(lg1, lm); // задаем линию с указанными координатами и материалом
| |
− | boxQ.add(line1);
| |
− |
| |
− |
| |
− |
| |
− | lg2 = new THREE.Geometry(); // создаем новую геометрию, предназначенную для изображения линии
| |
− | lg2.vertices.push(
| |
− | new THREE.Vector3(-R*Math.sin(A),R*Math.cos(A),0),
| |
− | new THREE.Vector3(-R*Math.sin(A)-lengthTHREAD*Math.cos(A),R*Math.cos(A) - lengthTHREAD*Math.sin(A),0)
| |
− | );
| |
− | line2 = new THREE.Line(lg2, lm); // задаем линию с указанными координатами и материалом
| |
− | disk.add(line2);
| |
− |
| |
− | lg3 = new THREE.Geometry(); // создаем новую геометрию, предназначенную для изображения линии
| |
− | lg3.vertices.push(
| |
− | new THREE.Vector3(0,0,0),
| |
− | new THREE.Vector3(0,radiusp+5,0)
| |
− | );
| |
− | line3 = new THREE.Line(lg3, lm); // задаем линию с указанными координатами и материалом
| |
− | boxP.add(line3);
| |
− |
| |
− |
| |
− | ///// СОЗДАНИЕ ВЕКТОРОВ, ОТОБРАЖАЮЩИХ СИЛЫ, ДЕЙСТВУЮЩИЕ НА ТЕЛА /////
| |
− | var boxPv= new THREE.Vector3( 0, -1, 1 );
| |
− | var v0 = new THREE.Vector3( 0, 0, 0 );
| |
− | var color = 0xDC143C;
| |
− | var lengthP = P/5; // задаем длину (численно равную исходному параметру в задаче)
| |
− | boxPvec = new THREE.ArrowHelper( boxPv, v0, lengthP, color ); // создаем срелочку
| |
− | boxP.add( boxPvec ); // прикрепляем вектор к первому телу
| |
− |
| |
− | var boxQv= new THREE.Vector3( 0, -1, 1 );
| |
− | Q=P*R/rV;
| |
− | var lengthQ = Q/5; // задаем длину (численно равную исходному параметру в задаче)
| |
− | boxQvec = new THREE.ArrowHelper( boxQv, v0, lengthQ, color ); // создаем срелочку
| |
− | boxQ.add( boxQvec ); // прикрепляем вектор к первому телу
| |
− |
| |
− |
| |
− | var XBV= new THREE.Vector3( 0,0, 1 );
| |
− | var Xb = 5*P*Math.cos(A)*LH/((L));
| |
− | XBvec = new THREE.ArrowHelper( XBV, v0, Xb, color ); // создаем срелочку
| |
− | XBvec.position.y = -L/2;
| |
− | //XB.rotation.y = Math.PI/2;
| |
− | palka1.add(XBvec );
| |
− |
| |
− |
| |
− |
| |
− | var ZBV= new THREE.Vector3( 1, 0, 0 );
| |
− | var Zb = Q*LL/(L) - P*Math.sin(A)*LH/(L);
| |
− | ZBvec = new THREE.ArrowHelper( ZBV, v0, Zb, color );
| |
− | ZBvec.position.y = -L/2;
| |
− | palka1.add(ZBvec );
| |
− |
| |
− | var ZAV= new THREE.Vector3( 1, 0, 0 );
| |
− | var Za = Q+ P*Math.sin(A)-Zb;
| |
− | ZAvec = new THREE.ArrowHelper( ZAV, v0, Za, color );
| |
− | ZAvec.position.y = L/2;
| |
− | //ZAvec.rotation.y = -Math.PI/2;
| |
− | palka1.add(ZAvec );
| |
− |
| |
− | var XAV= new THREE.Vector3( 0, 0, -1 );
| |
− | var Xa = P*Math.cos(A) + Xb;
| |
− | XAvec = new THREE.ArrowHelper( XAV, v0, Xa, color );
| |
− | XAvec.position.y = L/2;
| |
− | //XAvec.rotation.y = -Math.PI/2;
| |
− | palka1.add(XAvec );
| |
− |
| |
− |
| |
− | renderer.render(scene,camera);
| |
− | }
| |
− |
| |
− | function renderScene()
| |
− | {
| |
− | stats.update();
| |
− | LH = controls.lengthH;
| |
− | LL = controls.LengthL;
| |
− | LV = controls.lengthVAL;
| |
− | P = controls.weightP;
| |
− | L = controls.length;
| |
− | rV = controls.radiusVAL;
| |
− | R=controls.radius;
| |
− | P=controls.weightP;
| |
− | A=controls.alpha;
| |
− | requestAnimationFrame(renderScene);
| |
− | renderer.render(scene,camera);
| |
− | }
| |
− |
| |
− |
| |
− | function initStats()
| |
− | {
| |
− | var stats=new Stats();
| |
− | stats.setMode(0);
| |
− | stats.domElement.style.position='0px';
| |
− | stats.domElement.style.left='0px';
| |
− | stats.domElement.style.top='0px';
| |
− | document.getElementById("Stats-output").appendChild(stats.domElement);
| |
− | return stats;
| |
− | }
| |
− |
| |
− | function onResize()
| |
− | {
| |
− | camera.aspect = window.innerWidth/window.innerHeight;
| |
− | camera.updateProjectionMatrix();
| |
− | renderer.setSize(window.innerWidth,window.innerHeight);
| |
− | }
| |
− |
| |
− | window.onload = init;
| |
− | //window.addEventListener('resize',onResize,true);
| |
− | </script>
| |
− |
| |
− |
| |
− | <!-- http://colorscheme.ru/html-colors.html -->
| |