urho icon indicating copy to clipboard operation
urho copied to clipboard

Vector3.CalculateAngle can return NaN when it shouldn't

Open Fastran opened this issue 7 years ago • 2 comments

The static method in Vector3.cs

public static float CalculateAngle(Vector3 first, Vector3 second)
{
	return (float)System.Math.Acos((Vector3.Dot(first, second)) / (first.Length * second.Length));
}

can return NaN if the value passed to Acos is outside the range 1 -1 because (Vector3.Dot(first, second)) / (first.Length * second.Length) returns a float number and when it is casted to double the value can go outside the range To solve this issue it seems sufficient to change the method as

public static float CalculateAngle(Vector3 first, Vector3 second)
{
	float temp = (Vector3.Dot(first, second)) / (first.Length * second.Length);
	return (float)System.Math.Acos(temp);
}

Fastran avatar Oct 10 '18 08:10 Fastran

Wow - this is a first. I do not quite understand how a double within [-1..1] can go outside that range when cast to a float, can you show me what reproduces this?

migueldeicaza avatar Nov 05 '18 19:11 migueldeicaza

It's not the double casted to float but the float casted to double. Granted that the 2 Vectors have lenght > 0, it should always be possible to calculate the angle between them. You can try this code:

                Urho.Vector3 v = new Urho.Vector3(0.11008f, 0, 0);
                Urho.Vector3 v1 = new Urho.Vector3(0.6184301f, 0, 0);
                float cosFloat = Urho.Vector3.Dot(v, v1) / (v.Length * v1.Length);
                double cosDouble = Urho.Vector3.Dot(v, v1) / (v.Length * v1.Length);
                double angleF = Math.Acos(cosFloat);
                double angleD = Math.Acos(cosDouble);
                float a = Urho.Vector3.CalculateAngle(v, v1);

You will see that cosDouble > 1 and a = angleD = NaN

Fastran avatar Nov 15 '18 15:11 Fastran