Редактирование: КП: Движение спутника в двойной системе

Перейти к: навигация, поиск

Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.

Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия Ваш текст
Строка 11: Строка 11:
  
 
[[Файл:2planets.png|thumb|Модель системы|450px]]
 
[[Файл:2planets.png|thumb|Модель системы|450px]]
 
== Аннотация проекта ==
 
Данный проект посвящен изучению движения спутника в двойной системе под действием гравитации. В ходе работы над проектом была написана программа, которая моделирует процесс движения спутника. Программа написана на языке [https://ru.wikipedia.org/wiki/JavaScript JavaScript].
 
  
 
== Формулировка задачи ==
 
== Формулировка задачи ==
Исследовать движение спутника двойной системы под действием гравитационной силы. Двойная система состоит из 2 неподвижных планет и спутника вращающегося вокруг них как показано на рисунке сверху. Определить стационарные орбиты спутника, а также устойчивость движения спутника.
+
Исследовать движение спутника двойной системы. Двойная система состоит из 2 неподвижных планет и спутника вращающегося вокруг них как показано на рисунке сверху. Определить стационарные орбиты спутника, а также устойчивость движения спутника.
  
 
== Общие сведения по теме ==
 
== Общие сведения по теме ==
Строка 40: Строка 37:
 
Дальнейшим дифференцированием получаем уравнение движения.
 
Дальнейшим дифференцированием получаем уравнение движения.
  
'''2 способ''': записываем 2-ой закон Ньютона для данной задачи и получаем:
+
'''2 способ''':записываем 2-ой закон Ньютона для данной задачи и получаем:
  
[[Файл:IC694010.png]]
+
[[Файл:2newton.jpg|400px|left]]
  
  
Строка 48: Строка 45:
  
  
, где ''G''- гравитационная постоянная,''m''- массы планет.
+
,где [[Файл:gamma.png|10px]] - гравитационная постоянная,''m''- массы планет,''q'' - координаты планет.
  
 
== Решение ==
 
== Решение ==
Строка 136: Строка 133:
  
  
Стационарные орбиты спутника будут близки к овалам Кассини
 
  
-это семейство кривых, которые задаются уравнением  [[Файл:oval.png]] , где ''2c''-расстояние между фокусами, ''а''- некоторая константа.
 
  
графики овалов Кассини:
 
[[Файл:cass.png]]
 
  
  
Строка 147: Строка 140:
  
  
Частным случаем овалов Кассини является лемниската Бернулли, которая выглядит как знак бесконечности или восьмерка
 
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/MuschakND/K/traMOON.html |width=600 |height=350 |border=0 }}
 
  
{{#widget:Iframe |url=http://tm.spbstu.ru/htmlets/MuschakND/K3/K3.html |width=1024 |height=900 |border=0 }}
 
  
  
Программа: [[Медиа:K3.zip|скачать]]
 
  
<div class="mw-collapsible mw-collapsed">
 
'''Текст программы на языке JavaScript:''' <div class="mw-collapsible-content">
 
Файл '''"K3.html"'''
 
<syntaxhighlight lang="javascript" line start="1" enclose="div">
 
<!DOCTYPE html>
 
  
<html>
 
<head>
 
  <meta charset="utf-8" />
 
  <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <!-- For IE on an intranet. -->
 
  <title>Moon in Binary System</title>
 
  <style>
 
    html, body {
 
      margin: 0;
 
      padding: 0;
 
    }
 
  
    html {
 
      overflow-y: scroll; /* There's an issue with the scrollbar "randomly" appearing - this just keeps it always visible in case the user is using a very wide and narrow monitor. */
 
    }
 
  
    body {
 
      width: 1024px; /* Currently, most screens can handle this. */
 
      margin: auto; /* Center the page content. */
 
      background-color: #777;
 
      font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; /* Start screen font. */
 
    }
 
  
    header {
 
      color: #FFF;
 
      text-shadow: 5px 5px 10px #333;
 
    }
 
  
    section {
 
      position: relative; /* Float children relative to this element. */
 
    }
 
  
      section form {
 
        width: 210px; /* This is a bit less than the "section #WebGLCanvasElementContainer margin-left" value to provide a nice space between the form and the viewport. */
 
        float: left;
 
        text-align: center; /* Center the button elements. */
 
      }
 
  
        section form fieldset {
 
          text-align: left; /* Undo the button center aligning trick for the text in the form. */
 
          margin-bottom: 1.25em; /* Adjust this so that the height of the form is about the same height as the WebGL Three.js viewport element. */
 
        }
 
  
          section form fieldset input {
 
            width: 100%;
 
          }
 
  
        section form td {
+
Стационарные орбиты спутника будут близки к овалам Кассини
          white-space: nowrap; /* Don't let words like "x-position" break at the hyphen (which occurs in Chrome). */
 
        }
 
  
      section #WebGLCanvasElementContainer {
+
-это семейство кривых, которые задаются уравнением  [[Файл:oval.png]] , где ''2c''-расстояние между фокусами, ''а''- некоторая константа.
        border: 1px solid #DDD; /* Match the native color of the fieldset border. */
 
        width: 800px; /* The assumed fixed width of the WebGL Three.js viewport element. */
 
        height: 600px; /* The assumed fixed height of the WebGL Three.js viewport element. */
 
        margin-left: 224px; /* This is "body width" minus "section #WebGLCanvasElementContainer width" or 1024px - 800px = 224px. */
 
        background-image: url('starField.jpg'); /* 0.15 opacity value. */
 
      }
 
  
      section article {
+
графики овалов Кассини:
        padding: 0 1em;
+
[[Файл:cass.png]]
        color: white;
 
      }
 
  
      section button {
 
        width: 4.5em;
 
      }
 
  </style>
 
  <script>
 
    /*// Preload all images/bitmaps.
 
    var preloadImages = [];
 
    var preloadImagePaths = ["jupiter.png", "saturn.png", "moon.png", "starField.jpg", "starField.jpg"];
 
   
 
    for (var i = 0; i < preloadImagePaths.length; i++) {
 
      preloadImages[i] = new Image();
 
     
 
      preloadImages[i].onerror = function() {
 
        if (console) {
 
          console.error(this.src + " error.");
 
        } // if
 
      }; // onerror
 
     
 
      preloadImages[i].src = preloadImagePaths[i]; // Preload images to improve perceived app speed.
 
    } // for 
 
  */</script>
 
</head>
 
  
<body>
 
  <header>
 
    <h1>Moon in Binary System </h1>
 
  </header>
 
  <section>
 
    <form id="initialConditions">
 
      <fieldset>
 
        <legend>Moon</legend>
 
        <table id="mass1">
 
          <tr>
 
            <td>mass:</td>
 
            <td><input id="m1_mass" type="number" value="1E18" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>x-position:</td>
 
            <td><input id="m1_position_x" type="number" value="-141" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>y-position:</td>
 
            <td><input id="m1_position_y" type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>x-velocity:</td>
 
            <td><input id="m1_velocity_x" type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>y-velocity:</td>
 
            <td><input id="m1_velocity_y" type="number" value="2" required="required" /></td>
 
          </tr>
 
          <tr style="display: none;">
 
            <td>bitmap:</td>
 
            <td><input type="text" value="moon.png" required="required" /></td>
 
          </tr>
 
        </table>
 
      </fieldset>
 
      <fieldset>
 
        <legend>1st star</legend>
 
        <table id="mass2">
 
          <tr>
 
            <td>mass:</td>
 
            <td><input type="number" value="1E19" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>x-position:</td>
 
            <td><input type="number" value="-100" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>y-position:</td>
 
            <td><input type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>x-velocity:</td>
 
            <td><input type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>y-velocity:</td>
 
            <td><input type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr style="display: none;">
 
            <td>bitmap:</td>
 
            <td><input type="text" value="jupiter.png" required="required" /></td>
 
          </tr>
 
        </table>
 
      </fieldset>
 
      <fieldset>
 
        <legend>2nd star</legend>
 
        <table id="mass3">
 
          <tr>
 
            <td>mass:</td>
 
            <td><input type="number" value="1E19" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>x-position:</td>
 
            <td><input type="number" value="100" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>y-position:</td>
 
            <td><input type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>x-velocity:</td>
 
            <td><input type="number" value="0"  required="required" /></td>
 
          </tr>
 
          <tr>
 
            <td>y-velocity:</td>
 
            <td><input type="number" value="0" required="required" /></td>
 
          </tr>
 
          <tr style="display: none;">
 
            <td>bitmap:</td>
 
            <td><input type="text" value="saturn.png" required="required" /></td>
 
          </tr>
 
        </table>
 
      </fieldset>
 
      <button id="submitButton">Submit</button>
 
      <button id="reloadButton">Reload</button>
 
     
 
    </form>
 
    <div id="WebGLCanvasElementContainer">
 
      <!-- Three.js will add a canvas element to the DOM here. -->
 
      <!-- The following <article> element (along with its content) will be removed via JavaScript just before the simulation starts: -->
 
      <article>
 
        <h2></h2>
 
        <p>
 
         
 
        </p>
 
        <h2>Running the simulation</h2>
 
        <ul>
 
          <li>To start the simulation with the current set of initial conditions, click the <strong>Submit</strong> button.</li>
 
          <li>To orbit, left-click and drag the mouse.</li>
 
          <li>To pan, right-click and drag the mouse.</li>
 
          <li>To zoom, roll the mouse wheel.</li>
 
          <li>To enter your own initial conditions, enter numeric values of your choice (in the form to the left) and click <strong>Submit</strong>.
 
          Note that large values such as 10<sup>18</sup> can be entered as 1E18.</li>
 
          <li>To restart the simulation from scratch, click the <strong>Reload</strong> button (equivalent to refreshing the page).</li>
 
          <li>For additional information and resources, click the <strong>Info</strong> button.</li>
 
        </ul>
 
      </article>
 
    </div>
 
  </section>
 
  <script src="https://rawgithub.com/mrdoob/three.js/master/build/three.js"></script> <!-- The "CDN" for Three.js  -->
 
  <script src="https://rawgithub.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script> <!-- Allows for orbiting, panning, and zooming. -->
 
  <script>
 
    var  DENSITY= 1.38E14; // This value determined qualitatively by observing how large the spheres look onscreen (i.e., their radii).
 
  
    document.getElementById('submitButton').addEventListener('click', handleSubmitButton, false);
 
    document.getElementById('reloadButton').addEventListener('click', handleReloadButton, false);
 
   
 
  
    var simulation = Simulation(); // Call the Simulation constructor to create a new simulation object.
 
  
    function Simulation() { // A constructor.
+
Частным случаем овалов Кассини является лемниската Бернулли, которая выглядит как знак бесконечности или восьмерка
      var that = {}; // The object returned by this constructor.
+
{{#widget:Iframe |url=http://tm.spbstu.ru:8090/ws-htmlets/MuschakND/K.html |width=900 |height=450 |border=0 }}
      var worker; // Will contain a reference to a fast number-chrunching worker thread that runs outside of this UR/animation thread.
 
      var requestAnimationFrameID = null; // Used to cancel a prior requestAnimationFrame request.
 
      var gl = {}; // Will contain WebGL related items.
 
  
      gl.viewportWidth = 800; // The width of the Three.js viewport.
+
== Обсуждение результатов и выводы ==
      gl.viewportHeight = 600; // The height of the Three.js viewport.
 
  
      gl.cameraSpecs = {
 
        aspectRatio: gl.viewportWidth / gl.viewportHeight, // Camera frustum aspect ratio.
 
        viewAngle: 50 // Camera frustum vertical field of view, in degrees.
 
      };
 
  
      gl.clippingPlane = {
+
<br>
        near: 0.1, // The distance of the near clipping plane (which always coincides with the monitor).
+
Скачать отчет:
        far: 1000 // The distance of the far clipping plane (note that you get a negative far clipping plane for free, which occurs at the negative of this value).
+
<br>
      };
+
Скачать презентацию:
  
      gl.quads = 32; // Represents both the number of vertical segments and the number of horizontal rings for each mass's sphere wireframe.
+
== Ссылки по теме ==
 
 
      gl.renderer = window.WebGLRenderingContext ? new THREE.WebGLRenderer({ alpha: true }) : new THREE.CanvasRenderer({ alpha: true }); // If WebGL isn't supported, fallback to using the canvas-based renderer (which most browsers support). Note that passing in "{ antialias: true }" is unnecessary in that this is the default behavior. However, we pass in "{ alpha: true }" in order to let the background PNG image shine through.
 
      gl.renderer.setClearColor(0x000000, 0); // Make the background completely transparent (the actual color, black in this case, does not matter) so that the PNG background image can shine through.
 
      gl.renderer.setSize(gl.viewportWidth, gl.viewportHeight); // Set the size of the renderer.
 
 
 
      gl.scene = new THREE.Scene(); // Create a Three.js scene.
 
 
 
      gl.camera = new THREE.PerspectiveCamera(gl.cameraSpecs.viewAngle, gl.cameraSpecs.aspectRatio, gl.clippingPlane.near, gl.clippingPlane.far); // Set up the viewer's eye position.
 
      gl.camera.position.set(0, 450, 0); // The camera starts at the origin, so move it to a good position.
 
      gl.camera.lookAt(gl.scene.position); // Make the camera look at the origin of the xyz-coordinate system.
 
 
 
      gl.controls = new THREE.OrbitControls(gl.camera, gl.renderer.domElement); // Allows for orbiting, panning, and zooming via OrbitsControls.js by http://threejs.org. For an example, see http://threejs.org/examples/misc_controls_orbit.html.
 
 
 
      gl.pointLight = new THREE.PointLight(0xFFFFFF); // Set the color of the light source (white).
 
      gl.pointLight.position.set(0, 250, 250); // Position the light source at (x, y, z).
 
      gl.scene.add(gl.pointLight); // Add the light source to the scene.
 
 
 
      gl.spheres = []; // Will contain WebGL sphere mesh objects representing the point masses.
 
 
 
      var init = function (initialConditions) { // Public method, resets everything when called.
 
        if (requestAnimationFrameID) {
 
          cancelAnimationFrame(requestAnimationFrameID); // Cancel the previous requestAnimationFrame request.
 
        }
 
 
 
        if (worker) {
 
          worker.terminate(); // Terminate the previously running worker thread to ensure a responsive UI.
 
        }
 
        worker = new Worker('K3.js'); // Spawn a fast number-chrunching thread that runs outside of this UR/animation thread.
 
 
 
        document.getElementById('WebGLCanvasElementContainer').style.backgroundImage = "url('starField.jpg')"; // Switch back to the non-opaque PNG background image.
 
        document.getElementsByTagName('article')[0].style.display = "none"; // Remove from page-flow the one (and only) article element (along with all of its content).
 
        document.getElementById('WebGLCanvasElementContainer').appendChild(gl.renderer.domElement); // Append renderer element to DOM.
 
 
 
        while (gl.spheres.length) { // Remove any prior spheres from the scene and empty the gl.spheres array:
 
          gl.scene.remove(gl.spheres.pop());
 
        } // while
 
 
 
        for (var i = 0; i < initialConditions.length; i++) { // Set the sphere objects in gl.spheres to initial conditions.
 
          initializeMesh(initialConditions[i]); // This call sets the gl.spheres array.
 
        } // for
 
 
 
        worker.postMessage({
 
          cmd: 'init', // Pass the initialization command to the web worker.
 
          initialConditions: initialConditions // Send a copy of the initial conditions to the web worker, so it can initialize its persistent global variables.
 
        }); // worker.postMessage
 
  
        worker.onmessage = function (evt) { // Process the results of the "crunch" command sent to the web worker (via this UI thread).
 
          for (var i = 0; i < evt.data.length; i++) {
 
            gl.spheres[i].position.x = evt.data[i].p.x;
 
            gl.spheres[i].position.z = evt.data[i].p.y;
 
            gl.spheres[i].position.y = 0; // 3BodyWorker.js is 2D (i.e., the physics are constrained to a plane).
 
            gl.spheres[i].rotation.y += initialConditions[i].rotation; // Place worker.onmessage in the init method in order to access its initialConditions array.
 
          }
 
          gl.renderer.render(gl.scene, gl.camera); // Update the positions of the masses (sphere meshes) onscreen based on the data returned by 3BodyWorker.js.
 
        }; // worker.onmessage
 
 
        function initializeMesh(initialCondition) {
 
          var texture = THREE.ImageUtils.loadTexture(initialCondition.bitmap); // Create texture object based on the given bitmap path.
 
          var material = new THREE.MeshPhongMaterial({ map: texture }); // Create a material (for the spherical mesh) that reflects light, potentially causing sphere surface shadows.
 
          var geometry = new THREE.SphereGeometry(initialCondition.radius, gl.quads, gl.quads); // Radius size, number of vertical segments, number of horizontal rings.
 
          var mesh = new THREE.Mesh(geometry, material); // A mesh represents the object (typically composed of many tiny triangles) to be displayed - in this case a hollow sphere with a bitmap on its surface.
 
 
          mesh.position.x = initialCondition.position.x;
 
          mesh.position.z = initialCondition.position.y; // Convert from 2D to "3D".
 
          mesh.position.y = 0; // The physics are constrained to the xz-plane (i.e., the xy-plane in 3BodyWorker.js).
 
 
          gl.scene.add(mesh); // Add the sphere to the Three.js scene.
 
          gl.spheres.push(mesh); // Make the Three.js mesh sphere objects accessible outside of this helper function.
 
        } // initializeMesh
 
      } // init
 
      that.init = init; // This is what makes the method public.
 
 
      var run = function () { // Public method.
 
        worker.postMessage({
 
          cmd: 'crunch' // This processing occurs between animation frames and, therefore, is assumed to take a relatively small amount of time (as compared to current frame rates).
 
        }); // worker.postMessage
 
        gl.controls.update(); // Allows for orbiting, panning, and zooming.
 
        requestAnimationFrameID = requestAnimationFrame(run); // Allow for the cancellation of this requestAnimationFrame request.
 
      }; // run()
 
      that.run = run;
 
 
      return that; // The object returned by the constructor.
 
    } // Simulation
 
 
    function handleSubmitButton(evt) {
 
      var m1 = InitialCondition(document.getElementById('mass1').querySelectorAll('input')); // A constructor returning an initial condition object.
 
      var m2 = InitialCondition(document.getElementById('mass2').querySelectorAll('input'));
 
      var m3 = InitialCondition(document.getElementById('mass3').querySelectorAll('input'));
 
 
      evt.preventDefault(); // Don't refresh the page when the user clicks this form button.
 
 
      if (!window.WebGLRenderingContext) { displayCanvasRendererWarning(); } // If necessary, warn the user that they're using a canvas-based Three.js renderer and that they should upgrade their browser so that a faster WebGL-based renderer can be used instead.
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
      simulation.init([m1, m2, m3]);
 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////   
 
simulation.run(); // The images have been preloaded so this works immediately.
 
 
      function InitialCondition(inputElements) {
 
        var mass = parseFloat(inputElements[0].value);
 
 
        return {
 
          mass: mass,
 
          radius: calculateRadius(mass),
 
          rotation: calculateRotation(mass),
 
          position: { x: parseFloat(inputElements[1].value), y: parseFloat(inputElements[2].value) },
 
          velocity: { x: parseFloat(inputElements[3].value), y: parseFloat(inputElements[4].value) },
 
          bitmap: inputElements[5].value // This is a string value (hence the non-use of parseFloat).
 
        };
 
 
        function calculateRadius(mass) {
 
          /*
 
            Mass equals density times volume or m = D * V = D * (4/3 * PI * r^3), and solving for r = [(3 * m)/(4 * PI * D)]^(1/3)
 
          */
 
          var radicand = (3 * mass) / (4 * Math.PI * DENSITY); // Only change the value of DENSITY to affect the value returned by this function.
 
 
          return Math.pow(radicand, 1 / 3);
 
        } // calculateRadius
 
 
        function calculateRotation(mass) {
 
          /*
 
            Using a power model, let the x-axis represent the radius and the y-axis the rotational rate of the sphere.
 
            The power model is y = a * x^b, where a and b are constants (which were empirically derived).
 
          */
 
          var radius = calculateRadius(mass);
 
 
          return 1.7 * Math.pow(radius, -1.9); // Rotational rate as a function of the sphere's radius.
 
        } // calculateRotation
 
      } // InitialCondition
 
    } // handleSubmitButton
 
 
    function handleReloadButton(evt) {
 
      /* 
 
        Clicking a form button automatically refreshes the page, which is exactly the behavior we want (i.e., location.reload() is not necessary here).
 
      */
 
    } // handleReloadButton
 
 
    function handleInfoButton(evt) {
 
      /*
 
        Note that when the info page covers up the animation, the animation stops because this is how requestAnimationFrame works. In this sense, we get a free pause feature.
 
      */
 
      evt.preventDefault(); // Don't refresh the page when the user clicks this form button.
 
      window.open("info.html"); // Open the info.html page in another tab.
 
    } // handleInfoButton
 
 
    function displayCanvasRendererWarning() { // This assumes that the user's browser at least supports canvas.
 
      var articleElement = document.getElementsByTagName('article')[0];
 
 
      articleElement.innerHTML = "<h2>WebGL not supported, using canvas-based renderer, please upgrade your browser.</h2>";
 
      articleElement.style.display = "block";
 
    }
 
  </script>
 
</body>
 
</html>
 
</syntaxhighlight>
 
</div>
 
 
 
<div class="mw-collapsible mw-collapsed">
 
'''Текст программы на языке JavaScript (продолжение):''' <div class="mw-collapsible-content">
 
Файл '''"K3.js"'''
 
<syntaxhighlight lang="javascript" line start="1" enclose="div">
 
/*
 
The acceleration equations for the 2D three-body problem (see equations 42 through 50):
 
 
  d^2[x1]/dt^2 = G*m2*(x2 - x1)/alpha + G*m3*(x3 - x1)/beta
 
 
  d^2[y1]/dt^2 = G*m2*(y2 - y1)/alpha + G*m3*(y3 - y1)/beta
 
 
  d^2[x2]/dt^2 = G*m1*(x1 - x2)/alpha + G*m3*(x3 - x2)/gamma
 
 
  d^2[y2]/dt^2 = G*m1*(y1 - y2)/alpha + G*m3*(y3 - y2)/gamma
 
 
  d^2[x3]/dt^2 = G*m1*(x1 - x3)/beta  + G*m2*(x2 - x3)/gamma
 
 
  d^2[y3]/dt^2 = G*m1*(y1 - y3)/beta  + G*m2*(y2 - y3)/gamma
 
 
where G = gravitational constant = 6.6725985 X 10^(-11) N-m^2/kg^2
 
      alpha = [ (x2 - x1)^2 + (y2 - y1)^2 ]^(3/2)  AND  alpha <> 0
 
      beta  = [ (x1 - x3)^2 + (y1 - y3)^2 ]^(3/2)  AND  beta <> 0
 
      gamma = [ (x3 - x2)^2 + (y3 - y2)^2 ]^(3/2)  AND  gamma <> 0
 
*/
 
 
var N = 3; // The number of bodies (point masses) this code is designed to handle.
 
var G = 6.67384E-11; // Big-G, in N(m/kg)^2.
 
var h = 0.000001; // Interval between time steps, in seconds. The smaller the value the more accurate the simulation. This value was empirically derived by visually observing the simulation over time.
 
var iterationsPerFrame = 400; // The number of calculations made per animation frame, this is an empirically derived number based on the value of h.
 
   
 
var m1;
 
var m1_half; // Initially, will contain a copy of m1.
 
var m2;
 
var m2_half;
 
var m3;
 
var m3_half;
 
 
self.onmessage = function (evt) { // evt.data contains the data passed from the calling main page thread.
 
  switch (evt.data.cmd) {
 
    case 'init':
 
      init(evt.data.initialConditions); // Transfer the initial conditions data to the persistant variables in this thread.
 
      break;
 
    case 'crunch':
 
      crunch();
 
      break;
 
    default:
 
      console.error("ERROR FROM worker.js: SWITCH STATEMENT ERROR IN self.onmessage");
 
  } // switch
 
};
 
 
// The denominators alpha, beta, and gamma for the acceleration equations 42 through 47:
 
function alpha(m1, m2) { // Equation 48.
 
  var delta_x = m2.p.x - m1.p.x;
 
  var delta_y = m2.p.y - m1.p.y;
 
 
  var delta_x_squared = delta_x * delta_x;
 
  var delta_y_squared = delta_y * delta_y;
 
 
  var base = delta_x_squared + delta_y_squared;
 
 
  return Math.sqrt(base * base * base); // Raise the base to the 3/2 power so as to calculate (x_2 - x_1 )^2 + (y_2 - y_1 )^2]^(3/2), equation 48.
 
}
 
 
function beta(m1, m3) { // Equation 49.
 
  var delta_x = m3.p.x - m1.p.x;
 
  var delta_y = m3.p.y - m1.p.y;
 
 
  var delta_x_squared = delta_x * delta_x;
 
  var delta_y_squared = delta_y * delta_y;
 
 
  var base = delta_x_squared + delta_y_squared;
 
 
  return Math.sqrt(base * base * base); // Raise the base to the 3/2 power so as to calculate (x3 - x1)^2 + (y3 - y1)^2 ]^(3/2), equation 49.
 
}
 
 
function gamma(m2, m3) { // Equation 50.
 
  var delta_x = m3.p.x - m2.p.x;
 
  var delta_y = m3.p.y - m2.p.y;
 
 
  var delta_x_squared = delta_x * delta_x;
 
  var delta_y_squared = delta_y * delta_y;
 
 
  var base = delta_x_squared + delta_y_squared;
 
 
  return Math.sqrt(base * base * base); // Raise the base to the 3/2 power so as to calculate (x3 - x2)^2 + (y3 - y2)^2]^(3/2), equation 50.
 
}
 
 
/*
 
  Note that the alpha, beta, and gamma functions could be replaced with a single alpha_beta_gamma(massA, massB) function but for clarity, this was not done.
 
*/
 
 
this.init = function (initialConditions) {
 
 
  // Define local mass object constructor function:
 
  function Mass(initialCondition) {
 
    this.m = initialCondition.mass; // The mass of the point mass.
 
    this.p = { x: initialCondition.position.x, y: initialCondition.position.y }; // The position of the mass.
 
    this.v = { x: initialCondition.velocity.x, y: initialCondition.velocity.y }; // The x- and y-components of velocity for the mass.
 
    this.a = {}; // Will contain the x- and y-components of acceleration for the mass.
 
  }
 
 
  if (initialConditions.length != N) {
 
    console.error("ERROR FROM worker.js: THE initialConditions ARRAY DOES NOT CONTAIN EXACTLY " + N + " OBJECTS - init() TERMINATED");
 
    return;
 
  }
 
 
  // Set the local mass object global variables:
 
  m1 = new Mass(initialConditions[0]);
 
  m1_half = new Mass(initialConditions[0]); // Create a copy of m1.
 
  m2 = new Mass(initialConditions[1]);
 
  m2_half = new Mass(initialConditions[1]);
 
  m3 = new Mass(initialConditions[2]);
 
  m3_half = new Mass(initialConditions[2]);
 
 
  // Calculate initial acceleration values (using initial conditions) in preparation for using equation 25:
 
  m1.a.x = G * m2.m * (m2.p.x - m1.p.x) / alpha(m1, m2) + G * m3.m * (m3.p.x - m1.p.x) / beta(m1, m3); // Equation 42.
 
  m1.a.y = G * m2.m * (m2.p.y - m1.p.y) / alpha(m1, m2) + G * m3.m * (m3.p.y - m1.p.y) / beta(m1, m3); // Equation 43.
 
  m2.a.x = G * m1.m * (m1.p.x - m2.p.x) / alpha(m1, m2) + G * m3.m * (m3.p.x - m2.p.x) / gamma(m2, m3); // Equation 44.
 
  m2.a.y = G * m1.m * (m1.p.y - m2.p.y) / alpha(m1, m2) + G * m3.m * (m3.p.y - m2.p.y) / gamma(m2, m3); // Equation 45.
 
  m3.a.x = G * m1.m * (m1.p.x - m3.p.x) / beta(m1, m3)  + G * m2.m * (m2.p.x - m3.p.x) / gamma(m2, m3); // Equation 46.
 
  m3.a.y = G * m1.m * (m1.p.y - m3.p.y) / beta(m1, m3)  + G * m2.m * (m2.p.y - m3.p.y) / gamma(m2, m3); // Equation 47.
 
 
  function equation25(x, v, a) {
 
    return x + 0.5 * h * v + 0.25 * (h * h) * a;  // Equation 25.
 
  }
 
 
  // For the first iteration (and only the first iteration), use equation 25 (instead of equation 22) to calculate the initial half-integer position values:
 
  m1_half.p.x = equation25(m1.p.x, m1.v.x, m1.a.x);
 
  m1_half.p.y = equation25(m1.p.y, m1.v.y, m1.a.y);
 
  m2_half.p.x = equation25(m2.p.x, m2.v.x, m2.a.x);
 
  m2_half.p.y = equation25(m2.p.y, m2.v.y, m2.a.y);
 
  m3_half.p.x = equation25(m3.p.x, m3.v.x, m3.a.x);
 
  m3_half.p.y = equation25(m3.p.y, m3.v.y, m3.a.y);
 
} // this.init
 
 
 
this.crunch = function () {
 
  for (var i = 0; i < iterationsPerFrame; i++) {
 
    // Calculate half-integer acceleration values (using equations 18 through 21) in preparation for using equation 23:
 
    m1_half.a.x = G * m2_half.m * (m2_half.p.x - m1_half.p.x) / alpha(m1_half, m2_half) + G * m3_half.m * (m3_half.p.x - m1_half.p.x) / beta(m1_half, m3_half); // Equation 42.
 
    m1_half.a.y = G * m2_half.m * (m2_half.p.y - m1_half.p.y) / alpha(m1_half, m2_half) + G * m3_half.m * (m3_half.p.y - m1_half.p.y) / beta(m1_half, m3_half); // Equation 43.
 
    m2_half.a.x = G * m1_half.m * (m1_half.p.x - m2_half.p.x) / alpha(m1_half, m2_half) + G * m3_half.m * (m3_half.p.x - m2_half.p.x) / gamma(m2_half, m3_half); // Equation 44.
 
    m2_half.a.y = G * m1_half.m * (m1_half.p.y - m2_half.p.y) / alpha(m1_half, m2_half) + G * m3_half.m * (m3_half.p.y - m2_half.p.y) / gamma(m2_half, m3_half); // Equation 45.
 
    m3_half.a.x = G * m1_half.m * (m1_half.p.x - m3_half.p.x) / beta(m1_half, m3_half)  + G * m2_half.m * (m2_half.p.x - m3_half.p.x) / gamma(m2_half, m3_half); // Equation 46.
 
    m3_half.a.y = G * m1_half.m * (m1_half.p.y - m3_half.p.y) / beta(m1_half, m3_half)  + G * m2_half.m * (m2_half.p.y - m3_half.p.y) / gamma(m2_half, m3_half); // Equation 47.
 
   
 
    // Calculate velocity values using equation 23:
 
    m1.v.x = equation23(m1.v.x, m1_half.a.x);
 
    m1.v.y = equation23(m1.v.y, m1_half.a.y);
 
    m2.v.x = equation23(m2.v.x, m2_half.a.x);
 
    m2.v.y = equation23(m2.v.y, m2_half.a.y);
 
    m3.v.x = equation23(m3.v.x, m3_half.a.x);
 
    m3.v.y = equation23(m3.v.y, m3_half.a.y);
 
   
 
    // Calculate position values using equation 24:
 
    m1.p.x = equation24(m1_half.p.x, m1.v.x);
 
    m1.p.y = equation24(m1_half.p.y, m1.v.y);
 
    m2.p.x = equation24(m2_half.p.x, m2.v.x);
 
    m2.p.y = equation24(m2_half.p.y, m2.v.y);
 
    m3.p.x = equation24(m3_half.p.x, m3.v.x);
 
    m3.p.y = equation24(m3_half.p.y, m3.v.y);
 
 
    // Calculate half-integer position values using equation 22:
 
    m1_half.p.x = equation22(m1.p.x, m1.v.x);
 
    m1_half.p.y = equation22(m1.p.y, m1.v.y);
 
    m2_half.p.x = equation22(m2.p.x, m2.v.x);
 
    m2_half.p.y = equation22(m2.p.y, m2.v.y);
 
    m3_half.p.x = equation22(m3.p.x, m3.v.x);
 
    m3_half.p.y = equation22(m3.p.y, m3.v.y);
 
  } // for
 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
  self.postMessage([m1/*, m2, m3*/]); // Send the crunched data back to the UI thread to be rendered onscreen.
 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
  function equation23(v, a) {
 
    return v + h * a; // Equation 23.
 
  }
 
 
  function equation24(x, v) {
 
    return x + 0.5 * h * v; // Equation 24.
 
  }
 
 
  function equation22(x, v) {
 
    return x + 0.5 * h * v; // Equation 22, this function is of course the same as the equation24(x, v) function.
 
  }
 
} // this.crunch
 
</syntaxhighlight>
 
</div>
 
 
В случае трех материальных тел на каждое из них действуют две силы со стороны двух других тел. Например, на тело m₁ действуют следующие силы (F₂ и F₃):
 
[[Файл:IC694.png]]
 
 
 
 
 
 
 
 
Сначала заметим, что результирующая сила F₁, действующая на тело m₁, будет суммой сил F₂ и F₃. Это значит, что F₁ = m₁a₁ = F₂ + F₃.
 
Теперь по тригонометрическим законам, мы можем разложить модуль результирующей силы F₁, действующей на тело m₁, на компоненты x и y:
 
[[Файл:IC694007.png]]
 
 
В красном и зеленом треугольниках на рис.  мы видим:
 
 
[[Файл:IC694008.png]]
 
 
 
 
 
 
 
Согласно закону всемирного тяготения Ньютона, F₂ и F₃ можно выразить как:
 
[[Файл:IC694009.png]]
 
 
 
 
 
 
Подставляя формулы, получим:
 
 
[[Файл:IC694010.png]]
 
 
 
Упрощая формулы, имеем:
 
[[Файл:IC694012.png]]
 
 
 
Здесь α и β равны:
 
[[Файл:IC694013.png]]
 
 
Эту систему уравнений (34,35,38-41) можно решить численно методом интегрирования "чехарда" (формулы 22–24) по заданным начальным условиям (значения массы, положения и скорости для каждого тела) с приемлемой точностью и стабильностью. Чтобы быстро добиться высокой точности, можно использовать рабочий веб-процесс для выполнения численного интегрирования в потоке, отдельном от потока пользовательского интерфейса главной страницы.
 
 
Рассмотрим N небесных тел. Пусть i обозначает одно из тел (i = 1, …, N), а h — малый интервал времени. В позиционном алгоритме Верле следующие значения положения и скорости тела i вычисляются следующим образом:
 
[[Файл:IC693998.png]]
 
номера возле формул соответствуют номерам формул в программе(см.текст программы K3.js)
 
 
firekeepers casino <a href="https://onlinecasinodd.com/">zone online casino games</a> free slots games <a href="https://onlinecasinodd.com/">online casino gambling</a> | https://onlinecasinodd.com/ - free online casino https://onlinecasinodd.com/ - firekeepers casino
 
 
== Ссылки по теме ==
 
*[https://msdn.microsoft.com/ru-ru/library/dn528554(v=vs.85).aspx,  Физические законы и формулы для задачи двух и трех тел.]
 
* [http://edu.sernam.ru/book_sm_math1.php?id=85, Овалы Кассини и лемниската- Курс высшей математики, Т.1]
 
*[http://elementy.ru/lib/432046, «Гравитация» А. Н. Петров]
 
  
 
== См. также ==
 
== См. также ==
Вам запрещено изменять защиту статьи. Edit Создать редактором

Обратите внимание, что все добавления и изменения текста статьи рассматриваются как выпущенные на условиях лицензии Public Domain (см. Department of Theoretical and Applied Mechanics:Авторские права). Если вы не хотите, чтобы ваши тексты свободно распространялись и редактировались любым желающим, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого.
НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ МАТЕРИАЛЫ, ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ!

To protect the wiki against automated edit spam, we kindly ask you to solve the following CAPTCHA:

Отменить | Справка по редактированию  (в новом окне)