 Colonel Panic -4 years ago 196
Python Question

# How to calculate all 24 rotations of 3d array?

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. Colonel Panic

So far I have 12 of them, composing `numpy.transpose` to permute the axes (xyz, yzx, zxy—all the same handedness) and rot90.

``````def rotations12(polycube):
for i in range(3):
polycube = numpy.transpose(polycube, (1, 2, 0))
for angle in range(4):
polycube = numpy.rot90(polycube)
yield polycube
``````

Quick test the 12 are distinct: `len(set(str(x) for x in rotations(polycube)))`

Update: here's how I made all 24.

``````def rotations24(polycube):
# imagine shape is pointing in axis 0 (up)

# 4 rotations about axis 0
yield from rotations4(polycube, 0)

# rotate 180 about axis 1, now shape is pointing down in axis 0
# 4 rotations about axis 0
yield from rotations4(rot90(polycube, 2, axis=1), 0)

# rotate 90 or 270 about axis 1, now shape is pointing in axis 2
# 8 rotations about axis 2
yield from rotations4(rot90(polycube, axis=1), 2)
yield from rotations4(rot90(polycube, -1, axis=1), 2)

# rotate about axis 2, now shape is pointing in axis 1
# 8 rotations about axis 1
yield from rotations4(rot90(polycube, axis=2), 1)
yield from rotations4(rot90(polycube, -1, axis=2), 1)

def rotations4(polycube, axis):
"""List the four rotations of the given cube about the given axis."""
for i in range(4):
yield rot90(polycube, i, axis)
``````

Using this helper function generalising rot90 to rotate about any axis:

``````def rot90(m, k=1, axis=2):
"""Rotate an array by 90 degrees in the counter-clockwise direction around the given axis"""
m = numpy.swapaxes(m, 2, axis)
m = numpy.rot90(m, k)
m = numpy.swapaxes(m, 2, axis)
return m
``````

I realise the helper function might not be quite right, but it worked

edit : correction in helper function m = numpy.rot90(m, k)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download