如何使用 matplotlib or/and 离线绘制由顶点定义的 3D 多面体?
How to visualize polyhedrons defined by their vertices in 3D with matplotlib or/and plotly offline?
我想可视化由 3 个形状为 (8, 3) 的 numpy 数组定义的 3 个多面体。
我正在寻找类似的东西:
我的数据如下:
A = np.array([[0.92523719, 0.26843252, 0.77794309],
[0.73156748, 0.27794309, 0.57476281],
[0.62113842, 0.37886158, 0.87886158],
[0.72205691, 0.07476281, 0.76843252],
[0.57476281, 0.23156748, 0.72205691],
[0.77794309, 0.42523719, 0.73156748],
[0.87886158, 0.12113842, 0.62113842],
[0.76843252, 0.22205691, 0.92523719]])
B = np.array([[0.23156748, 0.72205691, 0.57476281],
[0.26843252, 0.77794309, 0.92523719],
[0.12113842, 0.62113842, 0.87886158],
[0.22205691, 0.92523719, 0.76843252],
[0.27794309, 0.57476281, 0.73156748],
[0.37886158, 0.87886158, 0.62113842],
[0.07476281, 0.76843252, 0.72205691],
[0.42523719, 0.73156748, 0.77794309]])
C = np.array([[0.73156748, 0.77794309, 0.42523719],
[0.62113842, 0.87886158, 0.12113842],
[0.77794309, 0.92523719, 0.26843252],
[0.57476281, 0.73156748, 0.27794309],
[0.87886158, 0.62113842, 0.37886158],
[0.72205691, 0.57476281, 0.23156748],
[0.76843252, 0.72205691, 0.07476281],
[0.92523719, 0.76843252, 0.22205691]])
您似乎有 3D 点,但没有边或多边形信息。假设多面体是凸的,scipy.spatial
的ConvexHull
可以找到凸包上的所有多边形。凸包存在三角形,可以作为 Poly3DCollection
.
添加到 3D 图
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull
A = np.array([[0.92523719, 0.26843252, 0.77794309], [0.73156748, 0.27794309, 0.57476281], [0.62113842, 0.37886158, 0.87886158], [0.72205691, 0.07476281, 0.76843252], [0.57476281, 0.23156748, 0.72205691], [0.77794309, 0.42523719, 0.73156748], [0.87886158, 0.12113842, 0.62113842], [0.76843252, 0.22205691, 0.92523719]])
B = np.array([[0.23156748, 0.72205691, 0.57476281], [0.26843252, 0.77794309, 0.92523719], [0.12113842, 0.62113842, 0.87886158], [0.22205691, 0.92523719, 0.76843252], [0.27794309, 0.57476281, 0.73156748], [0.37886158, 0.87886158, 0.62113842], [0.07476281, 0.76843252, 0.72205691], [0.42523719, 0.73156748, 0.77794309]])
C = np.array([[0.73156748, 0.77794309, 0.42523719], [0.62113842, 0.87886158, 0.12113842], [0.77794309, 0.92523719, 0.26843252], [0.57476281, 0.73156748, 0.27794309], [0.87886158, 0.62113842, 0.37886158], [0.72205691, 0.57476281, 0.23156748], [0.76843252, 0.72205691, 0.07476281], [0.92523719, 0.76843252, 0.22205691]])
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
for cube, color in zip([A, B, C], ['r', 'g', 'b']):
hull = ConvexHull(cube)
# draw the polygons of the convex hull
for s in hull.simplices:
tri = Poly3DCollection(cube[s])
tri.set_color(color)
tri.set_alpha(0.5)
ax.add_collection3d(tri)
# draw the vertices
ax.scatter(cube[:, 0], cube[:, 1], cube[:, 2], marker='o', color='purple')
plt.show()
假设每个三角形的最长边是立方体的一条面对角线,我们可以搜索最短的两条边画成黑色:
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull, distance
A = np.array([[0.92523719, 0.26843252, 0.77794309], [0.73156748, 0.27794309, 0.57476281], [0.62113842, 0.37886158, 0.87886158], [0.72205691, 0.07476281, 0.76843252], [0.57476281, 0.23156748, 0.72205691], [0.77794309, 0.42523719, 0.73156748], [0.87886158, 0.12113842, 0.62113842], [0.76843252, 0.22205691, 0.92523719]])
B = np.array([[0.23156748, 0.72205691, 0.57476281], [0.26843252, 0.77794309, 0.92523719], [0.12113842, 0.62113842, 0.87886158], [0.22205691, 0.92523719, 0.76843252], [0.27794309, 0.57476281, 0.73156748], [0.37886158, 0.87886158, 0.62113842], [0.07476281, 0.76843252, 0.72205691], [0.42523719, 0.73156748, 0.77794309]])
C = np.array([[0.73156748, 0.77794309, 0.42523719], [0.62113842, 0.87886158, 0.12113842], [0.77794309, 0.92523719, 0.26843252], [0.57476281, 0.73156748, 0.27794309], [0.87886158, 0.62113842, 0.37886158], [0.72205691, 0.57476281, 0.23156748], [0.76843252, 0.72205691, 0.07476281], [0.92523719, 0.76843252, 0.22205691]])
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
for cube, color in zip([A, B, C], ['r', 'g', 'b']):
hull = ConvexHull(cube)
for s in hull.simplices:
tri = Poly3DCollection(cube[s])
tri.set_color(color)
tri.set_alpha(0.5)
tri.set_edgecolor('none')
ax.add_collection3d(tri)
edges = []
if distance.euclidean(cube[s[0]], cube[s[1]]) < distance.euclidean(cube[s[1]], cube[s[2]]):
edges.append((s[0], s[1]))
if distance.euclidean(cube[s[1]], cube[s[2]]) < distance.euclidean(cube[s[2]], cube[s[0]]):
edges.append((s[1], s[2]))
else:
edges.append((s[2], s[0]))
else:
edges.append((s[1], s[2]))
if distance.euclidean(cube[s[0]], cube[s[1]]) < distance.euclidean(cube[s[2]], cube[s[0]]):
edges.append((s[0], s[1]))
else:
edges.append((s[2], s[0]))
for v0, v1 in edges:
ax.plot(xs=cube[[v0, v1], 0], ys=cube[[v0, v1], 1], zs=cube[[v0, v1], 2], color='black')
ax.scatter(cube[:, 0], cube[:, 1], cube[:, 2], marker='o', color='purple')
plt.show()
我想可视化由 3 个形状为 (8, 3) 的 numpy 数组定义的 3 个多面体。
我正在寻找类似的东西:
我的数据如下:
A = np.array([[0.92523719, 0.26843252, 0.77794309],
[0.73156748, 0.27794309, 0.57476281],
[0.62113842, 0.37886158, 0.87886158],
[0.72205691, 0.07476281, 0.76843252],
[0.57476281, 0.23156748, 0.72205691],
[0.77794309, 0.42523719, 0.73156748],
[0.87886158, 0.12113842, 0.62113842],
[0.76843252, 0.22205691, 0.92523719]])
B = np.array([[0.23156748, 0.72205691, 0.57476281],
[0.26843252, 0.77794309, 0.92523719],
[0.12113842, 0.62113842, 0.87886158],
[0.22205691, 0.92523719, 0.76843252],
[0.27794309, 0.57476281, 0.73156748],
[0.37886158, 0.87886158, 0.62113842],
[0.07476281, 0.76843252, 0.72205691],
[0.42523719, 0.73156748, 0.77794309]])
C = np.array([[0.73156748, 0.77794309, 0.42523719],
[0.62113842, 0.87886158, 0.12113842],
[0.77794309, 0.92523719, 0.26843252],
[0.57476281, 0.73156748, 0.27794309],
[0.87886158, 0.62113842, 0.37886158],
[0.72205691, 0.57476281, 0.23156748],
[0.76843252, 0.72205691, 0.07476281],
[0.92523719, 0.76843252, 0.22205691]])
您似乎有 3D 点,但没有边或多边形信息。假设多面体是凸的,scipy.spatial
的ConvexHull
可以找到凸包上的所有多边形。凸包存在三角形,可以作为 Poly3DCollection
.
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull
A = np.array([[0.92523719, 0.26843252, 0.77794309], [0.73156748, 0.27794309, 0.57476281], [0.62113842, 0.37886158, 0.87886158], [0.72205691, 0.07476281, 0.76843252], [0.57476281, 0.23156748, 0.72205691], [0.77794309, 0.42523719, 0.73156748], [0.87886158, 0.12113842, 0.62113842], [0.76843252, 0.22205691, 0.92523719]])
B = np.array([[0.23156748, 0.72205691, 0.57476281], [0.26843252, 0.77794309, 0.92523719], [0.12113842, 0.62113842, 0.87886158], [0.22205691, 0.92523719, 0.76843252], [0.27794309, 0.57476281, 0.73156748], [0.37886158, 0.87886158, 0.62113842], [0.07476281, 0.76843252, 0.72205691], [0.42523719, 0.73156748, 0.77794309]])
C = np.array([[0.73156748, 0.77794309, 0.42523719], [0.62113842, 0.87886158, 0.12113842], [0.77794309, 0.92523719, 0.26843252], [0.57476281, 0.73156748, 0.27794309], [0.87886158, 0.62113842, 0.37886158], [0.72205691, 0.57476281, 0.23156748], [0.76843252, 0.72205691, 0.07476281], [0.92523719, 0.76843252, 0.22205691]])
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
for cube, color in zip([A, B, C], ['r', 'g', 'b']):
hull = ConvexHull(cube)
# draw the polygons of the convex hull
for s in hull.simplices:
tri = Poly3DCollection(cube[s])
tri.set_color(color)
tri.set_alpha(0.5)
ax.add_collection3d(tri)
# draw the vertices
ax.scatter(cube[:, 0], cube[:, 1], cube[:, 2], marker='o', color='purple')
plt.show()
假设每个三角形的最长边是立方体的一条面对角线,我们可以搜索最短的两条边画成黑色:
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull, distance
A = np.array([[0.92523719, 0.26843252, 0.77794309], [0.73156748, 0.27794309, 0.57476281], [0.62113842, 0.37886158, 0.87886158], [0.72205691, 0.07476281, 0.76843252], [0.57476281, 0.23156748, 0.72205691], [0.77794309, 0.42523719, 0.73156748], [0.87886158, 0.12113842, 0.62113842], [0.76843252, 0.22205691, 0.92523719]])
B = np.array([[0.23156748, 0.72205691, 0.57476281], [0.26843252, 0.77794309, 0.92523719], [0.12113842, 0.62113842, 0.87886158], [0.22205691, 0.92523719, 0.76843252], [0.27794309, 0.57476281, 0.73156748], [0.37886158, 0.87886158, 0.62113842], [0.07476281, 0.76843252, 0.72205691], [0.42523719, 0.73156748, 0.77794309]])
C = np.array([[0.73156748, 0.77794309, 0.42523719], [0.62113842, 0.87886158, 0.12113842], [0.77794309, 0.92523719, 0.26843252], [0.57476281, 0.73156748, 0.27794309], [0.87886158, 0.62113842, 0.37886158], [0.72205691, 0.57476281, 0.23156748], [0.76843252, 0.72205691, 0.07476281], [0.92523719, 0.76843252, 0.22205691]])
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
for cube, color in zip([A, B, C], ['r', 'g', 'b']):
hull = ConvexHull(cube)
for s in hull.simplices:
tri = Poly3DCollection(cube[s])
tri.set_color(color)
tri.set_alpha(0.5)
tri.set_edgecolor('none')
ax.add_collection3d(tri)
edges = []
if distance.euclidean(cube[s[0]], cube[s[1]]) < distance.euclidean(cube[s[1]], cube[s[2]]):
edges.append((s[0], s[1]))
if distance.euclidean(cube[s[1]], cube[s[2]]) < distance.euclidean(cube[s[2]], cube[s[0]]):
edges.append((s[1], s[2]))
else:
edges.append((s[2], s[0]))
else:
edges.append((s[1], s[2]))
if distance.euclidean(cube[s[0]], cube[s[1]]) < distance.euclidean(cube[s[2]], cube[s[0]]):
edges.append((s[0], s[1]))
else:
edges.append((s[2], s[0]))
for v0, v1 in edges:
ax.plot(xs=cube[[v0, v1], 0], ys=cube[[v0, v1], 1], zs=cube[[v0, v1], 2], color='black')
ax.scatter(cube[:, 0], cube[:, 1], cube[:, 2], marker='o', color='purple')
plt.show()