[原][算法][earth]三段smooth,传入时间,返回距离。仿谷歌视角飞跃处理

算法需求:

传入【0~1】的时间time,返回【0~1】的路程。

整个路程distance【0~1】分为三段路径:

第一段:在0.25time的时间里,速度从0,位置从distance:0加速移动到距离distance:K

第二段:在0.25time时间里,位置从distance:k减速移动到某距离distance:1 – ratio

第三段:在0.5time时间里,位置从distance:1 – ratio减速移动到distance:1

但是变化率由第一段1/4总时间经过的路程K和总路程长度distance大小决定:如果总路程超过10000米,。如果总路程不超过10000米,第三段就用0.2*distarationce

 

已知参数:

 

初速度

末速度

时间

距离

路程

加速度

距离与时间算法

第一段

0

 

0.25

K

K

 

 

第二段

 

 

0.25

Ratio-k

1-Ratio

 

 

第三段

 

0

0.5

Ratio

1

 

 

 

第一段推导算法与参数

S = A * time * time / 2

A = S / time * time

V = S * time

 

初速度

末速度

时间

距离

路程

加速度

距离与时间算法

第一段

0

8k

0.25

K

K

32k

Time * time *16K

第二段

8K

 

0.25

Ratio-k

1-Ratio

 

 

第三段

 

0

0.5

Ratio

1

 

 

 

第三段推导算法与参数

S = A * time * time / 2

A = S / time * time

V = S * time

S = V *time + A * time * time / 2

 

初速度

末速度

时间

距离

路程

加速度

距离与时间算法

第一段

0

8k

0.25

K

K

32k

Time * time *16K

第二段

8K

4Ratio

0.25

Ratio-k

1-Ratio

 

 

第三段

4Ratio

0

0.5

Ratio

1

-8Ratio

1 –(1 – Time) *(1 – Time)*4Ratio

 

接下来是第二段的推导,参数很多,似乎不用推导,但是突然发现,其实参数太多导致推导由问题:如果加速度A是固定的:

  1. A = 2*S/time*time  即: 32*(Ratio - k)
  2. A = (V1-V0)/time 即:4*(4Ratio - 8K)

32*(Ratio - k) = 4*(4Ratio - 8K)

为了满足以上算例,Ratio必须为0才行,这样不符合我们的预期。

 

 

我试了各种办法也没有能力让第二段保持这种状态,所以我舍弃第二段的初速度,使得第二段与第三段的初速度能连接。

 

初速度

末速度

时间

距离

路程

加速度

距离与时间算法

第一段

0

8k

0.25

K

K

32k

Time * time *16K

第二段

 

4Ratio

0.25

Ratio-k

1-Ratio

 

 

第三段

4Ratio

0

0.5

Ratio

1

-8Ratio

1 –(1 – Time) *(1 – Time)*4Ratio

 

继续推导第二段:

S = V0 * TIME + A * TIME * TIME /2

V1 = V0 + A * TIME

à

1 - Ratio - k = v0 /4 + a / 32

4Ratio = v0 + a / 4

à

         A = 32 * (k + 2Ratio - 1)

         V0 = 4 * Ratio – 8 * k

 

初速度

末速度

时间

距离

路程

加速度

距离与时间算法

第一段

0

8k

0.25

K

K

32k

Time * Time *16K

第二段

8-8k-12Ratio

4Ratio

0.25

1-Ratio-k

1-Ratio

32k+64Ratio-32

 

第三段

4Ratio

0

0.5

Ratio

1

-8Ratio

1 –(1 – Time) *(1 – Time)*4Ratio

注意:为了保障第二段的初速度大于零:需要Ratio < 2/3 * ( 1 - k)

第一段距离时间函数:time < 0.25

         Time * Time *16K

第二段距离时间函数:time < 0.5

         K + (8-8k-12Ratio)*Time + (16k+32Ratio-16)*Time*Time

第三段距离时间函数:time < 1

         1 –(1 – Time) *(1 – Time)*4Ratio

 

 1 //将前0到0.8的距离用0到0.2的时间完成,后0.8到1的距离用0.2到1的时间完成
 2     //传入的是时间0~~~0.2~~~1
 3     //返回的是距离0~~~0.8~~~1
 4     //pathLength是总距离,作为加减速参考值
 5     //timeRatio传入的是时间t  返回的是移动距离S(当前位置)
 6     double GY_threeSectionSmooth(double timeRatio, double pathLength = 100000.0)
 7     {
 8         //
 9         //            初速度                末速度        时间    距离            路程            加速度                    距离与时间算法
10         //    第一段    0                    8k            0.25    K                K                32k                        Time * Time * 16K
11         //    第二段    8 - 8k - 12Ratio    4Ratio        0.25    1 - Ratio - k    1 - Ratio        32k + 64Ratio - 32        K + (8 - 8k - 12Ratio)*Time + (16k + 32Ratio - 16)*Time*Time
12         //    第三段    4Ratio                0            0.5        Ratio            1                - 8Ratio                1 –(1 – Time) *(1 – Time) * 4Ratio
13         //
14         //  定义:k是第一段的路程,Ratio是第三段的路程
15         //    注意:为了保障第二段的初速度大于零:需要Ratio < 2 / 3 * (1 - k)
16         //  例如 k定义为0.6时,Ratio不能大于0.26
17         //
18         //    第一段距离时间函数:time < 0.25
19         //    Time * Time * 16K
20         //    第二段距离时间函数:time < 0.5
21         //    K + (8 - 8k - 12Ratio)*Time + (16k + 32Ratio - 16)*Time*Time
22         //    第三段距离时间函数:time < 1
23         //    1 –(1 – Time) *(1 – Time) * 4Ratio
24 
25         //定义k    
26         double k = 0.6;
27 
28         //计算Ratio  注意:Ratio < 2/3 * ( 1 - k)
29         double pathRatio = pathLength / 10000.0;
30         pathRatio = std::max(1.0, pathRatio);
31         double ratio = 0.2 / pathRatio;
32         ratio = std::min(ratio, 2.0/3.0*(1.0-k));
33 
34         
35         //计算三段位置与时间关系
36         double distanceRatio = timeRatio;
37         if (timeRatio < 0.25)                                    //第一段:Time * Time * 16K                            
38         {                                                        
39             distanceRatio = k*timeRatio*timeRatio * 16;    
40         }
41         else if (timeRatio < 0.5)                                //第二段:K + (8 - 8k - 12Ratio)*Time + (16k + 32Ratio - 16)*Time*Time
42         {
43             timeRatio -= 0.25;
44             distanceRatio = k + (8 - 8 * k - 12 * ratio) * timeRatio + (16 * k + 32 * ratio - 16) * timeRatio * timeRatio;
45         }
46         else if (timeRatio <= 1.0)                                //第三段:1 –(1 – Time) *(1 – Time) * 4Ratio
47         {
48             distanceRatio = 1 - (1 - timeRatio)* (1 - timeRatio) * 4 * ratio;
49         }
50 
51         //logInfo("time: " + float_to_String(timeRatio) + " distance: " + float_to_String(distanceRatio) + " pathLength: " + float_to_String(pathLength) + " ratio: " + float_to_String(ratio));
52 
53         return distanceRatio;
54     }

 

posted @ 2019-01-02 16:18  南水之源  阅读(445)  评论(0编辑  收藏  举报