Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it legal to take acos of 1.0f or -1.0f?

Tags:

c++

math

I have a problem with my code where agents moving around suddenly disappear. This seems to be because their positions suddenly become 1.#INF000 in the x and y axis. I did a little research and someone said this can occur with acos if a value is over or under 1 and -1 respectively, but went on to say it could happen if the values were close too. I added an if statement to check to see if I'm ever taking acos of 1 or -1 and it does evaluate to 1 a few frame cycles before they disappear, however I don't really understand the problem to be able to fix it. Can anyone shed any light on this matter?

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()
like image 765
Dollarslice Avatar asked Dec 13 '11 13:12

Dollarslice


1 Answers

It is dangerous to call acos on a value that may be exactly +/-1.0, because rounding errors can cause the computed value to be outside this range.

But it's easy to fix -- use this function instead:

double SafeAcos (double x)
  {
  if (x < -1.0) x = -1.0 ;
  else if (x > 1.0) x = 1.0 ;
  return acos (x) ;
  }
like image 124
TonyK Avatar answered Sep 28 '22 03:09

TonyK