Исходя из вашего вопроса, я не совсем уверен, как разные линии должны быть выровнены относительно друг друга, но я предоставлю вам следующий небольшой скрипт, который в любом случае должен послужить отправной точкой.Для поворота вы можете использовать rotate
из пакета scipy.
import matplotlib.pyplot as plt
import numpy as np
from scipy.ndimage import rotate
np.random.seed(181003)
N = 100 # Number of images.
m, n = 100, 100 # row and column dimension.
test = np.random.uniform(0, 1, (N, m, n))
def create_bars(d):
"""Parameter d indicates thickness of the bar in number of rows"""
bars = np.zeros((N, m, n), dtype=float)
bars[:, m//2 - d : m//2 + d, :] = np.random.uniform(0.95, 1.0, (N, 2*d, n))
for i, angle in enumerate(np.random.uniform(0, 180, N)): # Angle in degrees.
bars[i, :, :] = rotate(bars[i], angle, reshape=False)
return bars
test += create_bars(m // 5) # Thick bars.
test += create_bars(m // 25) # Thin bars.
for i in range(3):
plt.figure()
plt.imshow(test[i])
plt.show()
Из следующих примеров изображений вы можете видеть, что область перекрытия имеет большую интенсивность, чем остальные столбцы,Если это нежелательно, необходимо создать галочку и тонкие полосы, и можно позаботиться об области перекрытия.
![Example](https://i.stack.imgur.com/2TGQH.png)
Редактировать на основе обновленияOP
Мы можем сгенерировать плоскость и цилиндр с помощью соответствующих индексов для трехмерного массива.Мы можем повернуть эти индексы, чтобы получить новые индексы для повернутых фигур (нам нужно отцентрировать индексы перед вращением, а затем снова сдвинуть назад).Вот пример кода:
"""Coordinate system is z, y, x for indexing the 3D array (i.e. test[z, y, x])."""
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def rotate_z(angle):
return np.array([
[1, 0, 0],
[0, np.cos(angle), -np.sin(angle)],
[0, np.sin(angle), np.cos(angle)],
])
def rotate_y(angle):
return np.array([
[np.cos(angle), 0, np.sin(angle)],
[0, 1, 0],
[-np.sin(angle), 0, np.cos(angle)],
])
def rotate_x(angle):
return np.array([
[np.cos(angle), -np.sin(angle), 0],
[np.sin(angle), np.cos(angle), 0],
[0, 0, 1],
])
l = m = n = 40 # Use only small number of points due to plotting.
test = np.random.uniform(0, 0.95, (l, m, n))
d = l // 10 # Thickness of plane.
i_thick = np.array([*np.ndindex(d, m, n)]).T # Indices for plane.
i_thick[0, :] -= d // 2
i_thick[1, :] -= m // 2
i_thick[2, :] -= n // 2
angle_y = angle_x = 0 # Angles about which the plane is rotated.
i_thick = rotate_y(angle_y) @ i_thick
i_thick = rotate_x(angle_x) @ i_thick
i_thick[0, :] += d // 2 + l // 2
i_thick[1, :] += m // 2
i_thick[2, :] += n // 2
i_thick = np.clip(np.round(i_thick).astype(int), 0, np.array(test.shape)[:, None] - 1) # Correct rounding errors.
test[i_thick.tolist()] = np.random.uniform(0.95, 1.0, i_thick.shape[1]) # Add the plane.
r = m // 8 # Radius of cylinder.
i_cylinder = np.array([*np.ndindex(l, m, n)])
i_cylinder = i_cylinder[
(i_cylinder[:, 0] < l // 2)
& (np.sqrt((i_cylinder[:, 1] - m // 2)**2 + (i_cylinder[:, 2] - n // 2)**2) < r)
].T
i_cylinder[0, :] -= l // 2
i_cylinder[1, :] -= m // 2
i_cylinder[2, :] -= n // 2
# Align cylinder with plane.
i_cylinder = rotate_y(angle_y) @ i_cylinder
i_cylinder = rotate_x(angle_x) @ i_cylinder
angle2_z = angle2_y = angle2_x = 0 # Angles about which the cylinder is rotated.
i_cylinder = rotate_z(angle2_z) @ i_cylinder
i_cylinder = rotate_y(angle2_y) @ i_cylinder
i_cylinder = rotate_x(angle2_x) @ i_cylinder
i_cylinder[0, :] += l // 2
i_cylinder[1, :] += m // 2
i_cylinder[2, :] += n // 2
i_cylinder = np.clip(np.round(i_cylinder).astype(int), 0, np.array(test.shape)[:, None] - 1)
test[i_cylinder.tolist()] = np.random.uniform(0.95, 1.0, i_cylinder.shape[1])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
test_plot = test.copy()
test_plot = np.moveaxis(test_plot, [0, 1, 2], [-1, 0, 1]) # Reorder axes from `z, y, x` to `y, x, z` in order to be aligned with plt.scatter.
test_plot = np.flip(test_plot, axis=2) # Flip along `z` in order to plot top-to-bottom rather than bottom-to-top.
ax.scatter(*np.array([*np.ndindex(m, n, l)]).T[:, test_plot.ravel() >= 0.95].tolist(), s=1)
ax.set_xlim([0, test.shape[1] - 1])
ax.set_ylim([0, test.shape[0] - 1])
ax.set_zlim([0, test.shape[2] - 1])
plt.show()
Например, обе фигуры не повернуты:
![Example 3D no rotation](https://i.stack.imgur.com/rGLBK.png)
Другой пример для плоскости, вращающейся вокруг x
на -pi/2
и цилиндр дополнительно вращается вокруг z
и x
на pi/8
:
![Example 3D with rotation](https://i.stack.imgur.com/o223a.png)