如何计算与每个点相关联的边的长度?

How can I count the length of the edge associated with each point?

我在 python 中构建了 Delaunay 三角剖分。 现在我有 8 个点(黑色)并生成 14 个边(灰色)。 如何计算与每个点相关联的边的长度? 我想要的矩阵是每个点连接的边的长度,比如

[[P1, E1_length, E2_length, ...], [P2, E6_length, E7_length, ...], ...]
import numpy as np
points = np.array([[0, 0], [0, 1.1], [1, 0], [1, 1],[1.5, 0.6],[1.2, 0.5],[1.7, 0.9],[1.1, 0.1],])
from scipy.spatial import Delaunay
tri = Delaunay(points)

import matplotlib.pyplot as plt
plt.triplot(points[:, 0], points[:, 1], tri.simplices.copy(), color='0.7')
plt.plot(points[:, 0], points[:, 1], 'o', color='0.3')
plt.show()

新答案

这是一种方法,可以为您提供点和与每个点相关联的边长的字典:

simplices = points[tri.simplices]
edge_lengths = {}

for point in points:
    key = tuple(point)
    vertex_edges = edge_lengths.get(key, [])
    adjacency_mask = np.isin(simplices, point).all(axis=2).any(axis=1)
    for simplex in simplices[adjacency_mask]:
        self_mask = np.isin(simplex, point).all(axis=1)
        for other in simplex[~self_mask]:
            dist = np.linalg.norm(point - other)
            if dist not in vertex_edges:
                vertex_edges.append(dist)
    edge_lengths[key] = vertex_edges

输出:

{(0.0, 0.0): [1.4142135623730951, 1.1, 1.3, 1.0],
 (0.0, 1.1): [1.004987562112089, 1.3416407864998738, 1.4866068747318506],
 (1.0, 0.0): [1.4866068747318506, 0.5385164807134504, 0.7810249675906654, 1.140175425099138, 0.14142135623730956],
 (1.0, 1.0): [1.004987562112089, 1.4142135623730951, 0.5385164807134504, 0.6403124237432849, 0.7071067811865475],
 (1.5, 0.6): [0.6403124237432849, 0.36055512754639896, 0.31622776601683794, 0.6403124237432848],
 (1.2, 0.5): [0.5385164807134504, 1.3, 0.31622776601683794, 0.41231056256176607],
 (1.7, 0.9): [0.7071067811865475, 0.36055512754639896],
 (1.1, 0.1): [0.14142135623730956, 0.41231056256176607, 0.6403124237432848]}

要求更改前的旧答案

Delaunay 对象有一个 simplices 属性,returns 构成单纯形的点。使用 scipy.spatial.distance.pdist() 和高级索引,您可以获得所有边长,如下所示:

>>> from scipy.spatial.distance import pdist

>>> edge_lengths = np.array([pdist(x) for x in points[tri.simplices]])
>>> edge_lengths
array([[1.00498756, 1.41421356, 1.1       ],
       [0.53851648, 1.3       , 1.41421356],
       [0.53851648, 1.        , 1.3       ],
       [0.64031242, 0.70710678, 0.36055513],
       [0.64031242, 0.31622777, 0.53851648],
       [0.14142136, 0.53851648, 0.41231056],
       [0.64031242, 0.41231056, 0.31622777]])

但是请注意,这里的边长是重复的,因为每个单纯形与另一个单纯形至少共享一条边。

循序渐进

tri.simplices 属性为 Delaunay 对象中每个单纯形中的每个顶点提供 points 中的索引:

>>> tri.simplices
array([[2, 6, 5],
       [7, 2, 5],
       [0, 7, 5],
       [2, 1, 4],
       [1, 2, 7],
       [0, 3, 7],
       [3, 1, 7]], dtype=int32)

使用高级索引,我们可以获得构成单纯形的所有点:

>>> points[tri.simplices]
array([[[1. , 1. ],
        [0. , 1.1],
        [0. , 0. ]],

       [[1.2, 0.5],
        [1. , 1. ],
        [0. , 0. ]],

       [[1. , 0. ],
        [1.2, 0.5],
        [0. , 0. ]],

       [[1. , 1. ],
        [1.5, 0.6],
        [1.7, 0.9]],

       [[1.5, 0.6],
        [1. , 1. ],
        [1.2, 0.5]],

       [[1. , 0. ],
        [1.1, 0.1],
        [1.2, 0.5]],

       [[1.1, 0.1],
        [1.5, 0.6],
        [1.2, 0.5]]])

最后,这里的每个子数组代表一个单纯形和构成它的三个点,通过使用scipy.spatial.distance.pdist(),我们可以通过迭代单纯形得到每个单纯形中每个点的成对距离:

>>> np.array([pdist(x) for x in points[tri.simplices]])
array([[1.00498756, 1.41421356, 1.1       ],
       [0.53851648, 1.3       , 1.41421356],
       [0.53851648, 1.        , 1.3       ],
       [0.64031242, 0.70710678, 0.36055513],
       [0.64031242, 0.31622777, 0.53851648],
       [0.14142136, 0.53851648, 0.41231056],
       [0.64031242, 0.41231056, 0.31622777]])