'How to get a 4x4 translation matrix from a vector in python

I want to get a 4x4 translation matrix from a vec3 in Python. I don't know how I can do that correctly.

Can someboday explain what exactly needs to be done and how I can achieve this?

This is what I mean: img vector to matrix So basically the vector of T should become a 4x4 Matrix (like in the picture)

This is my code and the formula for the translation matrix:

# 4x4 Translations-Matrix T(-Px, -Py, -Pz) - needs to be 4x4 matrix
translation_matrix = (-P.x, -P.y, -P.z)

My Mat4x4 looks like this:

from __future__ import annotations


class Mat4x4:
def __init__(
        self,
        a11: float, a12: float, a13: float, a14: float,
        a21: float, a22: float, a23: float, a24: float,
        a31: float, a32: float, a33: float, a34: float,
        a41: float, a42: float, a43: float, a44: float,
):
    self.a11 = a11, self.a12 = a12, self.a13 = a13, self.a14 = a14
    self.a21 = a21, self.a22 = a22, self.a23 = a23, self.a24 = a24
    self.a31 = a31, self.a32 = a32, self.a33 = a33, self.a34 = a34
    self.a41 = a41, self.a42 = a42, self.a43 = a43, self.a44 = a44

# Matrix multiplication
def __mul__(self, other: Mat4x4) -> Mat4x4:
    return Mat4x4(
        self.a11 * other.a11 + self.a12 * other.a21 + self.a13 * other.a31 + self.a14 * other.a41,  # a11
        self.a11 * other.a12 + self.a12 * other.a22 + self.a13 * other.a32 + self.a14 * other.a42,  # a12
        self.a11 * other.a13 + self.a12 * other.a23 + self.a13 * other.a33 + self.a14 * other.a43,  # a13
        self.a11 * other.a14 + self.a12 * other.a24 + self.a13 * other.a34 + self.a14 * other.a44,  # a14

        self.a21 * other.a11 + self.a22 * other.a12 + self.a23 * other.a13 + self.a24 * other.a14,  # a21
        self.a21 * other.a21 + self.a22 * other.a22 + self.a23 * other.a23 + self.a24 * other.a24,  # a22
        self.a21 * other.a31 + self.a22 * other.a32 + self.a23 * other.a33 + self.a24 * other.a34,  # a23
        self.a21 * other.a41 + self.a22 * other.a42 + self.a23 * other.a43 + self.a24 * other.a44,  # a24

        self.a31 * other.a11 + self.a32 * other.a12 + self.a33 * other.a13 + self.a34 * other.a14,  # a31
        self.a31 * other.a21 + self.a32 * other.a22 + self.a33 * other.a23 + self.a34 * other.a24,  # a32
        self.a31 * other.a31 + self.a32 * other.a32 + self.a33 * other.a33 + self.a34 * other.a34,  # a33
        self.a31 * other.a41 + self.a32 * other.a42 + self.a33 * other.a43 + self.a34 * other.a44,  # a34

        self.a41 * other.a11 + self.a42 * other.a12 + self.a43 * other.a13 + self.a44 * other.a14,  # a41
        self.a41 * other.a21 + self.a42 * other.a22 + self.a43 * other.a23 + self.a44 * other.a24,  # a42
        self.a41 * other.a31 + self.a42 * other.a32 + self.a43 * other.a33 + self.a44 * other.a34,  # a43
        self.a41 * other.a41 + self.a42 * other.a42 + self.a43 * other.a43 + self.a44 * other.a44,  # a44
    )

# Add
def __add__(self, other: Mat4x4) -> Mat4x4:
    return Mat4x4(
        self.a11 + other.a11,  # a11
        self.a12 + other.a12,  # a12
        self.a13 + other.a13,  # a13
        self.a14 + other.a14,  # a14

        self.a21 + other.a21,  # a21
        self.a22 + other.a22,  # a22
        self.a23 + other.a23,  # a23
        self.a24 + other.a24,  # a24

        self.a31 + other.a31,  # a31
        self.a32 + other.a32,  # a32
        self.a33 + other.a33,  # a33
        self.a34 + other.a34,  # a34

        self.a41 + other.a41,  # a41
        self.a42 + other.a42,  # a42
        self.a43 + other.a43,  # a43
        self.a44 + other.a44,  # a44
    )

