长时间的听众,第一次打电话的人。我正在用XNA做一个业余爱好游戏,它是关于太空中的运输船,类似于海上的集装箱船。我需要能够在受限的2D环境中预测船与行星/卫星gravitational sphere of influence之间的相遇。船和行星/月球(简称天体)的时间位置是由keplerian orbital elements确定的。船和船身都围绕着同一个引力中心运行。
到目前为止,我设计的方法是首先对远心点和近心点(离吸引中心最远和最近的点)进行一些初步检查,看看是否有可能相遇。在像这样的检查之间,如果飞船的轨道是开放的(双曲线,我将抛物线的情况近似为双曲线),它可以排除许多不可能相遇的情况。
如果这些检查确定相遇是可能的,我就确定船有资格相遇的最小和最大距离。然后,我得到了船舶轨道与由该最小值和最大值定义的两个圆的交点。这会在飞船的轨道上产生零个、两个或四个点,定义可能与物体球体相遇的零个、一个或两个周期。在这一点上,如果有零个交叉点,则可能整个船舶轨道都在相遇区域,这可能是一个不常见的极端情况,但需要覆盖。
我可以得到飞船通过轨道上这些点的时间,给出一到两个时间窗口来检查相遇,但从那里我最好的解决方案是搜索时间跨度,将其分成几个步骤,计算身体在这些时间段的位置,然后测试相遇。
这种方法的问题是知道大小,以便有效地找到相遇的步骤。在时间上获得身体的位置有点昂贵,所以我宁愿尽可能少地做,但步数太大可能会错过相遇的机会。
共焦圆锥形状有什么属性可以帮助缩小搜索空间吗?或者,是否有其他方法来预测有效地沿着圆锥路径移动的点和沿着共享焦点的椭圆移动的圆之间的相遇/碰撞。
发布于 2013-03-14 21:09:11
使用径向碰撞检测(圆),其中一个圆表示行星的重力影响(将大于行星本身),另一个圆代表每艘船,并使每个圆的中心点在距离减小时以一条直线向对方移动。
将每个圆圈的拉力大小应用于每艘船的移动速率。移动只需要简单的trig,cos()表示x,sin()表示y,不需要任何复杂的数学运算。当任意两个物体之间的距离小于其半径之和时,则发生碰撞。
但是当只在所谓的“重力圈”上进行这种形式的碰撞时,当它们碰撞时,你可以在每次迭代中增加少量的船的速度,以模拟重力的拉动。
发布于 2013-03-15 03:48:07
您可以尝试使用通常的毕达哥拉斯距离表达式来构造描述行星和船舶之间的距离(平方)作为时间函数的函数。您正在寻找此函数的零,因此可以应用Newton's method或类似的方法来查找它们。
只要行星的运动速度比飞船慢得多,这种方法就能很好地工作--这样函数就会相对平滑,牛顿的方法就不会有收敛的问题。然而,如果行星的运动速度比飞船快得多,那么这个距离函数就会上下弹跳,就像一个叠加在抛物线状曲线上的“弹簧”,并且可能会多次与x轴相交。牛顿的方法在处理这样的函数时会遇到麻烦,因为导数的方向变化得很快。
希望在构造距离函数时,某些项将被抵消,或者表达式可以以其他方式简化或近似,但如果不是这样,在垂直和水平方向上寻找零可能就足够了。(事实上,您可以选择沿任何轴的距离--例如,行星轨道的长轴。)这两个函数中的任何一个中的零都是冲突的必要条件,但不是充分条件,并且计算起来可能更简单。如果您有一个按时间排序的x方向零的列表,并且y方向的零也是如此,您可以通过列表合并(a la mergesort)计算它们的交集来查找任何真正的碰撞。
发布于 2019-05-26 23:14:55
由于这还没有得到公认的答案,而且我没有看到下面的计算,所以我将添加这些计算,希望它能对某人有所帮助。我还没有想出如何获得约会时间,但我已经想出了如何获得角度。这将得到轨道物体与soi (或船)之间的距离(如果您知道角度):
public static double RadiusAtAngle(double angle, double semiLatusRectum, double eccentricity)
{
return semiLatusRectum / (1 + eccentricity * Math.Cos(angle));
}
更重要的是,如果您知道semiLatusRectum和偏心率(这里的半径是从身体到soi边的距离),则翻转该计算可以得到到soi边的角度:
public static double AngleAtRadus(double radius, double semiLatusRectum, double eccentricity)
{
//r = p / (1 + e * cos(θ))
//1 + e * cos(θ) = p/r
//((p / r) -1) / e = cos(θ)
return Math.Acos((semiLatusRectum / radius - 1) / eccentricity);
}
作为参考,可以从semiMajorAxis和semiLatusRectum中找到:
public static double SemiLatusRectum(double SemiMajorAxis, double eccentricity)
{
if (eccentricity == 0)//ie a circle
return SemiMajorAxis;
return SemiMajorAxis * (1 - eccentricity * eccentricity);
}
请注意,这些计算也适用于双曲线轨迹。
https://stackoverflow.com/questions/15029504
复制相似问题