Jump to content

  • Log In with Google      Sign In   
  • Create Account

Vector Projection with zero length


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 Grain   Members   -  Reputation: 468

Like
0Likes
Like

Posted 20 August 2013 - 03:32 AM

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?



Sponsor:

#2 Brother Bob   Moderators   -  Reputation: 8576

Like
0Likes
Like

Posted 20 August 2013 - 03:42 AM

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.



#3 Paradigm Shifter   Crossbones+   -  Reputation: 5433

Like
0Likes
Like

Posted 20 August 2013 - 03:42 AM

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, 20 August 2013 - 03:58 AM.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#4 Grain   Members   -  Reputation: 468

Like
0Likes
Like

Posted 20 August 2013 - 04:04 AM

 

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.  



#5 Paradigm Shifter   Crossbones+   -  Reputation: 5433

Like
0Likes
Like

Posted 20 August 2013 - 04:29 AM

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, 20 August 2013 - 04:50 AM.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#6 jjd   Crossbones+   -  Reputation: 2122

Like
2Likes
Like

Posted 20 August 2013 - 05:07 AM

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


--www.physicaluncertainty.com
--linkedin
--irc.freenode.net#gdnet


#7 Grain   Members   -  Reputation: 468

Like
0Likes
Like

Posted 20 August 2013 - 05:07 AM

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.



#8 Grain   Members   -  Reputation: 468

Like
0Likes
Like

Posted 20 August 2013 - 05:11 AM

 

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).  



#9 Álvaro   Crossbones+   -  Reputation: 13905

Like
1Likes
Like

Posted 20 August 2013 - 05:49 AM

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.

#10 Grain   Members   -  Reputation: 468

Like
0Likes
Like

Posted 20 August 2013 - 06:25 AM

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, 20 August 2013 - 06:29 AM.


#11 Álvaro   Crossbones+   -  Reputation: 13905

Like
0Likes
Like

Posted 20 August 2013 - 06:47 AM

That code is more robust, assuming division by 0 doesn't trigger an exception or anything (sorry, I don't know Java or whatever that language you are using is).

 

But I still wonder why you are projecting onto a vector that is not roughly unit length.



#12 jjd   Crossbones+   -  Reputation: 2122

Like
0Likes
Like

Posted 20 August 2013 - 06:48 AM

 

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);                
        }

 

 

The typical way of handling this would be,

float sqrA = Vector2.Dot(A, A);
if(sqrA < epsilon)
{
    return Vector2.Zero;
}

return Vector2.Multiply(A, Vector2.Dot(A, B) / sqrA));

where 'epsilon' is a tolerance that you choose.

 

 

-Josh


Edited by jjd, 20 August 2013 - 06:48 AM.

--www.physicaluncertainty.com
--linkedin
--irc.freenode.net#gdnet


#13 nowzer   Members   -  Reputation: 104

Like
0Likes
Like

Posted 23 August 2013 - 12:28 PM

... and I was going to say null until I saw Josh's answer...






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS