Подтвердить что ты не робот

Как получить все 24 оборота трехмерного массива?

У меня 3-мерный массив. Подумайте об этом как о кирпиче. Существует 24 возможных вращения этого кирпича (которые удерживают его края параллельно координатным осям). Как создать все соответствующие трехмерные массивы?

4b9b3361

Ответ 1

Смерть (половина пары костей) удобна для наблюдения за 24 различными ориентациями и может предлагать последовательности операций для их генерации. Вы увидите, что любая из шести граней может быть самой верхней, а стороны внизу могут быть повернуты в четыре разных кардинальных направления. Обозначим две операции: "поворот" и "рулон", где поворот поворачивает матрицу вокруг оси z от одного кардинального к следующему, а рулон вращает матрицу на 90 ° от вас, так что крайняя сторона становится нижней гранью а ближний край - сверху. Эти операции могут быть выражены с использованием матриц вращения, как указано в ответе Фелипе Лопеса, или могут быть выражены как простые функции, которые при задании (x, y, z) возвращают (-y, x, z) или (x, z, - y) соответственно.

Во всяком случае, если вы поместите штамп с 1 на ближайшую сторону, 2 справа и 3 сверху, вы обнаружите, что следующая последовательность шагов генерирует двенадцать различных ориентаций с 1, 2 или 3 точками сверху: RTTTRTTTRTTT. Затем последовательность RTR выставляет 6, 4, 5, где первоначально были 1, 2, 3, и повторение последовательности RTTTRTTTRTTT генерирует двенадцать ориентаций с 4, 5 или 6 пятнами сверху. Указанная последовательность встроена в следующий код python.

def roll(v): return (v[0],v[2],-v[1])
def turn(v): return (-v[1],v[0],v[2])
def sequence (v):
    for cycle in range(2):
        for step in range(3):  # Yield RTTT 3 times
            v = roll(v)
            yield(v)           #    Yield R
            for i in range(3): #    Yield TTT
                v = turn(v)
                yield(v)
        v = roll(turn(roll(v)))  # Do RTR

p = sequence(( 1, 1, 1))
q = sequence((-1,-1, 1))
for i in sorted(zip(p,q)):
    print i

Обоснование распечатки отсортированного списка преобразованных пар точек двояко: (i) любая ориентация лица может быть задана расположением двух его углов; (ii) тогда легко проверить единственность каждой пары, например, путем вывода трубопровода на uniq.

Вот как начинается сортированный вывод:

((-1, -1, -1), (-1, 1, 1))
((-1, -1, -1), (1, -1, 1))
((-1, -1, -1), (1, 1, -1))
((-1, -1, 1), (-1, 1, -1))
((-1, -1, 1), (1, -1, -1))
((-1, -1, 1), (1, 1, 1))
((-1, 1, -1), (-1, -1, 1))
((-1, 1, -1), (1, -1, -1))
((-1, 1, -1), (1, 1, 1))

Ответ 2

Вы можете использовать матрицы вращения. Вращение 3D-массива вокруг оси x означает, что элемент в позиции (i,j,k) будет отображаться в положение (i,-k,j). Конечно, если ваш массив индексируется 0, вам, вероятно, придется заменить -k на size-1-k или что-то в этом роде.

Аналогично, вращение вокруг оси y отображает (i,j,k) в (k,j,-i). Эти два вращения можно представить в виде матриц. Для вращения по оси x:

|i'|   |1  0  0| |i|
|j'| = |0  0 -1|*|j|
|k'|   |0  1  0| |k|

И для вращения оси y:

|i'|   |0  0  1| |i|
|j'| = |0  1  0|*|j| 
|k'|   |-1 0  0| |k|

Любое общее вращение можно описать как последовательность этих двух поворотов. Применяя два вращения последовательно, просто умножаем матрицы 3x3. Итак, если вы найдете все возможные продукты из них, вы получите 24 матрицы (включая идентификатор), каждая из которых соответствует действительному вращению вашего массива. Немного сложно найти все возможные умножения, потому что они не коммутируют.

Я думаю, вы можете просто скопировать все продукты формы (A^p)*(B^q)*(A^r)*(B^s), где A и B - две матрицы до и p,q,r,s являются их полномочиями и варьируются от 0 до 3 (экспоненциальный A или B до 4 вернет их к единичной матрице).

Выполняя это, вы можете сгенерировать все 24 действительных матрицы вращения и повернуть трехмерный массив с помощью каждого из них, обращая внимание на сдвиг отрицательных индексов, чтобы вы не получали доступ за пределы.

Ответ 3

Пусть X вращается на 90 градусов вокруг оси X, а Y поворачивается на 90 градусов вокруг оси Y, то есть 24 возможных уникальных комбинации (даны все возможные комбинации до 5 вращений, за исключением тех, которые имеют четыре раза одинаковое вращение (например, XXXX, XXXXY) XYYYY и т.д.):

1.  I
2.  X
3.  Y
4.  XX = YXXY
5.  XY
6.  YX
7.  YY = XYYX
8.  XXX = XYXXY = YXXYX = YXYXY = YYXYY
9.  XXY = YXXYY = YYYXX
10. XYX = YXY
11. XYY = XXYYX = YYXXX
12. YXX = XXYYY = YYXXY
13. YYX = XXXYY = XYYXX
14. YYY = XXYXX = XYXYX = XYYXY = YXYYX
15. XXXY
16. XXYX = XYXY = YXYY
17. XXYY = YYXX
18. XYXX = YXYX = YYXY
19. XYYY
20. YXXX
21. YYYX
22. XXXYX = XXYXY = XYXYY = YXYYY
23. XYXXX = YXYXX = YYXYX = YYYXY
24. XYYYX = YXXXY

