Python 绘制平行六面体

Python 绘制平行六面体,python,matplotlib,3d,mplot3d,Python,Matplotlib,3d,Mplot3d,我想画一个平行六面体。实际上,我是从python脚本开始画一个立方体的: import numpy as np from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt points = np.array([[-1, -1, -1], [1, -1, -1 ], [1, 1, -1], [-1, 1,

我想画一个平行六面体。实际上,我是从python脚本开始画一个立方体的:

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

points = np.array([[-1, -1, -1],
                  [1, -1, -1 ],
                  [1, 1, -1],
                  [-1, 1, -1],
                  [-1, -1, 1],
                  [1, -1, 1 ],
                  [1, 1, 1],
                  [-1, 1, 1]])


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

r = [-1,1]

X, Y = np.meshgrid(r, r)

ax.plot_surface(X,Y,1, alpha=0.5)
ax.plot_surface(X,Y,-1, alpha=0.5)
ax.plot_surface(X,-1,Y, alpha=0.5)
ax.plot_surface(X,1,Y, alpha=0.5)
ax.plot_surface(1,X,Y, alpha=0.5)
ax.plot_surface(-1,X,Y, alpha=0.5)

ax.scatter3D(points[:, 0], points[:, 1], points[:, 2])

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()
为了得到平行六面体,我将点矩阵乘以以下矩阵:

P = 

[[2.06498904e-01  -6.30755443e-07   1.07477548e-03]

 [1.61535574e-06   1.18897198e-01   7.85307721e-06]

 [7.08353661e-02   4.48415767e-06   2.05395893e-01]]
作为:

我的想法如下:

ax.scatter3D(Z[:, 0], Z[:, 1], Z[:, 2])

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()
这就是我得到的:


然后如何将曲面放置在这些不同的点上以形成平行六面体(以上面的立方体的方式)?

使用3D多集合()绘制曲面


鉴于这个问题的标题是“python绘制3D立方体”,这是我在谷歌搜索该问题时发现的文章

对于那些和我一样只想画一个立方体的人,我创建了以下函数,它取立方体的四个点,首先是一个角,然后是该角的三个相邻点

然后绘制立方体

功能如下:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

def plot_cube(cube_definition):
    cube_definition_array = [
        np.array(list(item))
        for item in cube_definition
    ]

    points = []
    points += cube_definition_array
    vectors = [
        cube_definition_array[1] - cube_definition_array[0],
        cube_definition_array[2] - cube_definition_array[0],
        cube_definition_array[3] - cube_definition_array[0]
    ]

    points += [cube_definition_array[0] + vectors[0] + vectors[1]]
    points += [cube_definition_array[0] + vectors[0] + vectors[2]]
    points += [cube_definition_array[0] + vectors[1] + vectors[2]]
    points += [cube_definition_array[0] + vectors[0] + vectors[1] + vectors[2]]

    points = np.array(points)

    edges = [
        [points[0], points[3], points[5], points[1]],
        [points[1], points[5], points[7], points[4]],
        [points[4], points[2], points[6], points[7]],
        [points[2], points[6], points[3], points[0]],
        [points[0], points[2], points[4], points[1]],
        [points[3], points[6], points[7], points[5]]
    ]

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

    faces = Poly3DCollection(edges, linewidths=1, edgecolors='k')
    faces.set_facecolor((0,0,1,0.1))

    ax.add_collection3d(faces)

    # Plot the points themselves to force the scaling of the axes
    ax.scatter(points[:,0], points[:,1], points[:,2], s=0)

    ax.set_aspect('equal')


cube_definition = [
    (0,0,0), (0,1,0), (1,0,0), (0,0,1)
]
plot_cube(cube_definition)
给出结果:

有关更简单的解决方案,请参阅我的其他答案()

下面是一组更复杂的函数,这些函数使matplotlib的缩放效果更好,并始终强制输入为立方体

传递给cubify_cube_定义的第一个参数是起点,第二个参数是第二个点,立方体长度是从该点定义的,第三个是旋转点,它将移动以匹配第一个和第二个点的长度

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

def cubify_cube_definition(cube_definition):
    cube_definition_array = [
        np.array(list(item))
        for item in cube_definition
    ]
    start = cube_definition_array[0]
    length_decider_vector = cube_definition_array[1] - cube_definition_array[0]   
    length = np.linalg.norm(length_decider_vector)

    rotation_decider_vector = (cube_definition_array[2] - cube_definition_array[0])
    rotation_decider_vector = rotation_decider_vector / np.linalg.norm(rotation_decider_vector) * length

    orthogonal_vector = np.cross(length_decider_vector, rotation_decider_vector)
    orthogonal_vector = orthogonal_vector / np.linalg.norm(orthogonal_vector) * length

    orthogonal_length_decider_vector = np.cross(rotation_decider_vector, orthogonal_vector)
    orthogonal_length_decider_vector = (
        orthogonal_length_decider_vector / np.linalg.norm(orthogonal_length_decider_vector) * length)

    final_points = [
        tuple(start),
        tuple(start + orthogonal_length_decider_vector),
        tuple(start + rotation_decider_vector),
        tuple(start + orthogonal_vector)        
    ]

    return final_points


def cube_vertices(cube_definition):
    cube_definition_array = [
        np.array(list(item))
        for item in cube_definition
    ]

    points = []
    points += cube_definition_array
    vectors = [
        cube_definition_array[1] - cube_definition_array[0],
        cube_definition_array[2] - cube_definition_array[0],
        cube_definition_array[3] - cube_definition_array[0]
    ]

    points += [cube_definition_array[0] + vectors[0] + vectors[1]]
    points += [cube_definition_array[0] + vectors[0] + vectors[2]]
    points += [cube_definition_array[0] + vectors[1] + vectors[2]]
    points += [cube_definition_array[0] + vectors[0] + vectors[1] + vectors[2]]

    points = np.array(points)

    return points


def get_bounding_box(points): 
    x_min = np.min(points[:,0])
    x_max = np.max(points[:,0])
    y_min = np.min(points[:,1])
    y_max = np.max(points[:,1])
    z_min = np.min(points[:,2])
    z_max = np.max(points[:,2])

    max_range = np.array(
        [x_max-x_min, y_max-y_min, z_max-z_min]).max() / 2.0

    mid_x = (x_max+x_min) * 0.5
    mid_y = (y_max+y_min) * 0.5
    mid_z = (z_max+z_min) * 0.5

    return [
        [mid_x - max_range, mid_x + max_range],
        [mid_y - max_range, mid_y + max_range],
        [mid_z - max_range, mid_z + max_range]
    ]


def plot_cube(cube_definition):
    points = cube_vertices(cube_definition)

    edges = [
        [points[0], points[3], points[5], points[1]],
        [points[1], points[5], points[7], points[4]],
        [points[4], points[2], points[6], points[7]],
        [points[2], points[6], points[3], points[0]],
        [points[0], points[2], points[4], points[1]],
        [points[3], points[6], points[7], points[5]]
    ]

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

    faces = Poly3DCollection(edges, linewidths=1, edgecolors='k')
    faces.set_facecolor((0,0,1,0.1))

    ax.add_collection3d(faces)

    bounding_box = get_bounding_box(points)

    ax.set_xlim(bounding_box[0])
    ax.set_ylim(bounding_box[1])
    ax.set_zlim(bounding_box[2])

    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.set_aspect('equal')


cube_definition = cubify_cube_definition([(0,0,0), (0,3,0), (1,1,0.3)])
plot_cube(cube_definition)
这将产生以下结果:


使用matplotlib和坐标几何图形完成

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


def cube_coordinates(edge_len,step_size):
    X = np.arange(0,edge_len+step_size,step_size)
    Y = np.arange(0,edge_len+step_size,step_size)
    Z = np.arange(0,edge_len+step_size,step_size)
    temp=list()
    for i in range(len(X)):
        temp.append((X[i],0,0))
        temp.append((0,Y[i],0))
        temp.append((0,0,Z[i]))
        temp.append((X[i],edge_len,0))
        temp.append((edge_len,Y[i],0))
        temp.append((0,edge_len,Z[i]))
        temp.append((X[i],edge_len,edge_len))
        temp.append((edge_len,Y[i],edge_len))
        temp.append((edge_len,edge_len,Z[i]))
        temp.append((edge_len,0,Z[i]))
        temp.append((X[i],0,edge_len))
        temp.append((0,Y[i],edge_len))
    return temp


edge_len = 10


A=cube_coordinates(edge_len,0.01)
A=list(set(A))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
A=zip(*A)
X,Y,Z=list(A[0]),list(A[1]),list(A[2])
ax.scatter(X,Y,Z,c='g')

plt.show()

有没有办法将这个立方体粘贴到现有的2D图像上?我喜欢这个。请务必注意,您需要主动管理轴比例限制,以保持形状的比例完整性。例如,如果将此立方体示例的x平面的长度增加到2(y和z平面的两倍),Matplotlib仍将以立方体的形式进行可视化打印。必须强制x、y和z轴比例匹配(全部设置为2.0),才能按比例渲染形状。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

def cubify_cube_definition(cube_definition):
    cube_definition_array = [
        np.array(list(item))
        for item in cube_definition
    ]
    start = cube_definition_array[0]
    length_decider_vector = cube_definition_array[1] - cube_definition_array[0]   
    length = np.linalg.norm(length_decider_vector)

    rotation_decider_vector = (cube_definition_array[2] - cube_definition_array[0])
    rotation_decider_vector = rotation_decider_vector / np.linalg.norm(rotation_decider_vector) * length

    orthogonal_vector = np.cross(length_decider_vector, rotation_decider_vector)
    orthogonal_vector = orthogonal_vector / np.linalg.norm(orthogonal_vector) * length

    orthogonal_length_decider_vector = np.cross(rotation_decider_vector, orthogonal_vector)
    orthogonal_length_decider_vector = (
        orthogonal_length_decider_vector / np.linalg.norm(orthogonal_length_decider_vector) * length)

    final_points = [
        tuple(start),
        tuple(start + orthogonal_length_decider_vector),
        tuple(start + rotation_decider_vector),
        tuple(start + orthogonal_vector)        
    ]

    return final_points


def cube_vertices(cube_definition):
    cube_definition_array = [
        np.array(list(item))
        for item in cube_definition
    ]

    points = []
    points += cube_definition_array
    vectors = [
        cube_definition_array[1] - cube_definition_array[0],
        cube_definition_array[2] - cube_definition_array[0],
        cube_definition_array[3] - cube_definition_array[0]
    ]

    points += [cube_definition_array[0] + vectors[0] + vectors[1]]
    points += [cube_definition_array[0] + vectors[0] + vectors[2]]
    points += [cube_definition_array[0] + vectors[1] + vectors[2]]
    points += [cube_definition_array[0] + vectors[0] + vectors[1] + vectors[2]]

    points = np.array(points)

    return points


def get_bounding_box(points): 
    x_min = np.min(points[:,0])
    x_max = np.max(points[:,0])
    y_min = np.min(points[:,1])
    y_max = np.max(points[:,1])
    z_min = np.min(points[:,2])
    z_max = np.max(points[:,2])

    max_range = np.array(
        [x_max-x_min, y_max-y_min, z_max-z_min]).max() / 2.0

    mid_x = (x_max+x_min) * 0.5
    mid_y = (y_max+y_min) * 0.5
    mid_z = (z_max+z_min) * 0.5

    return [
        [mid_x - max_range, mid_x + max_range],
        [mid_y - max_range, mid_y + max_range],
        [mid_z - max_range, mid_z + max_range]
    ]


def plot_cube(cube_definition):
    points = cube_vertices(cube_definition)

    edges = [
        [points[0], points[3], points[5], points[1]],
        [points[1], points[5], points[7], points[4]],
        [points[4], points[2], points[6], points[7]],
        [points[2], points[6], points[3], points[0]],
        [points[0], points[2], points[4], points[1]],
        [points[3], points[6], points[7], points[5]]
    ]

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

    faces = Poly3DCollection(edges, linewidths=1, edgecolors='k')
    faces.set_facecolor((0,0,1,0.1))

    ax.add_collection3d(faces)

    bounding_box = get_bounding_box(points)

    ax.set_xlim(bounding_box[0])
    ax.set_ylim(bounding_box[1])
    ax.set_zlim(bounding_box[2])

    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.set_aspect('equal')


cube_definition = cubify_cube_definition([(0,0,0), (0,3,0), (1,1,0.3)])
plot_cube(cube_definition)
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np


def cube_coordinates(edge_len,step_size):
    X = np.arange(0,edge_len+step_size,step_size)
    Y = np.arange(0,edge_len+step_size,step_size)
    Z = np.arange(0,edge_len+step_size,step_size)
    temp=list()
    for i in range(len(X)):
        temp.append((X[i],0,0))
        temp.append((0,Y[i],0))
        temp.append((0,0,Z[i]))
        temp.append((X[i],edge_len,0))
        temp.append((edge_len,Y[i],0))
        temp.append((0,edge_len,Z[i]))
        temp.append((X[i],edge_len,edge_len))
        temp.append((edge_len,Y[i],edge_len))
        temp.append((edge_len,edge_len,Z[i]))
        temp.append((edge_len,0,Z[i]))
        temp.append((X[i],0,edge_len))
        temp.append((0,Y[i],edge_len))
    return temp


edge_len = 10


A=cube_coordinates(edge_len,0.01)
A=list(set(A))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
A=zip(*A)
X,Y,Z=list(A[0]),list(A[1]),list(A[2])
ax.scatter(X,Y,Z,c='g')

plt.show()