Векторная математика отключена в одной из функций

#javascript #math #vector #p5.js

#javascript #математика #вектор #p5.js

Вопрос:

Я намерен смоделировать гравитационное ускорение на двумерной плоскости (упрощенно, без гравитационной постоянной). Мой код интерпретируется в консоли без каких-либо ошибок, но вместо того, чтобы два круга медленно ускорялись навстречу друг другу, они удаляются друг от друга. Ускорение, похоже, остается на уровне 0. Я не могу понять это поведение.

 // orbiters is gonna be the array containing the two celestial bodies 
var orbiters;
var sun;
var earth;
function setup() {
  frameRate(.3);
  console.log("starting the program")
  createCanvas(640, 480);
  sun = new Orbiter(10, 0, 0, width/2, height/2);
  earth = new Orbiter (1, 0, 0, width/5, height/4);
  orbiters = [sun, earth];
}

function draw() {
  console.log("starting the loop")
  background(15, 40, 20);
  // [missing: calculate gravity acceleration], then update position, display position. 
  orbiters.forEach(function(celBody) { 
    celBody.update();
    })
  orbiters.forEach(function(celBody) { 
    celBody.display();
    })
    // for each celestial body, accelerate it towards every other celestial body
  orbiters.forEach(function(celBody){
    orbiters.forEach(function (otherCelBody){
      if(celBody != otherCelBody){
        celBody.gravityAccelerate(otherCelBody.weight, otherCelBody.pos)
      }
    })
  })
}
// No volume for now: describe a body with weight, velocity, position
function Orbiter(weight, vx, vy, posx, posy) {
  this.weight = weight;
  this.pos = createVector(posx, posy);
  this.vel = createVector(vx, vy);
  this.acc = createVector(0, 0);
  
  //this finds an acceleration and an angle and gives out a vector to accelerate a body by
  this.gravityAccelerate = function(otherBodyWeight, otherBodyPosition) {
    
    // calculate magnitude
    gravDistance = sqrt(sq(otherBodyPosition.x - this.pos.x) sq(otherBodyPosition.y - this.pos.y));
    // calculate angle
    gravHeading = createVector(otherBodyPosition.sub(this.pos)).heading();
    // calculate force and divide by own mass(acceleration amount)
    gravForce = (this.weight * otherBodyWeight) / gravDistance;
// calculate gravitational acceleration's magnitude as a vector
    gravAccMag = gravForce / this.weight;
    // apply amount to angle and give a vector
    console.log("gravity acceleration = ")
    gravAccVec = createVector(Math.cos(gravHeading), Math.sin(gravHeading));
// display gravitational acceleration vector
    console.log(gravAccVec.x);
    console.log(gravAccVec.y);
    console.log("this body's acceleration = ");
    console.log(this.acc.x);
    console.log(this.acc.y);
    this.acc = this.acc.add(gravAccVec);
    console.log("this body's position")
    console.log(this.pos.x)
    console.log(this.pos.x)
  }
  
  this.update = function() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
  }
  
  this.display = function() {
    this.size = sqrt(this.weight * 10);
    fill (60, 180, 70);
    ellipse(this.pos.x, this.pos.y, this.size, this.size);
  }
}
 

Я попытался снизить частоту кадров, чтобы лучше проанализировать выполнение, начальное положение двух кругов кажется правильным. Кажется, что они отталкиваются, а не притягиваются, и что еще более странно, я вижу изменение положения, но общее ускорение (this.acc) и изменение ускорения силы тяжести (gravAccVec) имеют значение 0 и не меняются, а заголовок вектора ускорения силы тяжести null равен, поэтому я нене понимаю, что вызывает отталкивающее движение. Изменение значения веса не влияет на результат, и даже переключение синуса и косинуса для оценки угла вектора силы тяжести ничего не меняет:

 body1(x,y)  body2(x,y)
320,240     -192,-120
512,360     -704,-480
1216,840    -1920,-1320
3136,2160   -5056,-3480
 

Для выполнения этого кода вам необходимо импортировать p5.js библиотека.

Комментарии:

1. В вашем комментарии говорится accelerate it towards every other celestial body , но ваш код этого не делает 🙂 вам нужно вставить if (celBody != otherCelBody)

2. Вы правы, я исправил это, поведение по-прежнему безумное, но я вижу, что оно изменилось

3. Гравитация — это сила притяжения. Вы должны проверить свои знаки.

4. Я обнаружил ошибку: a.sub(b) вычитает b из a, что означает, что при вычислении заголовка вы также изменили позицию. Вам нужно gravHeading = p5.Vector.sub(otherBodyPosition, this.pos).heading();

5. Я потратил кучу времени, чтобы исправить это, и вот результат: jsfiddle.net/khrismuc/un20ejvm (измените начальную скорость y для земли на 0,8, чтобы получить круговую орбиту) ((не публикуя ответ, потому что это в основном ошибка, указанная выше, а остальное — математика))