跳至内容

计算机编程/物理/物体在空间中的运动(分段逼近)

来自 Wikibooks,开放世界中的开放书籍

<维基文库:源代码

关于 加速物体位置函数 的问题是,虽然理论上是正确的,但它在描述物体在空间中的运动方面并不十分灵活。为了解决这个问题,我们分段进行计算。

我们回顾一下 泰勒级数 的位置函数形式

.

如果我们同步我们的时钟,使 为零,则可以将其简化为 麦克劳林级数

.

问题的解决方案就在这里。这个等式描述了基于初始常数因子 的完整路径。但是,如果我们分段处理,就像我们计算 等于某个小的增量时间 的数值解,并在每次计算周期后将 重新同步到 ,那么我们可以使用以下函数的增量形式通过连续计算动态构建物体的路径

.

请注意,当 以及我们使用越来越多的项时,精度会提高。

基于初始常数因子 计算物体初始位置变化后,我们只需要提供影响物体的任何外部加速度, ,然后我们可以计算物体的下一个位置 和速度 ,以及下一组常数因子 ,其中 已经是已知的。

速度的计算公式为

或者

.

其他 值可以通过以下公式估算

对于

前提是 很小。

也就是说,

.
template<class Vector,class Number>
void Motion(Vector *s,Vector *prev_s,Vector a,Number dt,size_t Accuracy)
//s[] is the array of "current derivative of s values" that we are trying to calculate
//prev_s[] is the array of "previous derivative of s values" that is used as the constant factors
{
     size_t n(0);
     Number factor(1);
     
     //Note: the following code for position and velocity can be optimized for speed
     //      but isn't in order to explicitly show the algorithm
     for(s[0]=0;n<Accuracy;n++)
     //Position
     {
          if(n)factor*=(t/n);
          s[0]+=(factor*prev_s[n]);
     }

     for(s[1]=0,n=0,factor=1;n<(Accuracy-1);n++)
     //Velocity
     {
          if(n)factor*=(t/n);
          s[1]+=(factor*prev_s[n+1]);
     }

     s[2]=  a; //Acceleration
            //+PositionDependentAcceleration(s[0])                    //e.g. Newtonian Gravity
            //+VelocityDependentAcceleration(s[1])                    //e.g. Infinite Electro-magnetic field
            //+PositionVelocityDependentAcceleration(s[0],s[1]);      //e.g. Finite Electro-magnetic field

     for(n=3;n<Accuracy;n++)
     //Everything else
     //We're going to assume that dt is so small that s-prev_s is also very small
     //     i.e. approximates the differential
     {
          s[n]=(s[n-1]-prev_s[n-1])/dt;
     }
}

//Calling the function
//...
     Vector *s,*prev_s,*temp;
//...
     //The previous "current s" becomes the current "previous s"
     temp=prev_s;     //Speed optimization (instead of copying all of the s array
     prev_s=s;        //     into the prev_s array, we just swap the pointers)
     s=temp;
     Motion(s,prev_s,a,dt,Accuracy);
//...
华夏公益教科书