Android VelocityTracker类中的缺陷在于,如果您在X方向上的速度超过maxVelocity,则将其更改为等于maxVelocity,并且对于Y进行更改。但是,这意味着如果我们以20°角和以200,我们的maxVelocity为20。我们的速度在45°角处更改为20 * sqrt(2)。正确的答案是通过实际速度与maxVelocity之比来缩放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);


从数学上讲,我认为求平方根是必需的,但是如何求平方根仍然对您开放。特别地,Fast Inverse Square Root适用于您的用例。这是使用fisr()的代码。

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


Here's a Java implementation of FISR.

注意事项:FISR是为较老的Intel CPU设计的,这些Intel CPU的浮点运算速度很慢(特别是除法,上面的代码仍然使用该运算法则),而不是在ARM(通用体系结构)上运行的JIT虚拟机(例如Java)对于Android)。切记对代码进行概要分析,以查看平方根成本是否足够显着优化,然后评估FISR是否带来了有价值的改进。

08-04 07:33