#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, чтобы получить круговую орбиту) ((не публикуя ответ, потому что это в основном ошибка, указанная выше, а остальное — математика))