Разделение Python MeshGrid на ячейки - PullRequest
0 голосов
/ 09 декабря 2018

Постановка задачи

Необходимо разделить N-мерную сетку на «кубики»:

Ex) Двумерный случай:

(-1,1) | (0,1) | (1,1)

(- 1,0) | (0,0) | (1,0)

(- 1, -1) | (0, -1) | (1, -1)

Будет 4 ячейки, каждая с 2 ^ D точками:

Я хочу иметь возможность обрабатыватьсетка, помещая точки координат каждой ячейки в контейнер для дальнейшей обработки.

Cells =   [{(-1,1) (0,1)(-1,0),(0,0)},

          {(0,1),(1,1),(0,0),(1,0)},

          {(-1,0),(0,0)(-1,-1),(0,-1)}

          {(0,0),(1,0)(0,-1),(1,-1)}]

Я использую следующее для генерации сетки для произвольного измерения d:

grid = [np.linspace(-1.0 , 1.0, num = K+1) for i in range(d)]
res_to_unpack = np.meshgrid(*grid,indexing = 'ij')

Который имеет вывод:

[array([[-1., -1., -1.],
   [ 0.,  0.,  0.],
   [ 1.,  1.,  1.]]), array([[-1.,  0.,  1.],
   [-1.,  0.,  1.],
   [-1.,  0.,  1.]])]

Так что я хочу иметь возможность генерировать вышеупомянутый контейнер ячеек для данной D-мерной сетки.Разделить на заданное K, которое является степенью 2.

Мне нужен этот контейнер, поэтому для каждой ячейки мне нужно сослаться на все 2 ^ D связанные точки и вычислить расстояние от начала координат.

Редактировать для уточнения

K должен разделить сетку на K ** D количество ячеек с (K + 1) ** D точками.Каждая ячейка должна иметь 2 ** D количества очков.Каждая «клетка» будет иметь объем (2 / К) ^ D.

То есть, для K = 4, D = 2

Cells = [ {(-1,1),(-0.5,1),(-1,0.5),(-0.5,0.5)},
          {(-0.5,1),(-0.5,0.5)(0.0,1.0),(0,0.5)},
            ...
          {(0.0,-0.5),(0.5,-0.5),(0.0,-1.0),(0.5,-1.0)},
          {(0.5,-1.0),(0.5,-1.0),(1.0,-0.5),(1.0,-1.0)}]

Это вывод для TopLeft, TopLeft + Right Over, Bottom Left, Bottom Left + Over Left.В этом наборе будет 16 ячеек, каждая с четырьмя координатами каждая.Для увеличения K, скажем, K = 8. Будет 64 ячейки, каждая с четырьмя точками.

1 Ответ

0 голосов
/ 09 декабря 2018

Это должно дать вам то, что вам нужно:

from itertools import product
import numpy as np

def splitcubes(K, d):
    coords = [np.linspace(-1.0 , 1.0, num=K + 1) for i in range(d)]
    grid = np.stack(np.meshgrid(*coords)).T

    ks = list(range(1, K))
    for slices in product(*([[slice(b,e) for b,e in zip([None] + ks, [k+1 for k in ks] + [None])]]*d)):
        yield grid[slices]

def cubesets(K, d):
    if (K & (K - 1)) or K < 2:
        raise ValueError('K must be a positive power of 2. K: %s' % K)

    return [set(tuple(p.tolist()) for p in c.reshape(-1, d)) for c in splitcubes(K, d)]

Демонстрация 2D-кейса

Вот небольшая демонстрация 2D-кейса:

import matplotlib.pyplot as plt

def assemblecube(c, spread=.03):
    c = np.array(list(c))
    c = c[np.lexsort(c.T[::-1])]

    d = int(np.log2(c.size))
    for i in range(d):
        c[2**i:2**i + 2] = c[2**i + 1:2**i - 1:-1]

    # get the point farthest from the origin
    sp = c[np.argmax((c**2).sum(axis=1)**.5)]
    # shift all points a small distance towards that farthest point
    c += sp * .1 #np.copysign(np.ones(sp.size)*spread, sp)

    # create several different orderings of the same points so that matplotlib will draw a closed shape
    return [(np.roll(c, i, axis=1) - (np.roll(c, i, axis=1)[0] - c[0])[None,:]).T for i in range(d)]

fig = plt.figure(figsize=(6,6))
ax = fig.gca()

for i,c in enumerate(cubesets(4, 2)):
    for cdata in assemblecube(c):
        p = ax.plot(*cdata, c='C%d' % (i % 9))

ax.set_aspect('equal', 'box')
fig.show()

Вывод:

enter image description here

Кубы были немного смещены в целях визуализации (чтобы они не перекрывали друг друга и не перекрывали друг друга).

Демонстрация трехмерного корпуса

Вот то же самое для трехмерного корпуса:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(111, projection='3d')

for i,c in enumerate(cubesets(2,3)):
    for cdata in assemblecube(c, spread=.05):
        ax.plot(*cdata, c=('C%d' % (i % 9)))

plt.gcf().gca().set_aspect('equal', 'box')
plt.show()

Выход:

enter image description here

Демонстрация для K=4

Вот выходные данные для тех же 2D и 3D демонстраций, что и выше, но с K=4:

enter image description here

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...