我已经完成了一个可以在python上旋转的立方体,但现在我想为我设置颜色,以便在旋转时识别每个面部。以下代码:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
from numpy import sin, cos
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("auto")
ax.set_autoscale_on(True)
#dibujar cubo
r = [-10, 10]
for s, e in combinations(np.array(list(product(r,r,r))), 2):
if np.sum(np.abs(s-e)) == r[1]-r[0]:
ax.plot3D(*zip(s,e), color="b")
#dibujar punto
#ax.scatter([0],[0],[0],color="g",s=100)
d = [-2, 2]
theta = np.radians(45)
for s, e in combinations(np.array(list(product(d,d,d))), 2):
if np.sum(np.abs(s-e)) == d[1]-d[0]:
s_rotated = [s[0]*cos(theta)-s[1]*sin(theta),
s[0]*sin(theta)+s[1]*cos(theta),
s[2]]
e_rotated = [e[0]*cos(theta)-e[1]*sin(theta),
e[0]*sin(theta)+e[1]*cos(theta),
e[2]]
ax.plot3D(*zip(s_rotated,e_rotated), color="g")
plt.show()
所以我想画一个里面的立方体。 有帮助吗? 谢谢!
答案 0 :(得分:1)
您可以使用补丁。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
from numpy import sin, cos
from matplotlib.patches import Rectangle, Circle, PathPatch
import mpl_toolkits.mplot3d.art3d as art3d
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("auto")
ax.set_autoscale_on(True)
r = [-10, 10]
for s, e in combinations(np.array(list(product(r,r,r))), 2):
if np.sum(np.abs(s-e)) == r[1]-r[0]:
ax.plot3D(*zip(s,e), color="b")
colors = ['b', 'g', 'r', 'c', 'm', 'y']
for i, (z, zdir) in enumerate(product([-2,2], ['x','y','z'])):
side = Rectangle((-2, -2), 4, 4, facecolor=colors[i])
ax.add_patch(side)
art3d.pathpatch_2d_to_3d(side, z=z, zdir=zdir)
plt.show()
如果需要比x-y平面更一般地旋转,可以使用Poly3Dcollection。这只是绘制立方体的顶部和底部。您希望如何生成顶点将取决于您正在做什么的详细信息。
from mpl_toolkits.mplot3d import Axes3D, art3d
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
from numpy import sin, cos
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("auto")
ax.set_autoscale_on(True)
r = [-10, 10]
for s, e in combinations(np.array(list(product(r,r,r))), 2):
if np.sum(np.abs(s-e)) == r[1]-r[0]:
ax.plot3D(*zip(s,e), color="b")
btm = np.array([[-2, -2, -2],
[-2, 2, -2],
[ 2, 2, -2],
[2, -2,-2]])
top = np.array([[-2, -2, 2],
[-2, 2, 2],
[ 2, 2, 2],
[2, -2,2]])
theta = np.radians(45)
rot_mx = np.array([[cos(theta), sin(theta), 0],
[-sin(theta), cos(theta), 0],
[ 0, 0, 1]])
btm = np.dot(btm, rot_mx)
side = art3d.Poly3DCollection([btm])
side.set_color('r')
ax.add_collection3d(side)
top = np.dot(top, rot_mx)
side = art3d.Poly3DCollection([top])
side.set_color('g')
ax.add_collection3d(side)
plt.show()
答案 1 :(得分:0)
由于以下原因,您难以实现的效果:
matplotlib
知道它是一个立方体,因此您需要计算平面中的颜色点。
Matplotlib 3D绘图是将3D数据投影到2D中,这在绘制直线和平面的交点时尤为明显:
当线条在平面下方时看起来不像它,你可以通过设置透明度来避免这种情况,当线条下方的线条alpha
更小。这意味着你需要根据旋转面向观察者的“前向”旋转来计算,这可以交互式地改变!
在matplotlib 3d中无法绘制某些内容,对于2D,您可以使用plt.fill_between
,但此功能不会扩展到3D。
虽然前两个问题理论上可以通过写出立方体的数学,定义平面和相对于观察者的可见性来解决,但最后我真的不知道你将如何解决。基本上你需要在两者之间写填充,这个函数用3D中的阴影多边形填充区域。
有了这个令人沮丧的前景,我可以建议一些替代方案,只需在每个面上添加一些对角线十字架,因为你已经检查了顶点是否在同一条边上,你只需要检查它们是否是对角线,绘图和颜色。< / p>
或转移到图形绘图工具,旨在做这种事情。如果您对乳胶有任何经验,那么试试tikz 3D plotting它将代码与非常漂亮的输出结合起来,尽管它有点像faf。
修改:以下是将crosses
放入多维数据集的方式:
for循环中的if
语句检查点s
和e
之间的距离。由于这样做的方式,它不会检查实际差异,而是检查两者之间有多少向量长度,这可以通过打印np.sum(np.abs(s-e))
来检查,4
返回8
,12
的长度和if
。所以我们希望用两个向量分隔的那些,即我们在另一个elif np.sum(np.abs(s-e))== 2 * (d[1]-d[0]):
s_rotated = [s[0]*cos(theta)-s[1]*sin(theta),
s[0]*sin(theta)+s[1]*cos(theta),
s[2]]
e_rotated = [e[0]*cos(theta)-e[1]*sin(theta),
e[0]*sin(theta)+e[1]*cos(theta),
e[2]]
ax.plot3D(*zip(s_rotated,e_rotated), color="r")
语句中添加
{{1}}
以红色绘制由两个矢量长度分隔的所有点
显然,您希望以不同的颜色绘制每个十字形,这对于当前形式的代码是不可能的。这是因为我们只检查点之间的长度,需要有一种方法来区分不同的点集。
我不确定这样做的最好方法因此会停在这里,在我看来,你需要停止只是运行所有点的组合并实际上正确地标记点。