Если у вас есть сетка в виде ndim+1
-мерного массива координат, например,
a = np.stack(np.mgrid[1:5, 1:5], -1)
, тогда это просто вопрос разумного изменения формы и транспонирования:
import itertools as it
# dimensions for reshape:
# split all coordinate axes into groups of two, leave the
# "dimension subscript" axis alone
chop = *it.chain.from_iterable((i//2, 2) for i in a.shape[:-1]),
# shuffle for transpose:
# regroup axes into coordinates then pairs then subscript
ax_shuf = *(1 ^ np.r_[1:4*a.ndim-3:2] % (2*a.ndim-1)), -1
# put it together and flatten, i.e. join coordinates and join pairs
a.reshape(*chop, -1).transpose(*ax_shuf).reshape(np.prod(chop[::2]), -1, a.shape[-1])
Результат:
array([[[1, 1],
[1, 2],
[2, 1],
[2, 2]],
[[1, 3],
[1, 4],
[2, 3],
[2, 4]],
[[3, 1],
[3, 2],
[4, 1],
[4, 2]],
[[3, 3],
[3, 4],
[4, 3],
[4, 4]]])
Обновление
Если B - неупорядоченное подмножество полной сетки, вы можете выполнить следующий трюк:
- вычтите минимум по столбцу, чтобы убедиться, что четность начинается с четного
- деления этажа на 2, углы каждого интересующего куба свернутся в одну точку
- , теперь используйте np.unique в строках, чтобыget goups
Примечание. При необходимости вы можете сделать это немного быстрее, заменив argsort
в приведенном ниже коде одним из решений на Самый эффективный способ сортировки массива вкорзины, заданные индексным массивом? .
B = np.array(B)
unq, idx, cts = np.unique((B-B.min(0))//2, axis=0, return_inverse=True, return_counts=True)
if (cts[0]==cts).all():
result = B[idx.argsort()].reshape(len(unq), cts[0], -1)
else:
result = np.split(B[idx.argsort()], cts[:-1].cumsum())
Результат:
array([[[1, 1, 1],
[1, 2, 1],
[2, 2, 1],
[2, 2, 2],
[2, 1, 2],
[1, 1, 2]],
[[2, 2, 3],
[2, 1, 3],
[1, 1, 3],
[2, 1, 4],
[2, 2, 4],
[1, 2, 4]],
[[1, 4, 2],
[2, 4, 2],
[1, 3, 1],
[1, 4, 1],
[2, 3, 1],
[2, 4, 1]],
[[1, 4, 4],
[1, 3, 4],
[2, 4, 3],
[2, 3, 3],
[1, 4, 3],
[2, 3, 4]],
[[4, 1, 1],
[4, 1, 2],
[3, 2, 1],
[3, 2, 2],
[4, 2, 2],
[3, 1, 2]],
[[4, 2, 3],
[3, 2, 4],
[3, 1, 3],
[3, 2, 3],
[3, 1, 4],
[4, 1, 3]],
[[4, 4, 2],
[4, 3, 2],
[3, 4, 2],
[4, 3, 1],
[3, 4, 1],
[3, 3, 1]],
[[4, 3, 3],
[3, 3, 3],
[4, 3, 4],
[3, 3, 4],
[4, 4, 3],
[4, 4, 4]]])