[language-agnostic] Calculating a 2D Vector's Cross Product

From wikipedia:

the cross product is a binary operation on two vectors in a three-dimensional Euclidean space that results in another vector which is perpendicular to the plane containing the two input vectors.

Given that the definition is only defined in three (or seven, one and zero) dimensions, how does one calculate the cross product of two 2d vectors?

I have seen two implementations. One returns a new vector (but only accepts a single vector), the other returns a scalar (but is a calculation between two vectors).

Implementation 1 (returns a scalar):

float CrossProduct(const Vector2D & v1, const Vector2D & v2) const
{
    return (v1.X*v2.Y) - (v1.Y*v2.X);
}

Implementation 2 (returns a vector):

Vector2D CrossProduct(const Vector2D & v) const
{
    return Vector2D(v.Y, -v.X);
}

Why the varying implementations? What would I use the scalar implementation for? What would I use the vector implementation for?

The reason I ask is because I'm writing a Vector2D class myself and don't know which method to use.

This question is related to language-agnostic math vector 2d

The answer is


Implementation 1 returns the magnitude of the vector that would result from a regular 3D cross product of the input vectors, taking their Z values implicitly as 0 (i.e. treating the 2D space as a plane in the 3D space). The 3D cross product will be perpendicular to that plane, and thus have 0 X & Y components (thus the scalar returned is the Z value of the 3D cross product vector).

Note that the magnitude of the vector resulting from 3D cross product is also equal to the area of the parallelogram between the two vectors, which gives Implementation 1 another purpose. In addition, this area is signed and can be used to determine whether rotating from V1 to V2 moves in an counter clockwise or clockwise direction. It should also be noted that implementation 1 is the determinant of the 2x2 matrix built from these two vectors.

Implementation 2 returns a vector perpendicular to the input vector still in the same 2D plane. Not a cross product in the classical sense but consistent in the "give me a perpendicular vector" sense.

Note that 3D euclidean space is closed under the cross product operation--that is, a cross product of two 3D vectors returns another 3D vector. Both of the above 2D implementations are inconsistent with that in one way or another.

Hope this helps...


In short: It's a shorthand notation for a mathematical hack.

Long explanation:

You can't do a cross product with vectors in 2D space. The operation is not defined there.

However, often it is interesting to evaluate the cross product of two vectors assuming that the 2D vectors are extended to 3D by setting their z-coordinate to zero. This is the same as working with 3D vectors on the xy-plane.

If you extend the vectors that way and calculate the cross product of such an extended vector pair you'll notice that only the z-component has a meaningful value: x and y will always be zero.

That's the reason why the z-component of the result is often simply returned as a scalar. This scalar can for example be used to find the winding of three points in 2D space.

From a pure mathematical point of view the cross product in 2D space does not exist, the scalar version is the hack and a 2D cross product that returns a 2D vector makes no sense at all.


I'm using 2d cross product in my calculation to find the new correct rotation for an object that is being acted on by a force vector at an arbitrary point relative to its center of mass. (The scalar Z one.)


Another useful property of the cross product is that its magnitude is related to the sine of the angle between the two vectors:

| a x b | = |a| . |b| . sine(theta)

or

sine(theta) = | a x b | / (|a| . |b|)

So, in implementation 1 above, if a and b are known in advance to be unit vectors then the result of that function is exactly that sine() value.


In short: It's a shorthand notation for a mathematical hack.

Long explanation:

You can't do a cross product with vectors in 2D space. The operation is not defined there.

However, often it is interesting to evaluate the cross product of two vectors assuming that the 2D vectors are extended to 3D by setting their z-coordinate to zero. This is the same as working with 3D vectors on the xy-plane.

If you extend the vectors that way and calculate the cross product of such an extended vector pair you'll notice that only the z-component has a meaningful value: x and y will always be zero.

That's the reason why the z-component of the result is often simply returned as a scalar. This scalar can for example be used to find the winding of three points in 2D space.

From a pure mathematical point of view the cross product in 2D space does not exist, the scalar version is the hack and a 2D cross product that returns a 2D vector makes no sense at all.


Implementation 1 is the perp dot product of the two vectors. The best reference I know of for 2D graphics is the excellent Graphics Gems series. If you're doing scratch 2D work, it's really important to have these books. Volume IV has an article called "The Pleasures of Perp Dot Products" that goes over a lot of uses for it.

One major use of perp dot product is to get the scaled sin of the angle between the two vectors, just like the dot product returns the scaled cos of the angle. Of course you can use dot product and perp dot product together to determine the angle between two vectors.

Here is a post on it and here is the Wolfram Math World article.


In short: It's a shorthand notation for a mathematical hack.

Long explanation:

You can't do a cross product with vectors in 2D space. The operation is not defined there.

However, often it is interesting to evaluate the cross product of two vectors assuming that the 2D vectors are extended to 3D by setting their z-coordinate to zero. This is the same as working with 3D vectors on the xy-plane.

If you extend the vectors that way and calculate the cross product of such an extended vector pair you'll notice that only the z-component has a meaningful value: x and y will always be zero.

That's the reason why the z-component of the result is often simply returned as a scalar. This scalar can for example be used to find the winding of three points in 2D space.

