I have a 3d numpy array describing a polycube (imagine a 3d tetris piece). How can I calculate all 24 rotations?
Numpy's array manipulation routines includes a rot90 method, which gives 4 of the 24, but I'm clueless how to calculate the rest. My only idea is to convert the 3d array to a 2d matrix of co-ordinates, multiply by a rotation matrix, and convert back. But I'd rather work directly with the 3d array.
Example 2x2x2 array:
>>> from numpy import array >>> polycube array([[[1, 0], [1, 0]], [[1, 1], [0, 0]]])
Example 3x3x3 array:
array([[[1, 1, 0], [1, 1, 0], [0, 0, 0]], [[0, 0, 0], [1, 0, 0], [1, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]])
Edit: I only want the 24 orientation-preserving isometries, not all 48 rotations and reflections (though it would be interesting to know how to make them too). If it helps to test, I believe the 3x3x3 example has no rotational symmetry and is chiral (so the 48 are distinct).
Motivation: I'm writing a solver for a Soma cube-style puzzle.
3D Rotation is a process of rotating an object with respect to an angle in a three dimensional plane. Consider a point object O has to be rotated from one angle to another in a 3D plane.
The trace of a rotation matrix is equal to the sum of its eigenvalues. For n = 2, a rotation by angle θ has trace 2 cos θ. For n = 3, a rotation around any axis by angle θ has trace 1 + 2 cos θ. For n = 4, and the trace is 2(cos θ + cos φ), which becomes 4 cos θ for an isoclinic rotation.
The most general three-dimensional rotation matrix represents a counterclockwise rotation by an angle θ about a fixed axis that lies along the unit vector n. The rotation matrix operates on vectors to produce rotated vectors, while the coordinate axes are held fixed. This is called an active transformation.
Update: Simplified after Numpy 1.12.0 added an axes argument to the rot90 function
Here's how I made all 24 rotations:
from numpy import rot90, array def rotations24(polycube): """List all 24 rotations of the given 3d array""" def rotations4(polycube, axes): """List the four rotations of the given 3d array in the plane spanned by the given axes.""" for i in range(4): yield rot90(polycube, i, axes) # imagine shape is pointing in axis 0 (up) # 4 rotations about axis 0 yield from rotations4(polycube, (1,2)) # rotate 180 about axis 1, now shape is pointing down in axis 0 # 4 rotations about axis 0 yield from rotations4(rot90(polycube, 2, axes=(0,2)), (1,2)) # rotate 90 or 270 about axis 1, now shape is pointing in axis 2 # 8 rotations about axis 2 yield from rotations4(rot90(polycube, axes=(0,2)), (0,1)) yield from rotations4(rot90(polycube, -1, axes=(0,2)), (0,1)) # rotate about axis 2, now shape is pointing in axis 1 # 8 rotations about axis 1 yield from rotations4(rot90(polycube, axes=(0,1)), (0,2)) yield from rotations4(rot90(polycube, -1, axes=(0,1)), (0,2))
Test that all 24 rotations are indeed distinct:
polycube = array([[[1, 1, 0], [1, 1, 0], [0, 0, 0]], [[0, 0, 0], [1, 0, 0], [1, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]) assert len(set(str(x) for x in rotations24(polycube))) == 24
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With