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 me
First let's determine the 48 isometries, as matrices that permute the basis vectors, possibly flipping some signs:
def isometries():
basis = numpy.eye(3)
for ix in range(3):
for iy in range(3):
if iy == ix:
continue
for iz in range(3):
if iz == ix or iz == iy:
continue
for sx in range(-1, 2, 2): # -1, 1
for sy in range(-1, 2, 2):
for sz in range(-1, 2, 2):
yield numpy.array([sx * basis[ix], sy * basis[iy], sz * basis[iz]])
Then let's filter for the rotations, which are the isometries of determinant 1:
def rotations():
return filter(lambda x: numpy.linalg.det(x) > 0, isometries())
Finally, we can apply such a rotation to a polycube by shifting the array indices such that the inner point is the origin, and multiplying the index vector by the rotation matrix:
def rotate(rotation, shape):
shift = numpy.array([1,1,1])
res = numpy.zeros(27).reshape(3,3,3)
it = numpy.nditer(shape, flags=['multi_index'])
while not it.finished:
v = numpy.array(it.multi_index) - shift
w = rotation.dot(v)
dest = tuple(w + shift)
res[dest] = it[0]
it.iternext()
return res
For example:
>>> rotate(list(rotations())[5], polycube)
array([[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 1., 1.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 1., 1., 0.],
[ 1., 1., 0.],
[ 0., 0., 0.]]])