From a pure mathematical point of view the cross product in 2D space does not exist, the scalar version is the hack and a 2D cross product that returns a 2D vector makes no sense at all.


Another useful property of the cross product is that its magnitude is related to the sine of the angle between the two vectors:

| a x b | = |a| . |b| . sine(theta)

or

sine(theta) = | a x b | / (|a| . |b|)

So, in implementation 1 above, if a and b are known in advance to be unit vectors then the result of that function is exactly that sine() value.


A useful 2D vector operation is a cross product that returns a scalar. I use it to see if two successive edges in a polygon bend left or right.

From the Chipmunk2D source:

/// 2D vector cross product analog.
/// The cross product of 2D vectors results in a 3D vector with only a z component.
/// This function returns the magnitude of the z value.
static inline cpFloat cpvcross(const cpVect v1, const cpVect v2)
{
        return v1.x*v2.y - v1.y*v2.x;
}

Another useful property of the cross product is that its magnitude is related to the sine of the angle between the two vectors:

| a x b | = |a| . |b| . sine(theta)

or

sine(theta) = | a x b | / (|a| . |b|)

So, in implementation 1 above, if a and b are known in advance to be unit vectors then the result of that function is exactly that sine() value.


I'm using 2d cross product in my calculation to find the new correct rotation for an object that is being acted on by a force vector at an arbitrary point relative to its center of mass. (The scalar Z one.)


Another useful property of the cross product is that its magnitude is related to the sine of the angle between the two vectors:

| a x b | = |a| . |b| . sine(theta)

or

sine(theta) = | a x b | / (|a| . |b|)

So, in implementation 1 above, if a and b are known in advance to be unit vectors then the result of that function is exactly that sine() value.


In short: It's a shorthand notation for a mathematical hack.

Long explanation:

You can't do a cross product with vectors in 2D space. The operation is not defined there.

However, often it is interesting to evaluate the cross product of two vectors assuming that the 2D vectors are extended to 3D by setting their z-coordinate to zero. This is the same as working with 3D vectors on the xy-plane.

If you extend the vectors that way and calculate the cross product of such an extended vector pair you'll notice that only the z-component has a meaningful value: x and y will always be zero.

That's the reason why the z-component of the result is often simply returned as a scalar. This scalar can for example be used to find the winding of three points in 2D space.

From a pure mathematical point of view the cross product in 2D space does not exist, the scalar version is the hack and a 2D cross product that returns a 2D vector makes no sense at all.


Implementation 1 is the perp dot product of the two vectors. The best reference I know of for 2D graphics is the excellent Graphics Gems series. If you're doing scratch 2D work, it's really important to have these books. Volume IV has an article called "The Pleasures of Perp Dot Products" that goes over a lot of uses for it.

One major use of perp dot product is to get the scaled sin of the angle between the two vectors, just like the dot product returns the scaled cos of the angle. Of course you can use dot product and perp dot product together to determine the angle between two vectors.

Here is a post on it and here is the Wolfram Math World article.


A useful 2D vector operation is a cross product that returns a scalar. I use it to see if two successive edges in a polygon bend left or right.

From the Chipmunk2D source:

/// 2D vector cross product analog.
/// The cross product of 2D vectors results in a 3D vector with only a z component.
/// This function returns the magnitude of the z value.
static inline cpFloat cpvcross(const cpVect v1, const cpVect v2)
{
        return v1.x*v2.y - v1.y*v2.x;
}

Examples related to language-agnostic

IOException: The process cannot access the file 'file path' because it is being used by another process Peak signal detection in realtime timeseries data Match linebreaks - \n or \r\n? Simple way to understand Encapsulation and Abstraction How can I pair socks from a pile efficiently? How do I determine whether my calculation of pi is accurate? What is ADT? (Abstract Data Type) How to explain callbacks in plain english? How are they different from calling one function from another function? Ukkonen's suffix tree algorithm in plain English Private vs Protected - Visibility Good-Practice Concern

Examples related to math

How to do perspective fixing? How to pad a string with leading zeros in Python 3 How can I use "e" (Euler's number) and power operation in python 2.7 numpy max vs amax vs maximum Efficiently getting all divisors of a given number Using atan2 to find angle between two vectors How to calculate percentage when old value is ZERO Finding square root without using sqrt function? Exponentiation in Python - should I prefer ** operator instead of math.pow and math.sqrt? How do I get the total number of unique pairs of a set in the database?

Examples related to vector

How to plot vectors in python using matplotlib How can I get the size of an std::vector as an int? Convert Mat to Array/Vector in OpenCV Are vectors passed to functions by value or by reference in C++ Why is it OK to return a 'vector' from a function? Append value to empty vector in R? How to initialize a vector with fixed length in R How to initialize a vector of vectors on a struct? numpy matrix vector multiplication Using atan2 to find angle between two vectors

Examples related to 2d

Declare an empty two-dimensional array in Javascript? Most efficient way to find mode in numpy array 2D cross-platform game engine for Android and iOS? A simple algorithm for polygon intersection Difference between SurfaceView and View? Drawing Isometric game worlds Calculating a 2D Vector's Cross Product