jamesbf's picture

Vector2 Cross Product

Project:The Open Toolkit library
Version:all versions
Component:Code
Category:feature request
Priority:normal
Assigned:Robmaister
Status:in progress (commit)
Description

Hey,

Can we get a cross product method added to the Vector2/Vector2d classes? It's useful for 2d containment tests, checking winding direction of a polygon etc

#region Cross

///
/// Caclulate the cross (vector) product of two vectors
///
/// First operand
/// Second operand
/// The cross product of the two inputs
public static float Cross(Vector2 left, Vector2 right)
{
return left.X * right.Y - left.Y * right.X;
}

#endregion

Thanks


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Robmaister's picture

#1

Technically there is no cross product of 2d vectors, as a vector can only be perpendicular to two other vectors in 3d space. Also a cross product returns a vector, not a scalar. I'm not really sure what this code does, but it looks like you're constructing a 2x2 matrix from the vectors then taking the determinant.

The actual cross product of 2 2d vectors will always be <0, 0, ||left|| * ||right||>.

hannesh's picture

#2

It is the Z component of the result of the 3D Cross Product, where the Z-component of the input vectors is the Z-component.

I agree with the poster that this is a useful function, however calling it a cross product is a real stretch. Can we name it something else?

jamesbf's picture

#3

It is an analog to the cross product in 2 dimensions
http://mathworld.wolfram.com/CrossProduct.html

The result is still |a||b|sin(Theta), and the sign of the result will still indicate the rotation dir of theta.

It seems to me that calling it something else would just confuse people for no good reason. I don't really see what the benefit would be.

(Vector2.CalculateDeterminantOf2DMatrixFormedByTheseTwoVectors(a,b) :D )

Cheers,
James

Robmaister's picture

#4

A dot product indicates the direction of rotation as well, only it's |a| * |b| * cos(theta).

The difference is that by definition a dot product returns a scalar and a cross product returns a vector. Adding a new method that shortcuts converting the 2d vectors to 3d vectors, taking the actual cross product, and returning the magnitude of the resultant vector, while calling it a cross product isn't too good of an idea for a public API. Expecting a vector but getting a scalar would confuse people even more, especially for a function that is supposed to be undefined in a 2d coordinate system.

Also using the dot product involves less operations anyways, I don't see why we shouldn't stick to that:

Vector2 a, b;
Vector2 aNorm = Vector2.Normalize(a), bNorm = Vector2.Normalize(b);
double theta = Math.Acos(Vector2.Dot(aNorm, bNorm));

And you can calculate the direction to rotate by looking at the sign of the dot product, as acos only returns angles 0 < theta < pi

jamesbf's picture

#5

the cross returns
|a||b|sin(theta)
not just the magnitudes of the two vectors.

The dot product can't be used directly to find the direction of rotation as it's a reflection of itself around x=0. Sin is negative for x<0 (>-pi) so you can just check the sign of the result.

The dot is 2 multiplies and an add. The cross is 2 multiplies and a subtraction.

Robmaister's picture

#6

Assigned to:Anonymous» Robmaister
Status:open» in progress (review)

After doing quite a bit of googling, I found that there is actually a name for this, and it's used along with the dot product for atan2. Apparently the name for this is called the "perpendicular dot product" or "PerpDot."

http://www.wolframalpha.com/input/?i=perp+dot+product
http://number-none.com/product/Mathematical%20Growing%20Pains/index.html

Given it's usefulness with atan2 for 2d vectors (theta = atan2(perpdot(a,b), dot(a,b)), and a proper name, I feel it would be a useful method in Vector2. Here's a patch for review:

Index: Vector2.cs
===================================================================
--- Vector2.cs	(revision 3089)
+++ Vector2.cs	(working copy)
@@ -824,6 +824,32 @@
 
         #endregion
 
+        #region PerpDot
+
+        /// <summary>
+        /// Calculate the perpendicular dot (scalar) product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <returns>The perpendicular dot product of the two inputs</returns>
+        public static float PerpDot(Vector2 left, Vector2 right)
+        {
+            return left.X * right.Y - left.Y * right.X;
+        }
+
+        /// <summary>
+        /// Calculate the perpendicular dot (scalar) product of two vectors
+        /// </summary>
+        /// <param name="left">First operand</param>
+        /// <param name="right">Second operand</param>
+        /// <param name="result">The perpendicular dot product of the two inputs</param>
+        public static void PerpDot(ref Vector2 left, ref Vector2 right, out float result)
+        {
+            result = left.X * right.Y - left.Y * right.X;
+        }
+
+        #endregion
+
         #region Lerp
 
         /// <summary>
Robmaister's picture

#7

Status:in progress (review)» in progress (commit)

(Just realized I had the wrong status)

jamesbf's picture

#8

Nice. Sounds good