具有包裹尺寸的德劳内三角剖分?
Posted
技术标签:
【中文标题】具有包裹尺寸的德劳内三角剖分?【英文标题】:Delaunay triangulation with wrapped dimension? 【发布时间】:2022-01-09 23:07:29 【问题描述】:我想在二维姿势 (x, y, yaw) 的空间中进行 Delaunay 三角剖分 - 其中 yaw 是 [0, 2*pi) 中的角度。我想我需要在米和弧度之间定义一些比例因子以使问题得到明确定义 - 假设它现在是 1。
我一直在使用 scipy.spatial.Delaunay 进行 Delaunay 三角测量,但它们似乎不支持包裹尺寸(偏航)。是否有某种技巧或方法来按摩输入(或一些开源代码)以使其工作?
【问题讨论】:
您可以通过无限复制周期来模拟包裹维度。那么一个时期的德劳内三角剖分应该可以解决问题。由于无限复制是不切实际的 :-) 两侧的单个副本就足够了。 无论如何,这种混合距离和角度的想法似乎很可疑,并且可能揭示了一个 XY 问题。另请注意,三角剖分实际上是四面体化。 是的,@Peter,你要解决什么问题? 最终问题是找到一条有效地遍历一组姿势的路径。 delaunay 三角剖分的目标是找到相邻的位姿,将其转换为图形,以便将其视为旅行商问题。由于转弯半径有限,每个姿势的偏航都会影响所选路径。 谢谢 Yves - 是的,两边的单一副本似乎是要走的路。看起来它甚至可以更少 - 每边都有一个半包装 - 只需执行wrapped_yaw = yaw+2*pi if yaw < pi else yaw-2*pi
。如果我得到它的工作,我会发布一个解决方案。另一种方法是使用 cos(yaw)
和 sin(yaw)
作为输入,但是我们有一个 4d 问题,并且超四面体的计算复杂度可能要高得多。
【参考方案1】:
嗯,用包装做到了。我没有测试正确性,但这似乎有效。
(可以从here中删除或复制的数组注解)
def get_delaunay_pose_neighbours(poses: Array['N',3], meters_per_turn: float) -> Array['P,2', int]:
""" Do delaunay triangulation in pose-space. The trickiness here is in doing it correctly for the wrapped yaw dimension
"""
yaws = poses[:, [2]] # poses are (x, y, yaw)
wrapped_poses = np.hstack([poses[:, :2], yaws + np.where(yaws < np.pi, 2 * np.pi, -2 * np.pi)])
vertices = np.vstack([poses, wrapped_poses]) * (1, 1, meters_per_turn)
pairs = get_delaunay_neighbour_indices(vertices).T
pairs = pairs % len(poses) # Collapse the wrapping
pairs = pairs[pairs[:, 0] != pairs[:, 1]] # Remove self-pairs
pairs = get_unique_rows(pairs) # Remove duplicate pairs (from the wrapping)
return pairs
def get_delaunay_neighbour_indices(vertices: Array['N,D', int]) -> Array['2,P', int]:
"""
Find each pair of neighbouring vertices in the Delaunay triangulation.
# TODO: See if we can get better performance. This takes about 30ms on a BPearl Scan.
:param vertices: The vertices of the points to perform Delaunay triangulation on
:return: The pairs of indices of vertices
"""
tri = Delaunay(vertices)
spacing_indices, neighbours = tri.vertex_neighbor_vertices
ixs = np.zeros((2, len(neighbours)), dtype=int)
ixs[0, spacing_indices[1:np.argmax(spacing_indices)]] = 1 # The argmax is unfortuantely needed when multiple final elements the same
ixs[0, :] = np.cumsum(ixs[0, :])
ixs[1, :] = neighbours
return ixs
def get_unique_rows(arr: Array['N,D', float]) -> Array['M,D', float]:
""" Get unique rows, given the arrays"""
row_view = collapse_rows_into_values(arr)
values = np.unique(row_view)
values_recast = values.view(arr.dtype).reshape(len(values), -1)
return values_recast
def collapse_rows_into_values(arr: Array['N,D', Any]) -> Array['N', Any]:
""" Collapse rows into single values. Useful for finding unique rows with np.unique """
return np.ascontiguousarray(arr).view(np.dtype((np.void, arr.dtype.itemsize * np.prod(arr.shape[1:])))).ravel()
【讨论】:
以上是关于具有包裹尺寸的德劳内三角剖分?的主要内容,如果未能解决你的问题,请参考以下文章
计算几何德劳内三角剖分算法 | 利用 scatter 绘制散点图 | 实现外接圆生成 | scipy库的 Dealunay 函数 | 实战: A-B间欧氏距离计算
Python沃罗诺伊图 | KNN 最邻近算法 | Voronoi 函数
确定 UPS Shipping Rate API 的包裹尺寸