Jump to content
  • Advertisement
Sign in to follow this  
Grain

Vector Projection with zero length

This topic is 1886 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Currently I'm doing this 

        public static Vector2 Project(this Vector2 A, Vector2 B)
        {
            if (A.X != 0f || A.Y != 0)
                return Vector2.Multiply(A, Vector2.Dot(A, B) / Vector2.Dot(A, A));
            else
                return A;
                //return B; ???
        }

Without the zero length check in there every thing blows up because this method returns an effectively infinite length vector.  What is the best thing to return when the length of A is zero?

Share this post


Link to post
Share on other sites
Advertisement

If A is a zero-vector, then the result is undefined and anything you return is technically wrong. Which, among all incorrect, options is the better one depends on what it is you do with the result. But I would suggest that, in general, the best thing to do is avoid division by zero, or in this case having a zero-length A, in the first place.

Share this post


Link to post
Share on other sites

Return the zero vector.

 

You are trying to scale A (which is the zero vector) by an indeterminate dot(A, B) / dot(A, A). dot(A, B) == 0, dot(A, A) == 0, so you are trying to calculate A * (0/0), but A is zero anyway => return A (which is the zero vector).

 

To see this (non-rigorous argument) is correct, consider the limit when length(A) tends to zero. (EDIT: If you halve the length of A, the length of the projected vector is halved too, so it is easy to see that the limit when length(A) -> 0 is the zero vector).

 

EDIT: Considering the limit is the way to do it, but it doesn't apply in all cases e.g. normalisation of a vector, which has no limit as the length tends to zero. You have to consider each function separately.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

 

To see this (non-rigorous argument) is correct, consider the limit when length(A) tends to zero. (EDIT: If you halve the length of A, the length of the projected vector is halved too, so it is easy to see that the limit when length(A) -> 0 is the zero vector).

 

I'm not sure what you mean considering the result should be the same for all lengths of A with the sole exception 0.  

Share this post


Link to post
Share on other sites

Whoops, my mistake then.

 

You can't return anything meaningful in that case. Either return the zero vector anyway or throw an exception.

 

EDIT: I confused myself from looking at this picture in wikipedia from the vector projection page

 

200px-Projection_and_rejection.png

 

which suggested to me that if a was twice as long then the length a1 would be also. EDIT2: I was confused ;) More coffee required.

Edited by Paradigm Shifter

Share this post


Link to post
Share on other sites

Currently I'm doing this 

        public static Vector2 Project(this Vector2 A, Vector2 B)
        {
            if (A.X != 0f || A.Y != 0)
                return Vector2.Multiply(A, Vector2.Dot(A, B) / Vector2.Dot(A, A));
            else
                return A;
                //return B; ???
        }

Without the zero length check in there every thing blows up because this method returns an effectively infinite length vector.  What is the best thing to return when the length of A is zero?

 

What you are trying to do here is figure out how much of B is pointing in the A direction. This assumes that A is a direction vector. A direction vector is usually required to have a length of 1. Any vector that can be normalized can be a direction vector. However, a zero-length vector cannot be normalized and thus has no direction. If A was correctly normalized your project function simply return Vector2.Dot(A,B). If you should not be projecting zero-length vectors, it seems that there is a problem upstream of this function. Personally, I would get rid of this function and make sure that my direction vector was normalized and use the dot product directly.

 

-Josh

Share this post


Link to post
Share on other sites

Whoops, my mistake then.

 

You can't return anything meaningful in that case. Either return the zero vector anyway or throw an exception.

 

EDIT: I confused myself from looking at this picture in wikipedia from the vector projection page

 

200px-Projection_and_rejection.png

 

which suggested to me that if a was twice as long then the length a1 would be also. EDIT2: I was confused ;) More coffee required.

Also I'm projecting B onto A, as where this example projects A onto B.

Share this post


Link to post
Share on other sites

 

Currently I'm doing this 

        public static Vector2 Project(this Vector2 A, Vector2 B)
        {
            if (A.X != 0f || A.Y != 0)
                return Vector2.Multiply(A, Vector2.Dot(A, B) / Vector2.Dot(A, A));
            else
                return A;
                //return B; ???
        }

Without the zero length check in there every thing blows up because this method returns an effectively infinite length vector.  What is the best thing to return when the length of A is zero?

 

What you are trying to do here is figure out how much of B is pointing in the A direction. This assumes that A is a direction vector. A direction vector is usually required to have a length of 1. Any vector that can be normalized can be a direction vector. However, a zero-length vector cannot be normalized and thus has no direction. If A was correctly normalized your project function simply return Vector2.Dot(A,B). If you should not be projecting zero-length vectors, it seems that there is a problem upstream of this function. Personally, I would get rid of this function and make sure that my direction vector was normalized and use the dot product directly.

 

-Josh

 

Normalizing requires a square root call which I'd like to avoid as much as possible, and seeing as I can project just fine while avoiding that I see no benefit in doing so. Also zero vectors are perfectly valid in some cases(a velocity vector for example).  

Share this post


Link to post
Share on other sites
I want to point out that the code in the OP is not very robust: If the input is the vector (0, epsilon) --where epsilon is a number so small that its square is 0--, the code will still divide by zero.

Share this post


Link to post
Share on other sites

I want to point out that the code in the OP is not very robust: If the input is the vector (0, epsilon) --where epsilon is a number so small that its square is 0--, the code will still divide by zero.

How about this then? 

        public static Vector2 Project(this Vector2 A, Vector2 B)
        {
            float DotOverDot = Vector2.Dot(A, B) / Vector2.Dot(A, A);
            if (float.IsNaN(DotOverDot) || float.IsInfinity(DotOverDot))
                return Vector2.Zero;
            else
                return Vector2.Multiply(A, DotOverDot);                
        }
Edited by Grain

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!