What is going on in this SAT/vector projection code?

I'm looking at the example XNA SAT collision code presented here:

See the following code:

private int GenerateScalar(Vector2 theRectangleCorner, Vector2 theAxis)
{
//Using the formula for Vector projection. Take the corner being passed in
//and project it onto the given Axis
float aNumerator = (theRectangleCorner.X * theAxis.X) + (theRectangleCorner.Y * theAxis.Y);
float aDenominator = (theAxis.X * theAxis.X) + (theAxis.Y * theAxis.Y);

//Now that we have our projected Vector, calculate a scalar of that projection
//that can be used to more easily do comparisons
float aScalar = (theAxis.X * aCornerProjected.X) + (theAxis.Y * aCornerProjected.Y);
return (int)aScalar;
}


I think the problems I'm having with this come mostly from translating physics concepts into data structures. For example, earlier in the code there is a calculation of the axes to be used, and these are stored as Vector2, and they are found by subtracting one point from another, however these points are also stored as Vector2s. So are the axes being stored as slopes in a single Vector2?

Next, what exactly does the Vector2 produced by the vector projection code represent? That is, I know it represents the projected vector, but as it pertains to a Vector2, what does this represent? A point on a line?

Finally, what does the scalar at the end actually represent? It's fine to tell me that you're getting a scalar value of the projected vector, but none of the information I can find online seems to tell me about a scalar of a vector as it's used in this context. I don't see angles or magnitudes with these vectors so I'm a little disoriented when it comes to thinking in terms of physics. If this final scalar calculation is just a dot product, how is that directly applicable to SAT from here on? Is this what I use to calculate maximum/minimum values for overlap? I guess I'm just having trouble figuring out exactly what the dot product is representing in this particular context.

Clearly I'm not quite up to date on my elementary physics, but any explanations would be greatly appreciated.

the return value works out the same as aNumerator. I don't know why all the extra code is needed. And very definitely should not be returned as an int, should be returned as a float.

I'll re-write the above in pseudo-code;

//C is theRectangleCorner
//A is theAxis
aN = C DOT A;  //dot product
aDR = (C dot A) / lengthOfA^2;
aCP = ((C dot A) / lengthOfA^2 )*Ax, ((C dot A) / lengthOfA^2)*AY);

//Now that we have our projected Vector, calculate a scalar of that projection
//that can be used to more easily do comparisons

float aScalar = ((C dot A) / lengthOfA^2 )*Ax *Ax + ((C dot A) / lengthOfA^2)*AY*AY);
=((C dot A) / lengthOfA^2 )(Ax^2+Ay^2)
=((C dot A) / lengthOfA^2 )(lengthOfA^2 ) // 2 length^2 cancel out
= C dot A


Not sure if that made things clearer but it hopefully shows how aScalar==aNumerator. This might be a good candidate for The Daily WTF. Bizarre.

The scalar at the end is the dot product of the corner vertex and the axis, which represents the projection of the vertex ONTO the axis. If you think of the axis as a number-line (like you used in 1st grade/class). The dot-product tells us how far along that number-line the projection lies.

For example, if the 4 corners of box-a is projected onto an axis and you get values of {4.0,5.1,4.5, & 6.1}. Imagine the 3 corners of triangle-b are projected on to the same axis an we get {6.5,7,6.4} as our 3 values. We can see that there is no overlap as the largest value of box-a(6.1) is less than the smallest value of tri-b(6.4).

BTW we get the values above as follows;

4.0= box-A.corner1 DOT axis
5.1= box-A.corner2 DOT axis
4.5= box-A.corner3 DOT axis
6.1= box-A.corner4 DOT axis


Notice that the dot product generally results in a non-integer result, which is the SECOND bizarre thing about the code in question (it returns an int).

To answer your first question, an axis IS a vector, or at least can be considered a vector for the purposes of SAT.

• This is wonderfully helpful. So basically when I do this I can skip (most of) the math and just use the dot product of the projection of each corner onto the axis? – ssb Nov 16 '12 at 15:17
• @ssb, exactly, you just need to dot product of the axis and each of the vertices of the object. Remember The dot product IS the projection, the projection is just a distance, you ar projecting from 2D (or 3D) on to 1D. – Ken Nov 16 '12 at 15:26
• I'm running into a different problem, then. I'm getting my rotated axes to test by taking, for example, topLeft - topRight and topLeft - bottomLeft, which I assume should work since I'm only using rectangles. Yet when I project those points onto the axes, I get crazy numbers like -8000 and -6000. This is part of where I don't get how to turn an axis into a Vector2. – ssb Nov 16 '12 at 15:36
• Actually scratch that. Apparently those are normal numbers, I just had a bug elsewhere that was messing me up. Actually works perfectly now!! Just have to solve the MTV issue now. – ssb Nov 16 '12 at 15:44