Version: 13.0

    Show / Hide Table of Contents

    Linear Algebra with Mastapy

    This article is a brief overview of the linear algebra classes uniquely available to the Python API. These are handwritten classes specifically designed for ease-of-use in Python.

    These linear algebra classes are not suitable for intensive operations. If you require high performance it is highly recommended you use the numpy package. These classes can be easily converted to a numpy array (e.g. numpy.array(my_vector).)

    The following classes are currently available:

    • Scalar

    • Vector2D

    • Vector3D

    • Vector4D

    • Matrix2x2

    • Matrix3x3

    • Matrix4x4

    With the exception of Scalar, all classes can be instantiated and boast features such as swizzling, useful operator overrides, value broadcasting and more. Examples of these features can be seen below.

    In addition to being able to instantiate each class, there are also a large array of static mathematical functions available. These include things like interpolation, dot products and cross products for the vector classes, and transpose and inverse for the matrix classes. The full list of available properties and methods can be viewed via Intellisense or by calling the help method on each type.

    Additional static methods are available in the Scalar class that work on scalar values.

    Examples

    The following are a range of examples demonstrating some of the uses of the linear algebra classes.

    Vector3D Example

    This first example shows basic usage of the Vector3D class. Everything in this example is also applicable to Vector2D and Vector4D.

    from mastapy import Vector3D
    
    # You can create a vector in a few different ways
    my_vector = Vector3D(1.0, 2.0, 3.0)
    my_vector = Vector3D.broadcast(2.0)
    my_vector = Vector3D.from_tuple((1.0, 2.0, 3.0))
    
    # All x, y and z components can be accessed
    x = my_vector.x
    y = my_vector.y
    z = my_vector.z
    
    # They can also be accessed by index
    x = my_vector[0]
    y = my_vector[1]
    z = my_vector[2]
    
    # Swizzling is supported
    xy = my_vector.xy
    zyx = my_vector.zyx
    yyy = my_vector.yyy
    
    # As Vector3D behaves like a tuple, you can use built-in methods for
    # manipulating sequences
    length = len(my_vector)
    maximum = max(my_vector)
    
    # You can perform mathematical operations on vectors.
    # Note that both of these are component-wise operations. 
    # If you wish to perform a cross product, use the @
    # operator.
    added = my_vector + Vector3D(3.0, 2.0, 1.0)
    multiplied = my_vector * (4.0, 5.0, 6.0)
    
    # You can broadcast mathematical operations
    subtracted = my_vector - 1.0
    divided = my_vector / 2.0
    
    print('Original:', my_vector)
    print('ZYX swizzle:', zyx)
    print()
    print('Length:', length)
    print('Max:', maximum)
    print('Added:', added)
    print('Multiplied:', multiplied)
    print('Subtracted:', subtracted)
    print('Divided:', divided)
    

    Output:

    Original: (1.0, 2.0, 3.0)
    ZYX swizzle: (3.0, 2.0, 1.0)
    
    Length: 3
    Max: 3.0
    Added: (4.0, 4.0, 4.0)
    Multiplied: (4.0, 10.0, 18.0)
    Subtracted: (0.0, 1.0, 2.0)
    Divided: (0.5, 1.0, 1.5)
    

    Vector Linear Algebra Example

    In addition to the basic usages in the previous example, a range of linear algebra methods are available. Again, most of the following methods are also available on the Vector2D and Vector4D classes.

    from mastapy import Vector3D
    
    # Note that we do not have to explicitly declare  a vector as a Vector3D class
    # to use it in any of the linear algebra methods. Any iterable object with
    # a length of 3 can be used.
    
    my_vector0 = Vector3D(1.0, 2.0, 3.0)
    my_vector1 = 4.0, 5.0, 6.0
    
    # Notice how all methods are static methods. This is to allow any iterable
    # object to be passed into the methods.
    
    dot_result = Vector3D.dot(my_vector0, my_vector1)
    cross_result = Vector3D.cross(my_vector0, my_vector1)
    interp_result = Vector3D.interpolate(my_vector0, my_vector1, 0.5)
    
    my_vector0_n = Vector3D.normalize(my_vector0)
    my_vector1_n = Vector3D.normalize(my_vector1)
    reflect_result = Vector3D.reflect(my_vector0_n, my_vector1_n)
    
    print('my_vector0:', my_vector0)
    print('my_vector1:', my_vector1)
    print()
    print('Dot product:', dot_result)
    print('Cross product:', cross_result)
    print('Interpolation (0.5):', interp_result)
    print()
    print('my_vector0 normalized:', '{:.6f}'.format(my_vector0_n))
    print('my_vector1 normalized:', '{:.6f}'.format(my_vector1_n))
    print('Reflection:', '{:.6f}'.format(reflect_result))
    

    Output:

    my_vector0: (1.0, 2.0, 3.0)
    my_vector1: (4.0, 5.0, 6.0)
    
    Dot product: 32.0
    Cross product: (-3.0, 6.0, -3.0)
    Interpolation (0.5): (2.5, 3.5, 4.5)
    
    my_vector0 normalized: (0.267261, 0.534522, 0.801784)
    my_vector1 normalized: (0.455842, 0.569803, 0.683763)
    Reflection: (-0.621296, -0.576174, -0.531052)
    

    Matrix Example

    Along with the vector classes are accompanying matrix classes. Currently only square matrices are supported.

    from math import radians
    
    from mastapy import Matrix4x4
    
    # Matrices in the mastapy package are column-major. This means matrices are
    # constructed as a series of columns and that order of transformation is
    # right to left.
    #
    # Example:
    #
    #     >>> rotation_matrix @ translation_matrix @ my_vector
    #
    #     The order of transformation here is to translate first, then rotate.
    
    
    my_point = 2.0, 5.0, 1.0, 1.0
    my_direction = 2.0, 5.0, 1.0, 0.0
    
    # There are a series of new constructors for matrices
    identity_matrix = Matrix4x4.identity()
    scale_matrix = Matrix4x4.diagonal(2.0)
    translation_matrix = Matrix4x4.translation(1.0, 2.0, 3.0)
    rotation_matrix = Matrix4x4.rotation_y(radians(75.0))
    
    # You can access rows, columns and individual entries of a matrix
    col0 = rotation_matrix[0]
    col1 = rotation_matrix.column1
    row2 = rotation_matrix.row2
    elem = rotation_matrix.m33
    
    # To transform a point or direction, there are a number of options available
    
    # Notice how both transform_point and transform_direction return a Vector3D
    # whereas the matrix multiplication operator returns either a Matrix4x4 or
    # a Vector4D, depending on parameters
    point_transform = Matrix4x4.transform_point(translation_matrix, my_point)
    dir_transform = Matrix4x4.transform_direction(translation_matrix, my_point)
    general_transform = scale_matrix @ rotation_matrix @ my_direction
    
    # You can also manipulate matrices with a variety of built-in methods
    inverse = Matrix4x4.inverse(rotation_matrix)
    transpose = Matrix4x4.transpose(translation_matrix)
    determinant = Matrix4x4.determinant(scale_matrix)
    
    print('my_point:', my_point)
    print('my_direction:', my_direction)
    print()
    print('Identity matrix:')
    print(identity_matrix)
    print()
    print('Scale matrix:')
    print(scale_matrix)
    print()
    print('Translation matrix:')
    print(translation_matrix)
    print()
    print('Rotation matrix:')
    print('{:.6f}'.format(rotation_matrix))
    print()
    print('col0:', '{:.6f}'.format(col0))
    print('col1:', col1)
    print('row2:', '{:.6f}'.format(row2))
    print('elem:', elem)
    print()
    print('Point transform:', point_transform)
    print('Direction transform:', dir_transform)
    print('General transform:', '{:.6f}'.format(general_transform))
    print()
    print('Inverse:')
    print('{:.6f}'.format(inverse))
    print()
    print('Transpose:')
    print(transpose)
    print()
    print('Determinant:', determinant)
    

    Output:

    my_point: (2.0, 5.0, 1.0, 1.0)
    my_direction: (2.0, 5.0, 1.0, 0.0)
    
    Identity matrix:
    (1.0, 0.0, 0.0, 0.0,
     0.0, 1.0, 0.0, 0.0,
     0.0, 0.0, 1.0, 0.0,
     0.0, 0.0, 0.0, 1.0)
    
    Scale matrix:
    (2.0, 0.0, 0.0, 0.0,
     0.0, 2.0, 0.0, 0.0,
     0.0, 0.0, 2.0, 0.0,
     0.0, 0.0, 0.0, 2.0)
    
    Translation matrix:
    (1.0, 0.0, 0.0, 1.0,
     0.0, 1.0, 0.0, 2.0,
     0.0, 0.0, 1.0, 3.0,
     0.0, 0.0, 0.0, 1.0)
    
    Rotation matrix:
    (0.258819, 0.000000, 0.965926, 0.000000,
     0.000000, 1.000000, 0.000000, 0.000000,
     -0.965926, 0.000000, 0.258819, 0.000000,
     0.000000, 0.000000, 0.000000, 1.000000)
    
    col0: (0.258819, 0.000000, -0.965926, 0.000000)
    col1: (0.0, 1.0, 0.0, 0.0)
    row2: (-0.965926, 0.000000, 0.258819, 0.000000)
    elem: 0.25881904510252074
    
    Point transform: (3.0, 7.0, 4.0)
    Direction transform: (2.0, 5.0, 1.0)
    General transform: (2.967128, 10.000000, -3.346065, 0.000000)
    
    Inverse:
    (0.258819, 0.000000, -0.965926, 0.000000,
     0.000000, 1.000000, 0.000000, 0.000000,
     0.965926, 0.000000, 0.258819, 0.000000,
     0.000000, 0.000000, 0.000000, 1.000000)
    
    Transpose:
    (1.0, 0.0, 0.0, 0.0,
     0.0, 1.0, 0.0, 0.0,
     0.0, 0.0, 1.0, 0.0,
     1.0, 2.0, 3.0, 1.0)
    
    Determinant: 16.0
    
    Back to top