Построение контура поверхности для заданного значения в трехмерной матричной матрице - PullRequest
4 голосов
/ 22 марта 2019

У меня есть три трехмерные сетки (X, Y, Z), соответствующие координатному пространству XYZ.

У меня также есть трехмерная матрица Numpy A, где A[i,j,k] содержит число с плавающей точкой, связанное с точкой (x,y,z), где x=X[i,j,k], y=Y[i,j,k] и z=Z[i,j,k]. Значения с плавающей запятой непрерывны в пределах A (т. Е. Изменение значения между соседними элементами A обычно невелико).

Есть ли способ построить поверхность, которая соответствует заданному значению с плавающей точкой в ​​A, используя Matplotlib или любой другой графический пакет на основе Python? Например, если задано значение 2.34, мне интересно получить контурную контурную поверхность матрицы A везде, где появляется 2.34 (плюс или минус некоторое отклонение)?

До сих пор мне удалось восстановить координаты xyz всех значений в A, которые находятся в пределах некоторого допуска к целевому значению, а затем создать трехмерный график рассеяния, используя this (код ниже) , Возможно, есть также способ построения поверхности из этих точек?

def clean (A, t, dt):
    # function for making A binary for t+-dt
    # t is the target value I want in the matrix A with tolerance dt
    new_A = np.copy(A)
    new_A[np.logical_and(new_A > t-dt, new_A < t+dt)] = -1
    new_A[new_A != -1] = 0
    new_A[new_A == -1] = 1
    return (new_A)

def get_surface (X, Y, Z, new_A):
    x_vals = []
    y_vals = []
    z_vals = []

    # Retrieve (x,y,z) coordinates of surface
    for i in range(new_A.shape[0]):
        for j in range(new_A.shape[1]):
            for k in range(new_A.shape[2]):
                if new_A[i,j,k] == 1.0:
                    x_vals.append(X[i,j,k])
                    y_vals.append(Y[i,j,k])
                    z_vals.append(Z[i,j,k])

    return (np.array(x_vals), np.array(y_vals), np.array(z_vals))

cleaned_A = clean (A, t=2.5, dt=0.001)
x_f, y_f, z_f = get_surface (X, Y, Z, cleaned_A )

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', aspect='equal')
ax.scatter(x_f, y_f, z_f, color='g', s=1)

Я также пытался ax.plot_trisurf(x_f,y_f,z_f), но это дает мне плохо связанный сюжет. Я предполагаю, что порядок значений в моих массивах мог бы повлиять на это, и в этом случае есть пакет, который может сделать какой-то трехмерный интерполированный график поверхности со случайным упорядочением точек (например, путем минимизации площади поверхности или чего-то подобного ?)

Объект, который меня интересует, является приблизительно сферическим (то есть два z на (x, y)). Кажется, я не могу найти рабочих примеров того, как кто-то триангулировал над закрытой трехмерной поверхностью, но, возможно, я не смотрю в нужных местах.

1 Ответ

1 голос
/ 22 марта 2019

После долгих размышлений, я думаю, что я нашел решение, которое работает (по крайней мере, для сферы - обновит мой ответ, когда я попробую деформации сферы).Большое спасибо за комментарии, которые помогли мне придумать правильный путь.Я в основном использую ConvexHull для триангуляции от scipy.spatial:

from matplotlib.tri import Triangulation
from scipy.spatial import ConvexHull

def clean (A, t, dt):
    # function for making A binary for t+-dt
    # t is the target value I want in the matrix A with tolerance dt
    new_A = np.copy(A)
    new_A[np.logical_and(new_A > t-dt, new_A < t+dt)] = -1
    new_A[new_A != -1] = 0
    new_A[new_A == -1] = 1
    return (new_A)

def get_surface (X, Y, Z, new_A):
    x_vals = []
    y_vals = []
    z_vals = []

    # Retrieve (x,y,z) coordinates of surface
    for i in range(new_A.shape[0]):
        for j in range(new_A.shape[1]):
            for k in range(new_A.shape[2]):
                if new_A[i,j,k] == 1.0:
                    x_vals.append(X[i,j,k])
                    y_vals.append(Y[i,j,k])
                    z_vals.append(Z[i,j,k])

    return (np.array(x_vals), np.array(y_vals), np.array(z_vals))

cleaned_A = clean (A, t=2.5, dt=0.001)
x_f, y_f, z_f = get_surface (X, Y, Z, cleaned_A )

Xs = np.vstack((x_f, y_f, z_f)).T
hull = ConvexHull(Xs)
x, y, z = Xs.T

tri = Triangulation(x, y, triangles=hull.simplices)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', aspect='equal')
ax.plot_trisurf(tri, z, color='g', alpha=0.1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...