@@ -273,6 +273,23 @@ impl<B> Vec2<B> {
273273 pub fn to_vec3 ( self ) -> Vec3 < B > {
274274 vec3 ( self . x ( ) , self . y ( ) , 0.0 )
275275 }
276+
277+ /// Returns `self` rotated 90° counter-clockwise.
278+ pub fn perp ( self ) -> Self {
279+ vec2 ( -self . y ( ) , self . x ( ) )
280+ }
281+
282+ /// Returns the "perpendicular dot product" of `self` and `other`.
283+ ///
284+ /// This operation is also called a "2D cross product". Like its 3D analog,
285+ /// it satisfies the identity
286+ ///
287+ /// **a**<sup>⟂</sup> · **b** = |**a**| |**b**| sin *θ*,
288+ ///
289+ /// where θ is the (signed) angle between **a** and **b**.
290+ pub fn perp_dot ( self , other : Self ) -> f32 {
291+ self . perp ( ) . dot ( & other)
292+ }
276293}
277294
278295impl < R , Sc , B > Vector < R , Real < 3 , B > >
@@ -775,6 +792,23 @@ mod tests {
775792 vec4( 1.0 , -2.0 , 4.0 , -3.0 )
776793 ) ;
777794 }
795+
796+ #[ test]
797+ fn perp ( ) {
798+ assert_eq ! ( Vec2 :: <( ) >:: zero( ) . perp( ) , Vec2 :: zero( ) ) ;
799+ assert_eq ! ( Vec2 :: <( ) >:: X . perp( ) , Vec2 :: Y ) ;
800+ assert_eq ! ( vec2( -0.2 , -1.5 ) . perp( ) , vec2( 1.5 , -0.2 ) ) ;
801+ }
802+
803+ #[ test]
804+ fn perp_dot ( ) {
805+ const X : Vec2 = Vec2 :: X ;
806+ const Y : Vec2 = Vec2 :: Y ;
807+
808+ assert_eq ! ( X . perp_dot( X ) , 0.0 ) ;
809+ assert_eq ! ( X . perp_dot( Y ) , 1.0 ) ;
810+ assert_eq ! ( ( 2.0 * Y ) . perp_dot( 3.0 * X ) , -6.0 ) ;
811+ }
778812 }
779813
780814 mod i32 {
0 commit comments