Конечно, вы можете использовать любые два поворота на 90 градусов вместо X и Y. Например, Y и Z.

Или, если вы также используете Z, поворот на 90 градусов вокруг оси Z, тогда достаточно 4 поворотов:

1.  I
2.  X = YXZ
3.  Y = ZYX
4.  Z = XZY
5.  XX = XYXZ = YXXY = YXYZ = YXZX = YYZZ = YZXZ = ZXXZ = ZZYY
6.  XY = YZ = ZX = XZYX = YXZY = ZYXZ
7.  XZ = XXZY = YXZZ = YYYX = ZYYY
8.  YX = XZZZ = YYXZ = ZYXX = ZZZY
9.  YY = XXZZ = XYYX = YZYX = ZXYX = ZYXY = ZYYZ = ZYZX = ZZXX
10. ZY = XXXZ = XZYY = YXXX = ZZYX
11. ZZ = XXYY = XYZY = XZXY = XZYZ = XZZX = YYXX = YZZY = ZXZY
12. XXX
13. XXY = XYZ = XZX = YZZ = ZXZ
14. XXZ = ZYY
15. XYX = YXY = YYZ = YZX = ZXX
16. XYY = YZY = ZXY = ZYZ = ZZX
17. XZZ = YYX
18. YXX = ZZY
19. YYY
20. ZZZ
21. XXXY = XXYZ = XXZX = XYZZ = XZXZ = YZZZ = ZXZZ = ZYYX
22. XXYX = XYXY = XYYZ = XYZX = XZXX = YXYY = YYZY = YZXY = YZYZ = YZZX = ZXXY = ZXYZ = ZXZX = ZYZZ = ZZXZ
23. XYXX = XZZY = YXYX = YYXY = YYYZ = YYZX = YZXX = ZXXX
24. XYYY = YXXZ = YZYY = ZXYY = ZYZY = ZZXY = ZZYZ = ZZZX

Все эти 24 матрицы существуют из трех векторов столбцов, каждый из которых состоит из двух нулей и минус один или плюс один. В каждом ряду также есть ровно два нуля. Таким образом, они могут быть легко сгенерированы: первый вектор столбца имеет шесть возможностей ((1,0,0), (-1, 0,0), (0, -1, 0), (0,1, 0), (0,0, -1) и (0,0,1)), это соответствует перемещению положительной оси X к положительной или отрицательной оси x, y или z. Вектор второго столбца имеет только четыре возможности, потому что он должен содержать ноль, где первый столбец имеет ненулевое значение. Наконец, у вектора третьего столбца остается только одно место, где его плюс или минус может быть. Это дает 6 * 4 * 2 = 48 матриц, однако половина из них также отражает оригинал (они представляют собой комбинацию зеркала и, возможно, вращения). Следовательно, только 24 являются чистыми вращениями. Матрицы, являющиеся зеркальными операциями, будут иметь определитель, равный -1, определитель чистых вращений равен 1.

Ответ 4

Ответ джеймса Уолдби вдохновляет, и я хочу добавить немного улучшенную версию с двумя петлями for.

Мы знаем, что существует 24 уникальных направления. Я рассчитал это, представив себе кубик: есть 6 возможных вариантов верхней грани и 4 возможных поворота для каждой грани сверху.

Что если мы повторим эту идею? Я думал. Если мы сможем найти способ передвижения по всем 6 граням игральных костей, то нам нужно только наблюдать 4 поворота на каждой грани, и все готово!

Таким образом, я схватил ближайший "кирпичик" (в моем случае, картон Vitasoy) и начал вращаться, чтобы увидеть, что будет самым простым рисунком для посещения всех 6 лиц. Если мы введем дополнительный поворот против часовой стрелки, чтобы наши операции были следующими:

  • Ролл (в фиксированном направлении, например, чтобы лицо, обращенное к вам, теперь поворачивалось вниз)
  • Поверните по часовой стрелке (вдоль фиксированной оси, например, чтобы лицо, обращенное к вам, было повернуто по часовой стрелке, но все еще обращено к вам)
  • Поверните против часовой стрелки (вдоль той же оси, что и последняя)

Затем мы можем посетить все лица, выполнив:

Рулон → Поворот по часовой стрелке → Рулон → Поворот против часовой стрелки → Рулон → Поворот по часовой стрелке → Рулон → Поворот против часовой стрелки → Рулон → Поворот по часовой стрелке → Рулон → Поворот по часовой стрелке

С последним поворотом и поворотом мы вернулись к первоначальной ориентации. Как вы можете видеть, это повторяющаяся последовательность бросков + чередующихся поворотов CW и CCW.

Теперь, если мы расширим это, чтобы включить все повороты каждого лица, которое мы посещаем, это станет:

Рулон → 3 поворота по часовой стрелке → Рулон → 3-кратный поворот против часовой стрелки → Рулон → 3-кратный поворот по часовой стрелке → Рулон → 3-кратный поворот по часовой стрелке → Рулон → 3-кратный поворот по часовой стрелке → Рулон → 3-кратный поворот против часовой стрелки

... и мы вернулись к тому, с чего начали! Это можно перевести в два цикла for (на один меньше!):

def sequence(m):
  for roll_index in range(6):
    m = roll(m)
    yield(m)
    for turn_index in range(3):
      m = turn_cw(m) if roll_index % 2 == 0 else turn_ccw(m)
      yield(m)