[C#] [XNA] Using the dot product to find the angle between two vectors.

Started by
14 comments, last by Spa8nky 14 years, 5 months ago
Here I have a simple method that returns whether the angle (theta) is obtuse, perpendicular or acute based on the result of the dot product.

        public static Angle GetAngleBetweenVectors(Vector3 vector_1, Vector3 vector_2)
        {
            float theta = Vector3.Dot(vector_1, vector_2);

            if (theta < 0)
            {
                return Angle.Obtuse;
            }
            if (theta > 0)
            {
                return Angle.Acute;
            }
            if (theta == 0)
            {
                return Angle.Perpendicular;
            }
            return Angle.Perpendicular;
        }

The problem is that in XNA if I have two triangles, one with its normal pointing "left" (0,-1,0) and the other pointing "forward" (0,0,-1), then the dot product between them returns perpendicular. However, the two triangles themselves are not perpendicular (they are at 270°). How can I work out a fast way of checking the correct angle between two triangles? Do I have to use the cross product between the triangle normal and "up" (0,1,0) to get the triangle plane vector or is there a faster way? Thank you.
Advertisement
You need a better description of what you're trying here. Why do you think 0, -1, 0 and 0, 0, -1 are at 270 degrees rather than 90 degrees?
Apologies.

						^						|						| (Tri 2) [Normal = (0,0,-1)] 						|					______________					|					|					|(Tri 1) [Normal = (-1,0,0)	<----	|					|					|					|


The -ve halfspace of the triangle plane is ignored so therefore the angle between triangle 1 and triangle 2 is 270°.
I still don't see why that would give you 270 rather than 90. Assume I'm a complete idiot and spell it out for me in simple terms.
It is probably me being the idiot here but:

						^						|				      ___	| (Tri 2) [Normal = (0,0,-1)] 				     |	 |	|				     | Θ ______________				     |  |.............				      --|.............					|.............(Tri 1) [Normal = (-1,0,0)	<----	|............. (Solid)					|.............					|.............					|.............


If the negative half space is considered solid and therefore ignored, the angle (theta) between the face of triangle 1 and the face of triangle 2 (in non solid space) is 270°.

If the two areas solid/non solid areas were swapped then the angle theta would be 90°.

Does that make sense?
Quote:Original post by Spa8nky
Apologies.

						^						|						| (Tri 2) [Normal = (0,0,-1)] 						|					______________					|					|					|(Tri 1) [Normal = (-1,0,0)	<----	|					|					|					|


The -ve halfspace of the triangle plane is ignored so therefore the angle between triangle 1 and triangle 2 is 270°.
It seems that what you're looking for is the signed angle between the two triangle normals.

In 3-d, you have to use an external reference if you want to determine the sign of the angle between two vectors. I believe in your example it may work to use the direction of the edge shared by the two triangles as the reference (although I'd have to play around with it a bit to be sure).

Here's what a 3-d 'signed angle' function might look like:
float signed_angle(vector3 v1, vector3 v2, vector3 reference) {    vector3 c = cross(v1,v2);    float angle = atan2(length(c),dot(v1,v2));    return dot(c,reference) < 0 ? -angle: angle;}
Quote:Here's what a 3-d 'signed angle' function might look like


Hi jyk, a couple of things about your method confuse me:

Your code returns an angle of ±90° when converted from radians. If the angle is -90° should I then return 360-90 (270°)?

I'm also not sure I understand the reference angle to which you refer. How can it be determined for any two triangles with any position?

Thanks
Quote:Your code returns an angle of ±90° when converted from radians. If the angle is -90° should I then return 360-90 (270°)?
Assuming a typical implementation of atan2, the function will return an angle in the range [-180,180] (more or less) when converted from radians. If you need the angle in some other range, just adjust the result as necessary (e.g. by adding 360 for negative angles, as in your example).

Quote:I'm also not sure I understand the reference angle to which you refer. How can it be determined for any two triangles with any position?
It's not a reference angle, but a reference vector (note that the third argument to the function is a vector, not a scalar).

I'm assuming that the two triangles whose normals you wish to compare share an edge (if they don't, then that's a different problem). What I'm suggesting is that you use the direction vector associated with this shared edge as the reference vector for the 'signed angle' function.

To elaborate a bit, say the vertices of the first triangle are v1, v2, and v3, and that the edge v2->v3 is shared with the other triangle. You would then use 'v3 - v2' as the reference vector for the 'signed angle' function. (You might need to negate the reference vector to get the values that you expect - it just depends on what conventions you're using.)
Sorry I meant to say reference vector as I can see it is a vector being passed into the method.

The triangles will not share an edge in all cases, unfortunately.
Quote:The triangles will not share an edge in all cases, unfortunately.
In that case, I think we'll need more information (as SiCrane suggested earlier). To determine the sign of the angle between the normals of two arbitrarily oriented and possibly disjoint triangles, you're going to need some sort of reference or metric, and what to use for that reference or metric is necessarily context-dependent.

Can you tell us what problem you're trying to solve exactly?

This topic is closed to new replies.

Advertisement