законно ли брать акос 1.0f или -1.0f? - PullRequest
3 голосов
/ 13 декабря 2011

У меня проблема с моим кодом, из-за которой перемещающиеся агенты внезапно исчезают.Это происходит потому, что их позиции внезапно становятся 1. # INF000 по осям x и y.Я провел небольшое исследование, и кто-то сказал, что это может произойти с acos, если значение больше или меньше 1 и -1 соответственно, но потом сказал, что это может произойти, если значения тоже были близки.Я добавил оператор if, чтобы проверить, получаю ли я когда-либо acos, равный 1 или -1, и он оценивается в 1 за несколько циклов кадра, прежде чем они исчезнут, однако я не совсем понимаю проблему, чтобы иметь возможность ее исправить.,Кто-нибудь может пролить свет на этот вопрос?

D3DXVECTOR3 D3DXVECTOR3Helper::RotToTarget2DPlane(D3DXVECTOR3 position, D3DXVECTOR3 target)//XY PLANE
{
    //Create std::vector to target
    D3DXVECTOR3 vectorToTarget = target - position;

    D3DXVec3Normalize(&vectorToTarget, &vectorToTarget);

    //creates a displacement std::vector of relative 0, 0, 0
    D3DXVECTOR3 neutralDirectionalVector = D3DXVECTOR3(1, 0, 0);//set this to whatever direction your models are loaded facing   

    //Create the angle between them

    if(D3DXVec3Dot(&vectorToTarget, &neutralDirectionalVector) >= 1.0f ||D3DXVec3Dot(&vectorToTarget, &neutralDirectionalVector) <= -1.0f)
    {
        float i = D3DXVec3Dot(&vectorToTarget, &neutralDirectionalVector);
        float j = 0; //ADDED THIS IF STATEMENT
    }

    float angle = acos(D3DXVec3Dot(&vectorToTarget, &neutralDirectionalVector));

    if (target.y > position.y)
    {
        return D3DXVECTOR3(0, 0, angle);
    }
    else
    {
        return D3DXVECTOR3(0, 0, -angle);
    }
}//end VecRotateToTarget2DPlane()

Ответы [ 2 ]

17 голосов
/ 13 декабря 2011

Опасно вызывать acos для значения, которое может быть точно +/-1.0, потому что ошибки округления могут привести к тому, что вычисленное значение окажется за пределами этого диапазона.

Но это легко исправить - используйте эту функцию вместо:

double SafeAcos (double x)
  {
  if (x < -1.0) x = -1.0 ;
  else if (x > 1.0) x = 1.0 ;
  return acos (x) ;
  }
5 голосов
/ 13 декабря 2011

справочная страница для acos говорит об этом:

В случае успеха эти функции возвращают арккосинус x в радианах;возвращаемое значение находится в диапазоне [0, pi].

Если x является NaN, возвращается NaN.

Если x равен +1, возвращается +0.

Если x является положительной бесконечностью или отрицательной бесконечностью, возникает ошибка домена и возвращается NaN.

Если x выходит за пределы диапазона [-1, 1], возникает ошибка домена и NaN

Это означает, что для значения вне диапазона [-1, + 1] значение не является числом.Это также соответствует определению acos .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...