我是Python的新手,我的任务是编写一个创建Delaunay三角剖分图的脚本。我已经成功地做到了这一点,但我需要根据图中邻居的数量来改变点的颜色。我有一个函数,它定义邻居的数量,并将所有的点放入一个以邻居的数量为键的字典中。但是,我不知道如何将字典应用于我的绘图--有没有一个特定的函数可以让您使用triplot创建的绘图,并根据外部字典更改颜色?到目前为止,我的代码如下:
from curved_analysis import read_xyz, read_nfo, num_neighbors
from scipy.spatial import Delaunay
import matplotlib.tri as mtri
import numpy as np
import matplotlib.pyplot as plt
coords = np.array(read_xyz("traj0.xyz"))
for k in range(coords.shape[0]):
points = coords[k]
tri = Delaunay(points[:, :2], qhull_options=('Qz'))
neigh = num_neighbors(tri)
for key in neigh:
if key <=5:
plt.triplot(neigh[key], color = 'green')
if key == 6:
plt.triplot(neigh[key], color = 'red')
if key >= 7:
plt.triplot(neigh[key], color = 'yellow')
plt.triplot(points[:,0], points[:,1], tri.simplices)
plt.plot(points[:,0], points[:,1], 'o')
plt.show()谢谢你的帮助!
发布于 2021-02-09 01:01:53
您希望在三角剖分的顶点(即,点)上完成着色,因此应该使用plt.plot函数(替换最后一条线)。
这里有一种方法(继续你的代码)。将最后一行替换为以下行(也应删除其上的for key循环)。
for k, count in neigh.items():
if count <= 5:
plt.plot(tri.points[k, 0], tri.points[k, 1], "og")
elif count == 6:
plt.plot(tri.points[k, 0], tri.points[k, 1], "or")
else:
assert count >= 7
plt.plot(tri.points[k, 0], tri.points[k, 1], "oy")在对200个点的随机样本进行三角测量时,我得到了以下图:

注意:为了计算neigh字典,我使用了以下函数(您没有给出您的实现)。字典的关键是三角化点中顶点的索引。另请注意,有更有效的方法可以做到这一点。例如,将计数存储在numpy数组中而不是字典中(例如,使用np.diff(indptr)),并对每个情况使用矢量化操作,而不是在循环中逐个绘制。
def num_neighbors(tri):
indptr, indices = tri.vertex_neighbor_vertices
assert len(indptr) == len(tri.points) + 1
vertex_order_map = {}
for k in range(len(indptr) - 1):
num_neighbors_k = indptr[k+1] - indptr[k]
vertex_order_map[k] = num_neighbors_k
return vertex_order_map 编辑:下面是更有效的矢量化代码。结果是相同的(直到点的着色顺序)。
indptr, indices = tri.vertex_neighbor_vertices
neighbor_counter_array = np.diff(indptr)
cond_le_5 = (neighbor_counter_array <= 5)
cond_eq_6 = (neighbor_counter_array == 6)
cond_ge_7 = (neighbor_counter_array >= 7)
plt.plot(tri.points[cond_le_5, 0], tri.points[cond_le_5, 1], "og")
plt.plot(tri.points[cond_eq_6, 0], tri.points[cond_eq_6, 1], "or")
plt.plot(tri.points[cond_ge_7, 0], tri.points[cond_ge_7, 1], "oy")发布于 2021-02-09 01:39:02
Numpy允许通过条件过滤点。例如,假设num_neigh是一个包含每个点的邻居数量的numpy数组,则points[num_neigh <= 5]将收集具有5个或更少邻居的所有点。
num_neigh可以计算为tri.vertex_neighbor_vertices[0]中连续条目之间的差值,因此为num_neigh = np.diff(tri.vertex_neighbor_vertices[0])。
下面的代码使用plt.scatter来绘制带有较大点的点。代码假设coords中的第一个维度表示某种层。请注意,在Python中,建议直接使用元素而不是通过索引编写循环。问题不是那么清楚,是每一层都应该是一个单独的图,还是应该将它们组合在子图中。
import matplotlib.pyplot as plt
from scipy.spatial import Delaunay
import numpy as np
coords = np.random.uniform(0, 10, size=(1, 40, 2))
for points in coords:
tri = Delaunay(points[:, :2], qhull_options=('Qz'))
num_neigh = np.diff(tri.vertex_neighbor_vertices[0])
plt.triplot(points[:, 0], points[:, 1], tri.simplices, linestyle='--')
for filter, color in zip([num_neigh <= 5, num_neigh == 6, num_neigh >= 7], ['lime', 'crimson', 'gold']):
plt.scatter(points[filter, 0], points[filter, 1], s=80, color=color, zorder=2)
plt.gca().set_aspect('equal', 'box') # equal axes needed because Delaunay depends on the scales
plt.show()

https://stackoverflow.com/questions/66103783
复制相似问题