Compose multiple 3D transformation matrices in the correct order using NumPy.
3D transformations are represented as 4×4 homogeneous matrices. Composing transformations requires multiplying matrices in reverse order of application.
If we want to apply T1 first, then T2: Result = T2 @ T1
Return the composed matrix as a nested list of integers (e.g. 10, not 10.0); all test matrices have integer entries.
Common 3D transformations:
Translation: Move by (tx, ty, tz)
Rotation: Rotate around X, Y, or Z axis
Scale: Scale by (sx, sy, sz)
This is crucial for camera positioning, object manipulation, and scene graph traversal in 3D CV.
Example
Input
transforms = [
[[1,0,0,5],[0,1,0,0],[0,0,1,0],[0,0,0,1]], # Translate X by 5
[[2,0,0,0],[0,2,0,0],[0,0,2,0],[0,0,0,1]] # Scale by 2
]
Output
[[2,0,0,10],[0,2,0,0],[0,0,2,0],[0,0,0,1]]
Reasoning
transforms is a list of 4×4 homogeneous matrices in the order they act on a point: here T1 translates by (5,0,0) and T2 scales every axis by 2.
A point p=[x,y,z,1]T ends up at T2(T1p), so the one matrix doing both is M=T2T1: the transform applied later sits on the left.
Multiplying out, the upper-left 3×3 block is 2I⋅I=2I, and the translation column becomes 2⋅(5,0,0)=(10,0,0), giving [[2,0,0,10],[0,2,0,0],[0,0,2,0],[0,0,0,1]].
Check with the origin: (0,0,0)→(5,0,0) after translating, then →(10,0,0) after scaling, which is exactly the last column of M.
Notice the translation got scaled too. Swapping the two matrices gives T1T2, whose translation column stays (5,0,0): composition is not commutative.
The bottom row stays (0,0,0,1), and every entry is a whole number, returned as an integer.
Constraints
transforms: List of 4×4 transformation matrices
Return: Single composed 4×4 matrix
Apply transforms in order (first in list applied first)
3D transformations in computer vision are usually represented as 4×4 homogeneous matrices so that translation, rotation, and scaling can all be expressed as a single matrix multiplication on a 4D vector [x,y,z,1]T. Using homogeneous coordinates lets you chain multiple operations (like rotate then translate) as matrix products instead of applying each transformation separately. In this representation, the upper-left 3×3 block typically encodes rotation and scale, and the last column encodes translation.
A key subtlety is order of composition: matrix multiplication is not commutative, so A@B=B@A in general. In transformations, when you say “apply T1, then apply T2”, the combined matrix is T_{\text{combined}} = T_2 @ T_1. In other words, the matrix closest to the vector is applied first. This is crucial in 3D graphics and vision for placing cameras, moving objects, and traversing scene graphs: changing the order of multiplication can completely change the resulting pose.
1. Background Knowledge
Homogeneous coordinates:
A 3D point (x,y,z) is represented as a 4D vector (x,y,z,1). A 4×4 transformation matrix T acts on this vector by matrix multiplication:
p′=Tp
This form allows translation to be included in the same linear operation as rotation/scale.
Basic 3D transforms as 4×4 matrices:
Translation by (tx,ty,tz):
T=100001000010txtytz1
Rotation around X/Y/Z axes (using sin/cos in the top-left 3×3 block).
Scale by (sx,sy,sz):
S=sx0000sy0000sz00001
Composition rule:
If you have transforms T1,T2,T3 and you want to apply them to a point in this order:
p′=T3(T2(T1(p)))
then the combined matrix is:
Tcombined=T3@T2@T1
That is: the first applied transform appears rightmost in the product.
2. Algorithm / Approach
Given a list of 4×4 transformation matrices and a specified order of application:
Decide the application order (e.g., “apply T1, then T2, then T3”).
Compose by right-multiplying in that order:
Start from the identity matrix.
For each transform in application order, multiply it on the left of the current result.
Use the final composed matrix to transform points: result @ point_homogeneous.
Pattern in NumPy:
import numpy as np
M = np.eye(4)
for T in transforms_in_application_order:
M = T @ M
3. Step-by-Step Strategy
Represent each basic transform as a 4×4 NumPy array:
Each returns a np.array of shape (4, 4) with dtype float.
Understand the required order from the problem statement:
If the statement says: “Apply T1, then T2, then T3”, you must compute:
M = T3 @ T2 @ T1
If they give you a Python list like [T1, T2, T3] in application order, use a loop as above.
Initialize the composition:
Start with identity:
M = np.eye(4)
Iteratively apply transforms:
For a list Ts in application order:
for T in Ts:
M = T @ M # left-multiply
Use the composed matrix:
Convert points to homogeneous coordinates:
p = np.array([x, y, z, 1.0])
p_transformed = M @ p
Optionally convert back to 3D by dividing by p_transformed (usually 1).
4. Common Pitfalls
Reversing the order incorrectly:
Doing M = M @ T instead of M = T @ M will invert the order of application. Always remember: matrix closest to the vector is applied first.
Confusing “listed order” with “multiplication order”:
If the problem lists transforms in the order they should be applied, your multiplication must go from right to left in that list.
Mixing row-major / column-major mental models:
In NumPy, vectors are typically column-like and you use M @ v. Stick consistently to this convention to avoid transposed logic.
Shape errors:
Ensure all matrices are (4, 4) and points (4,) or (4, 1). Even one (3, 3) rotation sneaking in will break multiplication.
Angle units:
If building rotation matrices, ensure you use radians for NumPy trig functions, not degrees.
5. Time & Space Complexity
Let there be k transformations, each a 4×4 matrix.
Matrix–matrix multiplication of 4×4 matrices is O(1) with a small constant (since 4 is fixed).
Time complexity:
Composing k transforms: O(k) operations on constant-size matrices.
Applying the final matrix to n points: O(n) (each is a 4×4 @ 4×1 multiply).