Skip to content

(System.Numerics) Cross Product for Vector2 and Vector4 #28731

@danmoseley

Description

@danmoseley

I am proposing that a Cross Product function be added to both Vector2 and Vector4 of System.Numerics because its use in geometry is so common.

Rationale and Usage

The structs, Vector2, Vector3, and Vector4 are intended to model geometry functions that often need to be performed quickly and which would greatly benefit from SIMD inlining. Dot Product is just as popular and it is properly implemented in these structs. Cross Product is only possible for vectors of length 3 (yes, and 7, but that is not important right now). However, Vector2 and Vector4 are essentially modelling vectors in 3D space. In Vector2 the cross product is commonly used for functions like offsetting, for determining if the next edge in a polygon turns right or left (or convex or concave), or determining overlap/collisions. A cross-product of two Vector2 's would always result in an out-of-plane or z-direction, but it's value and sign is very useful and just as quick to process as Dot.
Vector4 is defined for use as a homogeneous 3D coordinate vector, and so it will be necessary for a Cross function to exist for it just as much as for Vector3.

Proposed Changes And API

The addition of two new methods are quite simple and the functions that these invoke are nothing other than add (+) and multiply (*).
To Vector2_Instrinsics.cs (under Dot() line 109):

         /// <summary>
        /// Returns the z-value of the cross product of two vectors.
        /// Since the Vector2 is in the x-y plane, a 3D cross product
        /// only produces the z-value
        /// </summary>
        /// <param name="value1">The first vector.</param>
        /// <param name="value2">The second vector.</param>
        /// <returns>The value of the z-coordinate from the cross product.</returns>
        [JitIntrinsic]
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static float Cross(Vector2 value1, Vector2 value2)
        {
            return value1.X * value2.Y 
                   - value1.Y * value2.X;
        }

to Vector4_Instrinsics.cs (under Dot() line 157):

        /// <summary>
        /// Computes the cross product of two vectors. For homogeneous
        /// coordinates, the product of the weights is the new weight
        /// for the resulting product.
        /// </summary>
        /// <param name="vector1">The first vector.</param>
        /// <param name="vector2">The second vector.</param>
        /// <returns>The cross product.</returns>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Vector4 Cross(Vector4 vector1, Vector4 vector2)
        {
            return new Vector4(
                vector1.Y * vector2.Z - vector1.Z * vector2.Y,
                vector1.Z * vector2.X - vector1.X * vector2.Z,
                vector1.X * vector2.Y - vector1.Y * vector2.X,
                vector1.W * vector2.W);
        }

Other Details

  • One will note that the 'Cross' for 'Vector2' looks like the 'Dot' except the values have moved around. Yes, essentially the 'Cross' for 'Vector2' is the same as taking the 'Dot' with a vector that has been rotate 90-degrees from the original. As such, this is the work around to invoking geometric functions - create a new vector 90-degrees from the original, and then use Dot. This process is not intuitive and requires extra steps. A simple function, like the one shown above, is both more intuitive and quicker.
  • The proposed Cross function for Vector4 is nearly the same as that for Vector3 with the addition of the fourth value which is the product of the original two w's. This can be derived by symbolically performing the cross product for Vector3 with values [x_1/w_1, y_1/w_1, z_1/w_1] and [x_2/w_2, y_2/w_2, z_2/w_2].

Open Questions

  • Will the name Cross be misleading for Vector2? If so, one could name it CrossZValue, but I think this is an unwarranted complication. In implementing 2D algorithms, the literature has called this the cross product and one would write the code to mimic the presentation of scientific papers. However, since the result is a single scalar (float), it could be confusing as to why a Cross product function is not returning a new vector.

Pull Request

A PR with the proposed changes is forthcoming.

Updates

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Numericsin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions