高于最大速度会将方向更改为对角线,解决方法



AndroidVelocityTracker类中的缺陷是,如果你在X方向上的速度超过maxVelocity,它的变化等于maxVelocity,Y也是如此。但是,这意味着如果我们以 20° 角和 200 的速度行驶,并且我们的最大速度为 20。我们的速度更改为 20*sqrt (2) 在 45° 角。正确答案是通过实际速度和最大速度的比率来缩放mXVelocity和mYVeloicity。

我的问题是我是否必须求助于两个平方根来修复此错误?

速度是物体的方向和速度。由于达到最大速度而改变方向必须被视为缺陷。这也显然会导致一个缺陷,即对角线速度比正交速度快。

有问题的代码位类似于:

mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity) : Math.min(accumX, maxVelocity);
mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity) : Math.min(accumY, maxVelocity);

为了解决这个问题,我使用:

tracker.computeCurrentVelocity(units); //maxVelocity
double velocityX = tracker.getXVelocity();
double velocityY = tracker.getYVelocity();
double actualVelocitySq = velocityX * velocityX  + velocityY * velocityY;
double maxVelocitySq = maxVelocity * maxVelocity;
if (actualVelocitySq > maxVelocitySq) {
//double excessFactor = Math.sqrt(maxVelocitySq) / Math.sqrt(actualVelocitySq);
double excessFactor = Math.sqrt(maxVelocitySq/actualVelocitySq); //leewz's optimization
velocityX *= excessFactor;
velocityY *= excessFactor;
}

有没有办法避免双平方根?或者其他一些事情可以修复这个棘手的错误?


更新:

答案似乎是根据超过最大速度的一个分量来缩放这两个分量。这不是严格根据实际速度进行缩放,但它通过简单的数学解决了大部分问题。

double scale;
double vectorX = Math.abs(velocityX);
double vectorY = Math.abs(velocityY);
if (vectorX > maxVelocity) {
scale = maxVelocity / vectorX;
if (vectorY > maxVelocity) {
scale = Math.min(scale, maxVelocity / vectorY);
}
velocityX *= scale;
velocityY *= scale;
} else {
if (vectorY > maxVelocity) {
scale = maxVelocity / vectorY;
velocityX *= scale;
velocityY *= scale;
}
}

你可以剪掉Math.sqrt(maxVelocitySq),因为你知道maxVelocitySq = maxVelocity * maxVelocity。即使没有它,您也可以通过先执行除法来使用单个sqrt()

double excessFactor = Math.sqrt(maxVelocitySq / actualVelocitySq);

从数学上讲,我相信取平方根是必需的,但如何取平方根仍然对你开放。特别是,快速平方根反比适用于您的用例。这是使用fisr()的代码。

if (actualVelocitySq > maxVelocitySq) {
double excessFactor = fisr(actualVelocitySq / maxVelocitySq);
velocityX *= excessFactor;
velocityY *= excessFactor;
}

这是FISR的Java实现。

警告:FISR是为老一代的Intel CPU设计的,这些CPU在浮点运算(特别是除法,上述代码仍然使用)时速度很慢,而不是在ARM(Android的通用架构)上运行的JIT虚拟机(如Java)。请记住分析您的代码,以查看平方根成本是否足以进行优化,然后衡量 FISR 是否提供了有价值的改进。

诀窍是不要根据实际矢量的大小进行缩放,而是根据超出要求的最大数量进行缩放。然后按此缩放 x 和 y。它不需要比除法更难的数学。并且根本不是矢量的角度。而最大速度的结果在一定角度上可能超过实际速度 sqrt(2) 的倍数。它更符合最大速度功能的文档。

最大速度浮点数:可由此计算的最大速度 方法。此值必须以与单位相同的单位声明 参数。此值必须为正数。

double scale;
double vectorX = Math.abs(velocityX);
double vectorY = Math.abs(velocityY);
if (vectorX > maxVelocity) {
scale = maxVelocity / vectorX;
if (vectorY > maxVelocity) {
scale = Math.min(scale, maxVelocity / vectorY);
}
velocityX *= scale;
velocityY *= scale;
} else {
if (vectorY > maxVelocity) {
scale = maxVelocity / vectorY;
velocityX *= scale;
velocityY *= scale;
}
}

相关内容

  • 没有找到相关文章

最新更新