【问题标题】:How to change color of Delaunay points in Python?如何在 Python 中更改 Delaunay 点的颜色?
【发布时间】:2021-05-12 04:28:21
【问题描述】:

我是 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()

感谢您的帮助!

【问题讨论】:

    标签: python matplotlib delaunay


    【解决方案1】:

    您希望在三角剖分的顶点(即点)上进行着色,因此您应该使用 plt.plot 函数(替换最后一行)。

    这是一种方法(继续您的代码)。将 last 之前的行替换为以下行(它上面的 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")
    

    【讨论】:

      【解决方案2】:

      Numpy 允许通过条件过滤点。例如,points[num_neigh &lt;= 5] 将收集所有具有 5 个或更少邻居的点,前提是 num_neigh 是一个包含每个点的邻居数量的 numpy 数组。

      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()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-10
        • 2020-08-16
        • 1970-01-01
        • 2012-08-05
        • 2021-01-07
        • 1970-01-01
        • 2021-07-09
        • 2017-06-23
        相关资源
        最近更新 更多