在 Python 中绘制 3D 立方体并在 3D 上绘制线

dro*_*hun 5 python matplotlib cube

我知道,对于那些熟悉 Python 的人来说这是小菜一碟的问题。

我有一个 Excel 文件,它看起来像这样:

1 7 5 8 2 4 6 3

1 7 4 6 8 2 5 3

6 1 5 2 8 3 7 4

我的目的是用Python画一个立方体,并根据这些数字的顺序画一条线。注意:数组中没有大于8的数字。

我可以用图片更好地解释。

在此输入图像描述

第一步:

在此输入图像描述

第二步

在此输入图像描述

最后一步:

在此输入图像描述

我需要打印 Excel 中每一行的 3D 立方体的最终版本

我的解决方法

import numpy as np 
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
import matplotlib.pyplot as plt
 
df = pd.read_csv("uniquesolutions.csv",header=None,sep='\t')
myArray = df.values

points = solutionsarray

def connectpoints(x,y,p1,p2):
   x1, x2 = x[p1], x[p2]
   y1, y2 = y[p1], y[p2]
   plt.plot([x1,x2],[y1,y2],'k-')

 # cube[0][0][0] = 1
 # cube[0][0][1] = 2
 # cube[0][1][0] = 3
 # cube[0][1][1] = 4
 # cube[1][0][0] = 5
 # cube[1][0][1] = 6
 # cube[1][1][0] = 7
 # cube[1][1][1] = 8

 for i in range():
     connectpoints(cube[i][i][i],cube[],points[i],points[i+1]) # Confused!



 ax = fig.add_subplot(111, projection='3d')
 # plot sides

 ax.add_collection3d(Poly3DCollection(verts, 
     facecolors='cyan', linewidths=1, edgecolors='r', alpha=.25))

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

plt.show()
Run Code Online (Sandbox Code Playgroud)

在这里的问题中,他们设法用立方体内给出的点画出一些东西。

我尝试使用这个2D连接功能。

最后一个问题:我可以3D打印红线的结果吗?我怎样才能在Python中做到这一点?

nik*_*ost 6

首先,看起来您正在使用pandaswithpd.read_csv而没有导入它。由于您不是在读取标题而只是想要一个值列表,因此仅使用该numpy read函数可能就足够了。

由于我无权访问您的 csv,因此我将顶点列表定义为下面的变量。

vertices = np.zeros([3,8],dtype=int)
vertices[0,:] = [1, 7, 5, 8, 2, 4, 6, 3]
vertices[1,:] = [1, 7, 4, 6, 8, 2, 5, 3]
vertices[2,:] = [6, 1, 5, 2, 8, 3, 7, 4]
vertices = vertices - 1 #(adjust the vertex numbers by one since python starts with zero indexing)
Run Code Online (Sandbox Code Playgroud)

这里我使用 2d numpy 数组来定义顶点。第一个维度,长度为 3,表示顶点列表的数量,第二个维度,长度为 8,表示每个顶点列表。

我从列表中减去 1 vertices,因为我们将使用这个列表来索引另一个数组,而 python 索引从 0 开始,而不是 1。

然后,定义立方体坐标。

# Initialize an array with dimensions 8 by 3
# 8 for each vertex
# -> indices will be vertex1=0, v2=1, v3=2 ...
# 3 for each coordinate
# -> indices will be x=0,y=1,z=1
cube = np.zeros([8,3])

# Define x values
cube[:,0] = [0, 0, 0, 0, 1, 1, 1, 1]
# Define y values
cube[:,1] = [0, 1, 0, 1, 0, 1, 0, 1]
# Define z values
cube[:,2] = [0, 0, 1, 1, 0, 0, 1, 1]
Run Code Online (Sandbox Code Playgroud)

然后初始化绘图。

# First initialize the fig variable to a figure
fig = plt.figure()
# Add a 3d axis to the figure
ax = fig.add_subplot(111, projection='3d')
Run Code Online (Sandbox Code Playgroud)

然后为顶点列表 1 添加红线。您可以通过增加顶点的第一个索引来对其他顶点列表重复此操作。

# Plot first vertex list
ax.plot(cube[vertices[0,:],0],cube[vertices[0,:],1],cube[vertices[0,:],2],color='r-')
# Plot second vertex list
ax.plot(cube[vertices[1,:],0],cube[vertices[1,:],1],cube[vertices[1,:],2],color='r-')
Run Code Online (Sandbox Code Playgroud)

可以通过定义每个面的边缘来添加面。每个面都有一个 numpy 数组。数组中有 5 个顶点,其中边由连续顶点之间的线定义。所以 5 个顶点创建 4 条边。

