【问题标题】:Reverse gravity / anti-gravity? What elements of a gravitational force algorithm do i need to change for reversing it?反重力/反重力?我需要更改重力算法的哪些元素才能反转它?
【发布时间】:2021-03-31 15:58:05
【问题描述】:

我想反转我的重力算法,以在多个物体相互作用的“过去”中生成位置。通过在一组物体上多次运行算法来生成未来的位置是微不足道的,但是将其反转以写出物体先前位置的位置让我感到难过。我不想存储过去的位置,因为这是确定性的,应该可以以某种方式向后运行算法,但我不确定如何。

在循环中从universe 测试的每个sn-p element 主体中,tick 是增量时间。

function forces(other) {
  if (element === other) {
    return;
  }
  
  var distancePoint = element.point.sub(other.point);
  var normal = Math.sqrt(100.0 + distancePoint.lengthSq());
  var mag = GravatationalConstant /
              Math.pow(normal, 3);
  
  var distPointMulOtherMass = distancePoint
    .mul(mag * other.mass);
  
  element.acceleration = element.acceleration.sub(distPointMulOtherMass);
  other.acceleration = other
    .acceleration
    .add(distancePoint
         .mul(mag * element.mass) 
        );
}

element.acceleration = new Point(0,0,0,0);
    
universe.forEach(forces);
element.velocity = element.velocity.add(element.acceleration.mul(ticks));
element.point = element.point.add(element.velocity.mul(0.5 * ticks));  

我尝试发送负滴答和负引力常数,但它为“过去”产生的位置似乎与元素在真实过去的表现不符。

我对物理学知之甚少,但我想知道是否可以做一些小的改变来扭转这个算法。

更新

感谢 Graeme Niedermayer,我已将重力算法更新为平方反比定律,并使用负时间来生成过去的位置!

function forces(other) {
  if (element === other) {
    return;
  }
  var distancePoint = element.point.sub(other.point);  
  const forceElementMass = GravatationalConstant * element.mass * other.mass / 
    Math.pow(element.mass,2)
  const forceOtherMass = GravatationalConstant * element.mass * other.mass / 
    Math.pow(other.mass,2)
  element.acceleration = element.acceleration
    .sub(distancePoint.mul(forceOtherMass))
  other.acceleration = other.acceleration
    .add(distancePoint.mul(forceElementMass))
}

const ticks = forwards ? dt : -dt;
element.acceleration = new Point(0,0,0,0);

universe.forEach(forces);
element.velocity = element.velocity.add(element.acceleration.mul(ticks));
element.point = element.point.add(element.velocity.mul(0.5 * ticks));  

轮廓圆圈位于当前位置,“过去”位置是其他逐渐消失到零不透明度的位置。

更新 2

意识到我在更新 1 中使用了错误的方程(两个力常数都使用了相同的质量对象)。我查看了更多示例并更新了代码,但现在我不确定我应该在哪里添加增量时间ticks,它目前仅设置为 1 用于向前,-1 用于向后。下面是如果我将加速度乘以ticks,然后将其添加到每帧的速度body.velocity = body.velocity.add(body.acceleration.mul(ticks)) 或者如果我将其中一个质量设为负const force = G * body.mass * (forward ? other.mass : -other.mass) / d ** 2 时的样子。

如您所见,绿体的“过去”位置(红色轮廓)向左上方移动。我希望他们看起来“跟随”当前位置,但我不确定如何反转或反转等式以显示“过去”位置,基本上如果身体朝相反的方向移动。有没有办法做到这一点?

在下一张图片中,我将速度乘以增量时间ticks,然后将其添加到位置body.point = body.point.add(body.velocity.mul(ticks)),这导致与记录的身体行进路径相似(通过将每个位置写入数组并绘制这些位置之间的一条线)但它有点偏离。此解决方案与我在更新 1 中看到的类似。这是否“几乎”正确?

下面的代码没有任何反转位置的添加。

function forces(other, ticks) {
  if (body === other) {
    return;
  }
  
  // Calculate direction of force
  var distanceVector = other.point.sub(body.point)

  // Distance between objects
  var d = distanceVector.mag()
  
  // Normalize vector (distance doesn't matter here, we just want this vector for direction)
  const forceNormalized = distanceVector.normalized()
  
  // Calculate gravitational force magnitude
  const G = 6.674
  const force = G * body.mass * other.mass / d ** 2
  
  // Get force vector --> magnitude * direction
  const magDirection = forceNormalized.mul(force)

  const f = magDirection.div(body.mass)  
  body.acceleration = body.acceleration.add(f)
}

body.acceleration = body.acceleration.mul(0)
universe.forEach(body => forces(body, ticks))
body.velocity = body.velocity.add(body.acceleration)
body.point = body.point.add(body.velocity)

更新 3

我最终移除了负质量和速度乘以刻度,只是颠倒了加速度应用于位置的方式:

if (forward) {
  universe.forEach(body => forces(body, ticks));
  body.velocity = body.velocity.add(body.acceleration)
  body.point = body.point.add(body.velocity)
} else {
  body.point = body.point.sub(body.velocity)
  universe.forEach(body => forces(body, ticks));
  body.velocity = body.velocity.sub(body.acceleration)
}

导致能够从当前位置及时向前和向后生成位置。在图像中,它显示为“过去”位置跟随当前位置的记录轨迹。

要在“过去”中生成一个步骤,它会从当前位置减去当前速度,将其置于它所在的最后一个位置。接下来,它通过检查来自其他物体的力来获得加速度,然后减去新的加速度(使用负质量会做同样的事情)从速度,所以“过去”中的下一个位置将是正确的。

【问题讨论】:

  • 我还没有完全分析你的算法,但是对于依赖于小时间增量的算法,只需使用负刻度就可以了。不要更改其他参数。

标签: javascript physics gravity


【解决方案1】:

你应该能够使其中一个群众成为负面的。

负时间不起作用的原因是因为您使用欧拉方法是隐含的。 Euler 方法在使用负步时不稳定。

而且你使用的物理也有点奇怪。重力通常是平方定律。

【讨论】:

  • 非常感谢!是否有替代欧拉方法的方法可以更好地使用我可以查找的反向时间?
  • 对重力使用二阶方法很有用。我建议使用中点规则。知道后退的欧拉方法很有用(它不仅仅是倒转时间)。这两个都需要更多的工作来实现。
猜你喜欢
  • 1970-01-01
  • 2016-07-16
  • 2016-04-01
  • 2021-09-25
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多