# Subtract
def __sub__(self, other: Mat4x4) -> Mat4x4:
    return Mat4x4(
        self.a11 - other.a11,  # a11
        self.a12 - other.a12,  # a12
        self.a13 - other.a13,  # a13
        self.a14 - other.a14,  # a14

        self.a21 - other.a21,  # a21
        self.a22 - other.a22,  # a22
        self.a23 - other.a23,  # a23
        self.a24 - other.a24,  # a24

        self.a31 - other.a31,  # a31
        self.a32 - other.a32,  # a32
        self.a33 - other.a33,  # a33
        self.a34 - other.a34,  # a34

        self.a41 - other.a41,  # a41
        self.a42 - other.a42,  # a42
        self.a43 - other.a43,  # a43
        self.a44 - other.a44,  # a44
    )

# Not Equal
def __ne__(self) -> Mat4x4:
    return Mat4x4(
        -self.a11,  # a11
        -self.a12,  # a12
        -self.a13,  # a13
        -self.a14,  # a14

        -self.a21,  # a21
        -self.a22,  # a22
        -self.a23,  # a23
        -self.a24,  # a24

        -self.a31,  # a31
        -self.a32,  # a32
        -self.a33,  # a33
        -self.a34,  # a34

        -self.a41,  # a41
        -self.a42,  # a42
        -self.a43,  # a43
        -self.a44,  # a44
    )

# Convert to string
def __str__(self) -> str:
    return (
            f'{self.a11} {self.a12} {self.a13} {self.a14}\n' +
            f'{self.a21} {self.a22} {self.a23} {self.a24}\n' +
            f'{self.a31} {self.a32} {self.a33} {self.a34}\n' +
            f'{self.a41} {self.a42} {self.a43} {self.a44}'
    )

And this is my code for Vec3:

import math

import numpy as np


class Vec3:
def __init__(self, x: float, y: float, z: float):
    self.x = x
    self.y = y
    self.z = z

# Addition
def __add__(self, other):
    return Vec3(self.x + other.x, self.y + other.y, self.z + other.z)

def __radd__(self, other):
    # other = self.convert2Vec3D(other)
    return self.__add__(other)

# Subtraktion
def __rsub__(self, other):
    # other = self.convert2Vec3D(other)
    return other.__sub__(self)

def __sub__(self, other):
    # other = self.convert2Vec3D(other)
    return Vec3(self.x - other.x, self.y - other.y, self.z - other.z)

# Multiplikation
def __mul__(self, other):
    return Vec3(self.x * other.x + self.y * other.y + self.z * other.z)

def __rmul__(self, other):
    return self.__rmul__(self, other)

# Division
def __truediv__(self, other):
    return Vec3(self.x / other.x, self.y / other.y, self.z / other.z)
    # AttributeError: 'float' object has no attribute 'x'

def __rtruediv__(self, other):
    # other = self.convert2Vec3D(other)
    return other.__rtruediv__(self)

# Kreuzprodukt
def cross(self, other):
    x1, y1, z1 = self.x, self.y, self.z
    x2, y2, z2 = other.x, other.y, other.z
    return Vec3(y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2)

def __str__(self):
    return '(%g, %g, %g)' % (self.x, self.y, self.z)

# Absoluter Wert
def __abs__(self):
    absValue = math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2)
    return Vec3(absValue, absValue, absValue)

I already tried to do some things like this

# translation_matrix = Mat4x4(a11=-P.x, a12=-P.y, a13=-P.z, a14=-P.x,
#                             a21=-P.x, a22=-P.y, a23=-P.z, a24=-P.x,
#                             a31=P.x, a32=P.y, a33=P.z, a34=P.x,
#                             a41=-P.x, a42=-P.y, a43=P.z, a44=-P.x)

But this approach doesn't seem right. So my question is: How can I properly get a 4x4 Matrix out of a Vector? It only needs to be printed out as a string, so I don't need it for drawing or something like that.



Solution 1:[1]

Assuming that this is the transformation you are trying to do:

The easiest to achieve that would be something along the lines of:

import numpy as np
v = np.array((-1, -1, 1))
T = np.identity(n=4)
T[0:3,3] = -v

This yields what I think you want:

>>> T
array([[ 1.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  1.],
       [ 0.,  0.,  1., -1.],
       [ 0.,  0.,  0.,  1.]])

All the magic happens in the last line, T[0:3,3] = -v, where you are assigning the three matrix elements: T[0,3]=-v[0], T[1,3]=-v[1], and T[2,3]=-v[2]. If you want to implement something similar within your own framework, you will need to use per-element assignments because your matrix is not a numpy ndarray. That said, I'd urge that you use ndarrays, they're much faster, more versatile and will save you from writing a lot of boilerplate code.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Andrej Prsa