# Initialize a list of vertex coordinates for each face
# faces = [np.zeros([5,3])]*3
faces = []
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
# Bottom face
faces[0][:,0] = [0,0,1,1,0]
faces[0][:,1] = [0,1,1,0,0]
faces[0][:,2] = [0,0,0,0,0]
# Top face
faces[1][:,0] = [0,0,1,1,0]
faces[1][:,1] = [0,1,1,0,0]
faces[1][:,2] = [1,1,1,1,1]
# Left Face
faces[2][:,0] = [0,0,0,0,0]
faces[2][:,1] = [0,1,1,0,0]
faces[2][:,2] = [0,0,1,1,0]
# Left Face
faces[3][:,0] = [1,1,1,1,1]
faces[3][:,1] = [0,1,1,0,0]
faces[3][:,2] = [0,0,1,1,0]
# front face
faces[4][:,0] = [0,1,1,0,0]
faces[4][:,1] = [0,0,0,0,0]
faces[4][:,2] = [0,0,1,1,0]
# front face
faces[5][:,0] = [0,1,1,0,0]
faces[5][:,1] = [1,1,1,1,1]
faces[5][:,2] = [0,0,1,1,0]
ax.add_collection3d(Poly3DCollection(faces, facecolors='cyan', linewidths=1, edgecolors='k', alpha=.25))
Run Code Online (Sandbox Code Playgroud)

总的来说,它看起来像这样。

import numpy as np
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import matplotlib.pyplot as plt
 
vertices = np.zeros([3,8],dtype=int)
vertices[0,:] = [1, 7, 5, 8, 2, 4, 6, 3]
vertices[1,:] = [1, 7, 4, 6, 8, 2, 5, 3]
vertices[2,:] = [6, 1, 5, 2, 8, 3, 7, 4]
vertices = vertices - 1 #(adjust the indices by one since python starts with zero indexing)

# Define an array with dimensions 8 by 3
# 8 for each vertex
# -> indices will be vertex1=0, v2=1, v3=2 ...
# 3 for each coordinate
# -> indices will be x=0,y=1,z=1
cube = np.zeros([8,3])

# Define x values
cube[:,0] = [0, 0, 0, 0, 1, 1, 1, 1]
# Define y values
cube[:,1] = [0, 1, 0, 1, 0, 1, 0, 1]
# Define z values
cube[:,2] = [0, 0, 1, 1, 0, 0, 1, 1]

# First initialize the fig variable to a figure
fig = plt.figure()
# Add a 3d axis to the figure
ax = fig.add_subplot(111, projection='3d')

# plotting cube
# Initialize a list of vertex coordinates for each face
# faces = [np.zeros([5,3])]*3
faces = []
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
faces.append(np.zeros([5,3]))
# Bottom face
faces[0][:,0] = [0,0,1,1,0]
faces[0][:,1] = [0,1,1,0,0]
faces[0][:,2] = [0,0,0,0,0]
# Top face
faces[1][:,0] = [0,0,1,1,0]
faces[1][:,1] = [0,1,1,0,0]
faces[1][:,2] = [1,1,1,1,1]
# Left Face
faces[2][:,0] = [0,0,0,0,0]
faces[2][:,1] = [0,1,1,0,0]
faces[2][:,2] = [0,0,1,1,0]
# Left Face
faces[3][:,0] = [1,1,1,1,1]
faces[3][:,1] = [0,1,1,0,0]
faces[3][:,2] = [0,0,1,1,0]
# front face
faces[4][:,0] = [0,1,1,0,0]
faces[4][:,1] = [0,0,0,0,0]
faces[4][:,2] = [0,0,1,1,0]
# front face
faces[5][:,0] = [0,1,1,0,0]
faces[5][:,1] = [1,1,1,1,1]
faces[5][:,2] = [0,0,1,1,0]
ax.add_collection3d(Poly3DCollection(faces, facecolors='cyan', linewidths=1, edgecolors='k', alpha=.25))

# plotting lines
ax.plot(cube[vertices[0,:],0],cube[vertices[0,:],1],cube[vertices[0,:],2],color='r')
ax.plot(cube[vertices[1,:],0],cube[vertices[1,:],1],cube[vertices[1,:],2],color='r')
ax.plot(cube[vertices[2,:],0],cube[vertices[2,:],1],cube[vertices[2,:],2],color='r')

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

plt.show()
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望每组线条都有自己的颜色,请替换

ax.plot(cube[vertices[0,:],0],cube[vertices[0,:],1],cube[vertices[0,:],2],color='r')
ax.plot(cube[vertices[1,:],0],cube[vertices[1,:],1],cube[vertices[1,:],2],color='r')
ax.plot(cube[vertices[2,:],0],cube[vertices[2,:],1],cube[vertices[2,:],2],color='r')

Run Code Online (Sandbox Code Playgroud)

colors = ['r','g','b']
for i in range(3):
    ax.plot(cube[vertices[i,:],0],cube[vertices[i,:],1],cube[vertices[i,:],2],color=colors[i])
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 我确实得到了台词,我将图片添加为答案的编辑。我最好的猜测是,如果您正在从 csv 读取顶点,这可能是错误的根源。它们在图片中呈现棕色,但那是因为透明面的效果。我通过复制并粘贴包含所有代码的代码片段创建了这个。 (2认同)